Handoff — Pass The Baton
Summarize the current in-context conversation into a handoff a fresh agent (or
future-you) can pick up without re-reading the session. Two output modes:
- Inline mode (default) — render the handoff as Markdown directly in chat.
Nothing else. The output is the handoff.
- Doc mode — write the handoff to a per-project file and print only two
lines in chat: a link to the file and a copy-paste shortcut for the next
session.
Inline mode writes nothing. Doc mode writes exactly one Markdown file, in the host's
projects directory (or .tmp/handoff/ when the host is unknown). Neither mode edits
the project, stages, or commits.
Hard Rules
- No preamble. Do not say "Here's the handoff" or summarize what you're
about to write. The output is the handoff itself.
- No duplication. If a fact is captured in a committed file, plan, PRD,
issue, PR, or diff, link or path-reference it. Do not restate it.
- No fabrication. Every fact in the handoff comes from the in-context
conversation, files you read this session, or tool output you observed.
Don't invent decisions, file paths, or commit messages. Provenance is the
easiest thing to fake and the hardest to catch: a commit hash, a date, a
version, or a "this broke in" claim appears only if a command returned it in
this session. No result means the claim is dropped, not softened into
"has likely been broken for a while".
- Redact secrets. Never include API keys, tokens, passwords, PII, or
credentials visible in the conversation. If a secret is load-bearing
context, reference where it lives (env var name, 1Password item, secret
manager path) instead of pasting it.
- Empty sections never render. Pick from the section pool only what
applies. If only Goal and Next step exist, that's the whole handoff.
Argument parsing
The skill accepts a free-form argument string ($ARGUMENTS). Parse it once:
- Mode keyword. If the tokens contain any of
doc, document, or
--doc (case-insensitive, as a standalone token), switch to doc mode and
remove that token. Otherwise inline mode.
- Focus. The remaining tokens, joined with spaces, become the focus
string. The focus slants what the handoff emphasizes and seeds the
filename slug. Empty focus is fine — the handoff still works.
Examples:
| Invocation |
Mode |
Focus |
/handoff |
inline |
(none) |
/handoff fix login bug |
inline |
fix login bug |
/handoff doc |
doc |
(none) |
/handoff doc fix login bug |
doc |
fix login bug |
/handoff fix the login bug --doc |
doc |
fix the login bug |
Section pool
Pick from this pool. Include a section only if you actually have content for
it from the conversation. Order them as listed.
Core (almost always present)
- Goal — what the user wants, in one or two sentences. Top-level intent.
- Where we are — project path, branch, working-tree state (clean / dirty /
staged), last commit hash + subject. One short paragraph or a tight list.
- What's been decided — design choices, assumptions adopted, scope cuts.
Prevents the next session from re-litigating settled questions.
- Next step — the specific concrete action the next session should take
first. What "progress" means from here.
Conditional (only when applicable)
- Problem & repro — bug sessions: failure, reproduction steps, expected
vs actual.
- Findings — discoveries from this session that aren't yet captured in
code or commits.
- Tried & ruled out — paths explored and dropped, with the reason. Stops
the next agent re-walking dead ends.
- Open questions — gaps the previous session didn't close.
- Gotchas — non-obvious constraints learned the hard way.
- References — paths and URLs to issues, PRs, plans, ADRs, diffs.
Pointers, not copies.
- Suggested skills — by name (e.g.
superpowers:systematic-debugging,
dev:gh-actions-debug). One short line each — what the next agent might
reach for, why.
Deliberately not standalone sections
- "Impact" — folds into Goal if it matters.
- "Changes made" — that's what
git log / git diff is for. Reference the
branch and commits under Where we are / References.
- "Summary of what we did" — narrative recap of the session is noise. The
core sections already say where we ended up.
Inline mode
Render the handoff directly as Markdown in chat. No code-fence wrapper.
Start with:
# Handoff
<project-name> · <branch> · <YYYY-MM-DD HH:MM>
Then the applicable sections, each as ## Section name followed by its
content. Do not print a trailing summary, sign-off, or question.
A complete inline handoff
# Handoff
acme-api · issue-214 · 2026-09-02 17:40
## Goal
Stop the profile cache serving one tenant's body to another, without losing the
p95 win the cache was added for.
## Where we are
`~/repo/acme-api`, branch `issue-214`, tree dirty (3 modified, nothing staged).
Last commit `a91c4e2 fix: key the profile cache by tenant #214`.
## What's been decided
Key on `tenant + URL` rather than dropping the cache — measured at
`bench/parse.ts`, a correct per-tenant cache still saves ~12ms of the 40ms parse.
## Tried & ruled out
Keying on the resolved `Host` header: `resolveTenant()` runs after routing
(`src/router.ts:88`), so the header is not yet normalised at cache-write time.
## Next step
Add the seeded two-tenant case to `test/cache.test.ts` — it currently passes
against the buggy key, which is why the bug shipped.
## References
- Issue: https://github.com/acme/api/issues/214
Doc mode
Resolve the encoded cwd: take the absolute working directory and replace
every / with -. Example: /Users/foo/repo/proj → -Users-foo-repo-proj.
Build the filename: YYYY-MM-DD-HHMM[-slug].md, local time. Slug is
derived from the focus string if present:
- Lowercase, replace non-alphanumeric runs with
-, trim leading/trailing
-, collapse repeats, cap at ~40 chars. Use the first 4–6 meaningful
words.
- Omit the slug entirely if focus is empty.
Target path — use the first directory that matches the host you are running in:
| Host |
Base directory |
| Claude Code |
~/.claude/projects/<encoded-cwd>/handoff/ |
| Codex |
~/.codex/projects/<encoded-cwd>/handoff/ |
| OpenCode |
${XDG_CONFIG_HOME:-~/.config}/opencode/projects/<encoded-cwd>/handoff/ |
| pi |
~/.pi/agent/projects/<encoded-cwd>/handoff/ |
| Unknown, or you cannot tell |
.tmp/handoff/ in the current project — take this over guessing a home directory |
Create the handoff/ directory if needed.
On collision (same filename), suffix with -2, -3, … before .md.
Write the same Markdown body as inline mode to the file.
Print to chat exactly two lines, nothing else:
[<filename>](<absolute-path>)
Read @<absolute-path> and continue the work.
The first line renders as a clickable link in hosts that support it; the second is
the copy-paste shortcut for starting the next session.
Gathering data
Use only what the in-context conversation already provides plus light,
read-only inspection if needed:
git rev-parse --abbrev-ref HEAD — current branch.
git status --short — working-tree state.
git log -1 --oneline — last commit.
basename "$PWD" — project name for the strap line.
Read-only commands only. Reading project files to ground a fact is fine, but
only if the conversation pointed at them — don't go exploring.
Edge cases
- Empty session / nothing substantive happened — exit with one line:
Nothing worth handing off from this session.
No file, no Markdown body.
- Compacted session — early turns may be invisible. Note this once under
Goal or in a one-line aside if it materially affects the handoff.
- Focus argument unrelated to actual session work — trust the focus as
the user's framing for the next session, even if the previous session
drifted. Slant the handoff toward continuing in the focus direction.
- Multiple intermixed threads in the session — pick the one the focus
points at; if no focus, pick the thread the user spent the most recent
turns on. Mention dropped threads under Open questions only if they're
load-bearing.
1---2name: handoff3description: Compact the current conversation into a handoff so a fresh agent, or future-you, can pick up the work cold. With a `doc`, `document`, or `--doc` keyword, writes a per-project handoff file and prints only its path plus a shortcut to start the next session.4license: MIT5---67# Handoff — Pass The Baton89Summarize the current in-context conversation into a handoff a fresh agent (or10future-you) can pick up without re-reading the session. Two output modes:1112- **Inline mode** (default) — render the handoff as Markdown directly in chat.13 Nothing else. The output is the handoff.14- **Doc mode** — write the handoff to a per-project file and print only two15 lines in chat: a link to the file and a copy-paste shortcut for the next16 session.1718Inline mode writes nothing. Doc mode writes exactly one Markdown file, in the host's19projects directory (or `.tmp/handoff/` when the host is unknown). Neither mode edits20the project, stages, or commits.2122## Hard Rules23241. **No preamble.** Do not say "Here's the handoff" or summarize what you're25 about to write. The output is the handoff itself.262. **No duplication.** If a fact is captured in a committed file, plan, PRD,27 issue, PR, or diff, link or path-reference it. Do not restate it.283. **No fabrication.** Every fact in the handoff comes from the in-context29 conversation, files you read this session, or tool output you observed.30 Don't invent decisions, file paths, or commit messages. Provenance is the31 easiest thing to fake and the hardest to catch: a commit hash, a date, a32 version, or a "this broke in" claim appears only if a command returned it in33 this session. No result means the claim is dropped, not softened into34 "has likely been broken for a while".354. **Redact secrets.** Never include API keys, tokens, passwords, PII, or36 credentials visible in the conversation. If a secret is load-bearing37 context, reference where it lives (env var name, 1Password item, secret38 manager path) instead of pasting it.395. **Empty sections never render.** Pick from the section pool only what40 applies. If only Goal and Next step exist, that's the whole handoff.4142## Argument parsing4344The skill accepts a free-form argument string (`$ARGUMENTS`). Parse it once:45461. **Mode keyword.** If the tokens contain any of `doc`, `document`, or47 `--doc` (case-insensitive, as a standalone token), switch to doc mode and48 remove that token. Otherwise inline mode.492. **Focus.** The remaining tokens, joined with spaces, become the **focus**50 string. The focus slants what the handoff emphasizes and seeds the51 filename slug. Empty focus is fine — the handoff still works.5253Examples:5455| Invocation | Mode | Focus |56| ---------------------------------- | ------ | -------------------- |57| `/handoff` | inline | _(none)_ |58| `/handoff fix login bug` | inline | `fix login bug` |59| `/handoff doc` | doc | _(none)_ |60| `/handoff doc fix login bug` | doc | `fix login bug` |61| `/handoff fix the login bug --doc` | doc | `fix the login bug` |6263## Section pool6465Pick from this pool. Include a section only if you actually have content for66it from the conversation. Order them as listed.6768**Core (almost always present)**6970- **Goal** — what the user wants, in one or two sentences. Top-level intent.71- **Where we are** — project path, branch, working-tree state (clean / dirty /72 staged), last commit hash + subject. One short paragraph or a tight list.73- **What's been decided** — design choices, assumptions adopted, scope cuts.74 Prevents the next session from re-litigating settled questions.75- **Next step** — the specific concrete action the next session should take76 first. What "progress" means from here.7778**Conditional (only when applicable)**7980- **Problem & repro** — bug sessions: failure, reproduction steps, expected81 vs actual.82- **Findings** — discoveries from this session that aren't yet captured in83 code or commits.84- **Tried & ruled out** — paths explored and dropped, with the reason. Stops85 the next agent re-walking dead ends.86- **Open questions** — gaps the previous session didn't close.87- **Gotchas** — non-obvious constraints learned the hard way.88- **References** — paths and URLs to issues, PRs, plans, ADRs, diffs.89 Pointers, not copies.90- **Suggested skills** — by name (e.g. `superpowers:systematic-debugging`,91 `dev:gh-actions-debug`). One short line each — what the next agent might92 reach for, why.9394**Deliberately not standalone sections**9596- "Impact" — folds into Goal if it matters.97- "Changes made" — that's what `git log` / `git diff` is for. Reference the98 branch and commits under Where we are / References.99- "Summary of what we did" — narrative recap of the session is noise. The100 core sections already say where we ended up.101102## Inline mode103104Render the handoff directly as Markdown in chat. No code-fence wrapper.105106Start with:107108```109# Handoff110111<project-name> · <branch> · <YYYY-MM-DD HH:MM>112```113114Then the applicable sections, each as `## Section name` followed by its115content. Do not print a trailing summary, sign-off, or question.116117### A complete inline handoff118119```markdown120# Handoff121122acme-api · issue-214 · 2026-09-02 17:40123124## Goal125Stop the profile cache serving one tenant's body to another, without losing the126p95 win the cache was added for.127128## Where we are129`~/repo/acme-api`, branch `issue-214`, tree dirty (3 modified, nothing staged).130Last commit `a91c4e2 fix: key the profile cache by tenant #214`.131132## What's been decided133Key on `tenant + URL` rather than dropping the cache — measured at134`bench/parse.ts`, a correct per-tenant cache still saves ~12ms of the 40ms parse.135136## Tried & ruled out137Keying on the resolved `Host` header: `resolveTenant()` runs after routing138(`src/router.ts:88`), so the header is not yet normalised at cache-write time.139140## Next step141Add the seeded two-tenant case to `test/cache.test.ts` — it currently passes142against the buggy key, which is why the bug shipped.143144## References145- Issue: https://github.com/acme/api/issues/214146```147148## Doc mode1491501. Resolve the encoded cwd: take the absolute working directory and replace151 every `/` with `-`. Example: `/Users/foo/repo/proj` → `-Users-foo-repo-proj`.1522. Build the filename: `YYYY-MM-DD-HHMM[-slug].md`, local time. Slug is153 derived from the focus string if present:154 - Lowercase, replace non-alphanumeric runs with `-`, trim leading/trailing155 `-`, collapse repeats, cap at ~40 chars. Use the first 4–6 meaningful156 words.157 - Omit the slug entirely if focus is empty.1583. Target path — use the first directory that matches the host you are running in:159160 | Host | Base directory |161 | ---- | -------------- |162 | Claude Code | `~/.claude/projects/<encoded-cwd>/handoff/` |163 | Codex | `~/.codex/projects/<encoded-cwd>/handoff/` |164 | OpenCode | `${XDG_CONFIG_HOME:-~/.config}/opencode/projects/<encoded-cwd>/handoff/` |165 | pi | `~/.pi/agent/projects/<encoded-cwd>/handoff/` |166 | Unknown, or you cannot tell | `.tmp/handoff/` in the current project — take this over guessing a home directory |1671684. Create the `handoff/` directory if needed.1695. On collision (same filename), suffix with `-2`, `-3`, … before `.md`.1706. Write the same Markdown body as inline mode to the file.1717. Print to chat exactly two lines, nothing else:172173 ```174 [<filename>](<absolute-path>)175 Read @<absolute-path> and continue the work.176 ```177178 The first line renders as a clickable link in hosts that support it; the second is179 the copy-paste shortcut for starting the next session.180181## Gathering data182183Use only what the in-context conversation already provides plus light,184read-only inspection if needed:185186- `git rev-parse --abbrev-ref HEAD` — current branch.187- `git status --short` — working-tree state.188- `git log -1 --oneline` — last commit.189- `basename "$PWD"` — project name for the strap line.190191Read-only commands only. Reading project files to ground a fact is fine, but192only if the conversation pointed at them — don't go exploring.193194## Edge cases195196- **Empty session / nothing substantive happened** — exit with one line:197 > **Nothing worth handing off from this session.**198 No file, no Markdown body.199- **Compacted session** — early turns may be invisible. Note this once under200 Goal or in a one-line aside if it materially affects the handoff.201- **Focus argument unrelated to actual session work** — trust the focus as202 the user's framing for the next session, even if the previous session203 drifted. Slant the handoff toward continuing in the focus direction.204- **Multiple intermixed threads in the session** — pick the one the focus205 points at; if no focus, pick the thread the user spent the most recent206 turns on. Mention dropped threads under Open questions only if they're207 load-bearing.