Continue an unfinished coding task in another agent when the current tool hits a usage limit, loses access, or becomes unavailable.
agent-handoff reads local Claude Code or Codex session history, extracts portable user/assistant context, snapshots the current Git state, writes a local handoff packet, and launches the other agent in the same workspace.
Claude Code session JSONL ─┐
├─> HANDOFF.md + handoff.json ─> Codex or Claude Code
Codex session JSONL ───────┘
It does not need the rate-limited model to respond.
Install from GitHub with pipx:
pipx install git+https://github.com/wentaoz/coding-agent-handoff.gitFrom the repository where the interrupted task was running:
# Claude Code hit its limit: create a handoff and open Codex.
agent-handoff switch --from claude --to codex
# Codex hit its limit: create a handoff and open Claude Code.
agent-handoff switch --from codex --to claudeIf the newest session in the current directory is the source, let the tool detect it:
agent-handoff switch --from autoPreview the target command without launching it:
agent-handoff switch --from claude --to codex --dry-runInspect the session that would be selected:
agent-handoff inspect --from claudeExport a handoff without launching another agent:
agent-handoff export --from claude --to codexSelect an older session by UUID or JSONL path:
agent-handoff switch \
--from claude \
--to codex \
--session 23b23542-ee30-45d9-a2f9-1ac56fc86e96Run the target once in non-interactive mode:
agent-handoff switch --from codex --to claude --non-interactiveBy default, the handoff is written inside the workspace:
.agent-handoff/
├── HANDOFF.md
└── handoff.json
The directory is excluded by this repository's .gitignore; add it to your own global or project ignore rules if you never want handoffs committed.
The handoff contains:
- portable user and assistant text from the selected local session;
- the original and latest user messages;
- the latest assistant progress message;
- workspace, branch, HEAD, working-tree status, and diff statistics;
- source agent, session ID, version, and transcript fingerprint;
- a takeover contract that tells the target to reconcile the real workspace before acting.
The handoff deliberately excludes:
- hidden thinking or reasoning;
- developer/system instructions;
- tool results and raw command output;
- API keys, auth tokens, and credential stores;
- any claim that a Claude Code session has become a native Codex session, or vice versa.
Common secret patterns are redacted. Handoff files are created with user-only permissions (0600), but they still contain conversation text and should be treated as sensitive local artifacts.
Claude Code and Codex use different private session schemas, runtime instructions, tools, permission models, and authentication. Copying one tool's raw session into another would be brittle and unsafe.
This project transfers the durable parts of the task instead:
- user intent;
- visible agent progress;
- repository state;
- explicit resume and idempotency rules.
The target agent then inspects the actual files and continues rather than trusting stale prose.
| Agent | Read local sessions | Launch as target |
|---|---|---|
| Claude Code | Yes | Yes |
| Codex CLI | Yes | Yes |
The adapter boundary is intentionally small. To add another coding agent, implement its session discovery/parser in src/agent_handoff/sessions.py and its safe argv builder in src/agent_handoff/launcher.py. Do not use a shell string to launch agents.
The repository includes skills/resume-agent-handoff. Install it in either agent's skills directory if you want an explicit reusable takeover workflow. The CLI does not depend on the skill; its launch prompt works without it.
git clone https://github.com/wentaoz/coding-agent-handoff.git
cd coding-agent-handoff
PYTHONPATH=src python3 -m unittest discover -s tests -v
PYTHONPATH=src python3 -m agent_handoff --helpThe project uses only the Python standard library at runtime and supports Python 3.10+.
- Automatic handoff after an interactive TUI failure is not yet implemented; run
agent-handoff switchfrom the affected workspace. - A source session must have been persisted locally.
- Conversation text may be truncated to the configured message and per-message limits.
- The portable transcript defaults to at most 24 messages and 80,000 characters; use
--max-messagesand--max-charsto adjust it. - External side effects cannot be inferred reliably from prose. The target is instructed to verify them before retrying.
- Session schemas are not a shared standard and may evolve; file an issue with a redacted structural sample if a parser stops working.
MIT