拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CLAUDE.md 写三十条规则就听三十条?我拿 Claude Code 的 Hook 和 skill 做了个实验

CLAUDE.md 写三十条规则就听三十条?我拿 Claude Code 的 Hook 和 skill 做了个实验

1. 为什么 CLAUDE.md 写了三十条规则,Claude Code 却只执行了七八条

先说结论:CLAUDE.md 不是合同,是便利贴。你写进去的每一条规则,Claude Code 在每一轮对话里都会重新读一遍,但读进去不等于会执行。这中间隔着一整套上下文预算、注意力分配和加载时机的机制。

我在一个算法可视化项目里维护了大半年的 CLAUDE.md,一度涨到 600 多行,项目约定、代码规范、踩过的坑全堆在里面。当时我的想法很简单:写得越全,Claude 就越听话。结果实测下来,二十多条规则里真正每次都被稳定遵守的,也就七八条。剩下的要么被淹没在几百行噪声里,要么写成了模糊的描述句,还有几条压根和 Claude Code 本身的默认行为冲突,属于注定无效。

这个落差逼着我把 CLAUDE.md、Hook、skill 三者的协同边界彻底拆了一遍。今天这篇就是那轮实验的完整复盘:为什么规则数量不等于执行数量,怎么搭一套可复现的验证流程,以及 CLAUDE.md 骨架、settings.json 里的 Hook 配置、skill 目录结构到底该怎么写。

适合谁看:已经在用 Claude Code 但感觉"写了规则它不听"的开发者;想把项目约定沉淀成可维护配置的团队;以及准备面试被问"你怎么维护 CLAUDE.md"的人。

核心检索词先摆出来:CLAUDE.md 规则不生效、Claude Code Hook 配置、skill 渐进式披露、上下文预算管理。这四个词贯穿全文,你带着它们往下读会顺很多。

先讲清楚一个最容易被忽略的事实:CLAUDE.md 是会话一启动就被注入上下文、并且每一轮对话都保留在那里的常驻内容。它不是你需要的时候才去读,是从头到尾常驻。这一点和 skill 正好相反。skill 走的是渐进式披露,平时只把名字和描述放进上下文,真正命中某个场景才加载正文,所以你装一堆 skill 也不太占每轮的预算。CLAUDE.md 没有这个机制,你写多少,模型每一轮就得带着多少。

我用那个算法可视化项目举个实在的例子。CLAUDE.md 涨到 600 多行之后,我开始明显感觉到两件坏事。第一,每轮对话光这一个文件就吃掉小两万 token,一次会话几十轮下来,重复读它的开销很可观。第二,也是更要命的,里面真正每天用得上的可能就二三十行,剩下五百多行全是低频内容,把那二三十行也一起淹了。

这里要补一个很多人不知道的细节,它直接影响你对成本的判断。CLAUDE.md 其实分四层,从高到低是:企业级、用户全局(~/.claude/CLAUDE.md,对你所有项目生效)、项目级(./CLAUDE.md,跟着仓库走)、本地级(./CLAUDE.local.md,只对当前项目生效且不进版本控制)。这四层不是覆盖关系,是全部串联进上下文。也就是说你在全局写了一堆、项目里又写了一堆,它们是叠加在一起常驻的,不是谁替换谁。算成本的时候,得把这几层加起来算。

唯一不常驻的是子目录里的 CLAUDE.md。它走懒加载,只有当 Claude 真的去读那个子目录里的文件时才会被加载进来。这个特性后面讲分层的时候是个好工具,先记住这个区别:项目根的常驻,子目录的按需。

还有一个很少人注意、但直接关系到长会话稳定性的机制:自动压缩(auto-compact)的时候,CLAUDE.md 的命运是分裂的。会话开太长触发压缩,上下文会被裁剪重组,但项目根的 CLAUDE.md 会被从磁盘重新读一遍、重新注入回去,所以它不会因为压缩而丢失,压缩后照样常驻。可子目录那些懒加载进来的 CLAUDE.md 不享受这个待遇,压缩之后它们不会自动重注入,得等 Claude 下次再读那个目录的文件时才会重新加载。这个差别的实际后果是:长会话里,你写在项目根的约定一直稳,写在子目录里的约定可能在某次压缩之后就悄悄失效了一段时间。所以越是要在长会话里全程生效的硬约定,越要往项目根放,别图清爽全塞进子目录。

2. 规则为什么会被稀释:CLAUDE.md 加载机制与上下文预算的真相

搞清楚常驻这件事,下一个问题就自然冒出来了:既然每轮都在上下文里,为什么写了的规则还是会被无视?

答案是稀释。CLAUDE.md 加载进来之后,是作为一条用户消息待在上下文里的,它要和这一轮对话里的所有东西,你的提问、读进来的代码、工具返回的结果,一起争夺模型的注意力。它不是写在系统提示里的铁律,本质上只是一条优先级正常的建议。当这个文件很短、规则很具体的时候,模型基本都能照顾到;可一旦它涨到几百行,规则之间互相挤占,重要的那几条就被埋进噪声里,模型对靠后、靠中间那些内容的实际利用率会明显下降。官方自己给的经验值是:CLAUDE.md 最好控制在 200 行以内,超过这个数,模型很可能会忽略掉其中一半的规则。

我在那个算法可视化项目上栽过一个特别典型的跟头。我写过一条规则:"题解动画的 HTML 必须先在本地渲染验证通过,再提交。"这条很重要,因为动画渲染失败是这个项目最常见的事故。但我把它埋在了 CLAUDE.md 第 80 行左右,夹在一大段关于目录结构和命名约定的描述中间。结果就是,Claude 三次里有两次直接跳过它,生成完动画连渲染都没验证就提交了,我上线才发现一片空白,粗算下来遵守率也就三成上下。同一条规则,措辞没变,我把它从那段描述里拎出来,单独成行,前面加上"提交前必须执行"的祈使口气,再探几次,基本每次都守了,遵守率从三成提到了八九成。这件事让我明白,规则失不失效,很多时候不在内容,在它有没有被淹没。

这里还有个位置上的讲究值得说。一份长文档里,开头和结尾的内容,模型的注意力天然更高,最容易被忽略的恰恰是夹在正中间那一大段。我那条渲染验证规则栽在第 80 行,就是栽在了这个"中间地带"。所以同样一条规则,你把它放在文件最前面那几条,和埋在第八十行、第一百五十行,实际遵守率是有明显差别的。维护 CLAUDE.md 的时候,把最不能被忽略的几条规则顶到最前面,是个几乎零成本、收益却很直接的动作,很多人却从来没排过序,只是按写入时间一条条往后堆。

从这个坑里能总结出几个让规则失效的常见写法。第一,文件太长,整体稀释,这是根因。第二,把规则混在大段叙述里,而不是单独成行、加粗或者用列表拎出来,模型容易扫过去。第三,把规则写成描述句而不是祈使句。"我们倾向于在提交前跑测试"这种软描述,远不如"提交前必须运行 npm test"来得有约束力。第四,一条规则里塞了好几个要求,模型往往只执行最前面那个,后面几个要求要拆成独立的条目,别挤在一句话里。

还有最后一招,是当某条规则你怎么调写法都还是不听的时候用的。要知道 CLAUDE.md 终究只是建议,不是强制。官方的兜底办法有两个:轻一点的,给这条规则前面加上 IMPORTANT 或者 YOU MUST 这种强调词,能再抢回一些注意力;重一点的,干脆别指望 CLAUDE.md 了,把它改成一个 PreToolUse Hook。Hook 是真正的强制执行,每次都会跑,不依赖模型的"自觉"。我那条动画渲染验证的规则,最后就是改成了提交前自动跑渲染检查的 hook 才彻底根治的。这里我要给一个旗帜鲜明的判断:凡是"绝对不能错"的硬约束,别赌 CLAUDE.md 的遵守度,直接上 Hook。CLAUDE.md 适合放约定和倾向,不适合放红线。

3. 可复制的 CLAUDE.md 骨架与 settings.json Hook 配置片段

光讲机制不够,得给你能直接抄的东西。这一节交付三份配置:CLAUDE.md 骨架、settings.json 里的 Hook 配置、skill 目录结构。三件套里的 Base URL、Key、Model ID 在接入环节会一起说清楚。

先看 CLAUDE.md 骨架。核心原则是:高频、稳定、跨会话且模型推断不出来的内容才进,其余全部外移。下面这份骨架控制在 130 行以内,你可以直接改成自己项目的:

# 项目约定 ## 核心命令(每次干活都用) - 包管理器:pnpm(不要用 npm/yarn) - 开发:pnpm dev - 测试:pnpm test - 构建:pnpm build ## 硬性约定(提交前必须执行) - 提交前必须运行 pnpm test,测试不通过禁止提交 - 新增题解动画后,必须更新首页题目索引 - 所有动画 HTML 必须先在本地渲染验证通过,再提交 ## 架构铁律 - 渲染层与数据层严格分离,渲染层不直接读全局状态 - 新增依赖前必须确认是否已有同类库,避免重复引入 ## 代码风格(模型推断不出来的部分) - 组件命名用 PascalCase,工具函数用 camelCase - 异步逻辑统一用 async/await,禁止裸 Promise 链 ## 历史包袱说明(代码里看不出来的) - legacy/ 目录是旧版渲染器,仅维护不扩展 - 为什么不用某库:早期踩过 SSR 兼容坑,详见 @docs/why-not-xxx.md

注意几个细节。第一,硬性约定单独成段、放在靠前位置,每条都是祈使句。第二,能从代码推断出来的命名规范尽量少写,这里只留了模型不容易统一的部分。第三,长背景知识用@docs/why-not-xxx.md引用出去,别撑爆主文件。

然后是 settings.json 里的 Hook 配置。Hook 是强制执行的兜底,把"绝对不能错"的规则从 CLAUDE.md 挪到这里。下面是一个 PreToolUse Hook 的片段,作用是在 Claude 执行 git commit 之前自动跑测试:

{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "if echo \"$CLAUDE_TOOL_INPUT\" | grep -q 'git commit'; then pnpm test || exit 2; fi" } ] } ] } }

这段配置的关键在exit 2。Hook 返回非零退出码时,Claude Code 会拦截这次工具调用,把失败信息回传给模型,模型就知道"这一步被挡住了"。这比在 CLAUDE.md 里写一百遍"提交前必须跑测试"都管用,因为它是机制层面的强制,不依赖模型的自觉。

再说 skill 目录结构。skill 走渐进式披露,适合放低频但需要完整流程的内容。目录结构长这样:

.claude/skills/ deploy-cdn/ SKILL.md references/ cdn-config.md render-check/ SKILL.md

每个 skill 的SKILL.md开头要有 name 和 description,平时只有这两行进上下文,命中场景才加载正文。这样你装十个 skill,常驻预算也只增加十行描述,而不是十个完整文档。

三件套里的接入信息在这里统一说清楚。如果你要把 Claude Code 接到兼容 Anthropic 协议的服务上,需要配三个东西:Base URL、API Key、Model ID。Base URL 填https://taotoken.net/api,API Key 在控制台的 API Keys 页面生成,Model ID 按你选的模型填。这三样配齐,Claude Code 才能正常发起请求。配置入口在 Claude Code 的 settings 里,或者用环境变量注入。

4. 验证请求与成功结果:探针测试怎么跑、日志怎么看

配置写完不等于生效,这一节讲怎么验证。核心方法是探针测试:针对你最在意的规则,故意制造一个会触发它的场景,看 Claude 到底守不守。

先讲探针测试的具体动作。假设你 CLAUDE.md 里有一条"新增题解动画后,必须更新首页题目索引"。探针流程是这样的:

第一步,给 Claude 一个明确任务:"帮我加一道新题的动画,题目是 XXX。"注意,任务描述里不要提索引的事,让它自己想起来。

第二步,观察它的执行过程。如果它做完动画就停了,索引压根没碰,说明这条规则没生效。如果它主动去更新了索引,说明生效了。

第三步,记录结果。每条核心规则都这么探一遍,哪条被无视一目了然。

我在那个项目上真探过一轮,二十几条规则里真正稳定生效的就七八条。这个结果直接推着我做了三件事:把被稀释的核心规则拎出来、提到文件靠前的位置并改成祈使句;把那条最硬的渲染验证规则从 CLAUDE.md 挪进了 Hook;把那些注定无效和早就过期的直接删掉。

再讲日志观察方法。Claude Code 在跑的时候,你可以通过/memory命令查看当前会话实际加载了哪些 CLAUDE.md、CLAUDE.local.md 和规则文件。每次你怀疑"到底哪些文件被加载了""我这条规则到底在不在上下文里"的时候,跑一下/memory就清楚了,比你瞎猜强。

Hook 的日志观察是另一个维度。Hook 执行时,命令的 stdout 和 stderr 会被捕获。如果 Hook 返回非零退出码,Claude Code 会把失败信息展示出来。你可以在 Hook 命令里加日志输出,比如:

if echo "$CLAUDE_TOOL_INPUT" | grep -q 'git commit'; then echo "[hook] 检测到 commit,开始跑测试" >> /tmp/claude-hook.log pnpm test >> /tmp/claude-hook.log 2>&1 || exit 2 fi

这样每次 Hook 触发,你都能在/tmp/claude-hook.log里看到记录,确认它到底跑没跑、跑的结果是什么。

验证成功的标志是什么?三个层面。第一,探针测试里,核心规则每次都被遵守。第二,/memory显示加载的文件符合预期,没有多余的常驻内容。第三,Hook 日志显示硬约束每次都被强制执行,没有漏网。三个都满足,说明你的配置真的生效了。

这里要提醒一个常见误区:很多人验证时只看"Claude 有没有提到这条规则",而不是看"它有没有真的执行"。提到不等于执行,模型可能嘴上说"我会遵守",实际动作里压根没做。探针测试要看的是实际动作,不是口头承诺。

5. 本篇常见错误排查:401、local proxy failed、reading choices、OAuth

配置和验证过程中,最容易撞上的是接入层的报错。这一节把几个高频错误对照着讲清楚。

401 Unauthorized。这个最常见,基本是 API Key 的问题。排查顺序:先确认 Key 有没有复制完整,前后有没有多余空格;再确认 Key 有没有过期或被禁用;最后确认 Base URL 和 Key 是不是配套的。如果你用的是https://taotoken.net/api作为 Base URL,Key 就要从对应的控制台生成,别混用其他来源的 Key。

local proxy failed。这个报错通常出现在本地代理配置环节。排查方向:确认本地没有残留的代理环境变量(HTTP_PROXY、HTTPS_PROXY)干扰请求;确认 Base URL 填的是完整地址,没有漏掉协议头;确认网络能正常访问目标地址。如果你在 settings 里配了自定义 endpoint,检查一下有没有拼写错误。

reading choices 相关报错。这类报错一般出现在响应解析环节,说明请求发出去了但返回格式不符合预期。排查方向:确认 Model ID 填对了,不同模型的响应结构可能不同;确认 Base URL 指向的是兼容 Anthropic 协议的端点;确认请求没有触发限流。如果报错信息里提到choices字段,多半是响应格式和客户端预期不匹配,检查一下 Model ID 和端点是否配套。

OAuth 相关报错。如果你用的是需要 OAuth 认证的接入方式,报错通常和 token 过期或权限不足有关。排查方向:确认 OAuth token 有没有过期,需要的话重新走一遍授权流程;确认授权范围包含了你要用的能力;确认回调地址配置正确。OAuth 流程比 API Key 复杂,出问题时优先看 token 状态。

除了接入层报错,还有一类是配置层的"静默失效":没有报错,但规则就是不生效。这种最难查,因为没有任何提示。排查方法就是前面讲的探针测试加/memory检查。如果/memory显示某个文件没被加载,检查它的路径和层级对不对;如果加载了但规则不生效,检查它是不是被稀释了、是不是写成了描述句、是不是和默认行为冲突。

把这两类问题分开:接入层报错看错误码和日志,配置层失效看探针和加载状态。分开排查,效率会高很多。

6. 从 CLAUDE.md 到 Hook 到 skill:三者协同的长期维护心法

把前面五节串起来,其实是一套分工逻辑:什么常驻、什么按需、什么强制。

CLAUDE.md 负责常驻的约定和倾向。判断标准是三个条件同时满足:高频、稳定、跨会话且模型推断不出来。高频撑得起每轮重读的成本,稳定保证它不会很快过期,推断不出来说明它补的是代码里看不出的信息。三条都满足才进,缺一条就外移。

skill 负责按需的完整流程。低频但需要完整步骤的内容,做成 skill,平时只占一行描述,命中场景才加载正文。这样你装再多 skill,常驻预算也不会爆。

Hook 负责强制的硬约束。凡是"绝对不能错"的红线,别赌 CLAUDE.md 的遵守度,直接上 PreToolUse Hook。它是机制层面的强制,每次都会跑,不依赖模型的自觉。

这三者的边界清楚了,维护动作就顺了。定期做三件事:一是探针测试,看哪条规则真在起作用;二是精简,把不起作用的、过期的、注定无效的清掉;三是迁移,把该进 Hook 的硬约束从 CLAUDE.md 挪过去,把该进 skill 的低频流程从常驻区挪出去。

怎么判断该瘦身了?给几个信号。行数超过 200 行就该警惕。某些规则遵守率越来越低,往往不是模型变笨,是文件涨太长把它们稀释了。还有一个很朴素的信号:当你自己都记不清 CLAUDE.md 里到底写了哪些条的时候,它一定已经太长了。

维护 CLAUDE.md 这件事,考验的不是你会不会写 Markdown,而是你有没有"上下文是有成本的、注意力是会被稀释的"这层意识。有了这层意识,你对 skill、Hook、记忆这些机制的取舍才会都顺起来,因为它们解决的是同一个问题的不同切面:什么常驻、什么按需、什么强制。想清楚这三个词怎么分配,你就真的会用 Claude Code 了。

如果你要把这套配置落到实际项目里,接入环节的三件套别忘了:Base URL 填https://taotoken.net/api,API Key 在控制台的 API Keys 页面生成,Model ID 按你选的模型填。配齐这三样,Claude Code 才能正常跑起来,后面的 CLAUDE.md、Hook、skill 配置才有意义。

需要生成 Key 和查接入文档的话,走这两个入口:API Keys 在https://taotoken.net/console/api-keys,接入文档在https://taotoken.net/doc。想先验证模型对话效果,用https://taotoken.net/chat。长期做编码和 Agent 任务,看 Coding Plan:https://taotoken.net/coding-plan。

返回列表