✂️ CLAUDE.md → AGENTS.md
Portable on one side, residue on the other. Your instructions file has two natures mixed together: rules that hold for any agent, and commands only Claude Code understands. In this module you separate the two with adapt-instructions.sh, review the cut by hand, and let Claude keep reading everything through an @AGENTS.md.
🧳 What is portable in an instruction
Open your CLAUDE.md and read it line by line asking a single question: would this sentence still be true if the executor were Codex, Gemini CLI or a local model? If the answer is yes, the line is portable. It speaks about your world — the way you publish, your paths, your conventions — and not about the program that is reading it.
In this machine's global CLAUDE.md, the overwhelming majority of the file is portable. Rules like "publishing = commit + push to git, never poke Vercel directly", "the commit author follows the repo's target GitHub account", "semver versioning vX.XX.YY: minor bumps the XX and carries the YY, never resets it", "API keys always in ~/projetos/openpcbotv2/.env or ~/projetos/wifi/.env, load at runtime and never print the value" — none of them mentions Claude. They are work policy. Any agent that reads them behaves better.
Look at the two numbers on the right: in this machine's global CLAUDE.md the cut produced 71 portable lines versus 7 of residue. Almost everything you wrote was never about Claude — it was about your work.
✓ Portable (goes into AGENTS.md)
- ✓Publishing rules: "publishing = commit + push; the deploy belongs to the webhook, not to me".
- ✓Commit authorship: which account and which e-mail for each target repository.
- ✓Versioning: the
vX.XX.YYscheme and when each digit resets to zero. - ✓Paths: where the keys live, where the artifacts go, where the portal lives.
- ✓Language, tone and expected response format.
✗ Not portable (stays in the residue)
- ✗Names of exclusive tools:
AskUserQuestion,Artifact,advisor. - ✗Plugin names:
superpowers,context-mode,claude-mem. - ✗Hook configuration and precedence over hook injections.
- ✗Slash commands that only exist in one runtime (
/code-review). - ✗Any secret value — that goes nowhere at all.
💡 New here?
Runtime is the program that executes the agent: Claude Code, Codex CLI, Gemini CLI, OpenCode. Instruction is the Markdown file the runtime reads before acting — CLAUDE.md in Claude, AGENTS.md in the rest. Portable means the text doesn't depend on which program is reading it. Residue is what's left after you remove the portable part: small, specific and disposable when you switch executors.
Key concepts
Holds for any executor; it's about your work.
Only makes sense inside a specific runtime.
"Is it still true with another executor?"
71 portable to 7 residue on this machine.
🧪 What Claude residue is
Residue is not garbage. These are legitimate, useful instructions — they're just tied to one program. The kit's script recognizes residue through a list of keywords, which is literally a regular expression inside the file: AskUserQuestion, superpowers, context-mode, fable-mindset, claude-mem, ultrareview, /code-review, Artifact, advisor, plugin and hook. Every line matching one of these terms goes to the residue; all the others go to the portable file.
# inside scripts/adapt-instructions.sh — the cut rule, in one line:
CLAUDE_ONLY='AskUserQuestion|superpowers|context-mode|fable-mindset|claude-mem|ultrareview|/code-review|Artifact|advisor|plugin|hook'
Notice what this implies. The rule "never use AskUserQuestion (interactive menu), always ask in free text" is residue because of the tool name — but the intent ("I prefer to answer in text, not pick from a menu") is portable. The script can't tell intent from name: it cuts by word. That's why the result is a proposal, not a final file. When you review it, rewrite the intent in neutral language and leave the tool name in the residue.
🎯 See the residue before cutting
Goal: find out, without writing anything, how many lines of your file are Claude-specific and which ones they are.
cd ~/projetos/<your-project>
# how many lines in total
wc -l CLAUDE.md
# which lines are residue (same regex as the script)
grep -nE 'AskUserQuestion|superpowers|context-mode|fable-mindset|claude-mem|ultrareview|/code-review|Artifact|advisor|plugin|hook' CLAUDE.md
How to check: add up the lines grep showed and compare with wc -l. In the global CLAUDE.md on this machine the result was 7 residue out of 78 lines — 71 portable. If in your project the residue exceeds a third of the file, there's probably tool configuration where there should be work rules.
Named tools
AskUserQuestion, Artifact, advisor. Codex doesn't have these tools; citing their names in an AGENTS.md only creates confusion.
Plugins
superpowers, context-mode, claude-mem, fable-mindset. A plugin is Claude Code packaging; there's no equivalent concept in Codex CLI.
Hooks and precedence
Rules like "this file wins over whatever the hook injects". They make sense where a session hook exists; in Codex, SessionStart doesn't even exist.
Slash commands
/code-review, /formato-curso-v5. Slash routing is an interface convention, not content. Translate it to the skill name when migrating.
Key concepts
Eleven terms decide what is residue. It's in the script, you can edit it.
The intent is almost always portable; the tool name is not.
The script works line by line, without understanding paragraphs.
The result calls for human review; it's not a deliverable.
⚙️ adapt-instructions.sh and the .proposto.md files
The script takes a project folder and looks for a CLAUDE.md inside it. If it doesn't find one, it says so and exits with code 0 — that's not an error, it's "nothing to adapt". If it does find one, it writes two files next to the original, with the suffix .proposto.md. That detail is the safety guarantee of the whole module: the script never overwrites anything. You read, fix, and only then rename by hand.
🎯 Generate the pair of proposals
Goal: produce AGENTS.proposto.md and CLAUDE.proposto.md in a project of yours, without touching the original file.
cd ~/projetos/agente-claude-codex
# 1. rehearsal: generates, shows the counts and deletes the files
scripts/adapt-instructions.sh ~/projetos/<your-project> --dry-run
# 2. for real: leaves the two .proposto.md in the project folder
scripts/adapt-instructions.sh ~/projetos/<your-project>
# Proposed (review and rename manually):
# ~/projetos/<your-project>/AGENTS.proposto.md (71 lines)
# ~/projetos/<your-project>/CLAUDE.proposto.md (7 lines)
# 3. see what changed before accepting
diff ~/projetos/<your-project>/CLAUDE.md \
~/projetos/<your-project>/AGENTS.proposto.md | head -40
How to verify: the original CLAUDE.md remains identical (git status shows no modification to it, only two new untracked files). The two counts added together, plus the header the script adds, roughly match the original's total.
💡 Practical tip
Always run --dry-run first. It generates, prints the two counts and then removes the files. You learn the project's portable/residue ratio without cluttering the folder — useful when you're going to sweep dozens of projects to decide where to start.
This is worth scaling up. On this machine, 165 projects have a CLAUDE.md, 54 already have an AGENTS.md and 39 have both. In other words: 15 projects have AGENTS.md without CLAUDE.md (born portable) and 126 are still tied to a single runtime. On top of that, 13 projects marked as trusted in Codex have no AGENTS.md — those are the obvious pilot candidates, because Codex can already work in them but doesn't yet know the rules.
✓ What the script guarantees
- ✓Never overwrites an existing
CLAUDE.mdorAGENTS.md. - ✓Exits with code 0 and a clear message when there's nothing to adapt.
- ✓Always inserts the reading order at the top of the portable file.
- ✓Puts
@AGENTS.mdas the first line of the residue. - ✓
--dry-runcleans up the files it just created.
✗ What it does NOT do
- ✗Understand paragraphs: the split is line by line, with no context.
- ✗Rename
.proposto.mdto the final name — that's on you. - ✗Tell intent apart from a tool name.
- ✗Preserve mentions of
CLAUDE.mdfrom other projects (see topic 6). - ✗Prove that any agent read the result — that's the readback, in 2.5.
Key concepts
Output for review, next to the original. You rename it.
Measures the ratio without leaving a file behind.
Running it twice produces the same pair; nothing accumulates.
165 CLAUDE.md on this machine; start with the 13 trusted ones.
🔗 @AGENTS.md: Claude importing the portable file
The question everyone asks at this point: "if I pull the rules out of CLAUDE.md, does Claude stop knowing them?". No. Claude Code understands an import line: an @ followed by the path of another Markdown file pulls that file's contents into the instructions. So the new CLAUDE.md starts with @AGENTS.md and continues with the seven lines of residue. Claude reads both. Codex reads only the AGENTS.md. Neither one loses anything that concerns it.
Compare the two sides: on the right, three runtimes reading the file directly; on the left, Claude reaching the same file through the dashed import arrow. What matters is that there is a single central block — if there were two, you'd have two truths to maintain.
🎯 Accept the proposals safely
Goal: promote the .proposto.md files to real files, keeping the original as a dated backup.
cd ~/projetos/<your-project>
# 1. back up the original, with the date in the name
cp CLAUDE.md CLAUDE.md.bak-$(date +%Y%m%d)
# 2. promote the ALREADY REVIEWED proposals
mv AGENTS.proposto.md AGENTS.md
mv CLAUDE.proposto.md CLAUDE.md
# 3. the new CLAUDE.md must start with the import
head -1 CLAUDE.md
# @AGENTS.md
How to verify: open a new Claude session in that folder and ask "quote the commit authorship rule and tell me which file it came from". The answer must cite AGENTS.md. If it cites CLAUDE.md, the import was not resolved — check that the path is right and that the @ is on the first line.
Key concepts
One line pulls another Markdown file into Claude's instructions.
The rules live in one file only; nobody duplicates them.
Before promoting, keep the original with the date.
Asking where the rule came from reveals which file was loaded.
🧭 Explicit reading order at the top
Here is the detail that separates a workspace that works from one that only looks organized: nothing auto-loads. The runtime reads the instruction file — and that's it. The context/, tasks/ and handoffs/ folders are a human convention; no program will open them on its own. If you want the agent to read them, you write that it must, at the top of AGENTS.md. That is why the script injects this line automatically into every portable file it generates.
# AGENTS.md — portable project instructions
> Reading order for any agent: 1) this file, 2) context/overview.md,
> 3) context/current-state.md, 4) tasks/current.md, 5) handoffs/latest.md.
> These names are a convention: nothing is loaded automatically outside of
> AGENTS.md/CLAUDE.md.
AGENTS.md
The rules. How to work, what never to do, where things live. The only file the runtime actually loads by itself.
context/overview.md
What this project is, who it is for, with which dated facts. Stable: it changes over weeks, not hours.
context/current-state.md
Where things stand right now: what already runs, what is broken, what was decided and not yet implemented.
tasks/current.md
Goal, owner, definition of done, concrete next action, blockers. One task at a time, with a real file name.
handoffs/latest.md
What the last session did and what the next one needs to know. It is the bridge between runtimes: Claude writes, Codex picks up.
💡 Practical tip
Order is a hierarchy of trust, not just a sequence. When tasks/current.md contradicts overview.md, the one that is wrong is the overview — it has aged. Write this into AGENTS.md: "in case of conflict, the more specific and more recent one wins, and report the conflict instead of choosing silently". An agent that points out a contradiction is worth more than an agent that guesses.
Key concepts
Outside of AGENTS.md/CLAUDE.md, nobody opens anything on their own.
The folder names are an agreement between humans.
The more specific and recent one wins in a conflict.
Every AGENTS.proposto.md is born with the order at the top.
🪤 The sed trap
When building the portable file, the script does two things: it filters out the residue lines and, on what remains, runs sed 's/CLAUDE\.md/AGENTS.md/g'. The replacement is global and blind. It does not distinguish "the CLAUDE.md of this project" from "the CLAUDE.md of that other project" — and the second mention should not change, because that other project still has a real CLAUDE.md on disk. The script's own header warns about this in a comment line.
# what the script does with the portable part:
grep -vE "$CLAUDE_ONLY" "$SRC" | sed 's/CLAUDE\.md/AGENTS.md/g'
# before (correct):
# See the portal's `CLAUDE.md` for the update step by step.
# Each project can have its own `CLAUDE.md` saying which account to use.
# after (broken — these files do not exist):
# See the portal's `AGENTS.md` for the update step by step.
# Each project can have its own `AGENTS.md` saying which account to use.
⚠️ Why this really hurts
An agent that reads "see the portal's AGENTS.md" will try to open ~/projetos/portal/AGENTS.md. The file does not exist. From there it does one of two bad things: it invents the content, or it declares that there are no instructions for the portal and carries on without them — which is exactly the scenario where the commit goes out with the wrong author. A harmless text substitution became a lost rule.
🎯 Review the sed before renaming
Goal: list every mention that sed replaced and decide, one by one, whether the replacement was right.
cd ~/projetos/<your-project>
# 1. where the original talked about CLAUDE.md
grep -n 'CLAUDE\.md' CLAUDE.md
# 2. where the proposal now talks about AGENTS.md
grep -n 'AGENTS\.md' AGENTS.proposto.md
# 3. the two lists side by side: every extra line is a replacement to check
diff <(grep -c 'CLAUDE\.md' CLAUDE.md) <(grep -c 'AGENTS\.md' AGENTS.proposto.md)
# 4. revert a mention that belonged to ANOTHER project
sed -i 's|AGENTS.md do portal|CLAUDE.md do portal|' AGENTS.proposto.md
How to verify: after step 4, grep -n 'do portal' AGENTS.proposto.md cites CLAUDE.md again. Rule of thumb: every mention that comes with a project name ("do portal", "do inemavox", "de cada projeto", i.e. "the portal's", "inemavox's", "each project's") is an external reference and must be reverted; standalone mentions ("this file", "this repo's CLAUDE.md") are internal and the replacement is correct.
✓ Correct replacement
- ✓"the rules in this CLAUDE.md" → refers to the local file, which became AGENTS.md.
- ✓"write it in the current project's CLAUDE.md" → the current one is precisely the one you migrated.
- ✓Section titles that name the file itself.
✗ Replacement to revert
- ✗"the portal's CLAUDE.md" → another repository, which was not migrated.
- ✗"each project may have its own CLAUDE.md" → refers to third-party projects.
- ✗Literal paths such as
~/.claude/CLAUDE.md— it is a real path on disk. - ✗Quotes from external documentation that use Claude's file name.
💡 Practical tip
When you finish the review, log the round: one line in FALHAS.md if something broke ("the sed replaced the reference to the portal's CLAUDE.md; smallest fix: revert the line; category: prompt") and a paragraph in handoffs/latest.md saying which projects already have a promoted AGENTS.md. Without that, two weeks from now you will not remember which of the 165 projects have already been through this.
Key concepts
sed replaces text; it does not understand references.
A mention of another project's file: it must not change.
~/.claude/CLAUDE.md exists on disk; preserve it.
The proposal only becomes the file after you have read it.
Self-check (optional): AGENTS.proposto.md ended up with the sentence "see the portal's AGENTS.md to update the card". What should you do?
🎯 Module summary
AGENTS.proposto.md and CLAUDE.proposto.md next to the original and never overwrites anything.Next module:
2.3 — Install the portable core: init-core.sh without overwriting