Reduce a project's project context into "AGENTS.md as the single source of truth (SSOT), compatible with multiple agents”——CLAUDE.md
or an existing AGENTS.md converge via two paths into the same tool-agnostic AGENTS.md, with each agent loading it through its own entry point
(the ones that natively read AGENTS.md / those via the thin shell CLAUDE.md → @AGENTS.md ), without having to maintain two copies
Design and Rationale
The core is to make AGENTS.md the single source of truth: all project context is maintained in only one place here, andCLAUDE.md degenerates into the
thin shell that imports it (plus a small number of Claude-specific escape hatches).AGENTS.md is the de facto standard across agents—agents that natively read it allnatively recognize,
with no extra configuration required; agents that do not natively read AGENTS.md import the same content via the thin shell CLAUDE.md → @AGENTS.md ,
and supportrecursion @import, so the @MEMORY/MEMORY.md inside AGENTS.md will also be automatically expanded
The L2 memory layer uses @MEMORY/MEMORY.md to consolidate(R2): AGENTS.md introduces the index in a single line + a mandatory Read instruction at the topto handle both
categories of agents, expanded or not—one general rule, not tied to any specific agent, with no separate per-section guidance; for why the index is not inlined into the body, and how expansion behavior is classified, see the full rationale in ref/layering.mdthe "L2 Index Consolidation" section
Memory travels with the repo(R6): the source of truth for cross-session memory is the repo root MEMORY/; writing to agent-private memory is forbidden; before migration, when there is no
MEMORY/ , create a minimal MEMORY/MEMORY.md index under the repo, without skipping or omitting the memory section (see R6 for the three hard problems with private paths)
The complete layered model (L1 resident / L2 memory) andsection layering decision treeare in ref/layering.md
—read it when classifying sections in Step 1; for rewrite rules R1–R6 + the path 2 diagnostic checklist, see
ref/rewrite-rules.md—execute by reference during Step 2 / 3 / 4 (generating AGENTS.md / MEMORY / thin shell)
Compatibility matrix (classified by loading behavior, without naming each vendor—whether or not it automatically expands @import is already handled by the mandatory Read instruction at the top):
| Layer | Agents that natively read AGENTS.md | Agents via the thin shell CLAUDE.md → @AGENTS.md agent |
|---|---|---|
| L1 body | Natively read | Imported via the thin shell @AGENTS.md introduces |
| L2 memory index | @MEMORY/MEMORY.md one line; the mandatory Read instruction at the top handles whether or not it is expanded |
Same as left (equivalent effect after the thin shell recursively expands) |
| L2 memory body | Read on demand | Read on demand |
| Trigger-based rule | Not involved (read in full); this skill does not generate some agents' own trigger-based rule directories | Same as left |
Thin shell structure + information flow:
AGENTS.md 唯一真源(工具无关,人工维护的唯一目标)
└── ## 跨会话记忆(索引) @MEMORY/MEMORY.md(顶部强制 Read 指令兜底不展开 @import 的 agent)
CLAUDE.md 薄壳(自动生成,不需要人工维护)
├── @AGENTS.md 引入全部共用内容(递归展开里面的 @MEMORY/MEMORY.md)
└── <!-- Claude Code 专属 --> 几行无法泛化的工具绑定内容(如有)
Inputs and Outputs
Input
| Input | Required | Description |
|---|---|---|
| Project root | is | the default cwd; one of two paths: contains CLAUDE.md / contains AGENTS.md(if neither → first use /init) |
MEMORY/ |
No | if it exists, de-brand it as well (Step 3 MEMORY) + add to AGENTS.md @MEMORY/MEMORY.md; if it does not exist, create it under the repo (R6) |
| Source file snapshot | Automatic | Step 1 snapshot the source (CLAUDE.md / AGENTS.md) to .migration-backup/(temporary directory), for Step 5 coverage comparison; delete once verification passes |
Output
<project-root>/
├── AGENTS.md 新/改:工具无关真源(原生读 / 经薄壳 CLAUDE.md 引入),
│ 含“## 跨会话记忆(索引)”段:@MEMORY/MEMORY.md(顶部强制 Read 指令在文件顶部)
├── CLAUDE.md 薄壳(@AGENTS.md + <!-- Claude Code 专属 --> 逃生舱)——让 Claude Code 也
│ 加载同一份 AGENTS.md(含递归 @MEMORY/MEMORY.md 展开);有现有 CLAUDE.md
│ 则改写,纯 AGENTS.md 项目则新建最小薄壳
└── MEMORY/ 新/改:存在则 MEMORY.md + 各 slug 正文按 R1 去品牌;不存在则建最小 MEMORY.md(R6)
Two paths (pre-check routing)
precheck.py detects the project state and routes to one of two reduction paths—the twoshare the latter half(de-branding R1 + R3–R5 + L2 via
@MEMORY/MEMORY.md 's R2 + coverage verification), only the former half (source extraction) differs:
| Project state | Path | Former half (source extraction) |
|---|---|---|
Has CLAUDE.md, no AGENTS.md |
1 Migration | Scan CLAUDE.md section classification → de-brand (existing flow) |
Has AGENTS.md(possibly +CLAUDE.md) |
2 Normalization | Diagnose the existing AGENTS.md (brand remnants? memory section form?) + merge and coexist with CLAUDE.md, let the user adjudicate conflicts; see the checklist in ref/rewrite-rules.md |
| Neither (bare project) | Hard block | Out of scope for this skill—first use the agent's /init to generate an initial CLAUDE.md / AGENTS.md and come back |
Both converge to the same tool-agnostic AGENTS.md SSOT, and produce a CLAUDE.md thin shell so that agents that do not natively read AGENTS.md also load the same content
Execution principles
- Only touch context files(
CLAUDE.md/AGENTS.md/MEMORY/)—do not touch migration permissions (e.g..claude/settings.local.json), MCP configuration, the target project'sscripts//references/, or other non-context files - Do not delete
CLAUDE.md—this skill keeps a thin shell coexisting; complete deletion requires explicit user confirmation - Do not generate agent-specific trigger-style rule files(e.g.
.qoder/rules/)—most are undocumented officially; leave it to the user to configure in the target agent IDE
Rewrite rules R1–R6 (summary)
- R1 Tool-agnosticization: de-brand, do not change facts. For the complete replacement table (
Claude Code→AI coding agent、claude -p→agent CLI, etc., including the "when to keep tool names" criterion) seeref/rewrite-rules.md— refer to it when rewriting in Step 2 / 3 - R2 Memory index
@importconsolidation: AGENTS.md's## 跨会话记忆(索引)section uses a single-line@MEMORY/MEMORY.mdintroduction index—do not expand; agents of@importare covered by AGENTS.md top mandatory Read instructionas a fallback (seelayering.mdskeleton), and no separate guidance is attached within the section.Do notinline the index line—for the rationale see the above section 's L2 memory layer section (Step 2 references the same R2 template) - Unified memory writing (default, see R6): R2 solvesreadunification;Writeunified (agent writes new memories to
MEMORY/rather than private memory) is the default, and together with repo-local + existence it is consolidated into R6 (no private memory + minimalMEMORY.mdtemplate + write specification). Seeref/rewrite-rules.mdR6 - R3 line width unchanged: keep the original line width constraint (e.g.
.markdownlint.jsoncMD013) — full constraints seeref/rewrite-rules.mdR3 - R4 MEMORY rewrite: MEMORY body is de-branded per R1, directory structure / file count unchanged (only wording changed, no merging / splitting /
deleting entries) — full constraints see
ref/rewrite-rules.mdR4 - R5 escape hatch: tool-specific content that cannot be generalized (e.g. script hardcoded
claude -psubprocess), write the generalized version in AGENTS.md, append the specific implementation at the end of the CLAUDE.md thin shell.Criterion: if after removing the tool name the reader cannot perform the operation → goes into the escape hatch - R6 MEMORY repo repo-local + existence: cross-session memory source of truth = repo root
MEMORY/, writing agent private memory is forbidden (~/.claude/...). If there is noMEMORY/before migration → createMEMORY/MEMORY.mdminimal index under the repo (do not skip, do not omit the memory section); the "repository specification" section includes the write specification by default. Full constraints + template seeref/rewrite-rules.mdR6
Runtime constraints
- Idempotent: repeated runs overwrite existing
AGENTS.md, no duplicate files are produced;.migration-backup/is a temporary snapshot directory, deleted at the end of Step 5, not left in the project
Workflow
Throughout the whole process: two places, the classification table (Step 1) and the escape hatch content (Step 4)interactive confirmation points, do not decide silently
Step 0: Pre-check + path determination (run tools/precheck.py, from the skill root)
python3 tools/precheck.py <project-root>
Report the project status and determine the path according to the routing table above; also report whether MEMORY/ exists.Path 2 modify existing AGENTS.md
(normalize / merge coexisting CLAUDE.md) stop and let the user confirm the merge strategy, never overwrite silently
Step 1: Snapshot + source extraction (branch by path)
- Snapshot source files to
.migration-backup/(path 1 snapshotCLAUDE.md; path 2 snapshot originalAGENTS.md, and when coexistingCLAUDE.mdalso snapshot it) — needed for the Step 5 coverage comparison, this is theonly chance; this directory is for temporary use only, deleted at the end of Step 5 - Extract source content by path:
- Path 1: parse
CLAUDE.mdall##sections, runref/layering.mdlayered decision tree - Path 2: for existing
AGENTS.mdrunref/rewrite-rules.md'snormalization diagnostic checklist (brand remnants? any L2 memory inlined? any MEMORY support?); ifCLAUDE.mdcoexists, also parse and merge according to the layered decision tree
- Path 1: parse
- Output the classification / diagnostic table,show it to the user for confirmation / adjustmentthen continue
Step 2: Generate AGENTS.md (LLM, core step)
- According to
ref/layering.mdAGENTS.md skeleton organizes L1 content (project positioning / repository conventions / common commands / high-level structure / notes)- Path 1: de-brand CLAUDE.md paragraphs and rewrite them into the skeleton
- Path 2: normalize on the basis of the existing AGENTS.md (change the memory section to
@MEMORY/MEMORY.md, remove brand remnants, merge and deduplicate CLAUDE.md content), and let the user adjudicate conflicts in wording
- add the
## 跨会话记忆(索引)section (R2):single line@MEMORY/MEMORY.md—no further in-section guidance is attached within the section (do not expand@importagents are covered by the forced Read instruction at the top).when there is noMEMORY/, first createMEMORY/MEMORY.mdunder the repo as a minimal index (R6), then place this section. For the complete section template, seeref/rewrite-rules.mdR2 - apply R1 (de-branding) + R3 (line width)
- control the L1 body word count (for the budget + memory index exclusion rules, see
ref/layering.md); if exceeded, push detailed content down to L2 (MEMORY/) - self-check:
grep -iE "claude code|\.claude/" AGENTS.mdshould have no matches (de-branding passed)grep -nE '^@MEMORY/MEMORY\.md$' AGENTS.mdshould have 1 matching line (R2 reference; MEMORY/ now exists by default, see R6)- there should be a forced Read instruction blockquote at the top (after H1, before the first
##; containing@+ Read characteristics—required for all AGENTS.md)
Step 3: MEMORY (LLM)—if it exists, de-brand it; if not, create the repo
- Exists: apply R4—de-brand the MEMORY body per R1; the directory structure / file count stays unchanged. Self-check
grep -riE "claude code|Claude Code|\bCC\b" MEMORY/should have no matches (\bCC\bavoids false hits on abbreviations) - Does not exist: apply R6—create a new
MEMORY/MEMORY.mdminimal index under the repo (for the template, seeref/rewrite-rules.mdR6). A new file has no brand to remove; just create the repo
Step 4: generate the CLAUDE.md thin shell
so that agents that do not natively read AGENTS.md (loaded via CLAUDE.md ) can also use the same copy: if there is an existing CLAUDE.md(Path 1; Path 2 coexisting scenario), rewrite it as a thin shell;
for a pure AGENTS.md project (Path 2 has no CLAUDE.md), create a new minimal thin shell. Follow the ref/rewrite-rules.md
thin shell template: a “thin shell declaration” at the top (stating that AGENTS.md is the single source of truth and that shared parts must not be edited here) + a @AGENTS.md +
<!-- Claude Code 专属 --> escape hatch (TOOL_SPECIFIC content identified in Step 2, handled per R5). If there is no escape hatch content, omit the comment block.
Show the escape hatch content to the user for confirmation. self-check criteria (line count limit,@AGENTS.md exists, thin shell declaration, no large body text) are in
ref/rewrite-rules.md thin shell verification section
Step 5: coverage verification (run tools/coverage.py, from the skill root)
python3 tools/coverage.py <project-root>
take the original CLAUDE.mdfrom the Step 1 snapshot, compare line by line by token against AGENTS.md + thin shell CLAUDE.md
(built-in de-branding normalization, so that after Claude Code→agent it can still match), and output the list of unmatched lines + coverage %.
Unmatched lines ≠ definitely lost—they may be de-branding rewrites or reasonable pushdowns; confirm with the user item by item whether they were lost or rewritten.
100% coverage is the goal. Finally run markdownlint to check that all new / modified files have 0 errors
cleanup and delete .migration-backup/: after all flags are confirmed item by item + markdownlint 0 error, the snapshot's mission is complete—
rm -rf .migration-backup/, do not leave temporary directories in the user's project (the original git project text can be restored from history at any time).
If there are unresolved flags / the user still needs to roll back and compare, keep them for now, and delete them after the next round of verification passes
Reference example
End-to-end minimal example (path 1 migration). Input: the project root has only one CLAUDE.md
User: "This project only has CLAUDE.md, help me migrate it to AGENTS.md that multiple agents can read"
precheck.pyreport [path 1] → snapshotCLAUDE.mdto.migration-backup/(Step 1)- classify paragraphs according to the hierarchical decision tree → de-brand (R1) and write into the AGENTS.md skeleton, attach
@MEMORY/MEMORY.md(R2)- none
MEMORY/→ create minimalMEMORY/MEMORY.md(R6)- generate thin shell
CLAUDE.md(@AGENTS.md+ escape hatch comment block, Step 4 shows confirmation)coverage.pycompare 100% target → markdownlint 0 error →rm -rf .migration-backup/