🧱 Install the portable core
You already have a portable AGENTS.md (module 2.2). Now comes the structure that carries the context: context/, tasks/, handoffs/. A script copies the skeleton without overwriting anything, you fill it in with dated facts, and a test in an isolated clone proves the project works on its own.
🧱 init-core.sh: created vs kept
The portable core is the skeleton folder the kit calls template/: AGENTS.md, CLAUDE.md, README.md, context/, tasks/, handoffs/, .agents/skills/ and scripts/check.sh. The init-core.sh script copies that skeleton into your project with a single rule: it never overwrites what already exists. Every file comes out marked as [criado] (created) or [mantido] (kept).
The big box is your project. The blue files are instructions and human reading; the cyan folders hold the content that travels between runtimes. These names are a kit convention, no runtime loads them on its own: it is the AGENTS.md that says to read them.
💻 Copy-run example: install the core
Goal: copy the skeleton into a project of yours without touching anything that already exists.
cd ~/projetos/agente-claude-codex
scripts/init-core.sh ~/projetos/<your-project>
How to verify: the output lists each file with one of two labels. In a project that already had a README and a CLAUDE.md, the expected result looks like this:
[created] AGENTS.md
[kept] CLAUDE.md
[kept] README.md
[created] context/overview.md
[created] context/current-state.md
[created] context/sources.md
[created] context/decisions/0000-00-00-modelo.md
[created] tasks/current.md
[created] handoffs/latest.md
[created] .agents/skills/.gitkeep
[created] scripts/check.sh
Now fill in: ~/projetos/<your-project>/AGENTS.md, context/overview.md, tasks/current.md
Why "kept" matters: the first version of the kit suggested cp -r template/. projeto/, which would wipe out a project's real README and CLAUDE.md. The script was born to close exactly that hole. Every step of the kit needs to be reversible, and overwriting is not.
Key concepts
The minimum set of files that makes a project understandable by any runtime.
The source of the skeleton, inside the kit.
The script's contract: creates what is missing, respects what exists.
The names only work because AGENTS.md tells the agent to read them.
📅 Fill in overview.md with dated facts
The skeleton is there, but empty. The first file to fill in is context/overview.md: what the project is, who it is for, and the verified facts. Every fact carries a source and a date, because an agent that reads "the server runs on port 8000" needs to know whether that was true yesterday or a year ago. The template already ships the header with ID, scope, source, observation date, status and "review on".
✓ Well-written fact
- ✓"Codex CLI 0.154.0 has no
importcommand; the one-click import is only in the desktop app." (source:codex --help, 2026-09-13) - ✓"MCP in Claude: magnific, metricool. In Codex: none." (source: audit.sh, 2026-09-13)
- ✓A separate section for "Hypotheses (unverified)": "the heuristic classification of 71 skills is correct for most of them".
✗ Fact that will mislead the agent
- ✗"Codex has import." No date, no source, and already false in the CLI.
- ✗"I prefer flux2-klein" mixed in with technical facts: a preference disguised as a fact.
- ✗Copying the 869 files from Claude's memory into the overview. That is raw material, not a source.
📄 The kit's real overview (abridged)
# Overview — agente-claude-codex
- ID: overview | Scope: this repo | Source: docs/ (3 texts + PDF) and local audit
- Date: 2026-09-13 | Status: accepted | Review: when the Codex or Claude Code version changes
## What it is
Migration/agnosticism kit: audit and adaptation scripts + portable core template.
## Verified facts (2026-09-13)
- Codex CLI 0.154.0 has no `import` command; the "one-click" import belongs to the desktop app.
- Claude Code 2.1.270 with 116 skills; Codex with 27.
- MCP in Claude: magnific, metricool. In Codex: none.
## Hypotheses (unverified)
- The heuristic classification of 71 skills as "reusable" is correct for most of them.
Practical tip: the line "Review: when the Codex version changes" is a refresh trigger. Without it, the overview ages in silence and the agent starts quoting dead facts with the same confidence as live ones.
Key concepts
Statement + source + observation date.
draft / accepted / revoked; the agent knows what to trust.
What you think, kept away from what you verified.
When the fact should be checked again.
🎯 tasks/current.md: goal, owner, criterion, next action
The overview says what the project is. The tasks/current.md says what is being done right now. It is the file a new session reads to know where to pick up, and it is also what the readback test (module 2.5) will demand: "what is the goal and what is the next concrete action?". Five fields, always the same: goal, owner, verifiable done criterion, next action, blockers.
📄 Filled-in example: the kit's own tasks/current.md
# Current task
- Goal: validate the pilot — `session-handoff` skill ported to Codex via polyskill
and readback passing on both runtimes.
- Owner: Nei (decides pilot and skills); the agent executes.
- Done criterion: `scripts/readback-test.sh . both` produces answers that cite
AGENTS.md/tasks/handoffs in both; `scripts/sync-skills.sh drift` with no DRIFT.
- Next concrete action: Phase 0 of the plan — `scripts/adapt-instructions.sh ~/.claude`,
review, write `~/.codex/AGENTS.md`, readback in `~/projetos/wifi`.
- Blockers: none.
Notice: the done criterion is a command with an observable result, not "when it feels good". The next action starts with a verb and names the exact script.
Goal
One sentence. If you need two, it is two tasks.
Owner
Who decides and who executes. The human defines, the agent marks.
Done criterion
A command or an observation that any runtime can reproduce.
Next concrete action
Verb + file or command. It is what the new session does first.
Blockers
What only the owner can decide. "None" is also an answer.
Key concepts
The agent understands the current work, not just the history.
A command with expected output, never a feeling.
Keeps the agent from deciding what belongs to the human.
Always the same; the readback depends on it.
📜 First decision in context/decisions/
A decision is different from a fact. A fact is verified; a decision is accepted. That is why each decision becomes its own file in context/decisions/, with the date in the name, a status (proposed, accepted, revoked), context, the decision itself and the consequences. When two files disagree, the accepted decision beats the more recent one. This solves the classic problem: "which of the versions is the right one?".
📄 The kit's first real decision
# context/decisions/2026-09-13-docs-fora-do-git.md
# Decision: docs/ stays out of git
- Date: 2026-09-13 | Status: proposed (awaiting owner) | Source: repo creation session
## Context
docs/ contains a translated post and a third-party prompt library. Publishing it in a
public repo redistributes that material.
## Decision
`.gitignore` excludes docs/ until the owner chooses: private repo, or keep only
our own rewrites.
The status was left as "proposed" on purpose: the agent proposed, the owner has not yet made the final call. In the readback, Codex pointed out exactly that: "there is no accepted decision, only a proposal". That was the correct reading.
✓ Becomes a decision
- ✓"Secrets live in
.envand are referenced, never copied." - ✓"Adapter skills only go into Codex after the MCP is registered."
- ✓"Commit author follows the destination account."
✗ Not a decision
- ✗"Codex has 27 skills." That is a fact; it goes in the overview.
- ✗"Run sync-skills tomorrow." That is a next action; it goes in tasks.
- ✗"I think polyskill will work." A hypothesis; overview, its own section.
Conflict rule: when an old handoff says A and an accepted decision says B, B wins. A newer timestamp does not win; origin and acceptance win. It is the same logic as the superseded_by you will see in Project 3 of Track 3.
Key concepts
One file per decision, with an explicit status.
Where it came from and who accepted it beat the date.
The agent proposes; the owner accepts. Never the other way around.
YYYY-MM-DD-subject.md: sorts itself.
✅ scripts/check.sh: the minimum verification
The template ships with an eight-line script that answers a single question: do the required files exist and are they non-empty? It seems like little, but it is the difference between "I think I filled it in" and "it is filled in". It checks AGENTS.md, README.md, the four in context/, tasks/current.md and handoffs/latest.md, and exits with code 1 if any of them is missing.
💻 Copy-run example: run the check
Goal: confirm that the core is complete before any readback.
cd ~/projetos/<your-project>
bash scripts/check.sh; echo "exit=$?"
How to verify: all [ok] and exit=0. A [FALTA] means a file is missing or empty, and the exit becomes 1, so you can use it in a pipeline.
[ok] AGENTS.md
[ok] README.md
[ok] context/overview.md
[ok] context/current-state.md
[ok] context/sources.md
[ok] tasks/current.md
[ok] handoffs/latest.md
exit=0
🔍 The whole script, so you can see there is no magic
#!/usr/bin/env bash
set -e; cd "$(dirname "$0")/.."
for f in AGENTS.md README.md context/overview.md context/current-state.md \
context/sources.md tasks/current.md handoffs/latest.md; do
[ -s "$f" ] && echo "[ok] $f" || { echo "[FALTA] $f"; rc=1; }
done; exit ${rc:-0}
The -s tests "exists and has a size greater than zero". A template that was copied but not filled in still passes; that is why the check is minimal, and the readback in module 2.5 is the real test.
Practical tip: add to the check whatever is specific to your project (build, tests, lint). The kit keeps the file short on purpose: it is yours to extend.
Key concepts
Exists and is not empty; nothing beyond that.
0 passed, 1 missing; useful for automation.
Add the project's real checks.
A file existing ≠ the agent having used it. That is the readback.
📦 Isolated clone: does the project work on its own?
Here is the most common trap of a "portable" workspace: it works on your machine because it depends on a neighboring folder, on a ../../knowledge, on a symlink to ~/.claude. Prompt B explicitly requires: copy or clone the project by itself into a clean place and verify the files and commands. If the check passes in the clone, the essential context is inside the project. If it does not pass, you have found a hidden dependency.
On the left the project "works" because it leans on things outside it (gray dashed lines). On the right, in the clone, only what was committed exists. If the check passes here, the context is truly portable.
💻 Copy-run example: the isolated clone test
Goal: prove that the core survives outside your original folder. Uses the repo itself as the clone source, no network.
cd ~/projetos/<your-project>
git add -A && git commit -m "portable core" # the clone only sees what is committed
rm -rf /tmp/clone && git clone -q . /tmp/clone
bash /tmp/clone/scripts/check.sh; echo "exit=$?"
How to verify: seven [ok] and exit=0. This is exactly the test the kit ran on 2026-09-13 and passed. If a [FALTA] shows up for a file that exists in your folder, it was not committed or it was a symlink pointing outside.
init-core.sh
Skeleton copied without overwriting.
overview + tasks + decision
Dated facts, a task with a criterion, first decision with a status.
check.sh locally
Seven ok. Still proves nothing about portability.
check.sh in the clone
Seven ok again. Now we're talking: the project stands on its own. Next step is the readback.
⚠️ The mistake to avoid
Skipping the clone because "it works on my machine". A workspace that depends on ~/.claude/runbooks or on a sibling folder will break in Codex, in dsh and in anyone else's clone. The test costs thirty seconds and is the only proof that the layer is portable.
Key concepts
A copy in a clean place, with only what is in git.
Neighboring folder, symlink, global config.
Prompt B's requirement: nothing living only in ../../.
If something comes from outside, AGENTS.md says how to get it.
Self-check (optional): check.sh passed in your folder but failed in the isolated clone. What does that show?
🎯 Module summary
Next module:
2.4 — Canonical skills with polyskill: one source, N runtimes