Handoff — Cross-CLI Session Context Transfer
Thin wrapper around the dotbabel handoff binary. The binary is the
authoritative contract; run dotbabel handoff --help for the full
sub-command list and flag reference. This file maps natural language to
the right invocation.
Auto-trigger phrase mapping
| Trigger phrase |
Invocation |
handoff <id> / resume-command fragments |
dotbabel handoff pull <id> |
continue in <cli> / switch to <cli> / pull from <cli> |
dotbabel handoff pull <id> --from <cli> |
what was that session about + identifier |
dotbabel handoff pull <id> --summary |
push handoff / send to other machine / save this |
dotbabel handoff push --from <host-cli> [--tag …] |
pull handoff / fetch handoff / continue from yesterday's machine |
dotbabel handoff fetch [<query>] |
Extract <id> from the user message (UUID, short UUID, or a deliberate-label
alias: claude customTitle/aiTitle, codex thread_name, copilot
workspace.yaml:name, or gemini checkpoint). Aliases match
case-insensitively. Resolution precedence: UUID > short-UUID > latest >
alias (no fall-through on miss).
The resolver probes Claude / Copilot / Codex / Gemini roots automatically. If the
query is missing or ambiguous, ask one clarifying question before proceeding.
The --from filling rule
When invoking dotbabel handoff push without a query positional,
include --from <your-cli> where <your-cli> is the agent the host LLM
is running in (claude for Claude Code, copilot for GitHub Copilot CLI,
codex for Codex). The flag is required in that mode; the binary exits
64 without it.
Layered fidelity (Approach A and Approach B)
The digest combines two layers of context fidelity. Justification and
tradeoffs are captured in
docs/experiments/handoff-hardening-2026-05-08.md (added in PR #206;
this PR must merge after #206 for the link to resolve).
- B-floor (always on). Mechanical extraction the binary performs
unconditionally: TodoWrite mining in claude/codex transcripts,
user-prompt cap of 50 (prompt 1 pinned + last 49), and assistant
turn sampling (first turn + last 3). This is what every
push and
pull produces with no extra flags. See
references/digest-schema.md for the schema and size bounds.
- Approach A (opt-in via
--state-file). When
dotbabel handoff push --state-file <path> is passed, the file's
raw content (typically a <handoff-state> YAML block authored by
the source agent) is prepended above the mechanical <handoff>
block. This lets the agent author intent, decisions, and goals
verbatim instead of relying on extraction heuristics. The block
flows through the same secret scrubber. See
references/digest-schema.md for the rendered shape.
Tool execution failures
When the dotbabel binary cannot be executed for any reason —
permission denied, binary not found, network failure, sandbox
restriction — do NOT fabricate, reconstruct, or synthesize a
<handoff> block from raw session JSONL files. Report the
tool-execution error verbatim and stop; instruct the user to run
the command manually in a shell where dotbabel is available.
Specifically:
- Quote the exact command attempted and the failure message.
- Tell the user to run it themselves and paste the output back.
- Do not infer, summarize, or proceed as if the call had succeeded.
Why: the binary is the authoritative producer of <handoff> blocks
— it owns the scrub passes (push redaction) and the extraction
logic §4 data flow depends on. Fabricated output may pass shape
validation but bypasses scrubbing entirely; the consumer cannot
distinguish a hand-rolled block from a real one.
Cross-cutting flags
Brief reference. dotbabel handoff --help is authoritative.
--from <cli> narrows source-CLI auto-detection on push, fetch, pull; filters list, search, and prune.
For pull latest, omitting --from triggers host auto-detection: CLAUDECODE=1 / COPILOT_* / CODEX_* / GEMINI_CLI* env signals → narrowed to that CLI's root; host undetectable → cross-root union (newest mtime across all four roots).
--summary is pull-only; fetch --summary exits 64 because fetch retrieves the rendered remote handoff.md.
-o <path> (on pull) controls output: - forces stdout; auto writes to <repo>/docs/handoffs/<date>-<cli>-<short>.md; any other string is a literal path.
--since <ISO> cuts off list and search (default 30 days for search).
--limit <N> caps the row count.
--tag <label> annotates a push (repeatable). On fetch <tag>, exact-tag matches are preferred over description substring fallback.
--fixed / -F treats the search query as a literal string instead of a regex.
--json is honoured by list, pull, search.
--state-file <path> (on push) prepends a free-form state block (Approach A) to the digest before the mechanical extraction. The block is scrubbed for secrets like any other content.
Out of scope
- Invoking the target CLI directly. The skill prints; the user pastes. Keeps the transfer auditable.
- End-to-end encryption. The git transport is access-controlled by the host (private repo + auth); content is plaintext on the remote.
push runs the scrubber and fails closed (exit 2) if it can't run. Best-effort pattern pass — see references/redaction.md.
- Fuzzy or semantic search.
search is substring/regex only.
Internal references
dotbabel handoff --help — authoritative flag and sub-command list.
references/prerequisites.md — install matrix and remote-transport setup.
references/from-codex.md — Codex-specific notes.
references/redaction.md — scrubber behavior.
1---2name: handoff3description: Transfer conversation context between agentic CLIs (Claude Code, GitHub Copilot CLI, OpenAI Codex CLI) locally and across machines. Reads a source session transcript by UUID and produces either an inline summary, a paste-ready handoff digest, a written markdown file, or a branch in a user-owned private git repo that another machine can fetch. Use when switching agents mid-task, recovering context, or moving between Windows/Linux/macOS setups. Triggers on: "handoff", "transfer context", "continue in codex", "continue in claude", "continue in copilot", "switch to codex", "switch to claude", "what was that session about", "claude --resume", "copilot --resume", "codex resume", "find the session where", "search sessions", "which session did I", "push handoff", "fetch handoff", "handoff to other machine", "resume on my other laptop".4---56# Handoff — Cross-CLI Session Context Transfer78Thin wrapper around the `dotbabel handoff` binary. The binary is the9authoritative contract; run `dotbabel handoff --help` for the full10sub-command list and flag reference. This file maps natural language to11the right invocation.1213## Auto-trigger phrase mapping1415| Trigger phrase | Invocation |16| ---------------------------------------------------------------------- | --------------------------------------------------- |17| `handoff <id>` / resume-command fragments | `dotbabel handoff pull <id>` |18| `continue in <cli>` / `switch to <cli>` / `pull from <cli>` | `dotbabel handoff pull <id> --from <cli>` |19| `what was that session about` + identifier | `dotbabel handoff pull <id> --summary` |20| `push handoff` / `send to other machine` / `save this` | `dotbabel handoff push --from <host-cli> [--tag …]` |21| `pull handoff` / `fetch handoff` / `continue from yesterday's machine` | `dotbabel handoff fetch [<query>]` |2223Extract `<id>` from the user message (UUID, short UUID, or a deliberate-label24alias: claude `customTitle`/`aiTitle`, codex `thread_name`, copilot25`workspace.yaml:name`, or gemini `checkpoint`). Aliases match26case-insensitively. Resolution precedence: UUID > short-UUID > `latest` >27alias (no fall-through on miss).28The resolver probes Claude / Copilot / Codex / Gemini roots automatically. If the29query is missing or ambiguous, ask one clarifying question before proceeding.3031## The `--from` filling rule3233When invoking `dotbabel handoff push` without a query positional,34include `--from <your-cli>` where `<your-cli>` is the agent the host LLM35is running in (`claude` for Claude Code, `copilot` for GitHub Copilot CLI,36`codex` for Codex). The flag is required in that mode; the binary exits3764 without it.3839## Layered fidelity (Approach A and Approach B)4041The digest combines two layers of context fidelity. Justification and42tradeoffs are captured in43`docs/experiments/handoff-hardening-2026-05-08.md` (added in PR #206;44this PR must merge after #206 for the link to resolve).4546- **B-floor (always on).** Mechanical extraction the binary performs47 unconditionally: TodoWrite mining in claude/codex transcripts,48 user-prompt cap of 50 (prompt 1 pinned + last 49), and assistant49 turn sampling (first turn + last 3). This is what every `push` and50 `pull` produces with no extra flags. See51 `references/digest-schema.md` for the schema and size bounds.52- **Approach A (opt-in via `--state-file`).** When53 `dotbabel handoff push --state-file <path>` is passed, the file's54 raw content (typically a `<handoff-state>` YAML block authored by55 the source agent) is prepended above the mechanical `<handoff>`56 block. This lets the agent author intent, decisions, and goals57 verbatim instead of relying on extraction heuristics. The block58 flows through the same secret scrubber. See59 `references/digest-schema.md` for the rendered shape.6061## Tool execution failures6263When the `dotbabel` binary cannot be executed for any reason —64permission denied, binary not found, network failure, sandbox65restriction — do NOT fabricate, reconstruct, or synthesize a66`<handoff>` block from raw session JSONL files. Report the67tool-execution error verbatim and stop; instruct the user to run68the command manually in a shell where `dotbabel` is available.6970Specifically:71721. Quote the exact command attempted and the failure message.732. Tell the user to run it themselves and paste the output back.743. Do not infer, summarize, or proceed as if the call had succeeded.7576Why: the binary is the authoritative producer of `<handoff>` blocks77— it owns the scrub passes (`push` redaction) and the extraction78logic §4 data flow depends on. Fabricated output may pass shape79validation but bypasses scrubbing entirely; the consumer cannot80distinguish a hand-rolled block from a real one.8182## Cross-cutting flags8384Brief reference. `dotbabel handoff --help` is authoritative.8586- `--from <cli>` narrows source-CLI auto-detection on `push`, `fetch`, `pull`; filters `list`, `search`, and `prune`.87 For `pull latest`, omitting `--from` triggers host auto-detection: `CLAUDECODE=1` / `COPILOT_*` / `CODEX_*` / `GEMINI_CLI*` env signals → narrowed to that CLI's root; host undetectable → cross-root union (newest mtime across all four roots).88- `--summary` is `pull`-only; `fetch --summary` exits 64 because `fetch` retrieves the rendered remote `handoff.md`.89- `-o <path>` (on `pull`) controls output: `-` forces stdout; `auto` writes to `<repo>/docs/handoffs/<date>-<cli>-<short>.md`; any other string is a literal path.90- `--since <ISO>` cuts off `list` and `search` (default 30 days for `search`).91- `--limit <N>` caps the row count.92- `--tag <label>` annotates a `push` (repeatable). On `fetch <tag>`, exact-tag matches are preferred over description substring fallback.93- `--fixed` / `-F` treats the `search` query as a literal string instead of a regex.94- `--json` is honoured by `list`, `pull`, `search`.95- `--state-file <path>` (on `push`) prepends a free-form state block (Approach A) to the digest before the mechanical extraction. The block is scrubbed for secrets like any other content.9697## Out of scope9899- **Invoking the target CLI directly.** The skill prints; the user pastes. Keeps the transfer auditable.100- **End-to-end encryption.** The git transport is access-controlled by the host (private repo + auth); content is plaintext on the remote. `push` runs the scrubber and fails closed (exit 2) if it can't run. Best-effort pattern pass — see `references/redaction.md`.101- **Fuzzy or semantic search.** `search` is substring/regex only.102103## Internal references104105- `dotbabel handoff --help` — authoritative flag and sub-command list.106- `references/prerequisites.md` — install matrix and remote-transport setup.107- `references/from-codex.md` — Codex-specific notes.108- `references/redaction.md` — scrubber behavior.