ROADMAP.md was named as a destination in two places but never created, indexed, or read back. Add the convention to how-i-work.md, note it after the README decision tree and in the loads-when table, give it a row in the portability layer table, make the retrofit prompt create it, and have handoff seed it and pull from it when Current state's next steps run thin.
6.9 KiB
Portability Protocol
Purpose: keep every layer of my agent setup hot-swappable across model providers. Any compliant tool dropped into one of my repos should be productive immediately; adopting a new tool should cost minutes; returning to a previous tool should cost nothing.
Lives at: ~/Projects/standards/portability.md. The standards repo is laid out as:
~/Projects/standards/
how-i-work.md portability.md retrofit-playbook.md subagents-handbook.md
guides/ ← neutral substance (vendor-agnostic): checklists, role knowledge
adapters/
claude/
commands/ ← ~/.claude/commands symlinks here (global commands, e.g. /handoff)
agents/ ← ~/.claude/agents symlinks here (global subagents)
Companions: how-i-work.md (the always-loaded user layer, ~50 lines), retrofit-playbook.md (the one-time conversion manual), and subagents-handbook.md (designing and running delegated agents). This document is reference material — never symlink it into anything always-loaded.
The principle
Knowledge lives in vendor-neutral files; vendor-named paths are thin adapters — symlinks or pointers — into them.
Corollaries:
- Repos are self-contained. Everything required to work on a project correctly lives in the repo. Global and user-level files add preferences, never requirements.
- Swap at session boundaries. The close-out ritual (update Current state → commit → push) is the handoff protocol between providers, not just between sessions.
- Convert machinery, never knowledge. At adoption time, an agent regenerates wrappers (subagents, commands, rule loaders). The substance they point at never moves. Every command and subagent is a thin wrapper in
adapters/<tool>/whose substance lives inguides/— no inline exceptions, so any wrapper converts to a new tool by swapping its header. - Session state is disposable by design. Conversations and per-tool caches (e.g. Claude's auto memory) are conveniences. Anything important gets promoted into the files below.
- No secrets in any of these files. Secrets live in gitignored .env files; documents reference env-var names only.
The layers
| Layer | Neutral source of truth | Claude adapter | Portability status |
|---|---|---|---|
| Project knowledge | <repo>/AGENTS.md |
symlink CLAUDE.md → AGENTS.md |
Open standard — Cursor, Copilot, Codex, Gemini CLI, opencode read it |
| Project status (now) | ## Current state section in AGENTS.md |
(same symlink) | Fully portable; maintained by the close-out ritual |
| Project backlog (later) | ROADMAP.md at repo root |
— (plain committed file, no symlink) | Fully portable; committed and pushed like any file, read only on demand |
| Scoped guides | <repo>/docs/guides/<topic>.md with paths: frontmatter, plus one index line each in AGENTS.md |
symlinks from .claude/rules/ (auto lazy-load) |
Content fully portable; lazy-loading is per-tool. Other tools find guides via the index lines |
| User preferences | ~/Projects/standards/how-i-work.md |
symlink ~/.claude/CLAUDE.md → it |
No cross-tool standard above repo level; each tool's global file symlinks here at adoption |
| Skills (procedures) | folders of SKILL.md + plain bash/python scripts |
.claude/skills/ |
Format is open markdown; a cross-tool home (.agents/skills/) is emerging. Worst case: a pointer line in AGENTS.md |
| Subagents (delegation) | guides folder at matching scope — <repo>/docs/guides/ for project agents, standards/guides/ for global |
thin wrapper in .claude/agents/ (project) or standards/adapters/claude/agents/ (global, symlinked as ~/.claude/agents) |
No standard exists. Wrappers regenerated per tool at adoption |
| Commands (saved prompt shortcuts) | substance in guides/ at matching scope, same rule as subagents |
thin wrapper in .claude/commands/ (project) or standards/adapters/claude/commands/ (global, symlinked as ~/.claude/commands) |
No standard. Same treatment as subagents |
Scope rule: every artifact lives at the scope it describes — project-specific in that repo; universal in the standards repo. There, neutral substance goes in guides/ and vendor machinery is quarantined under adapters/<tool>/ (so a second provider's wrappers never intermix with Claude's or with the shared guides).
Swap protocol (between already-adopted tools)
- Finish the task and run the close-out ritual; exit the session.
- Open the other tool in the same repo.
- It reads AGENTS.md (plus its own global file) and Current state, and continues.
Nothing else. If step 3 stumbles, the missing fact belongs in AGENTS.md — add it and commit.
Adoption checklist (first time using a new provider)
Run by the new agent itself: "Read ~/Projects/standards/portability.md and onboard yourself as a new provider."
- Install and authenticate the tool — the only human-heavy step.
- Symlink (or copy) its global instruction file to
standards/how-i-work.md. - Confirm it reads
<repo>/AGENTS.md. If it expects a different filename, symlink that name to AGENTS.md. - If it supports path-scoped or lazy loading, wire its mechanism to
docs/guides/; otherwise the AGENTS.md index lines suffice. - If it supports skills or procedures, point it at the skills folders; otherwise add a pointer line in its global file.
- Regenerate the thin wrappers it supports (subagents, commands) from the guides they reference, placing global ones in
adapters/<tool>/and symlinking the tool's config home to them. - Record what was done in a new provider section at the bottom of this document.
Provider adapters
Claude Code (current)
CLAUDE.md→ symlink →AGENTS.mdat the root of every repo.claude/rules/<topic>.md→ symlinks →docs/guides/<topic>.md(auto lazy-load viapaths:frontmatter)~/.claude/CLAUDE.md→ symlink →standards/how-i-work.md.claude/agents/— thin subagent wrappers pointing at docs/guides (project-specific agents only).claude/commands/— thin command templates, regenerable (project-specific commands only)- Global commands and agents:
~/.claude/commands→ symlink →standards/adapters/claude/commands/;~/.claude/agents→ symlink →standards/adapters/claude/agents/(versioned and backed up with the standards repo) .claude/skills/— skills home for now; migrate to.agents/skills/if that convention solidifies- Auto memory: local cache only (
~/.claude/projects/<project>/memory/), outside git, not portable. Promote keepers into AGENTS.md or guides. Audit with/memory.
Next provider — template
- Global file location: ___ → symlink →
standards/how-i-work.md - Reads AGENTS.md natively? ___ (if not: symlink its expected filename → AGENTS.md)
- Scoped/lazy loading mechanism: ___ (wired to docs/guides, or relying on index lines)
- Skills support: ___
- Delegation/subagent equivalent: ___ (wrappers regenerated on: ___)
- Notes and quirks: ___