Skip to content

Make AGENTS.md the source of truth with CLAUDE.md as a symlink - #923

Open
billadunblock wants to merge 4 commits into
IABTechLab:mainfrom
billadunblock:agents-md-source-of-truth
Open

Make AGENTS.md the source of truth with CLAUDE.md as a symlink#923
billadunblock wants to merge 4 commits into
IABTechLab:mainfrom
billadunblock:agents-md-source-of-truth

Conversation

@billadunblock

@billadunblock billadunblock commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Make AGENTS.md the single source of truth for AI coding agent instructions, replacing CLAUDE.md with a symlink to it — AGENTS.md is the tool-agnostic industry convention (used by Codex, Cursor, and others; see agents.md), while the symlink keeps Claude Code working by its conventional filename with zero duplication or drift.
  • Drop the old AGENTS.md redirect stub and its fallback summary, so there is only one copy of the rules.
  • Update all in-repo references (PR template, onboarding docs, agent and command definitions) to point at AGENTS.md.

Rebased onto current main (was 49 commits behind) to resolve the review feedback — see Review feedback below.

Changes

File Change
AGENTS.md Now holds the full agent guide (moved from CLAUDE.md via git mv, so git log --follow preserves history); redirect stub removed
CLAUDE.md Replaced with a symlink to AGENTS.md (mode 120000)
.github/pull_request_template.md Checklist link now points at AGENTS.md
docs/guide/onboarding.md Docs table entry now references AGENTS.md
.claude/agents/code-simplifier.md Reference updated to AGENTS.md
.claude/agents/pr-reviewer.md All 5 references updated to AGENTS.md (the file grew from 1 to 5 references in #707, which landed after this branch forked)
.claude/commands/review-changes.md Reference updated to AGENTS.md

Historical docs/superpowers/ plans and specs still say CLAUDE.md. That is deliberate — they are dated records of past decisions, and the symlink keeps those references resolving.

Closes

No linked issue. Three follow-ups filed during review are intentionally not closed by this PR:

Test plan

  • Content paritygit diff main:CLAUDE.md AGENTS.md shows only the intentional header change, nothing else.
  • Merge cleanliness — rebased onto main; git merge-base --is-ancestor main HEAD confirms a clean fast-forward, so the earlier "distinct types" conflict is gone.
  • Symlink — tree entry mode is 120000 with a relative target that does not escape the repo root; head -2 CLAUDE.md resolves through to the AGENTS.md content.
  • Historygit log --follow AGENTS.md still reaches the original Add CLAUDE.md and consolidate AI agent conventions #352 commit.
  • Docs formatcd docs && npm run format passes. Scope note: that script is prettier --check . run from docs/, so it exercises the docs/guide/onboarding.md edit but does not inspect root-level AGENTS.md. A green format-docs check is not evidence that the moved file is well-formed; root Markdown is covered by no gate today (Root Markdown is not covered by any format gate and fails prettier --check #1093).

No Rust or JS code is touched, so the cargo and vitest gates don't apply to this change.

Review feedback

Finding Status
🔧 Content regression: the move reverts #767 Fixed. Rebased onto current main and carried #767's neutral-language wording into the AGENTS.md Project Overview. Verified by the content-parity check above.
🤔 "distinct types" conflict can silently re-drop the fix Fixed, both parts. CLAUDE.md keeps the symlink, and main's post-fork edit was ported into AGENTS.md. The branch is now a fast-forward on main, so no conflict resolution happens at merge time.
📝 "Docs format" does not cover the changed file Corrected in the test plan above, with the scope caveat spelled out.
📝 Description wrongly said issues are disabled Corrected — the Closes section now names the three follow-up issues.
🤔 Windows symlink failure is silent and undetected No change here — inherent to the symlink approach this PR chose. Tracked in #1091; the workaround stays documented under Notes.
🌱 Bare cargo test warning lost with the stub No change here, per review — pre-existing gap in the guide, tracked in #1092.

Notes

  • Windows: Git for Windows defaults to core.symlinks=false unless symlink support is available (Windows Developer Mode enabled, or an elevated shell). With symlinks disabled, git checks out CLAUDE.md as a plain 9-byte text file containing the path AGENTS.md, so an agent reading CLAUDE.md gets that string instead of the conventions — silently, with no failing check (see Guard against CLAUDE.md symlink checking out as a plain text file #1091). To get a real symlink: enable Developer Mode (Settings → System → For developers), then clone with git clone -c core.symlinks=true, or in an existing clone run git config core.symlinks true followed by git checkout -f CLAUDE.md to re-materialize it.

References

  • agents.md — the open AGENTS.md specification: a simple, tool-agnostic Markdown convention for giving coding agents project instructions.
  • openai/agents.md — the spec's source repository, with examples and the list of supporting tools.
  • Claude Code memory docs — Claude Code loads CLAUDE.md from the project root, which the symlink satisfies while keeping AGENTS.md as the single source.

🤖 Generated with Claude Code

@billadunblock

billadunblock commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator Author

@jevansnyc as we expand agent harnesses and enrich agentic workflows, this change can be pretty handy (prioritize AGENT.md wth CLAUDE.md as symlink). Consider for corporate users, they can only use Claude Code Enterprise plan (data not for training) which is not very practical for the token price, multi harnesses would be ideal in lots of cases.

@aram356 aram356 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

The direction is sound and the mechanics are mostly clean: git mv preserved
history, the symlink is well-formed (mode 120000, relative target, does not
escape the repo root), all five in-repo reference updates are correct, and the
deleted fallback summary is genuinely redundant with the moved content. All 18
CI checks pass.

One blocking issue: the branch forked 49 commits ago and the moved copy is
stale, so merging silently reverts a change that already landed on main.

1 of the inline comments below carries a one-click GitHub suggestion — use
Commit suggestion to apply it as a commit on the PR branch. The remaining
findings are body-level because they concern the merge, the PR description,
or repo-wide tooling rather than a single line.

Blocking

🔧 wrench

  • Content regression: the move reverts #767 — see inline at AGENTS.md:9

Non-blocking

🤔 thinking

  • "Distinct types" merge conflict can silently re-drop the fix — see below
  • Windows symlink failure mode is documented but unmitigated — see below

📝 note

  • "Docs format" in the test plan does not cover the changed file — see below
  • PR description states issues are disabled; they are not — see below

🌱 seedling

  • Bare cargo test warning was lost with the fallback summary — see below

Cross-cutting / body-level findings

  • 🤔 The merge conflict is a "distinct types" conflict, and naive resolution
    re-drops the blocking fix.
    git merge-tree origin/main <head> reports:

    CONFLICT (distinct types): CLAUDE.md had different types on each side;
    renamed one of them so each can be recorded somewhere.
    

    Git cannot auto-merge a regular-file-vs-symlink change, so it stages both
    sides rather than combining them. Resolving CLAUDE.md in favour of the
    symlink does not carry main's text edit into AGENTS.md — that edit
    lives in a different file after this PR. The resolution therefore has two
    parts, and skipping the second reintroduces the 🔧 finding even if the
    suggestion is applied now:

    1. CLAUDE.md → keep the symlink (this PR's side).
    2. AGENTS.md → port main's post-fork edit to the Project Overview.

    Worth rebasing on main and re-checking git diff origin/main:CLAUDE.md
    against AGENTS.md before merge: after the fix the two should differ only in
    the intentional header.

  • 🤔 The Windows failure mode is silent, and nothing detects it. The PR
    description documents the core.symlinks=false behavior and the manual
    workaround, which is good. But I reproduced the failure and the outcome is
    worse than "tools see the pointer text": with symlinks disabled, CLAUDE.md
    checks out as a 9-byte file whose entire contents are the string
    AGENTS.md. Claude Code loads that as the project instructions, so a
    contributor on such a clone gets zero conventions — no error-stack
    rule, no expect("should ..."), no target-matched clippy/test aliases — with
    no error and no failing check. Documentation only helps someone who already
    suspects the problem. Filed as #1091 for a cheap CI guard; not a merge
    blocker for this PR.

  • 📝 The "Docs format" test-plan item does not exercise this change.
    docs/package.json's format script is prettier --check . run from
    docs/, so it never inspects root-level AGENTS.md. The green format-docs
    check is not evidence that the moved file is well-formed. Separately: root
    AGENTS.md does fail prettier --check — but so does main's CLAUDE.md
    (identical table-alignment drift), so this is pre-existing and not a
    defect of this PR. Filed as #1093.

  • 📝 The PR description says "issues are disabled on this repository" — they
    are not.
    The repository has has_issues: true and issues are actively
    filed (#1085#1089 within the last two days). Minor, but it changes what the
    "Closes" section should say, and follow-ups from this review were filed as
    #1091, #1092, #1093.

  • 🌱 One line of guidance is genuinely lost with the fallback summary.
    Removing the duplicated summary is the right call, and I checked every rule
    in it against the moved guide — all are covered except one: "Do NOT use bare
    cargo test --workspace — it will attempt to compile the Fastly adapter for
    the host target." The main guide warns about bare cargo build and bare
    cargo check but not bare cargo test. Pre-existing gap in the guide rather
    than something this PR breaks; filed as #1092.

CI Status

  • cargo fmt: PASS (required)
  • cargo test: PASS (required)
  • format-docs: PASS (required)
  • format-typescript: PASS (required)
  • cargo test (axum native): PASS
  • cargo test (cross-adapter parity): PASS
  • cargo test (ts CLI, native): PASS
  • cargo check (cloudflare native + wasm32-unknown-unknown): PASS
  • cargo check/build/test (spin native + wasm32-wasip1): PASS
  • vitest: PASS
  • integration tests: PASS
  • integration tests (Fastly EC lifecycle): PASS
  • browser integration tests: PASS
  • prepare integration artifacts: PASS
  • Analyze (rust): PASS
  • Analyze (javascript-typescript): PASS
  • Analyze (actions): PASS
  • CodeQL: PASS

All checks pass, which is expected — no code changed. Worth noting that no
gate compares documentation content across branches, so CI cannot catch the
🔧 finding above.

Comment thread AGENTS.md Outdated
Comment thread CLAUDE.md
# CLAUDE.md

> Single source of truth for all AI coding agents (Claude Code, Codex, Cursor,
> etc.). If you're reading `AGENTS.md`, it redirects here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 thinking — The Windows failure mode here is silent, and nothing detects it.

The PR description documents the core.symlinks=false behavior and the manual workaround, which is good. But the outcome is worse than "tools see the pointer text". I reproduced a symlinks-disabled checkout of this head:

$ git config core.symlinks false && git checkout <head>
$ ls -la CLAUDE.md
-rw-r--r--  1 user  staff  9 CLAUDE.md
$ cat CLAUDE.md
AGENTS.md

These 457 lines become a 9-byte file whose entire contents are the string AGENTS.md. Claude Code loads that as its project instructions, so a contributor on such a clone gets zero conventions — no error-stack rule, no expect("should ..."), no target-matched clippy/test aliases, no WASM constraints — with no error raised and no failing check.

Documentation only helps someone who already suspects the problem. Filed #1091 for a cheap CI guard (assert the tree entry mode is 120000, or that the checked-out file is non-trivial in size).

Not a merge blocker — it's inherent to the symlink approach this PR deliberately chose, and the tradeoff looks correct. Flagging so the silent-failure characteristic is on record.

Comment thread CLAUDE.md
Comment thread AGENTS.md
AGENTS.md is the industry-adopted convention for AI coding agent
instructions, so the full guide now lives there. CLAUDE.md becomes a
symlink to AGENTS.md so Claude Code keeps resolving it by name, and the
previous fallback-summary stub is no longer needed. References in the
PR template, onboarding docs, and agent definitions now point at
AGENTS.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@billadunblock
billadunblock force-pushed the agents-md-source-of-truth branch from 62d178b to ac38cb5 Compare August 29, 2026 19:51
@billadunblock

billadunblock commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator Author

@aram356 Thanks for your review (and precious tokens of course 🤖). I've forced a sync from latest CLAUDE.md and updated the PR. Please assign #1091 to me and I am happy to address in separate PR.

In addition, I'll open separate PR for symlink .claude/skills|agents|etc. to .agents/skills|agents|etc. but want to monitor first symlink a bit in case we receive complaints.

@aram356

aram356 commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

@aram356 Thanks for your review (and precious tokens of course 🤖). I've forced a sync from latest CLAUDE.md and updated the PR. Please assign #1091 to me and I am happy to address in separate PR.

In addition, I'll open separate PR for symlink .claude/skills|agents|etc. to .agents/skills|agents|etc. but want to monitor first symlink a bit in case we receive complaints.

We will fix how to assign tickets to you but in meantime please work on #1091 and #1092

billadunblock and others added 2 commits August 31, 2026 23:14
A checkout with core.symlinks=false (the Git for Windows default)
materializes the CLAUDE.md symlink as a plain text file containing the
literal string "AGENTS.md". If that file is committed, Claude Code
silently loads it as the entire project instructions and operates with
no conventions. Fail CI when the tree entry for CLAUDE.md is not mode
120000, does not point at AGENTS.md, or points at a missing target.

Closes IABTechLab#1091

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MiYh5XY8eN2C9Qd5uVbvqS
The build and check alias blocks already warn that the bare cargo
commands fail at the workspace root, but the test aliases carried no
such caveat. The only copy of that warning lived in the old AGENTS.md
redirect stub, which this branch removes, so restore it alongside the
test aliases in the Testing & Quality section.

Closes IABTechLab#1092

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MiYh5XY8eN2C9Qd5uVbvqS
@billadunblock

Copy link
Copy Markdown
Collaborator Author

@aram356 Thanks for your review (and precious tokens of course 🤖). I've forced a sync from latest CLAUDE.md and updated the PR. Please assign #1091 to me and I am happy to address in separate PR.
In addition, I'll open separate PR for symlink .claude/skills|agents|etc. to .agents/skills|agents|etc. but want to monitor first symlink a bit in case we receive complaints.

We will fix how to assign tickets to you but in meantime please work on #1091 and #1092

Addressed both issue in the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document that bare cargo test fails at the workspace root Guard against CLAUDE.md symlink checking out as a plain text file

2 participants