SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-13

编码代理为何会忽略您的指令?

指令文件写着“停止”,代理却继续执行。本文解释上下文加载、冲突证据与旧规则位置的机制,并提供重写规则前可运行的诊断方法。

编码代理为何会忽略您的指令

编码代理会因4个原因忽略您的指令,但原因不是您的语气不够强硬。规则可能从未进入上下文窗口。规则可能过于模糊,无法据此检查某个操作。上下文中的其他内容可能与规则冲突,通常是代理刚刚读取的代码。或者,规则仍已加载,但位于当前轮次之前很远的位置,代理会优先依据附近的内容工作。

每种原因都有对应的修复方法,因此首先要做的是区分它们。使用大写字母和 IMPORTANT 一词并不能诊断问题。下面以 Claude Code 为例说明工作机制,因为截至 August 2026,其加载和压缩行为已有详细文档。其他工具在具体细节上有所不同,但总体行为相同。

先说明两个术语。上下文窗口是模型在某一轮看到的文本块,包括系统提示、您的指令文件、对话内容,以及代理读取过的每个文件。工具框架是模型外部的程序,负责从磁盘读取文件并组装这个文本块。本文中几乎所有抱怨,实际上都是在抱怨工具框架,而不是模型。

您的指令文件是一条消息,而不是配置

指令文件不是配置。运行时不会读取 CLAUDE.md 并强制执行其中的内容。执行框架会从磁盘读取该文件,然后将文本粘贴到对话中。在 Claude Code 中,这些内容会作为系统提示之后的用户消息传递,因此模型看到这些规则的方式,与看到您输入的其他内容相同。

这会带来一个令人不适的后果。您的规则会与窗口中的其他文本竞争,而且优先级相同。规则是一项声明。代理刚刚打开的文件则是证据。两者不一致时,证据往往会胜出,而且不会触发错误,因为从模型的角度看,没有任何操作出错。

官方文档对此说明得很清楚:指令文件会作为上下文处理,而不是作为受强制执行的配置。无论模型如何决策,都要阻止某项操作时,您需要使用 hook,而不是写一句话。请记住这一点。本文末尾的大多数修复方案,都是将这条原则应用到具体场景中。

加载哪些指令文件,以及何时加载

Claude Code 会从启动目录沿目录树向上查找。从文件系统根目录到工作目录之间的每个 CLAUDE.mdCLAUDE.local.md,都会在启动时完整加载。它们会按此顺序拼接,因此距离启动目录最近的文件最后读取;同一目录中的文件则先读取主文件,再追加 .local 文件。

工作目录下方子目录中的文件加载方式不同。它们不会在启动时加载,而是在代理读取该目录中的文件时加载。.claude/rules/ 中带有 paths: frontmatter 字段的路径范围规则也遵循相同机制:匹配文件被读取时,它们才会进入上下文,而不是在每一轮都加载。

这一差异解释了大量已报告的失败案例。您将规则放在 packages/api/CLAUDE.md 中,然后询问 API,代理却从未打开 packages/api/ 下的任何文件。规则并没有被忽略,而是从未存在于当前上下文中。如果您的代码仓库将指导信息拆分到 monorepo 中每个软件包的指令文件,每次都应首先检查这一点。

还有一个加载陷阱,也是“代理忽略了我的指令”最常见的原因:Claude Code 读取 CLAUDE.md,而不是 AGENTS.md。如果代码仓库统一使用 AGENTS.md,但没有 CLAUDE.md,Claude Code 就完全没有可加载的内容。受支持的桥接方式是创建一个 CLAUDE.md,其第一行写入 @AGENTS.md,这样 Claude Code 会在启动时导入该文件;下面还可以添加 Claude 专用说明。如果没有额外内容,也可以使用符号链接。首先决定哪些内容应放入该文件,是另一个问题,详见将代理指令与人工文档分开

确认文件已加载后再重写

在确认代理可以看到该文件之前,不要修改其中的措辞。这里有两项检查,应先执行成本较低的检查。

在会话中运行 /context。它会按类别列出当前窗口的内容,其中 Memory files 列表会列出实际已加载的每个指令文件。文件未出现在该列表中,说明它不在当前对话中,因此写入其中的内容不会生效。/memory 会列出文件位置并打开文件进行编辑,包括尚不存在的文件。

如需更确切的结果,请记录加载事件。每当 CLAUDE.md 或规则文件进入上下文时,InstructionsLoaded hook 事件都会触发;其 matcher 会说明加载原因:session_startnested_traversalpath_glob_matchincludecompact。将以下内容放入 .claude/settings.json

{
  "hooks": {
    "InstructionsLoaded": [
      {
        "matcher": "nested_traversal",
        "hooks": [
          {
            "type": "command",
            "command": "cat >> /tmp/instructions-loaded.log"
          }
        ]
      }
    ]
  }
}

该 hook 会将载荷以 JSON 形式写入标准输入,因此 cat 会追加完整记录。工作期间使用 tail -f /tmp/instructions-loaded.log 监控日志。该事件的退出状态会被忽略,因此 hook 只能观察,不能阻止加载。如果在预期应加载嵌套文件的会话中,日志始终没有出现该文件,请停止改写措辞。问题出在文件位置。

长会话对规则的影响

这里有两种不同的影响,需要分别处理。

距离。 第 1 轮中声明的规则到第 90 轮时仍在上下文窗口中,但此时它要与最近的 90 轮文本竞争,而后者与当前任务的关联更直接、具体。无法通过配置消除这种影响,但可以对其进行测量。在新会话中执行相同任务。如果规则在新会话中有效,但在长会话深入进行后失效,那么原因就是距离。

压缩。 上下文窗口填满后,运行框架会总结到目前为止的对话,然后根据该总结继续执行。能够保留下来的内容取决于总结器判断哪些内容重要,而不一定符合您的判断。Claude Code 会按机制记录具体结果,差异很大。项目根目录中的 CLAUDE.md 和未限定范围的规则会在压缩后从磁盘重新注入。自动记忆会从磁盘重新注入。带有 paths: frontmatter 的规则会丢失,直到再次读取匹配的文件。子目录中的嵌套 CLAUDE.md 文件会丢失,直到再次读取该子目录中的文件。

根据这张表为指令排序后,其脆弱性顺序就很清晰了。只在聊天中输入的规则是会话中最脆弱的内容:只有总结碰巧保留它时,规则才会继续存在。packages/api/CLAUDE.md 中的规则次之,因为它只加载过一次,之后可能被总结过程丢弃,只有下次在该目录中读取文件时才会恢复。项目根目录文件中的规则最持久,因为每次都会从磁盘重新读取。

因此,如果某条指令必须在整个会话期间有效,就应将其放入项目根目录文件,并且不要使用 paths: frontmatter。其他做法都存在取舍,应根据需要有意识地选择。管理上下文窗口中保留的内容介绍了带焦点参数的 /compact,以及无关任务之间的 /clear;这两者都会改变总结器决定您的规则内容的频率。

为什么周边代码的影响会超过规则

这是人们最常描述、却最少诊断的失败类型。您的文件规定数据库访问必须经过 repository 层。代理却编写了一个直接调用 ORM(对象关系映射器)的处理程序。代理并不是因为风格问题忽略了您。它是被证据说服了。

规则描述的是一种偏好。代码展示的是一种做法。当代理打开即将编辑的模块中的 3 个文件,而这 3 个文件都直接调用 ORM 时,上下文的一侧只有一条抽象句子,另一侧则有 3 个具体、近期且与任务匹配的示例。复制本地模式通常是正确行为。只有在您知道某些上下文中没有的信息时,这样做才会在此处出错:这些文件属于旧代码。

因此,请将这一点写入规则。明确说明自身反例的规则,才能经受真实代码库的检验。只陈述一般偏好的规则做不到这一点。

新增的数据库访问必须经过 app/repositories/app/legacy/ 下的文件仍会直接调用 ORM。这些是旧代码,不是应遵循的模式。不要复制这种写法。

真正发挥作用的是第二句。它会在代理发现这些文件之前,先告诉代理将会看到什么,以及应如何理解这些内容。同样的修复方式适用于代码库中明显与规则矛盾的任何情况:历史记录并未遵循的提交格式、半数测试套件都未采用的测试布局,或只在新代码中成立的导入约定。只要代码与文件中的规则不一致,就应在文件中明确说明这种不一致。

无法检查的规则就无法执行

“编写整洁的代码。”“不要过度设计。”“保持简单。”“谨慎处理迁移。”这些规则都无法针对某个具体操作进行测试,无论执行者还是您都无法测试。向执行者提供一条无法根据自身输出进行检查的规则,得到的只能是猜测,而您只能凭感觉评判这个猜测。

请对文件中的每一行应用以下测试。写出一条 shell 命令,在规则被违反时以非零状态退出。如果写不出这条命令,说明该规则不可检查。比较以下示例:

  • 不可检查:“保持函数简短。”可检查:“超过 60 行的函数必须在其上方添加注释,说明函数较长的原因。”
  • 不可检查:“测试您的更改。”可检查:“运行 npm test,并在将任务标记为完成前粘贴失败计数。”
  • 不可检查:“保持文件结构有序。”可检查:“HTTP 处理程序必须位于 src/api/handlers/ 中。该目录不得放置其他内容。”
  • 不可检查:“正确格式化代码。”可检查:“.ts 文件使用 2 个空格缩进。”

“不要过度设计”是人们最先放弃的规则,因为修复它所需的不是更短的句子,而是更长的句子:明确说明可行的最小更改具体意味着什么,才能为执行者提供可用于检查自身 diff 的标准。

规模问题只是换了一种形式。Claude Code 的指南要求每个指令文件少于 200 行,并明确指出,文件越长,执行遵循指令的程度越低。700 行的文件并不会让指令更明确。它只是包含 700 行声明,更容易彼此矛盾;而且每一轮都会占用您的上下文窗口,这会直接反映在 token 用量中。将文件组织为按标题划分、便于读者快速查阅的规则,可参考编写执行者能够执行的指令文件

十分钟内完成诊断

按顺序运行以下步骤。直接跳到最后一步,往往只会得到一份充斥着强制性规则、但仍然无法生效的长文件。

  1. 确认文件已加载。 运行 /context,查看 Memory 文件列表。如果文件不在列表中,请修正其位置,然后停止。此时列表中的其他步骤都不适用。
  2. 在全新会话中重现。 启动新会话,并执行一个应触发该规则的最小任务。如果在这里有效,但在长会话中失败,通常说明问题与上下文距离或压缩有关。如果在这里也失败,说明问题出在规则本身。
  3. 移除竞争规则。 在现有代码已经遵循该规则的目录中,请求执行相同的修改。如果合规性恢复,说明周围的代码覆盖了你的规则。
  4. 搜索冲突。 两个文件针对同一行为提供不同指导,是文档化的故障原因:模型可能会任意选择其中一条,而且不会告诉你它这样做了。
  5. 使规则可检查,然后重新测试。 使用具体路径和条件重写规则。如果合规性大幅提高,说明原因是措辞。

第 4 步只需运行一条命令。搜索所有指令来源中的相关主题,不要只搜索你正在编辑的文件:

grep -rni "migration" --include="CLAUDE.md" --include="CLAUDE.local.md" .
grep -rni "migration" .claude/rules/ ~/.claude/CLAUDE.md ~/.claude/rules/ 2>/dev/null

如果两个文件中的指导不同,这就是故障原因。删除其中一条。不要试图用更强的措辞为它们排序,因为不存在可供调用的排序引擎。

按作用强度排序的修复方法

下面每一步的作用强度都高于上一步,但设置成本也更高。如果规则只需简单改写,请从顶部开始。只要规则重要到不能接受偶尔遗漏,就立即向下采用更强的措施。

  1. 让规则具体明确。 指定路径、命令或条件。加入代理将在仓库中找到的反向证据,如前文所示。这不需要额外成本,却能解决出人意料多的问题。
  2. 将规则移到受其约束的内容附近。 可以使用嵌套的 CLAUDE.md.claude/rules/ 中按路径限定作用域的规则,或直接写在文件顶部的注释中。这样,规则会与适用的代码在同一次读取中一并出现。需要接受这一权衡:以这种方式加载的内容会在下一次压缩时消失,并在下一次匹配读取时重新出现。
  3. 将强制执行移到 hook 中。 文本说明只能提出要求,hook 才能作出决定。hook 以代码形式在固定的生命周期事件中运行,不受模型结论影响。
  4. 将规则交给确定性工具,然后删除文本说明。 例如格式化、导入排序、行长度、禁止导入和提交消息格式。使用 ruff formatprettier --writeeslintpre-commit hook。格式化程序每次都能正确执行,且不消耗 token。文本说明大多数时候有效,但每轮都会消耗 token。

以下完整说明第 3 步。假设迁移文件绝不能由代理编辑。将以下内容写入 .claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-migrations.sh"
          }
        ]
      }
    ]
  }
}

再将以下内容写入 .claude/hooks/guard-migrations.sh

#!/usr/bin/env bash
set -euo pipefail

path=$(jq -r '.tool_input.file_path // empty')

case "$path" in
  */migrations/*)
    echo "Files under migrations/ are written by hand. Stop and ask first." >&2
    exit 2
    ;;
esac

exit 0

运行 chmod +x .claude/hooks/guard-migrations.sh,然后启动新会话,并要求代理编辑 migrations/ 下的文件。编辑操作会被拒绝,您的消息会作为原因返回。PreToolUse 返回状态码 2 时,会在工具调用执行前阻止该调用;stderr 文本会作为阻止消息传递给模型。${CLAUDE_PROJECT_DIR} 会解析为项目根目录,因此无论代理当前位于哪个目录,hook 都能正常工作。代理不必同意这条规则、不必记住这条规则,也不必在当前上下文中仍保留这条规则。编辑操作不会发生。

如果只是禁止某项操作,且不包含任何逻辑,那么在设置中使用 permissions.deny 可以实现相同效果,而且无需维护脚本;权限模式决定哪些操作可以在不先询问您的情况下运行。如果某条指令确实必须位于系统提示词层级,而不能放在用户消息中,--append-system-prompt 可以将其放在那里。不过,每次调用都必须传入该指令,因此它更适合脚本,而不是交互式工作。

无法通过指令消除的问题

明确哪些部分由您负责。放置位置、措辞、文件之间的冲突以及文件大小,都是作者的问题,也应由作者修复。其余部分属于模型行为,改进措辞无法消除这些问题。

同意不等于遵守。 Agent 可能会确认某条规则,正确复述给您听,然后在两次工具调用后违反该规则。确认本身没有成本,也不能预测后续行为。不要把确认视为修复,也不要将其计为测试。

某些习惯会持续存在。 添加注释、加入防御性错误处理、编写结尾总结、运行显而易见的下一条命令。这些行为在规则禁止时仍会出现,只是发生率降低,而不是降为零。您可以测量自己的发生率:在全新的会话中重复执行同一任务 10 次,并统计违规次数。若该数字必须为零,就不能只依赖提示中的规则。

当前会话本身会成为示例。 如果 Agent 在第 12 轮违反了规则,而您没有处理,这次违规就会作为示例留在上下文中,而且它比规则新得多。发现违规后应立即纠正。未经纠正的违规会影响当前会话的后续行为。

指令文件不是安全边界。 它只能影响行为,不能强制执行规则。任何遗漏代价高昂的内容,例如凭据或破坏性命令,都应放在权限控制或 hook 中。让 Agent 无法接触机密对数据采用相同原则:不要要求 Agent 不读取某个文件,而应确保该文件不可读。

简而言之:证明文件已加载,使规则可检查,将规则放在其约束对象旁边;如果遗漏率仍然重要,就不要只依赖文字说明。Agent 无法忽略的规则,从一开始就不应要求 Agent 自行遵守。

FAQ

为什么 Claude Code 会忽略我的 CLAUDE.md?

在认定它被忽略之前,先确认它是否已加载。运行 /context,查看 Memory files 列表;未出现在列表中的文件不在当前对话中。指令文件会在系统提示之后作为用户消息传入,因此会被当作上下文,而不是强制配置,无法保证严格遵守。实际情况通常有以下4种:文件位于代理从未读取的子目录中;两个文件存在冲突,模型任意选择了其中一个;规则过于模糊,无法据此判断某项操作;或者周围的代码体现了与规则相反的做法。

在会话中途编辑指令文件会产生什么影响?

不会影响已经加载到当前对话中的副本。工作目录上级目录中的文件会在启动时完整加载,因此模型持有的文本是启动时的版本。要读取编辑后的内容,请启动新会话,或要求代理使用常规文件工具读取该文件;这样当前版本会作为新消息加入对话。压缩上下文后,项目根目录中的文件会从磁盘重新读取,因此新版本也会在此时加载。

根目录中的 CLAUDE.md 与嵌套文件发生冲突时,哪个文件优先?

没有哪个文件能够可靠地优先。已发现的文件会按从文件系统根目录到工作目录的顺序拼接到上下文中,而不是相互覆盖,因此距离当前目录最近的文件只是最后被读取。不存在用于解决冲突的优先级机制,Claude Code 文档也说明,冲突规则可能会被任意处理。应将嵌套文件写成补充规则,并明确写出其适用路径;不要试图通过提高优先级来解决冲突,直接删除冲突内容。

我的指令能在 /compact 后保留吗?

这取决于它们的加载方式。项目根目录中的 CLAUDE.md、未限定范围的规则和自动记忆会在压缩上下文后从磁盘重新注入。带有 paths: frontmatter 的规则,以及子目录中的嵌套 CLAUDE.md 文件,会在再次读取匹配文件之前丢失。只在聊天中输入的内容,只有在摘要程序恰好保留它时才会继续存在。如果某条规则必须在整个会话期间生效,请将其放在项目根目录文件中,并且不要使用 paths: frontmatter。

什么时候应该将规则改为 hook,而不是继续写成说明文字?

当检查条件是确定性的,并且遗漏检查的代价高于编写一个小脚本的代价时,就应使用 hook。文件路径限制、提交前必须执行的命令,以及禁止调用的工具都符合这一条件。一个退出状态为2的 PreToolUse hook 会直接阻止工具调用,并将 stderr 文本作为原因返回给模型,因此无论该规则是否仍存在于上下文中,都能强制执行。凡是格式化程序或 linter 可以判断的内容,都应交由相应工具负责,并从指令文件中完全删除。