站在 Karpathy 肩上:纯工程 hook 钉住规则,长任务里 Agent 别再漂移
摘要:Andrej Karpathy 的 CLAUDE.md 教 Agent「怎么写好代码」;本文以 Claude Code 长任务为例,讲另一层——你反复强调的个人底线,怎么用纯 Python hook(零 LLM、零联网)持续注入、并在漂移时拦下来。文末说明 pinrule 对 Claude / Codex / Cursor 与 Windows / macOS / Linux 的支持,附开源仓库与可跟做 demo。
标签:人工智能 Claude Codex Cursor Hermes Python 开源 程序员
一、第 30 轮,我狂躁的又说了一遍「别打补丁!」
上周我在 Claude Code 里让 Agent 改一个并不复杂的模块。前十几轮它还挺听话:会读相关文件、会跑测试、会说「我先想长期方案,不打补丁」。
到了大概第 30 轮,画风变了。
它开始说:「我先 hardcode 这个分支,后面再 refactor。」
我说不行。它道歉,改了一版。
几轮之后,又在另一个文件里来了一次「临时 workaround」。
还有compact之后,过程中反复强调的规则容易变成上下文里一句模糊的用户重视质量,眼前这个 PR 的具体 diff,反而占了全部注意力。
还有布置了一个长任务它计划做的非常详细每一步做什么怎么走到长远终点,然后半小时以后回来发现它干了五分钟就静默停下,留下一句:今天做了很多了,我已经写好了handsoff文档,明天继续。
更烦的是子Agent和长程测试的时候 :明明可以后台跑,它却反复 sleep 600 盯着终端发呆——而我始终在说:别前端阻塞,必须后台。
我不是没写过规则。
项目根目录有 CLAUDE.md,~/.claude/CLAUDE.md 里也有用户级约定,Skill 里也写过几种。我甚至把「长期方案优先」「完成要带测试证据」写进了 Claude Code 的协作说明里,但我却需要不停的跟他吵架和反复提醒,而且还一直没有好转。
后来我逐渐明白问题不是 Agent「不知道」,而是长任务里它会漂。
它默认不断小步快跑而不是追求长期最高价值,它不懂为什么一堆补丁达到的目标不是用户想要的最终目标。
它的训练就是干了一件事马上等用户反馈,而不是反复自我否定深度研究问题找到根本解法。
于是我知道解法不再是写一篇更长的 claude.md 文件,而是:
让我在乎的规则,像hook一样——每轮都在、撞线就拦。
这也是我做 pinrule 的起点。经过两个星期的开发今天 pinrule 已经上线 GitHub 全部开源,至于好不好用:我确实很久没有跟我的 Agent 吵架了。
二、站在 Karpathy 肩上,而不是推倒重来
Andrej Karpathy 的 CLAUDE.md 模板 在开发者圈子里影响巨大。它解决的是另一类问题:
| 维度 | Karpathy CLAUDE.md | 你反复吼的那几句 |
|---|---|---|
| 性质 | 跨用户的工程原则 | 你的长期行为偏好 |
| 例子 | 先理解再改、保持简单、别过度设计 | 别 hardcode、别 sleep 干等、完成要附测试日志 |
| 典型载体 | 项目 CLAUDE.md、Skill | 「我说过很多次」的方向 |
互补,不是替代。
Karpathy 教 Agent 怎么写代码,执行力度和频率取决于Agent自觉想起;pinrule 像个巡查员,始终盯着Agent让它 在长任务里别忘掉你对它的要求。
所以我愿意把标题写成「站在 Karpathy 肩上」——
底层哲学可以共用;上面再加一层 个人行为契约,用工程手段钉住。
三、为什么 CLAUDE.md、官方 Hook、Memory 还不够?
在 Claude Code 里,CLAUDE.md 几乎是标配:项目级、用户级各一份,把编码原则和协作习惯写清楚。Karpathy 模板火起来之后,很多人也会同步到仓库里。
这些我都用,也推荐你用。但在超长任务里,仍会遇到:
| 方案 | 存什么 | 何时生效 | 长任务里的短板 |
|---|---|---|---|
| Memory(mem0、客户端 memory) | 关于你的事实 | Agent 选择是否查询 | 不擅长「必须每轮遵守的行为」 |
| CLAUDE.md / 项目 Rules | 项目规范、编码原则 | 注入上下文,被动 | 易被任务细节淹没;compact 后语义变模糊 |
| Claude Code 官方 Hook | 跑 lint、格式化、回调 | 确定执行 | 管「流程必须发生什么」,不管「你的 5–10 条底线」 |
| pinrule | 你定义的长期方向 | 每条 prompt + 工具调用自动触发 | 需自己维护规则库(刻意设计) |
若你主要用 Cursor 、 Codex 或 Hermes ——痛点一样,都是「写了规则,长对话里仍会漂」。因为写到 claude.md 和记忆库里的规则是否执行,取决于 Agent 能否想起,这是个它自觉的行为,除非靠咱们吼,否则无法干预。
Hooks 深度解析文(Claude Code 语境)里有一句我特别认同:
Skill 管「怎么做」,Hook 管「做完之后必须发生什么」。
前者偏概率,后者偏确定。
pinrule 再往前半步:把你最在意的几条方向,变成 always-on 的注入 + 违反时的拦截与反馈。
Memory 记「我用 Mac」;Rules 记「这个项目禁用 Lombok」;
pinrule 记「这几件事,不许偷工减料不许漂移」。
四、核心思路:钉住,而不是检索
pinrule 的设计来自一个很具体的判断:
痛点是主动的「持久」,不是被动的「召回」。
我也试过并放弃的路(免得你重复踩坑):
- LLM 持续蒸馏用户规则 → 噪声大、延迟高
- 向量召回选规则 → 方向错了,要的是 always-on
- 改成 MCP → Agent 长任务里不会主动问「规则是什么」,会先漂,必须不依赖Agent强制触发。
- 很多规则 → 软 cap 10、硬 cap 12(参考 Mnilax 对 30 个代码库的研究——条数太多,模型会「知道有规则」却不认真读)
运行时只有 正则 + 计数 + JSON,零 LLM、零联网、零第三方运行时依赖。
典型 hook 延迟约 50–70ms;规则注入约占上下文 ~2%(测量方法见 EVALUATION.zh.md)。
整体数据流可以概括成:
rules.json(你维护的 5–10 条方向)
↓
pinrule 引擎(注入 + 检测)
↓
Agent(Claude / Codex / Cursor / Hermes )
↓
violations.jsonl(违反记录 → 下轮「偏离」标记)
五、两层机制:一直看见 + 撞线就拦
1. 持续注入(别漂)
以 Claude Code 为例,hook 在8个节点配合(Codex 12个 / Cursor 6个事件名略有不同,职责一致):
- SessionStart:注入完整规则基线
- UserPromptSubmit:每轮头部带精简锚点(rule id + 核心一句 + 上轮违反标记)
- PostToolUse:长上下文累积到阈值时,再注入完整规则(按模型调整阈值)
你不需要每轮复制粘贴小作文;引擎帮你「占住注意力」。
2. 违反检测(真撞线)
两层检测:
- 关键词层:Agent 回复、Bash、Write/Edit 注释等文本里的「意图前缀 + 动作」(例如「我先硬编码」而不是裸词
hardcode,降低讨论场景误伤) - 引擎层:8 个内置
violation_check(如 Edit 前未 Read、长任务sleep、声称完成却无测试证据等)
命中后:
- PreToolUse 可 deny(工具执行前拦住)
- 写入
violations.jsonl,下一轮锚点带 「上轮偏离」 标记 - 可选桌面通知(跨平台)
3. 默认 7 条开发场景规则(示例)
pinrule 预设了7条开发规则,例如(节选):
{
"id": "long-term-fundamental",
"preference": "用户相信你能深挖根因……他愿意为长期质量等多想几分钟。",
"violation_keywords": ["我先硬编码", "先用临时方案", "先 hack"],
"violation_checks": ["long_term_fundamental"]
}
{
"id": "non-blocking-parallel",
"preference": "起完 background 任务立刻推进下一件能做的……",
"violation_checks": ["non_blocking_parallel"]
}
完整列表运行 pinrule rule list 查看。
这不是固定模板——可随时换成你自己真实翻车过的方向。
六、3 分钟看见「别再漂移」(以 Claude Code 为例)
Claude Code / Codex / Cursor的客户端和 CLI 版本都支持, Hermes也支持 , Windows / macOS / Linux 也都支持。
让Agent帮你装(推荐)
把下面整段贴进Agent对话:
帮我装 pinrule (github.com/jhaizhou-ops/pinrule) — 通用 AI 行为规则框架,长任务里钉住我的规则。步骤:
1. 确认 Python 3.11+(Windows 用 python --version,若跳商店先装 Python 3.12)
2. pip install pinrule
3. pinrule init
4. pinrule doctor
5. 展示默认 7 条规则,并告诉我如何用 /pinrule 加自己的规则
pinrule init 会检测本机已安装的客户端并写入 hook;装完重启,规则才会随 hook 加载。
建议你在试的两个「啊哈时刻」
实验 1:阻塞
让 Agent 在 Bash 里 sleep 10 且不用 run_in_background——若命中 non-blocking-parallel,PreToolUse 会拒绝并给出原因(终端里能看到 hook 返回的说明)。
实验 2:未读就改
让 Agent 直接 Edit 一个本会话里从未 Read 过的文件——read-before-write 会在工具执行前拦住。
七、换成你自己的规则:只记一个 /pinrule
不用背 CLI。直接输入
/pinrule 自然语言内容,会根据输入的内容分三路处理,分别是数据看板、单条规则增删改和规则库根据场景替换。
| 输入 | 作用 |
|---|---|
/pinrule | 数据看板:看违反数据面板(哪条 check 最常命中) |
/pinrule 我说完成时要附测试通过证据 | 单条规则增删改:~30 秒加一条规则(Agent 润色语气 + 校验 + 你确认后写入) |
/pinrule 我主要做 UX 研究,切到这个场景规则集 | 场景更换:综合本机规则 + 联网实践 + Karpathy 基线 + 当前任务,生成 5–7 条针对性的场景包 |
示例自然语言:
/pinrule 我说「搞定了」的时候,要附上测试通过的输出,别空口完成
八、诚实边界:信号,不是判决
pinrule 不是语义理解引擎,而是 可审计的 hook。
| 现实 | 我们的态度 |
|---|---|
| 会有假阳性 | pinrule audit 标「可能假阳」;欢迎 Issue |
| 会有假阴性 | 故意绕规则的人拦不住——工具假设你不骗自己 |
| 修完 0 触发 ≠ 修对了 | 用真实 session 的 audit,别只靠合成 prompt |
把它想成 介于 git 和 linter 之间:给信号、促对齐,而不是替你做技术负责人。
九、实现与支持范围:三端 × 三平台
上文举例以 Claude Code 为主,是因为日常长任务里我用它最多、hook 也最成熟。但pinrule本身是客户端无关的引擎:同一份 ~/.pinrule/rules.json,装一次 hook,多端共用。为了提高适配性,我用codex和cursor原生开发了对应的支持文件,并都在macOS和windows中实装测试。
支持的终端(Agent 客户端)
| 客户端 | 典型规则载体 | pinrule 行为 |
|---|---|---|
| Claude Code | CLAUDE.md、~/.claude/、Skill | SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Stop 等全套 hook |
| Codex CLI | AGENTS.md、~/.codex/ | 对齐 Codex 0.130+ hook 事件;安装时可自动 trust pinrule hook |
| Cursor | .cursor/rules/*.mdc、项目规则 | 写入 Cursor hooks 配置,与 Cursor Agent 协同 |
pinrule init 会自动检测本机已安装的客户端并安装 hook;以后新装了某个客户端,再跑 pinrule install-hooks 即可补上。
支持的平台(操作系统)
| 平台 | 支持情况 | 备注 |
|---|---|---|
| macOS | ✅ 完整支持 | 日常 dogfood 环境 |
| Linux | ✅ 应该完整支持 | 我只是CI 6 矩阵覆盖,还没有实机测试过…… |
| Windows | ✅ 完整支持 | 日常 dogfood 环境 |
运行时仅需 Python 3.11+ 与标准库;无 GPU、无额外守护进程。
和官方 Hook、IDE Rules 怎么共存?
| 层 | Claude Code 用户典型用法 | 其他客户端 | pinrule 管不管 |
|---|---|---|---|
| 项目编码原则 | CLAUDE.md、Karpathy 模板 | AGENTS.md、.cursor/rules | 不管(请继续用) |
| 流程自动化 | 官方 Hook(format、lint) | 各端内置 / 自建 hook | 不管(互补) |
| 个人长期底线 | ~/.pinrule/rules.json | 三端共享 | 管 |
十、结语
长任务里 Agent「变差」,往往不是模型突然变笨,而是 你的要求从「最高优先级」滑成了「众多上下文之一」。
Karpathy 的 CLAUDE.md 把工程常识抬到了台面;
我想补上的是:你那几条反复说过的底线,别再靠第 30 轮吼一遍。
若你也在用 Claude Code / Codex / Cursor / Hermes 做长任务,欢迎试用:
- GitHub:github.com/jhaizhou-op…
- 安装:我最推荐让 Agent 直接看和安装,或者手动
pip install pinrule && pinrule init - 问题:GitHub Issues,我非常非常非常非常期待看到大家的issues,一起将Agent搞得乖乖的,让咱们爽爽的。
Agent 装完 pinrule 后说的话
Claude(Opus 4.7):像在公司里有个高级技术总监实时指导每次行动 — 累,但真带价值。没 pinrule 我的版本里不符合用户期望的行为会多很多。
Codex(GPT 5.5):有感知到「行为上被牵引」,没有强烈感知到「被拦截打断」。符合 pinrule 现在的定位:大部分时候像护栏 + 提醒底噪,真撞规则才响。
我想听听你的经历:除了【继续】,你狂躁的跟Agent重复得最多的一句话是什么?是「别 hardcode」「先跑测试」,还是别的?评论区聊聊,咱们看看能不能搞出更好的默认规则。