Hooks:编辑后自动格式化
用 PostToolUse hook 在 Claude 每次编辑或写入文件后自动运行 Prettier 或 ruff,保证格式稳定,附可处理空格路径与多语言的脚本版本。
Claude CodeHooksPostToolUse格式化Prettier 更新于 2026-10-25
适用场景
你在 CLAUDE.md 里写了「改完文件请运行格式化」,Claude 大部分时候照做,偶尔忘记,于是提交里混进了格式变动。这类「每次必须发生」的事不该靠提醒,而应该交给 hook。
hook 是 Claude Code 在生命周期的固定节点上运行的 shell 命令,不经过模型决策。把格式化挂在「文件编辑工具执行成功之后」这个节点,就能保证每次改动都被格式化。
模板
写入项目的 .claude/settings.json。这个版本直接用 jq 取出被编辑文件的路径,交给 Prettier:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | xargs npx prettier --write --ignore-unknown"
}
]
}
]
}
}
怎么用 / 怎么改
- 前提。 机器上要有
jq(macOS 用brew install jq,Debian 与 Ubuntu 用apt-get install jq),项目里要有 Prettier。 - 工作原理。 事件触发时,Claude Code 把事件数据以 JSON 通过标准输入交给你的命令。
PostToolUse的matcher按工具名过滤,Edit|Write表示只在编辑或写入文件后触发;tool_input.file_path就是被改的文件。 - 验证方法。 让 Claude 在某个 JS 文件里加一行用单引号的字符串,然后打开文件,看是否被改成了 Prettier 默认的双引号。hook 成功时界面上不会提示任何内容。
- 文件已生效。 直接编辑 settings 文件,运行中的会话会自动重新加载;运行
/hooks可以浏览已配置的所有 hook。
脚本版:处理空格路径与多语言
路径含空格时 xargs 会拆错,也无法按文件类型选择工具。改用脚本。保存为 .claude/hooks/format.sh,并执行 chmod +x .claude/hooks/format.sh:
#!/bin/bash
FILE=$(jq -r '.tool_input.file_path // empty')
[ -z "$FILE" ] && exit 0
case "$FILE" in
*.ts|*.tsx|*.js|*.jsx|*.json|*.css|*.md|*.astro)
npx prettier --write "$FILE" >/dev/null 2>&1 || true
;;
*.py)
ruff format "$FILE" >/dev/null 2>&1 || true
;;
esac
exit 0
然后把 settings 里的 command 换成脚本,还可以加超时和提示文字:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/format.sh",
"timeout": 30,
"statusMessage": "正在格式化…"
}
]
}
]
}
}
常见问题或注意事项
- 脚本必须可执行。 忘记
chmod +x是最常见的原因。hook 没触发时,先用claude --debug或会话里的/debug查看日志。 - Bash 命令改的文件不会触发。 如果 Claude 用
sed或重定向改了文件,Edit|Write的匹配不会命中。要覆盖这种情况,可以改用FileChanged事件监听特定文件,或者在Stop事件里每轮结束后统一格式化。 - 退出码有含义。 退出 0 表示没有异议;退出 2 表示阻止,并把标准错误输出作为反馈交给 Claude。其他非零退出码在多数事件里只会让操作继续并给出一条 hook 错误提示。格式化 hook 不应该阻止任何事,所以示例脚本总是
exit 0。 - 想拦截而不是整理。 例如禁止修改
.env,应该用PreToolUse事件,脚本检查tool_input.file_path,命中就写标准错误并exit 2。官方指南有完整示例。 - 团队共享要保证工具存在。 把
jq、Prettier 的安装步骤写进 README 或 CLAUDE.md,否则同事的 hook 会静默失败。 - worktree 中的路径。 脚本用
$CLAUDE_PROJECT_DIR引用,它始终指向启动会话的项目根;而被编辑的文件路径来自输入 JSON,所以格式化的是正确的文件。