9e5c42c25f
Introduce the cross-project capture->triage->roadmap loop: /capture appends an idea or bug to INBOX.md from any repo (new-project ideas included), /triage drains a project's items into its AGENTS.md or ROADMAP.md. Give the standards repo its own AGENTS.md (+ CLAUDE.md symlink) and ROADMAP.md so it follows its own standard, and add a 'What git tracks' section to portability.md plus the canonical .gitignore block answering what is committed vs gitignored around .claude and symlinks.
144 lines
9.8 KiB
Markdown
144 lines
9.8 KiB
Markdown
# 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/
|
|
AGENTS.md ← CLAUDE.md (relative symlink) ← agent-facing orientation to this repo
|
|
README.md how-i-work.md portability.md retrofit-playbook.md subagents-handbook.md
|
|
ROADMAP.md ← this repo's backlog (future agents, commands, standards)
|
|
INBOX.md ← cross-project capture buffer (/capture → here, /triage drains it)
|
|
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:
|
|
|
|
1. **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.
|
|
2. **Swap at session boundaries.** The close-out ritual (update Current state → commit → push) is the handoff protocol between providers, not just between sessions.
|
|
3. **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 in `guides/` — no inline exceptions, so any wrapper converts to a new tool by swapping its header.
|
|
4. **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.
|
|
5. **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).
|
|
|
|
## What git tracks
|
|
|
|
Symlinks and `.claude/` raise a recurring question: what belongs in the repo, what stays
|
|
local, and how does the global `~/.claude` layer get backed up? One rule resolves all three
|
|
— **git tracks knowledge and the wiring that serves it; it ignores machine-local state and
|
|
secrets** — but it lands in three places.
|
|
|
|
**1. Relative symlinks are committed and travel.** Git stores a symlink as its target path.
|
|
Because every vendor path in this standard is a *relative* symlink (`CLAUDE.md → AGENTS.md`,
|
|
`.claude/rules/x.md → ../../docs/guides/x.md`), it commits and clones correctly on any
|
|
machine. This is the concrete payoff of the relative-symlink mandate: an absolute symlink
|
|
would commit too, but break on every other clone. Never commit an absolute symlink.
|
|
|
|
**2. Inside a project repo — commit shared, ignore local.**
|
|
|
|
Committed (any agent or teammate needs them to work the repo correctly — corollary 1):
|
|
`AGENTS.md` and its `CLAUDE.md` symlink; `docs/guides/*.md` and their `.claude/rules/*.md`
|
|
symlinks; `ROADMAP.md`; `.claude/settings.json` (shared project settings and hooks —
|
|
deterministic behavior is part of the repo); `.claude/agents/*.md`, `.claude/commands/*.md`,
|
|
`.claude/skills/` (project-scoped wrappers).
|
|
|
|
Gitignored (per-user, per-machine, or secret): `.claude/settings.local.json` and any
|
|
`*.local.*` (personal permissions/overrides); `.env` and secrets (corollary 5); OS cruft.
|
|
|
|
Put these in the repo's **own committed `.gitignore`** — don't rely on a global
|
|
excludesfile, which a fresh clone or another machine won't have. Canonical block:
|
|
|
|
```
|
|
# Secrets & local env
|
|
.env
|
|
.env.*
|
|
!.env.example
|
|
|
|
# Claude Code — commit shared config, ignore personal/local
|
|
.claude/settings.local.json
|
|
.claude/*.local.json
|
|
|
|
# OS cruft
|
|
.DS_Store
|
|
```
|
|
|
|
**3. The global `~/.claude` layer is backed up *through the standards repo*, not on its
|
|
own.** `~/.claude` is not a git repo. Its durable, portable parts — `commands`, `agents`,
|
|
`CLAUDE.md` — are symlinks *into* this standards repo, so committing and pushing standards
|
|
backs them up. Everything else under `~/.claude` (the machine-local `settings.json`,
|
|
`projects/` session transcripts and auto-memory, history, todos, caches) is disposable
|
|
session state by design (corollary 4) and is neither committed nor backed up. What makes
|
|
this safe: promote anything durable out of auto-memory into a committed file (AGENTS.md or a
|
|
guide); audit with `/memory`.
|
|
|
|
So the answer to "are we backing up all of `.claude`?" is **no, by design**: knowledge and
|
|
shared wiring are committed per-repo or symlinked into a backed-up repo; machine-local state
|
|
and secrets never are.
|
|
|
|
## Swap protocol (between already-adopted tools)
|
|
|
|
1. Finish the task and run the close-out ritual; exit the session.
|
|
2. Open the other tool in the same repo.
|
|
3. 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."*
|
|
|
|
1. Install and authenticate the tool — the only human-heavy step.
|
|
2. Symlink (or copy) its global instruction file to `standards/how-i-work.md`.
|
|
3. Confirm it reads `<repo>/AGENTS.md`. If it expects a different filename, symlink that name to AGENTS.md.
|
|
4. If it supports path-scoped or lazy loading, wire its mechanism to `docs/guides/`; otherwise the AGENTS.md index lines suffice.
|
|
5. If it supports skills or procedures, point it at the skills folders; otherwise add a pointer line in its global file.
|
|
6. 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.
|
|
7. **Record what was done in a new provider section at the bottom of this document.**
|
|
|
|
## Provider adapters
|
|
|
|
### Claude Code (current)
|
|
|
|
- `CLAUDE.md` → symlink → `AGENTS.md` at the root of every repo
|
|
- `.claude/rules/<topic>.md` → symlinks → `docs/guides/<topic>.md` (auto lazy-load via `paths:` 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: ___
|