MODULE 2.2

✂️ 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.

6
Topics
~30
Minutes
Basic
Level
Practice
Type
1

🧳 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.

CLAUDE.md 78 lines all mixed together rules + residue adapt-instructions grep -vE / grep -E AGENTS.proposto.md 71 portable lines git, author, semver, key paths CLAUDE.proposto.md @AGENTS.md + 7 lines AskUserQuestion, plugins, hooks never overwrites the original writes *.proposto.md alongside

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.YY scheme 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

Portable

Holds for any executor; it's about your work.

Residue

Only makes sense inside a specific runtime.

The switch test

"Is it still true with another executor?"

Real ratio

71 portable to 7 residue on this machine.

2

🧪 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.

1

Named tools

AskUserQuestion, Artifact, advisor. Codex doesn't have these tools; citing their names in an AGENTS.md only creates confusion.

2

Plugins

superpowers, context-mode, claude-mem, fable-mindset. A plugin is Claude Code packaging; there's no equivalent concept in Codex CLI.

3

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.

4

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

The cut regex

Eleven terms decide what is residue. It's in the script, you can edit it.

Intent vs name

The intent is almost always portable; the tool name is not.

Line-by-line cut

The script works line by line, without understanding paragraphs.

Proposal

The result calls for human review; it's not a deliverable.

3

⚙️ 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.md or AGENTS.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.md as the first line of the residue.
  • --dry-run cleans up the files it just created.

✗ What it does NOT do

  • Understand paragraphs: the split is line by line, with no context.
  • Rename .proposto.md to the final name — that's on you.
  • Tell intent apart from a tool name.
  • Preserve mentions of CLAUDE.md from other projects (see topic 6).
  • Prove that any agent read the result — that's the readback, in 2.5.

Key concepts

.proposto.md

Output for review, next to the original. You rename it.

--dry-run

Measures the ratio without leaving a file behind.

Idempotent

Running it twice produces the same pair; nothing accumulates.

Scale

165 CLAUDE.md on this machine; start with the 13 trusted ones.

4

🔗 @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.

AGENTS.md portable rules · single source Codex CLIreads directly Gemini CLIreads directly OpenCodereads directly Claude Code CLAUDE.md @AGENTS.md + 7 lines of residue import one source, four readers edit here and they all change together

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

Import (@)

One line pulls another Markdown file into Claude's instructions.

Single source

The rules live in one file only; nobody duplicates them.

Dated backup

Before promoting, keep the original with the date.

Proof of reading

Asking where the rule came from reveals which file was loaded.

5

🧭 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.
1

AGENTS.md

The rules. How to work, what never to do, where things live. The only file the runtime actually loads by itself.

2

context/overview.md

What this project is, who it is for, with which dated facts. Stable: it changes over weeks, not hours.

3

context/current-state.md

Where things stand right now: what already runs, what is broken, what was decided and not yet implemented.

4

tasks/current.md

Goal, owner, definition of done, concrete next action, blockers. One task at a time, with a real file name.

5

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

Nothing auto-loads

Outside of AGENTS.md/CLAUDE.md, nobody opens anything on their own.

Convention

The folder names are an agreement between humans.

Order = trust

The more specific and recent one wins in a conflict.

Injected by the script

Every AGENTS.proposto.md is born with the order at the top.

6

🪤 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

Blind substitution

sed replaces text; it does not understand references.

External reference

A mention of another project's file: it must not change.

Literal path

~/.claude/CLAUDE.md exists on disk; preserve it.

Review before renaming

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

Portable vs residue — the question is "would it still be true with another executor?". In this machine's global CLAUDE.md: 71 portable, 7 residue.
adapt-instructions.sh — generates AGENTS.proposto.md and CLAUDE.proposto.md next to the original and never overwrites anything.
@AGENTS.md — Claude imports the portable part and keeps only the residue; Codex, Gemini and OpenCode read AGENTS.md directly.
Reading order and the sed trap — nothing auto-loads, so write the order at the top; and review every replaced mention before renaming.

Next module:

2.3 — Install the portable core: init-core.sh without overwriting