把AI编码中的重复操作变成钩子与命令
文章提供Claude Code钩子与自定义斜杠命令配置,并介绍Codex CLI的对应方式。核心是用事件脚本执行固定检查,用保存的提示词承载按需审查等任务。
AI 深度解读
让 AI 编程变慢的,未必是模型生成代码的速度,也可能是你反复提醒它格式化、粘贴 diff、检查它是否在等授权。作者给出的解法很直接:把必须执行的动作交给 Hooks,把按需调用的提示词做成命令。
这套配置值得看,因为它把「要求模型记住」变成了可复用的工作流程。不过,自动执行不等于安全可靠,Claude Code 与 Codex CLI 的兼容细节也需要在本机确认。原文提供了配置示例,没有提供效率提升的对照数据。
必须执行的事,为什么不该只写进提示词
Hooks 是在指定事件发生时运行的脚本,例如文件编辑成功之后、工具调用之前、会话启动时。Slash commands 则是保存好的提示词,需要时输入 /review,再把参数交给模型。
两者解决的问题不同。代码审查需要模型判断,可以按需触发;格式化属于确定性操作,适合直接运行程序。作者建议,遇到 CLAUDE.md 里的「每次编辑后都要执行 X」,先考虑能不能改成 Hook。
能交给程序稳定执行的步骤,就别反复消耗模型的注意力。
Hook 配置有三层:事件决定何时运行,matcher 筛选工具或场景,handler 执行动作。命令处理器通过标准输入接收事件 JSON,示例使用 jq 取字段,安装命令是 brew install jq。
下面这段配置解决「Claude 修改文件后总要提醒它运行 Prettier」的问题:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
}
]
}
]
}
}
关键是 .tool_input.file_path:它把本次编辑的文件交给格式化器,Edit|Write 则限制触发范围。其他技术栈可以换成 ruff format、gofmt -w、rustfmt 或 swift-format。
作者还给出 "if": "Edit(*.ts)",用于进一步限制到 TypeScript 编辑。这类字段的支持范围需要按实际安装版本确认。修改设置后,可以在 Claude Code 输入 /hooks,检查配置是否被加载以及来自哪个文件。
自动化除了省操作,还要处理等待和失控
作者给出的其他 Hooks,覆盖了三个常见断点。
首先是人没发现模型正在等待。macOS 可以用 Notification 事件调用 osascript 发送通知,放进 ~/.claude/settings.json 后跨项目生效。permission_prompt 用于权限请求,idle_prompt 用于等待下一条消息。
如果通知没有出现,作者提醒检查 Script Editor 的通知权限,可以先运行 osascript -e 'display notification "test"'。这是平台相关配置,不能直接搬到其他操作系统。
其次是危险操作。原文用 PreToolUse 调用 .claude/hooks/guard.sh,拦截包含 rm -rf、git push (-f|--force)、git reset --hard 的命令,以及对 *.env、*.env.* 文件的编辑。脚本需要通过 chmod +x 增加执行权限。
按原文描述,退出码 2 才会阻止调用,并把标准错误中的原因反馈给 Claude;退出码 1 只是非阻断错误。${CLAUDE_PROJECT_DIR} 用来定位项目根目录,避免切换工作目录后找不到脚本;作者还用 "args": [] 表示不经过 shell 执行,以处理带空格的路径。这些执行语义同样应在本机确认。
但正则只能识别特定写法,拦不住所有等价命令。作者明确建议,硬限制使用设置里的 permission deny rules,Hook 作为补充提醒。
最后是上下文和停止条件。SessionStart 配合 startup|resume,可以把当前分支和 git status --short | head -20 的输出送入上下文。适合放经常变化的事实,不适合每次塞入 300 行资料。
Stop 则更需要克制:退出码 2 会要求 Claude 继续工作。如果「测试通过才能停」永远无法满足,就可能持续循环。原文要求检查输入里的 stop_hook_active,已经由停止 Hook 触发续跑时,应退出 0。
把审查提示词做成命令,省掉的是什么
自定义命令是 Markdown 文件。项目共享配置放在 .claude/commands/,个人配置放在 ~/.claude/commands/,文件名成为命令名。作者也提到,命令已经并入 skills,.claude/skills/<name>/SKILL.md 可以承载相同用途,旧命令文件仍可使用。
下面的 .claude/commands/review.md 把收集变更和审查要求放在一起:
---
description: Review my uncommitted changes before I commit
argument-hint: [focus area]
allowed-tools: Bash(git diff *) Bash(git status *)
---
## Current changes
!`git status --short`
!`git diff HEAD`
## Task
Review the diff above as a strict senior reviewer. Focus on: $ARGUMENTS
List real problems only (bugs, missing error handling, unclear names,
missing tests), ordered by severity, with file and line. Don't rewrite
code unless I ask. If it looks good, say so in one line.
要看的是 ! 开头的两行:命令输出会在提示词交给模型之前填入,模型拿到的是实际 diff。输入 /review error handling,$ARGUMENTS 就会替换为审查重点。
allowed-tools 按原文说明为本轮预先授权对应工具;description 和 argument-hint 用于补全菜单。位置参数从 $0、$1 开始,多词参数需要引号,例如 /fix "login page" high。子目录还能形成命名空间,db/migrate.md 对应 /db:migrate。
这种封装也适合 /test-plan:基于 git diff main...HEAD 列出应补的测试;或者用 /explain $ARGUMENTS 解释代码、用 /handoff 整理交接记录。涉及部署、发布等副作用时,作者建议给 skill 添加 disable-model-invocation: true,保留人工触发入口。
Codex CLI 的对应方案,原文也给出了路径:Hooks 放在 ~/.codex/hooks.json、<repo>/.codex/hooks.json,或 config.toml 的 [hooks] 表中。作者称它支持 SessionStart、PreToolUse、PostToolUse、Stop,且 Edit、Write matcher 可以匹配 apply_patch;新增或修改后的 Hook,需要在 /hooks 审阅并信任才会运行。
可复用提示词则推荐迁移到 .agents/skills/ 或 ~/.agents/skills/,用带 name、description 的 SKILL.md 定义,通过 $ 加名称或 /skills 调用。旧的 ~/.codex/prompts/*.md 和 /prompts:name 被原文标为已弃用。两边采用 Agent Skills 格式,有利于复用提示词,但不能据此推断所有工具权限和配置都完全兼容。
我的判断
我认同这套分工:确定性操作交给脚本,需要理解和判断的任务交给模型。相比不断扩充 CLAUDE.md,它更容易检查「动作究竟有没有执行」。
但「复制粘贴就能提速」有前提。格式化器要已安装,项目规则要一致,Hook 失败也要有人发现。示例里的 xargs 没有专门处理带空格的文件路径,文件类型是否适用、格式化会不会触发额外监听,也需要结合仓库调整。
Hook 也替代不了 CI。前者在本地编辑时给反馈,后者检查最终提交结果。审查命令同样有盲区:git status --short 能显示未跟踪文件,但 git diff HEAD 不会包含这些文件的正文,模型可能看到文件名却审不到内容。
原文没有给出耗时、token 或问题发现率的对照实验,因此效率收益仍是经验判断。结尾还推广了作者开发的 TokenBar:一款售价 $15、终身购买的 Mac 菜单栏应用,基于 MIT 许可的 CodexBar。这个商业背景不否定配置价值,也不能拿来证明节省幅度。原文未注明具体适用版本,尤其是 Codex 的 Hooks 和信任机制,应以安装环境为准。
能拿来做什么
- 在前端或 Node 仓库先接入单文件格式化 Hook,用一个真实文件确认触发范围、路径处理和失败提示,再提交
.claude/settings.json供团队共享。 - 做一个项目级
/review,固定审查标准,通过参数切换错误处理、命名或测试重点;提交前另外检查未跟踪文件,避免漏审新增代码。 - 把分支和简短工作区状态放进
SessionStart,把长期约定留在项目说明中,避免每次启动重复注入大量资料。 - 将个人通知放在用户目录,把个人偏好放进
settings.local.json;每次修改 Hook 后检查/hooks,使用 Codex 时还要确认原文所述的信任步骤是否适用。