让 AI 越写越像你:用 Hook 自动积累编码规范的实践

让 AI 越写越像你:用 Hook 自动积累编码规范的实践

用 AI 写了一段时间代码之后,我开始觉得有点别扭。

功能是实现了,逻辑也没错,但代码"不像我写的"。方法命名的习惯不一样,返回值的处理方式不同,注释的位置也不对。每次让 AI 改代码,我都要再花时间把风格对齐,或者直接忍着。

解决这个问题最直接的办法是:把自己的编码规范写进CLAUDE.md,让 AI 每次都照着来。

这个方向没错,但有个问题——规范是写不完的。写出来的规范都是大原则,真正让代码"有个人味"的那些东西,是在一次次具体的改动中体现出来的。比如我偏好把 null 判断前置而不是嵌套、比如我不喜欢在 Service 层里写if/else分支、比如我觉得方法名里的do前缀是多余的。这些东西你事先想不到,只有在被触动的时候才知道。

所以真正的问题变成了:怎么把这些"被触动的瞬间"自动记录下来?


思路

整个方案的核心逻辑很简单:

  1. 每次让 AI 改代码,自动抓下「改了什么」
  2. 用 AI 对这次改动生成一句话摘要,说清楚背后的设计意图
  3. 按时间归档成 Markdown 文件
  4. 定期人工复盘,把高频模式提炼进正式的编码规范

关键在第一步和第二步——把人工成本压到几乎为零,记录才能持续。

Claude Code 有一个 Hook 机制,可以在工具调用前后、对话开始时、对话结束时执行自定义脚本。这是整个方案的技术基础。


Hook 架构

整体数据流如下:

整个系统由四个脚本组成,分别挂在四个 Hook 事件上:

UserPromptSubmit → opt_track.py 检测关键词,初始化追踪轮次 PreToolUse → opt_capture_before.py 修改前拍快照(只取最原始状态) PostToolUse → opt_capture_after.py 修改后拍快照(始终取最新状态) Stop → opt_write_record.py 生成 diff,调 AI 摘要,写文件

Hook 配置在~/.claude/settings.json里:

"hooks": { "UserPromptSubmit": [{ "matcher": "", "hooks": [{ "type": "command", "command": "python3 ~/.claude/hooks/opt_track.py" }] }], "PreToolUse": [{ "matcher": "Edit|Write|MultiEdit", "hooks": [{ "type": "command", "command": "python3 ~/.claude/hooks/opt_capture_before.py" }] }], "PostToolUse": [{ "matcher": "Edit|Write|MultiEdit", "hooks": [{ "type": "command", "command": "python3 ~/.claude/hooks/opt_capture_after.py" }] }], "Stop": [{ "hooks": [{ "type": "command", "command": "python3 ~/.claude/hooks/opt_write_record.py" }] }] }

各脚本逻辑

opt_track.py — 关键词触发

并不是每一轮对话都值得记录。我只想抓"有意识地让 AI 改代码"的那些时刻,所以用关键词做过滤:

KEYWORDS = ['优化', '重构', '改进'] has_keyword = any(kw in prompt for kw in KEYWORDS)

命中关键词时,创建一个新的追踪轮次(index 自增),记录下 prompt 内容和当前工作目录。没命中但当前有活跃追踪的,把这条 prompt 追加为"执行步骤",方便后续理解完整上下文。

所有中间状态都写在/tmp/claude-opt-{session_id}/里,按 session 隔离。

opt_capture_before.py — 修改前快照

每次 AI 调用Edit/Write/MultiEdit前,把文件当前内容备份到{session_dir}/changes/{index}/{safe_name}.before

有个细节:每个文件每轮只拍一次。如果 AI 对同一个文件做了多次修改,只保留最原始的版本,这样生成的 diff 才能反映完整的变化量。

opt_capture_after.py — 修改后快照

每次修改完,把文件内容备份到.after文件。这里是每次都覆盖,保留最终状态。

before+after凑成一对,就能算出本轮的完整 diff。

opt_write_record.py — 生成记录

对话结束时(Stop事件)触发,做三件事:

1. 生成 diff

用 Python 标准库difflib对 before/after 文件生成 unified diff:

diff = list(difflib.unified_diff( before_lines, after_lines, fromfile='修改前', tofile='修改后', n=3 ))

2. 调 AI 生成摘要

把本轮的 prompt(意图)+ 执行步骤 + diff 喂给 Claude Haiku,让它用 2~4 句话总结核心改动和设计原则:

summary_prompt = ( '以下是一次代码优化会话的内容,请用 2~4 句话总结:' '核心改动是什么,体现了哪些代码设计原则或最佳实践。\n\n' + context + '\n\n只输出总结内容,不要其他说明。' )

用 Haiku 而不是主模型,是为了省成本——摘要任务不需要很强的模型。

3. 写入 Markdown 文件

同一个 session 的多轮记录追加到同一个文件里,文件按时间戳命名,归档到代码规范积累/YYYY-MM/目录:

代码规范积累/ └── 2026-04/ ├── 20260401-143022.md ├── 20260415-090531.md └── 20260428-165847.md

每个文件的结构大致是:

# 代码优化记录 2026-04-28 16:58:47 > 项目目录:`/Users/.../my-project` ## 摘要(2026-04-28 16:58:47) 本次优化将 Service 层中散落的 null 判断统一前置, 避免了深层嵌套。提取了重复的校验逻辑为私有方法, 体现了单一职责原则。 --- ## 优化 1 **意图:** 重构 UserService,把 null 判断统一提到方法入口 ### 文件:`src/main/java/...UserService.java` \`\`\`diff - if (user != null) { - if (user.getStatus() != null) { + Objects.requireNonNull(user, "user must not be null"); + if (user.getStatus() == null) { \`\`\`

整理流程

自动记录只是第一步,记录本身不会让 AI 变聪明。真正起作用的是定期复盘,把模式提炼进规范

我大概每两周会做一次整理:

  1. 翻看代码规范积累/下最近的文件
  2. 找出多次出现的同类改动(这意味着这是我真实的习惯)
  3. 提炼成一条规则,写进代码风格.md
  4. 代码风格.md会被同步到工作项目的CLAUDE.md里,作为 AI 的编码约束

这个循环跑起来之后,规范会越来越准确,AI 的初稿也会越来越"像我的风格",需要手动对齐的次数自然减少。


几个实际体感

记录比想象中多。开始以为一周也就几条,实际跑起来发现每天都有。原来在无意识的情况下,已经在持续地用 AI 做小规模的代码调整了。

摘要质量够用。Haiku 生成的摘要不够精炼,但信息量足够判断这条记录值不值得提炼成规范。复盘时扫一眼摘要,再看 diff,效率还不错。

关键词过滤有局限。用"优化/重构/改进"触发追踪,会漏掉一些有价值的改动。比如直接说"把这个方法改一下",就不会被记录。后续可以考虑换成"所有有文件修改的对话都记录",让整理阶段来做筛选,而不是记录阶段。

这套东西的本质是个反馈回路。用 AI 改代码 → 自动记录 → 人工提炼 → 写进规范 → AI 按规范写代码。规范的准确性会随着时间提升,因为它是从真实行为里归纳出来的,而不是提前猜测的。


最后

这套方案没有什么神奇的地方,核心是把"总结经验"这件本来需要主动去做的事,变成被动自动发生的。

如果你也在用 Claude Code,可以把这几个脚本直接拿去用,按自己的关键词触发逻辑和归档路径改一改就行。

Hook 安装格式说明:脚本通过 stdin 接收 JSON 数据(包含session_idtool_inputprompt等字段),正常退出码为 0。PreToolUse的脚本若返回非 0,会阻断当次工具调用——所以opt_capture_before.py在找不到 session 追踪时直接sys.exit(0)而不报错。配置写在~/.claude/settings.jsonhooks字段下,支持matcher正则过滤触发的工具名。