Carry an AI coding-agent session from one harness to another — and resume it natively on the other side.
You hit a wall in one tool: a quota limit, a bug the other model debugs better,
a teammate on a different agent. Today you re-explain everything. portage
finds the session you mean, converts it, and writes it into the target tool's
own store so its --resume lists and continues it.
The name is the act of carrying a canoe overland between two rivers.
# From Claude Code, continue a Codex session you described from memory:
portage find --from codex "login page password encryption" # ranked + summaries
portage convert --from codex --to claude-code --match "login encryption" --cwd "$PWD"
# → cd <cwd> && claude --resume <id>Single static binary. Local-first — no network, no API keys, nothing leaves your machine.
Two different problems, and portage handles both:
- Format — every harness stores sessions in its own private, versioned,
usually-SQLite-or-JSONL shape. The hard part is writing a session the target
will actually resume (e.g. Claude Code needs a
uuid/parentUuidchain and the rightencoded-cwddirectory; Codex needs a SQLite index row). - Context — blindly replaying hundreds of messages is the wrong way to
continue work: it is bulky, carries stale tool output as if current, and
injects another model's reasoning. portage's default
handoffmode distills an action-preserving briefing (task · files touched · commands run · recent exchange) and lets the target agent re-read the live files itself.
Both are backed by research and real-install validation — see
docs/superpowers/specs/.
| harness | source | target | verification |
|---|---|---|---|
| Claude Code | ✅ | ✅ | real — read + claude --resume round-trip verified |
| Codex CLI | ✅ | ✅ | real — read verified incl. function/custom tool calls, reasoning |
| opencode | ✅ | ✅ | real — read verified on a 57k-part live session; write verified on a live opencode-compatible store: converted session listed and resumed natively |
| Qwen Code | ✅ | ✅ | synthetic round-trip |
| Kimi Code | ✅ | ✅ | synthetic round-trip |
| Copilot CLI | ✅ | — | tolerant reader, unverified |
"real" = run against actual sessions on a live install, parsed block counts
matched ground truth, and (Codex→Claude Code) claude --resume loaded the
converted session and restated the task. On-disk formats are vendor-private and
reverse-engineered; confirm a real resume with portage inspect against your
installed version.
opencode's store is a live multi-table SQLite database, so the writer
registers rows the same way the app itself does — one transaction, session +
message chain + parts, tool results merged into their call's tool part. No
event rows are needed (the materialized tables are the source of truth).
opencode-compatible forks that keep their own data dir work via
PORTAGE_OPENCODE_DB.
Not yet implemented (no local install to validate against, and speculative
writes into a live store risk corruption): Goose, Hermes, OpenClaw. Amp
(cloud-authoritative) and Aider (no session/resume) can only ever be read
sources. Adding a harness is one reader + writer (+ registrar).
cargo install --path .portage harnesses # what's supported, and read/write caps
portage list --from codex # sessions, newest first, with summaries
portage find --from codex "<words>" # ranked candidates for a description
portage find --from codex --latest # the most recent session
portage inspect <path> --from codex # parsed structure of one session
portage convert <path> --from codex --to claude-code --cwd "$PWD"You rarely remember the file path. Describe the session instead — find reads
each candidate and prints a one-line summary (task · files · tools), ranked by
match. You don't need exact keywords; a miss falls back to recent sessions to
browse. Then convert by description, or --latest:
portage convert --from codex --to claude-code --match "login encryption" --cwd "$PWD"
portage convert --from codex --to claude-code --latest --cwd "$PWD"--cwd matters for Claude Code: resume only finds the session when the
encoded-cwd directory matches where you launch claude.
--mode handoff(default) — compact action-preserving briefing + recent turns. Reasoning and stale tool output dropped; secrets redacted. Best for continuing work.--mode replay— faithful 1:1 of every message, for archival/debugging.
Both modes carry a workspace snapshot of the source work tree, captured at
convert time: repo/remote, branch @ HEAD, uncommitted files, recent commits.
The target agent resumes knowing which branch it is on and what was in flight —
without stale file contents (files live on disk; the brief points at them).
Non-git directories simply omit the section. --cwd overrides the tree
inspected, and doubles as the resume directory.
Every command renders the same way by default: TOON (Token-Oriented Object
Notation, tab-delimited) — uniform tables at ~30–55% fewer tokens than JSON
with equal retrieval accuracy, plus [N]/{fields} headers that make
truncation detectable. --format json for scripts, --format text for plain
lines; set PORTAGE_FORMAT to pin a default.
$ portage find --from claude-code "login encryption" --limit 2
from: claude-code
query: login encryption
latest: false
hits[2 ]{terms modified title cwd summary locator}:
2 2026-11-02T10:37:00Z login page /home/u/proj fix login password… /home/u/.claude/projects/…/a.jsonl
1 2026-11-01T18:02:00Z auth refactor /home/u/proj2 refactor auth flow… /home/u/.claude/projects/…/b.jsonlconvert prints target_session_id, the exact resume: command, artifacts,
and conversion notes in the same format (notes also go to stderr as • lines).
The CLI is the whole product; these make it one step from inside an agent.
MCP — portage mcp is a stdio MCP server exposing find, inspect, and
convert. Register it with your harness:
{ "mcpServers": { "portage": { "command": "portage", "args": ["mcp"] } } }Then just say "continue my Codex session about the login encryption work" —
the agent runs find (doing the fuzzy, cross-language matching itself from the
summaries), picks the session, and converts it. portage stays model-free; the
model that is already there does the semantic judgment.
Skill — copy skill/portage/SKILL.md into your
harness's skills directory (e.g. ~/.claude/skills/portage/) to teach the
find → convert flow.
Home-relative stores (Codex, Claude Code, Qwen, Kimi) resolve the same on Linux,
WSL, macOS, and Windows via the OS home dir. opencode uses the OS data dir
(~/.local/share, ~/Library/Application Support, or %APPDATA%); set
PORTAGE_OPENCODE_DB to override. Verified on WSL/Linux; macOS and
native-Windows paths resolve per-OS but are not yet confirmed on-platform.
Reported, never silently dropped: per-turn model switches, sandbox posture, thread branching (flattened), reasoning (summary text only; dropped entirely in handoff). Open tool calls and queued input are carried into the resume brief.
cargo test # synthetic fixtures + a real-schema opencode read + find rankingDesign and research notes live in
docs/superpowers/specs/.
MIT OR Apache-2.0.