关于 claude-md-doctor
claude-md-doctor 是用于审查仓库 Agent 指令文件的 Claude Code 技能,结合脚本检查与判断,并通过会话历史回测评估规则的准确性和遵循情况。
主要功能
- 01指令文件收集与状态检查
- 02引用和事实声明核验
- 03基于会话历史进行规则回测
- 04生成诊断与报告
适用场景
- 01审查 CLAUDE.md 和 AGENTS.md
- 02核对指令中的引用与事实声明
- 03评估过往会话是否遵守仓库规则
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ agent-clinic/ claude-md-doctor --skill claude-md-doctor安装后在 Claude Code 中输入/claude-md-doctor确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
scripts/_common.pybacktest.pycard.pycompile.pygenerate.pyintake.pymine.pyrefcheck.pyreport.pysessions.pyvitals.pytemplates/report.html详细介绍
CLAUDE.md Doctor — 检查流程
你正在检查此代码库中的 Agent 指令文件。确定性工作由脚本完成;你的任务是在脚本之间进行判断。 不要重新推导脚本已经测量过的内容,也不要跳过任何阶段——报告会核验工作状态清单,并披露跳过的阶段。
以下是本文使用的定义:
SCRIPTS=${CLAUDE_SKILL_DIR}/scripts— Claude Code 会在运行时将${CLAUDE_SKILL_DIR}替换为此技能所在的目录,因此无论当前工作目录是什么, 也无论此技能是如何安装的,脚本都能正确解析。请按字面使用;不要尝试自行查找此技能。REPO= 要检查的代码库(如果提供了参数,则为该参数;否则为当前工作目录)。WORK=REPO/.claude-md-doctor/work(脚本默认使用此路径;可传入--work指定其他位置,例如临时目录,以避免在用户的代码库中写入内容——如果代码库不属于你,优先采用这种方式)。
阶段 0 — 预检
运行 python3 --version。如果缺少 python3,请停止并告知用户,此技能需要 Python 3.9+(仅使用标准库,无需安装任何内容)。
阶段 1 — 收集信息
python3 SCRIPTS/intake.py --repo REPO --work WORK
然后读取 WORK/intake.json(文件很小)。记录以下信息,以供后续判断:
- 项目中的 CLAUDE.md 是否为指向 AGENTS.md 的指针(
is_pointer)?这是健康且官方推荐的模式——目标文件才是检查对象。 绝不要将指针文件诊断为“太短”。检查pointer_style:symlink和import均可正常工作;bare-text是失效的指针——这是一个只包含AGENTS.md、且不带@的普通文件,Claude Code 不会加载其目标文件。这是严重问题,只需一个字符即可修复(添加@),除非你检查的是原始抓取的副本,其中符号链接会被展平成文本。 - 祖先目录和用户范围的文件是会话加载的上下文,但代码库无法修复这些文件——请提及它们;除非用户要求,否则不要建议修改这些文件。
- 如果某个文件的作用域为
orphan-agents,表示代码库中有 AGENTS.md,但没有指向它的 CLAUDE.md——Claude Code 不会加载任何内容。这是严重问题,官方的一行修复方法是创建一个包含@AGENTS.md的 CLAUDE.md;同时仍应对 AGENTS.md 本身进行完整的静态检查,因为指针一旦存在,它就会成为检查对象。 - 如果完全不存在任何记忆文件,不要以空报告结束——改用模式 B(见下文):挖掘会话历史并撰写初始记录。只有在也没有会话历史时,才结束检查,并建议使用
/init,随后进行积极精简,同时说明无法运行其他检查的原因。
阶段 2 — 生命体征
python3 SCRIPTS/vitals.py --work WORK
读取 WORK/vitals.json。脚本负责测量;你负责解读。检测器说明:
init_boilerplate表示文件开头仍是/init生成的默认内容——这是内容生成后从未精简过的标记。emphasis_per_100_lines关注的是密度,而非强调格式是否存在(官方认可少量使用强调格式)。dated_per_100_lines数值偏高,说明内容可能不断累积会话日志或变更日志。- 大文件的
imperative_ratio非常低,说明内容可能是叙述性文档,而非指令——请抽查并判断;arcan 案例(某个 CLAUDE.md 包含一份破坏手册)正是存在这项检查的原因。 - 应评估整体上下文,而不只是逐个文件检查(
launch_loaded_combined加上文件数量):许多单独来看都很健康的文件,合起来仍可能造成过重的常驻上下文;跨文件的重复或矛盾也无法从单个文件中看出。如果问题出在整体上下文规模上,请按递进步骤提出建议——先合并重复内容,再建立一个精简的路由器/索引,指向按需加载的文件,最后将常驻内容缩减为一屏的核心约束,并把操作流程移至技能中(引用 IDsurface-bloat)。
阶段 3 — 引用检查
python3 SCRIPTS/refcheck.py --work WORK
阅读 WORK/refcheck.json。你的判断应通过以下检查:
- 审查失败项,不要照搬。 对每个
missing/machine_specific/glob_empty引用和每个missing命令, 打开所引用的文件及行号,确认它确实是一个引用(而不是看起来像路径的 普通文本——API 端点、MIME 类型、git 引用,以及文本中描述为已删除的文件是常见的误报)。将每个 误报及其原因记录在dismissed_refs中:报告只显示已确认的发现,并在折叠注释中披露已排除的项目。 - 提取脚本无法检查的断言,例如记忆文件中的可计数断言(“3,540 个测试,分布在 374 个文件中”“12 个 UI 组件”“没有 ESLint 配置”)。使用快速命令验证容易检查的内容(文件计数、搜索配置文件)。除非用户提出要求,否则不要运行测试套件或构建。将每项记录为
verified/drifted/unverified,并附上一行说明——对于耗时较高的项目,诚实地标记为unverified。
阶段 4 — 历史回测
仅当初步检查发现没有会话目录(sessions.dir 为 null)时,才跳过此阶段——并在聊天中说明;报告的“历史”部分也会注明这一点。
4a — 精简对话记录
python3 SCRIPTS/sessions.py --work WORK
4b — 将记忆文件分解为规则手册(由你判断)
编写 WORK/rulebook.json(架构定义见 backtest.py 顶部)。
指导:
- 拆解文件中的每一条指令——规则手册是完整的指令清单,只有当 M 是整个文件时,执行阶梯中的“N 项中的 M 项”才算诚实。只有可通过机械方式检查的规则才添加匹配器:Bash 命令或 Edit/Write 内容中可见的禁令和要求,以及通过
ordering检查的完成顺序规则。判别型规则和暂时无法机械化的规则应作为仅分类条目添加(不包含 enforcement 块和匹配器)——切勿强行为语义规则套用正则表达式。信息性内容(事实、架构、API 语义)不应纳入规则手册。 - 对于 edit/write 事件,可匹配的文本是首行的
PATH: <file_path>,后接(经过截断的)新内容——基于路径的规则以^PATH: .*…为锚点,基于内容的规则则以正文为锚点。 - 编写保守的正则表达式(宁可漏报,也不要误报),使用
scope.paths/scope.exclude_paths限定文件级规则的适用范围;如果文件历史易于查询,则使用git log --follow --format=%aI -- <file>获取introduced日期并为每条规则添加该日期——规则尚不存在前就已结束的会话,不得计入依从性统计。 - 对每条规则的执行方式进行分类(
enforcement块——架构定义见backtest.py顶部)。先将复合规则拆分为子句,再分别分类。分类应选择最省力且可靠的检测方式:hook(事件流正则:bash/edit/path/tool-input/output 门控、顺序、频率——将规则归入 judge 前,先尝试用事件顺序和持续不变的约束重新表述)、linter/test(对产物进行静态分析:lint 规则、规范测试、导入图边界——记录scope_kind: file|project),或judge(只有 LLM 能对其评分)。连 judge 都无法评分的内容就不是规则——应将其诊断为vague。检测现有执行机制:如果仓库已有正文所述的 test/lint/hook,则将其设置为current_layer——这条规则是一个合理的指向标,绝不能成为整改目标。current_layer也可以是组织级规则平台(具有集中式检测器/遥测的团队级规则手册)——这是跨仓库规则、规模化 judge 类审查,以及按单个仓库配置无法管控的分阶段 warn→block 部署的合适归属。为每条已分类的规则设置echo_regex,内容为其特征词元(用于检测已证实的违规),并设置origin(root/nested/rules——只有非 root 规则在压缩后才可能真正缺失)。还应在 enforcement 块中评估against_prior: true|false:如果没有这条规则,前沿模型是否也会默认这么做?遵循有-prior 规则时的高依从性可能只是巧合,而非服从(引用 idharness-if)——应在诊断中将其标记为冗余候选项,而非称赞其执行良好。另外,在建议移入 skill 时需注意:这种迁移只适用于流程——降级到 skill 描述中的约束会明显降低其优先级(项目文件的优先级高于工具/skill 描述)。 需要了解的引擎语义(以免你反向推断): - “Opportunities”(触发机会) = 正则规则的匹配器触发(违规+合规+上下文均命中),排序规则的变更会话数。数值为零可能意味着“规则从未适用”,也可能意味着“你的作用域有误”——对于任何触发次数为零的路径作用域规则,在判定其不起作用之前,先运行一次负向对照(确认会话中完全没有该作用域下的事件)。
scope.paths只过滤带有文件路径的事件;bash 事件会通过 paths 过滤器(它们没有路径)——对于混合 bash+编辑规则,如果必须排除 bash,就将路径约束写入正则(^PATH: …)。exclude_paths和repo_only会应用于排序规则的变更计数。- Edit/Write 可匹配的内容会被截断至约 1200 个字符的新内容(bash 命令约 600 个字符)——首行规则没问题;无法将文件末尾或大小规则表达为内容正则。
- 精简后的会话是一个顶层 JSON 数组,其中包含事件对象。
4c — 运行引擎
python3 SCRIPTS/backtest.py --work WORK
4d — 抽样验证(必须执行——匹配器存在缺陷)
阅读 WORK/backtest.json。对于每条有触发的规则——违规和合规样本都要检查——阅读样本摘录,并确认每条都是真阳性。只要匹配器出现任何假阳性,就在 rulebook.json 中修复并重新运行引擎——这个循环成本很低,也是结果可信的根本原因。只有在确认每个抽样触发都无误后,才在 backtest.json 中设置 "verified": true(编辑该文件)——否则报告会显示“provisional”(暂定)横幅。
提及不等于使用。 最常见的假阳性是某个会话只是在讨论规则,而不是违反规则:记录相关风险、搜索违规者、编写规则本身、在提交消息或撤回内容中引用规则。正则无法区分讨论和违规,而这类情况会被归为 defiance-proven——最严重的原因——因为规则文本就在会话中被复述了。如果仓库自身的文档会引用规则,就要预期这种情况,并检查摘录,判断该事件是执行了被禁止的操作,还是仅仅提到了它。记录自身规范的仓库会大量产生这类触发;应剔除这些触发并收紧匹配器(锚定实际操作,并通过 scope.exclude_paths 排除对记忆文件和文档的编辑)。
然后在 diagnosis.json 的 rule_verdicts 下记录每条规则的判定:
"rule_verdicts": {
"R1": {"verdict": "healthy|ignored|mixed|inert", "note": "one line of judgment"}
}
(以上是常见的子集——第 5 阶段的架构是规范版本,并新增了 unmeasured|abandoned|undocumented;挖掘出的规则使用 undocumented。)
inert(窗口期内触发机会为零)是一项发现,不是失败——说明它意味着什么:该规则在每个会话中都占用了上下文,却从未派上用场。
引擎还会按原因对每项违规进行分类:defiance-proven(Agent 在自己的文本中复述了规则,随后又违反规则——提醒已经出现,但未能奏效)、defiance(新鲜上下文)、dilution(轮次靠后/上下文繁重)、absence-risk(压缩边界之后的非根规则)。先阅读原因再作判断:它们决定了应采取的措施——已证实的抗命足以支持阻断模式;稀释意味着应精简或限定路径,而不是设下重重限制;缺失则需要重新注入钩子。在抽样验证时检查这些分类是否合理(第 2 轮的违规被标记为“dilution”,说明占用率代理指标误判了——请说明这一点)。排序规则注意事项:判定按单份转录记录分别进行——在子 Agent/工作树工作流中,所需命令可能已在同级转录记录中运行。对话消息声称命令已运行(“验证通过”)并不能作为证据;在判定中记录该说法,并检查此后是否发生过仓库编辑(相关义务会再次生效)。
4e — 编译执行提案
python3 SCRIPTS/compile.py --work WORK
这会写入 WORK/enforcement/——每条规则一份 PROPOSALS.md 提案文档、一份通用守护脚本、每条规则对应的配置(默认采用 warn 模式;已证明违抗的规则则从 block 模式开始),以及一段设置代码片段。绝不要自行安装其中任何内容;绝不要编辑用户的 .claude/settings.json。 注意 Goodhart 效应(引用 ID specbench):可见的模式门槛可能在不遵守规则的情况下也能通过——如果规则有实际结果(测试通过、构建成功),应优先选择能验证实际结果的门槛,而不是只搜索模式的门槛。告知用户提案所在位置,并说明这些提案需先审核再启用。
4f — 差距分析:会话中反复要求、但文件从未写明的内容
python3 SCRIPTS/mine.py --work WORK
读取 WORK/candidates.json,并将筛选后保留的组与规则手册进行比较:如果某个反复出现的信号(纠正聚类、失败→修复的命令对、反复出现的用户否定)与现有规则都不匹配,那么这就是用户在一次次会话中反复手动要求的规则。按下文模式 B2 的方式判断——剔除偶发情况和 stale 组(挖掘器已排除自动模式阻止的内容)。对于每项接受的遗漏,添加一条状态为 undocumented 的诊断(severity 为 warn,evidence = 1–2 条摘录);当遗漏足够重要时,写入 WORK/chart.json,其中 "mode": "gap"(架构见 generate.py 顶部),并运行 python3 SCRIPTS/generate.py --work WORK 生成 PROPOSED-ADDITIONS.md。注意总量预算:拟议的新增内容不得使内容规模超过本次审查评定的目标。
第 5 阶段 — 诊断(写入文件的判断结果)
写入 WORK/diagnosis.json:
{
"grade": "B",
"chief_complaint": "One sentence, doctor-voice, the single biggest issue.",
"history_note": "optional override for the History section",
"stale_claims": [
{"claim": "…", "file": "/abs/path", "line": 12,
"status": "verified|drifted|unverified", "detail": "…"}
],
"dismissed_refs": [
{"ref": "the exact ref string from refcheck.json", "line": 46,
"reason": "why it is a false positive (route not file, MIME type, described as deleted, …)"}
],
"rule_verdicts": {
"R1": {"verdict": "healthy|ignored|mixed|inert|unmeasured|abandoned|undocumented",
"note": "one line of judgment; 'abandoned' = the repo's own history contradicts the rule (e.g. git shows the team doing the banned thing routinely) even if sessions were inert"}
},
"diagnoses": [
{"state": "dead-ref|stale|vague|ignored|inert|redundant|contradictory|oversized|accretion|generated-unpruned|undocumented",
"severity": "critical|warn|info",
"title": "short name", "detail": "1–3 sentences, plain language",
"file": "/abs/path", "line": 46,
"evidence": ["short quoted lines or metric readouts"],
"citations": ["official-200"],
"prescription": "the concrete fix, imperative voice"}
],
"prescriptions": [
{"action": "repo-wide action", "rationale": "why", "citations": ["eth"]}
],
"followup": ["re-run cadence; transcript-retention advice; what to fix first"],
"share_note": "one quotable line for the public share card — dry doctor's wit backed by the findings. STRICT safety: no file paths, no rule text, no quotes from the repo, no session ids, nothing repo-identifying; aggregate truths only (e.g. 'The loudest rule was the broken one.'). Omit the field to use a deterministic fallback."
}
此阶段规则:
- 每条诊断都需要证据(引用的行、指标、未通过的检查),并在存在时附上引用 ID。运行
python3 SCRIPTS/report.py --list-citations列出有效 ID 及每个来源的主张——只使用这些 ID,且仅在来源确实支持相关论点时使用。没有官方或研究依据的检查,应在其detail中注明这是启发式判断。 - 如实评定严重程度:
critical= 文件会误导 Agent(无效引用、已过时的主张、矛盾),或内容被跳过(4 MiB);warn= 占用上下文或降低遵循度(过大、强调饱和、内容累积);info= 值得了解。 - 仅涉及结构的发现须附带提醒:唯一一项因子研究在其测试范围内未发现结构影响(引用 ID
mcmillan)——不要把有关大小或位置的民间说法说成因果事实。内容方面的发现(无效引用、过时内容)无需此类保留说明。 - 评分标准:A = 没有 critical,且 warn 不超过 2 项;B = 没有 critical,且 warn 至少 3 项;C = 1–2 项 critical;D = 3 项或更多 critical;F = 文件会积极误导(大部分内容无效或过时)或无法加载。采用指针式结构的 CLAUDE.md 应根据其指向的目标文件评分。
- 无法修复的范围(祖先文件、用户文件、托管文件)只能生成
info级诊断。 - 绝不要在报告内容中提及此工具的版本号(诊断、备注、后续事项、主要问题)。渲染器会在报告页脚标注版本;正文应保持历久弥新——读者不知道也不关心“v0.2”是什么意思。
- 指针式仓库通常供多个 Agent 共用。 如果分析对象是通过指针找到的 AGENTS.md,它很可能也供 Cursor/Codex/Copilot 使用——建议将内容移入仅供 Claude 使用的区域(
.claude/rules/、技能、钩子),会导致其他 Agent 无法看到这些内容。适当时仍可提出这类建议,但须在建议中说明权衡(“仅供 Claude 使用;读取 AGENTS.md 的其他 Agent 将无法看到这些内容”),并优先在文件内修复所有 Agent 都需要的内容。
阶段 6 — 报告
python3 SCRIPTS/report.py --work WORK
然后生成可安全分享的卡片和徽章:
python3 SCRIPTS/card.py --work WORK
card.svg(可发布的检查卡片)和 claude-md-health.svg(README 徽章)
会生成在 report.html 所在目录。两者的设计都只包含汇总信息,但在告诉用户可以安全发布之前,还是要检查一下卡片。将脚本打印的徽章代码片段提供给用户,以便他们添加到 README 中。
打开生成的 report.html 或将它发送给用户,并在聊天中总结:
评分、主要问题、排名前三的发现,以及价值最高的一条处方。告诉用户报告的存放位置。如果 report.py 打印了 INCOMPLETE 警告,说明缺失了哪个阶段以及原因。
模式 B — 没有病历的患者(没有记忆文件?挖掘一份)
如果初步检查发现完全没有记忆文件,或者用户要求根据历史记录生成 CLAUDE.md / hooks / lint 建议,则转到此模式——但如果仓库已经有记忆文件,绝不要运行模式 B:运行常规检查,并通过阶段 4f(差距分析,"mode": "gap" → PROPOSED-ADDITIONS.md)满足生成请求,这样现有文件仍是患者,初步检查中“没有记忆文件”的表述也依然成立。
记录中已经包含了未成文的规则手册:用户反复输入的更正、直到运行正确命令才成功的命令、每次会话开始时都要重新推导的事实、用户拒绝的工具调用。模式 B 会根据历史记录建立初始病历。
无论如何,先运行阶段 2 和阶段 3——在空白环境中,它们会立即完成,同时确保清单准确无误;而“每次会话加载 0 个 token”就是患者的基准生命体征。
B1 — 精简并挖掘
python3 SCRIPTS/sessions.py --work WORK
python3 SCRIPTS/mine.py --work WORK
candidates.json 中包含按规则预先筛选的信号,分为五类(更正、失败后恢复、重新发现、拒绝、开场信息),以及启动成本估算。词汇标记的校准精确率约为 65–75%——你需要负责判断;此文件中的内容还不能算规则。
B2 — 判断候选项(由你判断)
逐一分流所有条目:
- 规则是指用户仍会认同的持久内容:反复出现且逐渐明确的更正(“使用 pnpm”“绝不直接推送”)、失败→修复配对中具有系统性的修复方法(错误的执行器、目录、缺失的环境变量)、反复出现的
user-rejected/permission-rule拒绝。将其写成一行祈使句。 - 事实是指 Agent 反复重新推导的仓库知识:从重新发现分组中提取构建/测试命令,从开场信息聚类中提取布局/上下文。
- 拒绝收录一次性的偏好、特定任务指令、标记为
stale的内容(仓库可能已经更新),以及你无法确信可以泛化的摘录。(挖掘器已排除自动模式分类器拦截的内容——它们只会出现在meta.automode_blocked中;不要重新加入。)记录值得注意的拒绝收录项及原因——报告会披露这些信息。 - 分组类别(failure_recovery、rediscovery、denials、preambles)已通过重复出现门槛。更正类别未经过此门槛——任何一条带标记的消息都会送到你面前,因此要格外严格判断;只有内容明显具有持久性时,一次性的更正才算规则。
然后对所有内容应用意义检验:用户会确信这条内容吗? 如有疑问,就拒绝收录——挖掘出的草案越精简,越值得信任。
还要抽查召回率:预筛选会漏掉不含标记词的纯事实更正(
meta.known_gaps);如果产出看起来很少,就略读一两段精简会话中的用户文本。
B3 — 通过回测验证挖掘出的规则(凭据)
对于每条已接受且可通过机械方式检查的规则,编写一条标准的
WORK/rulebook.json 条目(架构见 backtest.py 文件顶部;设置
"source": {"file": "mined-from-history", "line": 0},对其执行方式进行分类,并填写
echo_regex),然后运行:
python3 SCRIPTS/backtest.py --work WORK
python3 SCRIPTS/compile.py --work WORK
回测计数就是规则的凭据——如果某条挖掘出的规则的匹配器在提出它的同一段历史记录中找不到任何内容,那么这条规则就是挖掘假阳性:将其删除。按照 Stage 4d 的方式对触发结果进行抽样验证。对于通过 hook 分类的挖掘规则,compile 会生成先审查、再启用的 hook 提案——这些规则从一开始就经过机械化处理:最佳的 CLAUDE.md 条目就是由守护机制强制执行的那一条。
B4 — 编写图表并生成草稿
编写 WORK/chart.json(架构见 generate.py 文件顶部):纳入已接受的事实和规则,以及挖掘或回测得出的 occurrences/sessions、每项的 evidence 摘录、startup_tax(从 candidates.json 复制 est_tokens/sessions——该估算归因于反复执行的发现命令自身的记录和结果,因此应原样表述为估算),以及 declined 列表。然后运行:
python3 SCRIPTS/generate.py --work WORK
此命令会在报告旁生成 PROPOSED-CLAUDE.md——凭据放在 HTML 注释中,Claude Code 加载时会将其剥离,因此不会给采用者带来任何成本。如果草稿超出官方的 200 行目标,此命令会以非零状态码退出:医生不会开出自己诊断出的疾病的处方。切勿自行将草稿复制到仓库中——是否采用由用户决定。
B5 — 诊断、报告、卡片
照常进行 Stage 5 和 Stage 6。模式 B 的具体要求:
chief_complaint:写明缺失情况及其代价,并附上证据(“不存在记忆文件;N 个会话显示有 M 条反复由人工口头交代的规则”)。- 评估差距,而非空白:如果历史记录显示反复口头重申或违反未成文规则,评为 D;如果挖掘出的图表内容单薄,则评为 C。F 仅用于存在主动误导行为的文件——缺失不等于欺骗。
- 对经过回测的挖掘规则,
rule_verdicts使用undocumented判定(它们不能被视为“ignored”——因为根本没有文件可供忽略)。 - 报告会从
chart.json呈现 Initial chart 部分,卡片也会自动切换为接收统计数据。告知用户PROPOSED-CLAUDE.md的位置、其中每一行都附有凭据,以及 hook 提案(如有)需要先审查再启用。
行为规范
- 所有操作均在本地运行;绝不向任何地方发送文件内容。
- 在证据中引用任何文件时,最多引用约 2 行。
- 在无头或后台运行时,不要尝试“打开”报告——说明其路径(report.html 位于工作目录的上级目录,与 report.json 并列),并对其内容作简要总结。