Skill v1.0.0
currentTrusted Publisher100/100version: "1.0.0" name: handoff description: "Hand off your in-flight work to ANY other AI coding tool so you can continue exactly where you left off — works in 8+ tools (Claude Code, Codex, OpenCode, Gemini, Antigravity, Cursor, Aider, Cline/Roo, Windsurf). Writes one portable, secret-scrubbed handoff document plus a full diff of your uncommitted edits, then prints the absolute path, a clickable link, and a copy-paste resume prompt. Use this skill whenever the user is running out of subscription tokens, wants to switch tools mid-task, says 'handoff', 'continue elsewhere', 'continue on another machine', 'switch to Codex/OpenCode/Gemini/Cursor', or 'I'm out of tokens'. Self-contained: needs only git and a shell; uses 'specweave handoff' as an optional accelerator if it is on PATH." metadata: tags: handoff, cross-tool, portable-context, out-of-tokens, switch-tools, resume, session, git-diff, secret-scrub, continue-elsewhere
/handoff — Cross-Tool Work Handoff
No AI coding tool can read another's transcript: Claude Code locks sessions in ~/.claude/projects/<munged-cwd>/<uuid>.jsonl, Codex/OpenCode in their own stores, Antigravity in encrypted .pb. The only thing portable across tools is a self-contained document. This skill writes that document — your current goal, decisions, and the EXACT uncommitted edits — so any other AI agent can pick up where you left off, without you re-explaining anything.
Use this skill when the user is low on tokens, wants to switch tools mid-task, is moving to another machine, or says "handoff" / "continue elsewhere" / "out of tokens".
This skill is self-contained: it works with only git + a shell. It calls specweave handoff as an optional accelerator when that binary is on PATH (high-fidelity, increment-aware) — but it has no hard dependency on SpecWeave being installed.
Decision: which path to take
command -v specweave >/dev/null 2>&1 && echo "ACCELERATOR" || echo "STANDALONE"
- ACCELERATOR (
specweaveon PATH) → run the engine, surface its output. Go to Path A. - STANDALONE (no
specweave) → build the doc yourself fromgit+ a short interview. Go to Path B.
Both paths emit the same doc format and the same paste-prompt (see the canonical template below), so a handoff is continuable in any tool regardless of which path produced it.
Path A — Accelerator (specweave on PATH)
Run the engine, forwarding any short context you can supply cheaply:
specweave handoff [incrementId] [--reason "..."] [--summary "..."] [--next "..."] [--gotcha "..."] [--decision "..."] [--inline]
Then surface its stdout verbatim, in order (do not reorder or paraphrase):
- absolute doc path as plain text (FIRST), 2. clickable markdown link, 3.
.diffpath, - fenced copy-paste resume prompt, 5. per-tool "find your source session" tips.
Done. The engine handled workspace detection, task/AC parsing, git capture, the full-diff dump, secret scrub, and rendering.
Path B — Standalone (no specweave)
Build a byte-compatible doc using only the shell.
B1. Capture git state (free — no tokens)
ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"mkdir -p "$ROOT/.handoff"printf '*\n' > "$ROOT/.handoff/.gitignore" # never let the handoff or its diff enter gitBRANCH="$(git -C "$ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null || echo '(no git)')"SHA="$(git -C "$ROOT" rev-parse --short HEAD 2>/dev/null || echo '(no commits)')"STATUS="$(git -C "$ROOT" status --porcelain 2>/dev/null)"STAT="$(git -C "$ROOT" diff --stat 2>/dev/null)"# Full uncommitted edits → sibling .diff (working tree + staged), the key fidelity artifact{ git -C "$ROOT" diff HEAD 2>/dev/null; git -C "$ROOT" diff --cached 2>/dev/null; } > "$ROOT/.handoff/handoff.diff"
B2. Five-question interview (only the non-derivable fields)
Ask the user (keep it to ~5 short strings — cheap even at token exhaustion):
- reason — why are you handing off? (e.g. "out of tokens")
- summary — one line: where do things stand?
- next — the exact next step.
- gotcha — anything the next agent must NOT do / must know?
- decisions — key decisions already made (semicolon-separated).
B3. Secret scrub (before writing — over BOTH free text AND the diff)
Replace matches with [REDACTED-<type>] and count per pattern. Patterns (12): sk-, ghp_, gho_, ghs_, AKIA, ASIA, -----BEGIN, vsk_, xox[bap]-, Bearer , password=, api_key=.
# scrub the captured diff in place, e.g.:sed -i.bak -E \-e 's/sk-[A-Za-z0-9_-]+/[REDACTED-sk]/g' \-e 's/gh[pos]_[A-Za-z0-9_-]+/[REDACTED-gh-token]/g' \-e 's/(A[KS]IA[0-9A-Z]{16})/[REDACTED-aws-key]/g' \-e 's/vsk_[A-Za-z0-9_-]+/[REDACTED-vsk]/g' \-e 's/xox[bap]-[A-Za-z0-9-]+/[REDACTED-slack]/g' \-e 's/Bearer [A-Za-z0-9._-]+/Bearer [REDACTED-bearer]/g' \-e 's/(password=)[^[:space:]]+/\1[REDACTED-password]/g' \-e 's/(api_key=)[^[:space:]]+/\1[REDACTED-api_key]/g' \"$ROOT/.handoff/handoff.diff" && rm -f "$ROOT/.handoff/handoff.diff.bak"
Scrubbing is heuristic — an empty redaction list is NOT a guarantee the file is clean.
B4. Write the doc
Write the canonical template below to $ROOT/.handoff/HANDOFF.md, filling the captured + interview fields.
Ownership sentinel: if a root ./HANDOFF.md already exists and does NOT contain the Doc format v1 marker, it is a foreign file — do NOT overwrite it; write to .handoff/HANDOFF.md instead (which is the default here anyway).
B5. Print the output — abs-path-first, in this order
- The absolute path of
.handoff/HANDOFF.mdas plain text. - A clickable markdown link to it.
- The absolute path of
.handoff/handoff.diff. - The fenced paste-prompt (see below).
- The per-tool "find your source session" tips.
Canonical handoff document template (INLINED — single source of truth)
Render these sections in this exact order, ending with the Doc format v1 footer marker. Square-bracket placeholders are filled from the captured git state + interview. This mirrors specweave's handoff-doc-format.ts so a doc produced here is byte-compatible with one produced by the CLI.
# Work Handoff[: <title if known>]-Doc path: <ABSOLUTE_DOC_PATH>-Doc link: [<ABSOLUTE_DOC_PATH>](<ABSOLUTE_DOC_PATH>)-Diff file: <ABSOLUTE_DIFF_PATH>-Generated: <ISO_TIMESTAMP>-Workspace: <ROOT> (non-SpecWeave)-Git: branch `<BRANCH>` @ `<SHA>`## Where I Left Off**Why handing off:** <reason>**Summary:** <summary>_No active SpecWeave increment — this is a git + interview handoff._## Done / Pending_No increment task/AC state available._## Key Decisions & Gotchas-<decision 1>-<decision 2>**Gotcha:** <gotcha>## Files Touched**UNCOMMITTED** — commit, stash, or keep editing BEFORE doing anything destructive.
<git status --porcelain>
<git diff --stat>
Full uncommitted diff: `<ABSOLUTE_DIFF_PATH>` — read it or run `git apply --check` against it to see the exact edits.## Exact Next Steps<next>## How To ResumeIf the doc path above does NOT exist on the machine you are reading this on, STOP and ask the user to paste the handoff — do not improvise context.To recover the ORIGINAL transcript (optional), find your source session per tool:### Claude Code- Find session: ls ~/.claude/projects/<munged-cwd>/ (munge: every non-alphanumeric char → "-", runs NOT collapsed; e.g. /Users/antonabyzov/Projects/github/specweave-umb/.claude-worktrees/x → -Users-antonabyzov-Projects-github-specweave-umb--claude-worktrees-x)- Resume: `claude -r <uuid>`### Codex- Find session: ls ~/.codex/sessions/ (newest dir = most recent session)- Resume: `codex resume <uuid> (or: codex resume --last)`### OpenCode- Find session: opencode sessions list- Resume: `opencode -s <id> (long form: opencode --session <id>)`### Gemini CLI- Find session: run /chat list inside the Gemini session to see saved tags- Resume: `/chat resume <tag>`### Antigravity- Find session: open the Antigravity Agent Manager and pick the prior task thread- Resume: `resume the thread from the Antigravity Agent Manager`### Aider- Find session: aider keeps .aider.chat.history.md in the repo root- Resume: `aider --restore-chat-history`## Redaction- <N> `<type>` strings masked_Scrubbing is heuristic (regex baseline). An empty redaction list is NOT a guarantee this file is clean — review before sharing or committing._---<!-- Doc format v1 -->
Notes on the template:
- If there are no uncommitted changes, replace the Files Touched body with
_Working tree clean — no uncommitted edits._(or_Not a git repository — no diff captured._when there is no git). - If there are no decisions, the Key Decisions body is
_No decisions recorded._; omit the Gotcha: line when no gotcha was given. - The Redaction body is
_No token-like strings were detected._when nothing was masked. - The footer marker
<!-- Doc format v1 -->is mandatory and must be the last line — it is the ownership sentinel.
Paste-prompt
Default (file reachable):
Resume my work. Read the handoff doc at: <ABSOLUTE_DOC_PATH>If that path does NOT exist on this machine, STOP and ask me to paste the handoff — do not improvise context.The exact uncommitted edits are in: <ABSOLUTE_DIFF_PATH>
`--inline` (cross-machine, file unreachable): embed the FULL doc body between markers so it travels in the prompt itself:
Resume my work using the self-contained handoff below.This is a full handoff doc — treat everything between the markers as ground truth. If it references a `.diff` path that does not exist on this machine, ask me to paste the diff.BEGIN HANDOFF<full rendered handoff document, including the Doc format v1 footer>END HANDOFF
Safety defaults
- The doc + diff are gitignored by default (
.handoff/.gitignore=*) and never auto-committed. Do not print agit addhint. - Secret scrubbing runs over both free text and the diff before any write.
- Scrubbing is heuristic — advise the user to review before sharing or committing.