
这是什么
一个 Claude Code 插件,在每条助手消息的原文下面显示一份大白话改写。改写由你用一个环境变量选的模型完成:默认是本机 ollama 模型,也可以换成 codex CLI、Anthropic API 或任何兼容 OpenAI 的接口。它只改显示——存下来的对话记录、以及 Claude 自己看到的,仍然是原文,变的只有屏幕上渲染出来的东西——所以这个钩子既不会改写也不会吞掉一条回复,任何一环出错都只是让你看到原样。另有一个可选钩子,在 agent 写入或编辑 Markdown 文件时把它改写成大白话,可以就地覆盖,也可以写成同级的 NAME.plain.md。/claudish 命令能在会话中途开关改写,并切换显示方式、风格预设、输出语言和模型;一个仪表盘会逐项打印当前取值以及它来自哪里,并把所有会活过这个会话的覆盖项标出来。
谁做的仓库有 37 次提交、九位贡献者,但它是一个人的项目:21 次提交挂在他自己的 GitHub 账号下,另有 6 次是他用同一个名字从两台 Mac 上提交的。他在评审评论末尾署名「Human Mike」;37 次提交里有 24 次带共同作者尾注,其中 21 次写的是一个 Claude 模型——带一百万上下文的 Opus 5 出现十一次。其余部分则是别人的活:provider 层、一条 oauth 登录路径、一个 caveman 风格预设和一个斜杠命令,都是以 pull request 的形式进来的。
它是怎么搭起来的
组成 · 6一个没有构建步骤、没有测试套件、除 bash、jq 和 curl 之外没有依赖的 Claude Code 插件。每个钩子都是一个短命进程:从标准输入读 JSON,往标准输出写 JSON;整套东西是围着「它一定会出错」这个假设组织的。三个钩子写在一个 719 字节的 hooks.json 里——会话开始的提示、60 秒上限的 MessageDisplay 改写、180 秒上限的可选 PostToolUse Markdown 改写——任何一个出问题都什么都不输出、退出码 0,把原文留在原地。两个改写钩子 source 同一对库,所以上屏和写文件用的是同一套 provider 选择与语言解析。配置优先级处处一致:~/.claude/ 下的旗标文件压过环境变量,环境变量压过项目 settings 里的 language 键,再压过内置默认值。旗标文件之所以存在,是因为环境变量在会话启动时就定死了,改不动一个正在跑的会话;斜杠命令负责写它们,钩子在每条消息上重新读一遍。
- rewrite.sh
- MessageDisplay 钩子,也是仓库里最大的脚本,22,877 字节:把每个流式片段缓冲进临时文件,在最后一片上重建整条消息,选定 prompt 与屏幕上的标签,跑一遍正文长度闸门,然后输出改写——或者什么都不输出。
- providers.sh
- 两个钩子共用的 provider 层,23,678 字节:ollama、codex CLI、Anthropic Messages API 与 OpenAI chat completions 各一套请求形态,按 provider 查 key、查 base URL、设超时,并执行那条规则——被 token 上限截断的改写直接丢掉,不上屏。
- rewrite-md.sh
- 可选的 PostToolUse 钩子,14,205 字节,负责改写 Markdown 文件。没指定目录时它什么都不做;改写时把 YAML frontmatter 拆下来再原样接回去,原子写入,默认写成同级的
NAME.plain.md,而不是改动拿到手的那份文件。 - claudish-ctl.sh、commands/claudish.md、session-notice.sh
- 分别 13,800、1,751 和 3,367 字节:写旗标文件并打印仪表盘(连每个值的出处一起)的脚本、把用户参数用带引号的 here-doc 递进去的斜杠命令定义,以及在会话开始时报告上一次会话遗留覆盖项的钩子。
- lang.sh
- 4,771 字节,语言解析器加清理函数,所有不可信的配置值都要过它:先读 CLAUDISH_LANG,再按优先级从四份 settings 文件里读 Claude Code 的 language 键,然后把控制字符折成空格、把取值限制在三个词或三十个码点以内,之后才可能进 prompt 或上屏。
- README、CHANGELOG、CONTRIBUTING、CLAUDE.md 与两个清单
- 文档比代码还重:README 34,435 字节,CHANGELOG 15,261,CONTRIBUTING 9,530,CLAUDE.md 5,501,pull request 模板 2,418,release skill 5,638,另有 825 字节的插件清单和 530 字节的 marketplace 清单。总共十八个文件。
取舍,以及它替代了什么
只改显示,不碰对话记录 替代 连 Claude 自己看到的内容一起改写
README 把它写成插件的定义性属性:变的只有屏幕上渲染出来的东西,Claude 自己的推理和存下来的对话记录都保留原文。贡献指南把它重复成一条底线规则——任何新增内容都不应改变 Claude 真正说过的话。也正是它让
/claudish last成为可能:这条命令重印一份从未被覆盖的原文,靠一个标记告诉钩子放行那条回复。永远 fail open 替代 把错误显示在屏幕上
这条规则在
CLAUDE.md里排在第一位,并写明它压过其他一切考虑:任何问题下钩子都什么都不输出、退出码 0,于是最坏情况就是读者看到的仍然一字不差是 Claude 写的东西。贡献指南说,一个可能吞掉或弄坏回答的显示钩子比没有插件更糟;这条护栏针对的那种失败——半截改写上了屏,或者在覆盖模式下盖到真文档上——正是被截断的改写一律丢弃的原因。只在最后一片上调用一次模型 替代 每来一片就改写一片
钩子每一片都会被触发一次,而每片只带消息的一个碎片,来一片改一片等于一次只改一句话。所以每个增量都先缓冲进临时文件,等标着 final 的那一片凑齐整条消息,才调用一次模型——也正是在这一刻,才能从对话记录里读出用户最初的问题并作为上下文一并送进去。
默认本机 ollama,上云要明确选择 替代 一个不用装东西就能跑的托管模型
默认值原样继承:本机模型,什么都不出这台机器。README 把「选一个云 provider」本身当作同意开关,并警告:环境里只要有一个来路不明的 OPENAI_API_KEY,改一个变量就足以把每条助手消息都发去 OpenAI;而那条 provider 的 pull request 是拿「默认路径与替换前逐字节一致」这个保证来评审的。
用 emoji 加粗体,不用颜色 替代 贡献者已经测过的彩色分隔标签
彩色版本在真实会话里渲染正常,最后仍然被换掉,作者给了三条理由:16 色码是调色板索引,终端主题可以把它映成灰色或背景色;转义序列会以字面字节漏进
claude -p重定向到文件的输出;而这个钩子在任何一个描述符上都没有终端,两种情况都发现不了,也就谈不上降级。那句「谁在说话」的说明连自定义 prompt 也要加 替代 和其它偏好行放在一起,摆在 prompt 文件覆盖之前
输出语言那一行摆在 prompt 文件覆盖之前,是为了让自定义 prompt 能替换掉它。0.9.0 加的那一行——「I」是助手、「you」是用户——反过来追加在覆盖之后,因为它是关于输入的事实,而不是偏好;只有一个插入点,也顺带避开了「新增一个预设要改四个文件、漏掉一个」的那种失败模式。
依据README.md(34,139 字符)、CHANGELOG.md(15,195 字符)、CONTRIBUTING.md(9,494 字符)、CLAUDE.md,以及完整的十八个文件树及其体积。
制作过程
5 个阶段- 01
十八天,十二个版本,2,707 个星
仓库创建于 2026-08-10T18:32:23Z,十二分钟后第一次提交就落了地,标题是「Initial release of claudish-to-english v0.1.0」。README 里描述的这一切都发生在接下来的十八天里:37 次提交全部落在 2026 年 8 月,最后一次是 2026-08-28。变更日志里记了十二个版本——第一天发了 0.1.0 和 0.1.1,2026-08-13 发 0.2.0 和 0.3.0,08-14 发 0.4.0,08-19 发 0.5.0,08-20 发 0.5.1 和 0.6.0,08-26 发 0.7.0,08-27 发 0.7.1 和 0.8.0,08-28 发 0.9.0——而 tag 有十三个,就是这十二个再加一个叫
assets的,GitHub 的 release 列表上却只有三条:v0.9.0、v0.8.0,以及那个装着 README 对比图的assets。到月底它有 2,707 个星、129 个 fork、10 个未关的 issue,issue 与 pull request 合计三十条。九个人贡献过代码,37 次提交里 24 次带共同作者尾注,其中 21 次写的是一个 Claude 模型——带一百万上下文的 Opus 5 十一次,两种上下文规格的 Opus 4.8 合计九次,Fable 5 一次。 - 02
这个钩子按流式分片触发,不是按消息触发
关于显示钩子最关键的事实是:Claude Code 按流式分片触发它,不是每条消息触发一次,而且每次触发都是一个独立进程,只带着这一片的增量文本。于是插件把每个片段追加进一个按会话与消息 id 命名的临时文件,什么都不输出,只在标着
final的那一片——整条消息已经齐了——调用一次模型。这次调用还会从对话记录里读出用户最初的问题,只作为上下文送进去,并写明绝不允许回答或重复它。由此有了两种显示方式:默认的append先正常流出原文,再在下面补上改写;标为实验性的replace压住原文分片,等模型答完只显示改写。只改显示正是整个设计安全的原因,而这个仓库里为此留了一场很长的争论:issue 12 一开始报告说钩子触发了、输出的 JSON 完全符合 schema,屏幕上却什么都没有;报告人先把结论收窄成「只发生在交互式终端里的问题」,最后整个撤回——真正的原因是他自己 settings 文件里的"verbose": true,因为 verbose 模式本来就会显示原文、绕过替换文本。 - 03
四个 provider,以及一个永远不出本机的默认值
用户最先要的是「别非得用 ollama」:issue 9 只有三行——「Would love to try this if it didn’t need Ollama」——加一条追问能不能自己选模型的回复。nircoh-onyx 用一个 pull request 回答:把模型调用从两个钩子里抽出来,做成共用的
providers.sh,默认仍是 ollama,同时把任何兼容 OpenAI 的接口和 Anthropic 的 Messages API 放到CLAUDISH_PROVIDER后面。作者在评审时补了两件贡献者没做的事:被输出 token 上限截断的改写直接丢弃、不上屏,三个 provider 一律如此,因为在 Markdown 钩子的覆盖模式下,半截改写会盖到真的文档上;以及把 HTTP 状态码记下来,好歹能解释失败出在哪,而不只是看见它失败。接着是 datvo06 贡献的 codex CLI provider,它用一个轮询杀进程的循环兜底,因为 macOS 自带环境里没有timeout(1)。再之后是 JackBhanded 的 oauth 模式,不花 API key,直接蹭本机 Claude Code 的登录:有测试者发现 macOS 把那个 token 放在登录钥匙串而不是凭据文件里,于是贡献了优先读钥匙串的实现和一次http=[200]的端到端验证,作者又做了硬化——只要 base URL 被改过,这个模式就拒绝运行,订阅 token 因此到不了代理,请求还带上claude-cli的 User-Agent。README 至今留着它挣来的那句警告:非官方,风险自负,并且每个会话第一次改写时会在屏幕上再说一遍。 - 04
一个来了两次的斜杠命令,和一个只来一次的代词 bug
有两个版本其实是别人的东西和作者自己的东西撞在了一起。MakhBeth 在自己的 fork claudish-tldr 里做了一个
/claudish命令;作者当时也在做同一件事,回复说「I was already working on the integration of your slash command into the plugin」,然后把自己那版作为另一个 pull request 合了进去,还把归属的账号名写错了,道了歉,再补上漏掉的那一处。那一处值得补:命令把$ARGUMENTS不加引号地插进 shell 命令行,而 0.5.1 的修法是把引号换成一个带引号的 here-doc 走标准输入,因为 Claude Code 是在 shell 解析之前把参数文本替换进去的,写在命令里的引号挡不住$(…)、反引号和裸*。第二份外部贡献成了caveman风格预设,它原本还附带彩色标签,而作者在真实会话里试过、确认渲染正常,然后还是换掉了:16 色码是调色板索引,终端主题可以把它映成灰色或背景色;转义序列会以字面字节漏进claude -p重定向到文件里的输出;而这个钩子在任何一个描述符上都没有终端,这两种情况它都发现不了。标签最后变成了一个 emoji 加一个加粗的词。最后一轮社区回合最锋利:issue 24 里两条改写主客颠倒,「Found the root cause.」被改成了「You’ve found the root cause.」。作者先问用的是哪个模型;报告人把「自己写来修这个问题」的那段提示词贴了回来,0.9.0 把它的一个版本写进了每一个 prompt。 - 05
规则是在被违反过之后才写下来的
最后一个版本是文档。0.9.0 加上了
CONTRIBUTING.md、一份 pull request 模板、一份 Claude Code 会自动读取的CLAUDE.md,以及一个分两阶段执行的/releaseskill;它之所以存在,用作者自己的话说,是因为发布流程和这个仓库的坑此前只活在「only in review comments and in whoever happened to remember them」里。这些文档记下来的,正是已经出过的事。新增一个风格预设会被四个地方读到,而caveman上线时漏了其中一个——会话开始时的提示——于是一个风格可以跨会话一直生效,屏幕上却什么都没说。斜杠命令里allowed-tools那行必须把引号收在路径之后,它已经回归过两次,有一次是解决合并冲突时弄的,结果从 0.5.0 到 0.7.0 每个版本里/claudish都用不了。项目 settings 文件里——一个会跟着仓库走、未必是本机用户自己写的文件——的language值可以把终端转义序列送上屏幕,因为清理函数只折叠了空白,而转义符不是空白。排在所有规则之前、并且在每一份文档里重复的那一条是:每个钩子都必须 fail open。这里没有测试套件;验证一次改动的办法是把构造出来的 JSON 喂给钩子,并确认三种坏输入都什么都不打印、退出码为 0。
相关档案
全部档案 →第 078 号
OpenChatCut
一个本地优先的视频剪辑器,剪辑方式是跟它说话:内置 agent 与外部 Codex、Claude Code 会话调用的是界面自己在用的同一套剪辑工具,于是每一处改动都落在一条真实的多轨时间线上——是片段、转场、字幕、特效或音频,仍然能拖、能撤销、能导出。工程与素材留在本机,预览与最终渲染都出自 Remotion。
第 132 号
typesafe-computer-use
它把你的 Mac 推向一句白话写下的目标:OCR 与无障碍树负责读屏,TypeSafe 分类器挑下一步动作,只有需要自由文本时才叫上写作模型。一次决策约 $0.0002,也就是五十分之一美分,而前沿模型读同一张截图要 $0.032。
第 125 号
OKF Agent Memory
把编码 agent 学到的东西以纯 Markdown 留在仓库里——一个用进程内 BM25 检索的 OKF v0.2 知识 bundle——于是这份记忆可以被 diff、被审阅,而不必住进数据库。