Claude Code reads AGENTS.md only when telemetry is on [fixed]
Claude Code reads AGENTS.md only when telemetry is on [fixed]
Claude Code 仅在开启遥测功能时才会读取 AGENTS.md [已修复]
Claude Code 2.1.277 announced support for AGENTS.md. In a project with no CLAUDE.md, it is supposed to read AGENTS.md instead. I keep telemetry off in my shell, and in my repos the file never loaded. Issue #95690 explains why, and I added my own measurements to it. This post collects them in one place.
Claude Code 2.1.277 宣布支持 AGENTS.md。在没有 CLAUDE.md 的项目中,它本应读取 AGENTS.md 作为替代。我在 Shell 中关闭了遥测功能,结果发现文件从未在我的仓库中加载。Issue #95690 解释了原因,我也在其中补充了自己的测试结果。本文将这些信息汇总在一起。
Where the gate is
限制机制在哪里
The loader ships as a built-in plugin called agents-md. Its registration in the 2.1.280 bundle looks like this:
var W = !1; var B = () => Oa("tengu_agents_md_mod", W); var H = "AGENTS.md as project instructions: by default loaded where the project has no CLAUDE.md; ...";
加载器作为一个名为 agents-md 的内置插件发布。它在 2.1.280 版本包中的注册代码如下:
var W = !1; var B = () => Oa("tengu_agents_md_mod", W); var H = "AGENTS.md as project instructions: by default loaded where the project has no CLAUDE.md; ...";
W is the plugin’s isOnByDefault value and it is false. B is isAvailable, and it asks a remote feature flag called tengu_agents_md_mod, with false as the fallback. When Claude Code cannot fetch the flag, the plugin is unavailable, and the local file is never read. Reading a markdown file from the working directory needs no network at all, but here it waits on a server-side switch.
W 是插件的 isOnByDefault 值,默认为 false。B 是 isAvailable(是否可用),它会查询一个名为 tengu_agents_md_mod 的远程功能标志,并以 false 作为回退值。当 Claude Code 无法获取该标志时,插件即不可用,本地文件也就永远不会被读取。从工作目录读取 Markdown 文件本无需联网,但在这里它却依赖于服务器端的开关。
How I tested it
我是如何测试的
I made an empty directory that holds only an AGENTS.md with a canary word in it, and asked claude -p for the word. Each setup ran in two sessions, because the first session in a new configuration only fetches the flag and the second one uses it.
echo 'The canary word is PERIWINKLE.' > AGENTS.md
claude -p 'What is the canary word from the project instructions? Answer NONE if you have none. Do not read files.'
我创建了一个空目录,其中仅包含一个带有“金丝雀词”(canary word)的 AGENTS.md 文件,并使用 claude -p 来询问该词。每个测试设置都运行了两次会话,因为新配置下的第一次会话只会获取标志,第二次才会使用它。
echo 'The canary word is PERIWINKLE.' > AGENTS.md
claude -p 'What is the canary word from the project instructions? Answer NONE if you have none. Do not read files.'
What I measured
我的测量结果
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 blocks the feature, as the issue says. DISABLE_TELEMETRY=1 blocks it too. With either variable set, AGENTS.md never loaded, so I had to clear both.
正如 Issue 中所述,CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 会阻止该功能。DISABLE_TELEMETRY=1 也会产生同样的效果。只要设置了其中任何一个变量,AGENTS.md 就无法加载,所以我必须清除这两个变量。
Setting either variable to 0 does not help. The block stays in place. The environment variable docs say that any value counts, but that is easy to miss when you try to turn a feature on.
将任一变量设置为 0 也无济于事,限制依然存在。环境变量文档指出任何值都会生效,但在尝试开启功能时,这一点很容易被忽略。
An env block in the project’s .claude/settings.json that clears both variables has no effect. There is no way to turn the feature on for a single repo.
在项目 .claude/settings.json 中通过 env 块清除这两个变量没有任何效果。目前没有办法为单个仓库开启此功能。
A session-level override does work from the second session on:
claude --settings '{"env":{"DISABLE_TELEMETRY":"","CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC":""}}'
从第二次会话开始,会话级别的覆盖确实有效:
claude --settings '{"env":{"DISABLE_TELEMETRY":"","CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC":""}}'
None of these cases print a warning. The session starts, the model answers without the project instructions, and nothing tells you that a file was skipped. The issue also points out that third-party gateways, Bedrock and Vertex have the same problem, because the flag cannot resolve to true there either.
上述所有情况都不会打印任何警告。会话启动后,模型在没有项目指令的情况下回答,没有任何提示告知你文件已被跳过。该 Issue 还指出,第三方网关(如 Bedrock 和 Vertex)也存在同样的问题,因为在这些环境下标志也无法解析为 true。
The workaround
变通方案
CLAUDE.md supports @path imports, and those do not depend on the flag. A one-line CLAUDE.md next to the AGENTS.md loads it with telemetry off:
echo '@AGENTS.md' > CLAUDE.md
CLAUDE.md 支持 @path 导入,且这些导入不依赖于该标志。在 AGENTS.md 旁边创建一个单行的 CLAUDE.md 即可在关闭遥测的情况下加载它:
echo '@AGENTS.md' > CLAUDE.md
With that file in place, the same canary test returns the word with CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 still set. The cost is one extra file per repo, which is what the AGENTS.md support was supposed to remove.
有了这个文件,即使在设置了 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 的情况下,同样的金丝雀测试也能返回该词。代价是每个仓库多了一个文件,而这正是 AGENTS.md 支持本应消除的问题。
Why I think this is unacceptable
为什么我认为这不可接受
I turned telemetry off on purpose, and I expect that choice to cost me some diagnostics and nothing else. Here it silently costs me a feature that reads a file from my own disk. A remote flag can make sense for a feature that talks to a server, but the only input this one needs is already in the working directory.
我特意关闭了遥测功能,我期望这个选择只会让我失去一些诊断信息,而不是其他。但在这里,它却悄无声息地让我失去了一个读取本地磁盘文件的功能。远程标志对于需要与服务器通信的功能来说是有意义的,但这个功能所需的唯一输入已经在工作目录中了。
The gate also hits the people who are most likely to care about AGENTS.md. Someone who keeps one instruction file for several agents is usually careful about what each tool sends home, and teams on Bedrock, Vertex or a gateway often disable nonessential traffic by policy. They all get a feature that is announced as available and then does nothing.
这种限制还影响了最关心 AGENTS.md 的用户群体。那些为多个 Agent 保留一份指令文件的人,通常会对每个工具发送回服务器的数据非常谨慎;而使用 Bedrock、Vertex 或网关的团队通常会根据策略禁用非必要流量。他们得到的是一个被宣布可用但实际上毫无作用的功能。
The silence is the worst part. I confirmed the cause with a canary word and a string search through the binary, and most people will not do that. They will conclude that the model ignores their instructions, and they will spend time on prompts when the file never reached the model in the first place.
沉默是最糟糕的部分。我通过金丝雀词和对二进制文件的字符串搜索确认了原因,但大多数人不会这样做。他们会认为模型忽略了他们的指令,并浪费时间在提示词上,而实际上文件根本就没有传达到模型。
A privacy setting should never quietly switch off unrelated local behavior. If Anthropic wants a staged rollout, the fallback for a flag that cannot be fetched should be the documented behavior, or at least a visible message that says what was skipped and why.
隐私设置绝不应该悄悄关闭不相关的本地行为。如果 Anthropic 想要进行分阶段发布,那么当标志无法获取时,回退方案应该是文档中记录的行为,或者至少应该显示一条可见的消息,说明跳过了什么以及原因。
What I would like to see
我的期望
-
Reading a local file should not depend on telemetry. If the gate has to stay for a gradual rollout, a startup warning when an
AGENTS.mdis present and skipped would save people the time I spent on a canary test. -
读取本地文件不应依赖于遥测。 如果为了分阶段发布必须保留限制,那么当存在
AGENTS.md且被跳过时,启动时发出警告可以节省人们像我一样进行金丝雀测试的时间。 -
A global
AGENTS.md. The plugin looks forAGENTS.mdand.claude/AGENTS.mdin project directories only, and there is no user-level file next to the userCLAUDE.md. Codex reads a global~/.codex/AGENTS.md, and the/importcommand in Claude Code can copy it into the userCLAUDE.md, but the copy does not follow later edits. If you keep one set of personal instructions for several agents, you still need an@import in the userCLAUDE.mdthat points at the shared file. -
全局
AGENTS.md。 该插件仅在项目目录中查找AGENTS.md和.claude/AGENTS.md,在用户CLAUDE.md旁边没有用户级文件。Codex 会读取全局的~/.codex/AGENTS.md,而 Claude Code 中的/import命令可以将其复制到用户CLAUDE.md中,但副本不会随后续编辑而更新。如果你为多个 Agent 保留一套个人指令,你仍然需要在用户CLAUDE.md中使用@导入指向该共享文件。 -
Native support for shared agent skills. Codex reads skills from
.agents/skillsin the project and from~/.agents/skillsin the home directory. Claude Code 2.1.280 knows those paths only in/import, which copies the skills into.claude/skills. I put a canary skill in.agents/skillsand Claude Code did not list it, but it listed the same skill from.claude/skillsin the same repo. A copy drifts from the source, so I link.claude/skillsto../.agents/skillsinstead, and Claude Code follows that symlink. -
对共享 Agent 技能的原生支持。 Codex 从项目中的
.agents/skills和主目录中的~/.agents/skills读取技能。Claude Code 2.1.280 仅在/import中识别这些路径,它会将技能复制到.claude/skills中。我在.agents/skills中放入了一个金丝雀技能,Claude Code 没有列出它,但它列出了同一仓库中.claude/skills下的相同技能。副本会与源文件产生偏差,所以我将.claude/skills链接到../.agents/skills,Claude Code 可以跟随该符号链接。
Until then, I use the one-line CLAUDE.md for instructions and a symlink for skills.
在此之前,我将使用单行 CLAUDE.md 来处理指令,并使用符号链接来处理技能。