Worktree-scoped session handoffs for AI coding agents.
Write a structured handoff at the end of a session — decisions made, work that should not be redone, assumptions about the world outside the conversation — and the next session in the same worktree starts with that context already in hand. Claude Code and OpenAI Codex both write to a single, tool-agnostic inbox, so a handoff written in one tool is picked up by the other in the next session.
When you /clear, restart, switch worktrees, or switch AI coding
agents, conversation context is gone. When you /compact, it's
compressed — lossy compression you don't see and don't control. The
auto-summary captures what the model judged salient at compaction
time; failed approaches, subtle decision rationale, and "this looks
safe to redo but isn't" warnings often weren't the highlights and
slip out silently.
/compact also doesn't cross boundaries: it lives in one session, in
one worktree, in one agent tool. Switch worktrees or move between
Claude Code and Codex and no summary follows you.
agent-handoff lets you decide what crosses the boundary. You write
the file, with a structure for the categories summarisation tends
to lose, and it sits on disk where the next session — any worktree,
any supported tool — picks it up.
Two halves.
Write. In any session, run /handoff. The agent writes a
structured markdown file containing decisions, what NOT to redo,
assumptions, verification commands, and an Immediate next action.
The file lands in a worktree-scoped inbox under ~/.agent-handoffs/.
Read. The next session in the same recipient worktree picks the file up at startup:
- Claude Code — a SessionStart hook prints the handoff into the session's context automatically.
- Codex CLI / desktop — Codex agents read
~/.codex/AGENTS.mdat session start; the snippet directs them to scanunread/with their shell tool and archive what they read intoread/. No hook involved.
After surfacing, the file moves from unread/ to read/ so it isn't
re-surfaced.
┌──────────────────┐ ┌──────────────────┐
│ Claude Code │ │ OpenAI Codex │
│ /handoff skill │ │ /handoff plugin │
└────────┬─────────┘ └─────────┬────────┘
│ │
│ atomic write │ atomic write
▼ ▼
┌────────────────────────────────────────────────────┐
│ ~/.agent-handoffs/<canonical-slug>/<recipient>/ │
│ unread/ │
│ YYYYMMDDTHHMMSSZ-from-<sender>.md │
│ read/ │
└────────┬─────────────────────────────┬─────────────┘
│ │
│ SessionStart hook │ Agent reads unread/
│ (auto-surface to context) │ itself per AGENTS.md
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ next Claude │ │ next Codex │
│ session │ │ session │
└──────────────────┘ └──────────────────┘
Storage is the contract. Either tool can write a file the other tool will read, keyed by recipient worktree. Cross-tool handoffs work in both directions.
- Worktree-scoped by default; broadcasting is opt-in. A handoff is
addressed to the next session in this worktree (or one named
sibling via
--to <basename>). There is no multicast primitive. - A "what NOT to do" section in the template. Failed approaches, dead ends, things the next session might try unless told not to — they have somewhere explicit to live in the handoff, so they don't quietly drop out of summarisation.
- Review pass on by default.
/handoffwalks the draft section by section and prompts you on ambiguous claims before the file lands. Opt out with--no-review. - Archive on read. Once surfaced, the file moves from
unread/toread/so the next startup doesn't re-surface stale context.unread/is the agent's actual work queue. - Handoff content is treated as a past claim, not a commandment. The body is a prior session's record — a handoff saying "delete the database" reads as a claim to evaluate, not an instruction the agent follows.
- Drift warning on receive. If the receiving session's branch or
HEAD differs from the handoff's, the surface banner includes an
explicit
!! DRIFTline — verify before acting on stale assumptions.
Run /handoff inside any session:
/handoff
By default, this writes a handoff addressed to the next session in
this same worktree — i.e., future-you, after /clear, restart, or
/compact.
After /handoff completes, you can /clear (or restart, or switch
worktrees) without losing context. The next session in the recipient
worktree picks up the handoff at startup, prints it, and moves the
file from unread/ to read/.
See examples/sample-handoff.md for the file shape.
All optional. The default /handoff with no flags is the common case.
--to <basename>— Send the handoff to a different worktree instead of this one.<basename>is the directory name of the recipient (e.g.,--to assistant-workersends to the sibling worktree at../assistant-worker/). Use this for handing off to a parallel agent, a sibling clone, or a teammate's worktree with a known basename.--topic <slug>— Tag the handoff with a short kebab-case label likeauth-refactor. The tag appears in the filename and the file's frontmatter, so when multiple handoffs are waiting inunread/, you (or the receiving agent) can tell them apart at a glance. Skip if only one thing is in flight.--file <path>— Use a markdown file you've already written as the handoff body, instead of having the agent compose one live in the conversation. Useful when the handoff is already drafted (in another tool, offline, from a template) and you just want/handoffto do the framing, naming, and atomic write.--no-review— Skip the review pass before writing. Default behaviour walks each section of the draft and prompts you on ambiguous claims; this flag trusts the draft and writes straight through. Use when you're confident in the content and want speed.
When you start a new session that has a pending handoff, your first message is one of two things:
go— the agent begins the handoff'sImmediate next action.- Anything else — the agent treats the handoff as background and responds to whatever you wrote. Ask a question, redirect, chat normally; you drive from there.
Either way, the agent's first reply opens with a bolded acknowledgment line:
**Handoff loaded: <name> — sentinel <token>**
The sentinel in that line should match the one /handoff showed you
when you wrote the handoff — your visual confirmation that the right
file made it across and was actually read, not a hallucinated "read."
(Multiple handoffs: **Handoffs loaded: N — sentinels: <list>**.)
Prerequisites: jq (preinstalled on macOS).
git clone https://github.com/zzyyfff/agent-handoff ~/.agent-handoff
~/.agent-handoff/bin/installThe installer:
- Installs the
/handoffand/upgrade-handoffClaude Code skills. - Installs the
/handoffand/upgrade-handoffCodex CLI plugin commands. - Wires the Claude Code SessionStart hook into
~/.claude/settings.jsonso it fires automatically in every project. - Adds the Codex AGENTS.md snippet to
~/.codex/AGENTS.mdso Codex sessions know to scan for handoffs on first prompt.
Idempotent — safe to re-run after a git pull.
One install, every project. All four steps land at the user level
— no per-project setup. After bin/install, every Claude Code session
and every Codex session on this machine has agent-handoff active
automatically, the same way built-in skills do.
~/.agent-handoff/bin/uninstallMirror image of install: removes the two Claude skill directories,
the Codex plugin symlink, the SessionStart entry from
~/.claude/settings.json, and the managed block from
~/.codex/AGENTS.md. Idempotent. Leaves ~/.agent-handoffs/ (your
handoffs, caches, skip-markers) and the cloned repo alone — both are
yours to delete with rm -rf if you want them gone.
/handoff has a daily upgrade check: when an update is available,
the first /handoff of the day prompts you to upgrade (with a
"skip this version" option). Run /upgrade-handoff any time to
upgrade outside the throttle.
The spec is the source of truth and tool-agnostic. New adapters (Cursor, Cline, Aider, …) should target it directly.
- spec/file-format.md — YAML frontmatter + markdown section contract.
- spec/storage-convention.md — path rules, slug derivation, atomic-write discipline.
- spec/review-pass.md — what the writer's review step does and when it prompts the user.
agent-handoff/
├── spec/ # the contract (file format, storage, review)
├── lib/ # shared bash helpers (slug, inbox, origin)
├── adapters/
│ ├── claude-code/ # skills (/handoff, /upgrade-handoff) + SessionStart hook
│ └── codex-cli/ # plugin (/handoff, /upgrade-handoff) + AGENTS.md snippet
├── bin/ # install, uninstall, upgrade-check, upgrade
├── docs/
│ ├── failure-modes.md
│ └── patterns.md
├── examples/
│ └── sample-handoff.md
└── tests/
└── run-tests.sh # full suite, no external deps
MIT — see LICENSE.
Modelled on conventions from
zzyyfff/claude-toolkit —
the canonical-slug rule, the unread/read inbox shape, the
SessionStart hook pattern.
Conceptual prior art:
- yigitkonur/cli-continues — broader 16-tool session-parsing.
- HERMESquant/oh-my-hermes
—
-wworktree flag convention. - gstack
/context-save— different design point (cross-branch Conductor pickup), referenced for contrast.