ccc-handoff · diff
git:20260707.947ab2f to git:20261013.fbe187d
89 added, 161 removed. Audit A to A.
---
name: ccc-handoff
- description: "Proactive context reset — write a dense handoff file and tell the user to start a NEW chat now. Context degrades quality as it fills; fix is frequent handoffs, not deeper compaction."
+ description: "Write a dense handoff file and tell the user to resume in a new chat before a long context degrades output quality. Use when a chunk of work is done, the topic is about to switch, the model starts forgetting context, or a long orchestration run is mid-flight."
+ allowed-tools:
+ - Read
+ - Write
+ - Bash
+ - Glob
+ argument-hint: "[optional topic or short-id]"
model: sonnet
effort: medium
---
- # /ccc-handoff — Hand Off to a Fresh Session
-
- **Core idea:** context windows degrade model quality as they fill up. The fix is not "compact harder" — it's "hand off to a fresh chat frequently." This skill writes a dense, information-preserving handoff file and then tells you, explicitly, to open a new chat and resume there. It is meant to be invoked **often**, not just when a session is dying.
+ # /ccc-handoff — Hand off to a fresh session
- Pattern popularized by Matt Pocock (open a fresh chat frequently instead of letting one session's context degrade).
+ **CC Commander** · /ccc-handoff · a resumable handoff file plus an explicit instruction to continue in a new chat.
- ## When to Use
+ Output quality drops as a context window fills. This skill preserves the session's state in a file and moves the work to a fresh chat. Run it often, at natural boundaries, not only when a session is failing.
- Use this proactively — the whole point is that you run it BEFORE quality degrades, not after:
+ ## When to use / when not to
- - After finishing a coherent chunk of work (a feature, a fix, a review pass) — even mid-session
- - Before starting an unrelated task in the same chat (topic switch = handoff point)
- - The moment you notice the model getting slower, forgetting earlier context, or making mistakes it wouldn't normally make
- - Mid-way through a long orchestration run (`/ccc-orchestrate`, `/ccc-plan-exec`) — long multi-step Executor loops are exactly when context degrades fastest; do not wait for the run to finish
- - End of a work session before closing Claude Code (same use case as `/ccc-save-session`, but treat "session end" as just one of many trigger points, not the primary one)
+ Use it:
- If you are asking "should I hand off now or wait" — the answer is hand off now. Frequency is cheap; degraded output is not.
+ - After finishing a coherent chunk of work (a feature, a fix, a review pass), even mid-session.
+ - Before starting an unrelated task in the same chat. A topic switch is a handoff point.
+ - As soon as the model slows down, forgets earlier context, or makes mistakes it normally would not.
+ - Mid-way through a long orchestration run (`/ccc-orchestrate`, `/ccc-plan-exec`, a Workflow run). Long multi-step executor loops degrade context fastest; do not wait for the run to finish.
+ - At the end of a work session. This overlaps `/ccc-save-session`; session end is one trigger among many here.
- ## Relationship to /ccc-save-session and /ccc-resume-session
+ If the question is "hand off now or wait", hand off now. Frequent handoffs are cheap; degraded output is not.
- This skill reuses the **exact same file format and location** as `/ccc-save-session` — same `~/.claude/sessions/` directory, same `YYYY-MM-DD-<short-id>-session.tmp` naming. It does not invent a second format. `/ccc-resume-session` loads a handoff file with zero changes.
+ Do not use it to summarize for a human reader (use `/ccc-standup`) or to compact in place. This skill ends the current chat's working life.
- The difference is framing and cadence: `/ccc-save-session` is typically invoked once, at the natural end of a session. `/ccc-handoff` is the same mechanic invoked deliberately and repeatedly, as a quality-preservation habit — and it always ends with an explicit instruction to leave the current chat.
+ ## Relationship to /ccc-save-session and /ccc-resume-session
- ## Process
+ The file format and location are identical to `/ccc-save-session`: the `~/.claude/sessions/` directory, `YYYY-MM-DD-<short-id>-session.tmp` naming, and the same section set. There is no second format. `/ccc-resume-session` loads a handoff file unchanged.
- ### Step 1: Gather context
+ The difference is cadence and ending. `/ccc-save-session` usually runs once at the end of a session. `/ccc-handoff` is the same mechanic used repeatedly as a quality habit, and it always ends by telling the user to leave this chat.
- Before writing the file, collect:
+ ## What happens
- - Read all files modified during this session (use git diff or recall from conversation)
- - Review what was discussed, attempted, and decided
- - Note any errors encountered and how they were resolved (or not)
- - Check current test/build status if relevant
- - If this handoff is firing mid-orchestration (`/ccc-orchestrate` or `/ccc-plan-exec` in flight), capture the exact step/phase the Executor is on — not just the overall goal
+ ### 1. Gather context
- ### Step 2: Create the sessions folder if it does not exist
+ Collect, before writing anything:
```bash
- mkdir -p ~/.claude/sessions
+ git status --short
+ git diff --stat
+ git log --oneline -10
```
- ### Step 3: Write the session file
-
- Create `~/.claude/sessions/YYYY-MM-DD-<short-id>-session.tmp`, using today's actual date and a short-id that satisfies these rules:
-
- - Allowed characters: lowercase `a-z`, digits `0-9`, hyphens `-`
- - Minimum length: 8 characters
- - No uppercase letters, no underscores, no spaces
-
- Valid examples: `abc123de`, `handoff-mid-orch1`
- Invalid examples: `ABC123de` (uppercase), `short` (under 8 chars), `test_id1` (underscore)
-
- Full valid filename example: `2024-01-15-abc123de-session.tmp`
-
- ### Step 4: Populate all sections
-
- Write every section honestly and completely — full depth, not a shorter or lossier version just because handoffs are meant to be frequent. Frequency should come from cheap, fast invocation of the full format, never from cutting corners on what's preserved. Write "Nothing yet" or "N/A" if a section genuinely has no content. An incomplete file is worse than an honest empty section.
-
- Use the identical section set as `/ccc-save-session`:
-
- ```markdown
- # Session: YYYY-MM-DD
-
- **Started:** [approximate time if known]
- **Last Updated:** [current time]
- **Project:** [project name or path]
- **Topic:** [one-line summary of what this session was about]
-
- ---
-
- ## What We Are Building
-
- [1-3 paragraphs describing the feature, bug fix, or task. Include enough
- context that someone with zero memory of this session can understand the goal.
- Include: what it does, why it is needed, how it fits into the larger system.]
-
- ---
-
- ## What WORKED (with evidence)
-
- [List only things that are confirmed working. For each item include WHY you
- know it works — test passed, ran in browser, Postman returned 200, etc.
- Without evidence, move it to "Not Tried Yet" instead.]
-
- - **[thing that works]** — confirmed by: [specific evidence]
-
- If nothing is confirmed working yet: "Nothing confirmed working yet — all approaches still in progress or untested."
-
- ---
-
- ## What Did NOT Work (and why)
-
- [This is the most important section. List every approach tried that failed.
- For each failure write the EXACT reason so the next session does not retry it.
- Be specific: "threw X error because Y" is useful. "did not work" is not.]
-
- - **[approach tried]** — failed because: [exact reason / error message]
-
- If nothing failed: "No failed approaches yet."
-
- ---
-
- ## What Has NOT Been Tried Yet
-
- [Approaches that seem promising but have not been attempted. Ideas from the
- conversation. Alternative solutions worth exploring.]
-
- - [approach / idea]
-
- If nothing is queued: "No specific untried approaches identified."
-
- ---
-
- ## Current State of Files
-
- [Every file touched this session. Be precise about what state each file is in.]
-
- | File | Status | Notes |
- | ----------------- | -------------- | -------------------------- |
- | `path/to/file.ts` | Done | [what it does] |
- | `path/to/file.ts` | In Progress | [what is done, what is left] |
- | `path/to/file.ts` | Broken | [what is wrong] |
- | `path/to/file.ts` | Not Started | [planned but not touched] |
-
- If no files were touched: "No files modified this session."
-
- ---
-
- ## Decisions Made
-
- [Architecture choices, tradeoffs accepted, approaches chosen and why.
- These prevent the next session from relitigating settled decisions.]
+ - Read the files modified this session (from the diff above or from the conversation).
+ - Review what was discussed, attempted and decided.
+ - Note every error hit and whether it was resolved.
+ - Record the current test/build result if relevant. Use the result already observed this session; if none was observed, write "not run this session" rather than claiming a status.
+ - If an orchestration is in flight (`/ccc-orchestrate`, `/ccc-plan-exec`, a Workflow run, a Routine or a `/loop`), capture the exact phase/step the executor is on and how to inspect it (`/workflows`, `/schedule`), not just the overall goal.
- - **[decision]** — reason: [why this was chosen over alternatives]
+ If `git` fails because the directory is not a repository, skip the git commands and list touched files from the conversation.
- If no significant decisions: "No major decisions made this session."
+ ### 2. Resolve the file path
- ---
+ ```bash
+ mkdir -p "$HOME/.claude/sessions" && echo "$HOME/.claude/sessions" && date +%F
+ ```
- ## Blockers and Open Questions
+ Build the filename `<date>-<short-id>-session.tmp` from that date and a short-id that:
- [Anything unresolved that the next session needs to address or investigate.
- Questions that came up but were not answered. External dependencies waiting on.]
+ - uses only lowercase `a-z`, digits `0-9` and hyphens `-`;
+ - is at least 8 characters;
+ - has no uppercase letters, underscores or spaces.
- - [blocker / open question]
+ Valid: `abc123de`, `handoff-mid-orch1`. Invalid: `ABC123de` (uppercase), `short` (under 8), `test_id1` (underscore). If `$ARGUMENTS` names a topic, derive the short-id from it (for example `auth-refactor`).
- If none: "No active blockers."
+ Every invocation gets its own file. Never append to an earlier handoff, even one from this same session. Confirm the target does not exist yet:
- ---
+ ```bash
+ test ! -e "$HOME/.claude/sessions/<date>-<short-id>-session.tmp" && echo free
+ ```
- ## Exact Next Step
+ If it exists, change the short-id and check again.
- [If known: The single most important thing to do when resuming. Be precise
- enough that resuming requires zero thinking about where to start. If this
- handoff fired mid-orchestration, name the exact phase/step the Executor
- should re-enter — e.g. "resume /ccc-plan-exec at Step 4 of the plan file,
- Task 4.2 (Task 4.1 is done and verified)."]
+ ### 3. Write the file
- [If not known: "Next step not determined — review 'What Has NOT Been Tried Yet'
- and 'Blockers' sections to decide on direction before starting."]
+ Write the file with the Write tool at the absolute path from step 2 (expand `$HOME`; the tool does not expand `~`). Use the section set in [references/handoff-template.md](references/handoff-template.md).
- ---
+ Fill every section at full depth. Frequency comes from fast invocation of the full format, never from a shorter or lossier file. Write "Nothing yet" or "N/A" when a section is genuinely empty; an incomplete file is worse than an honest empty section. Only "Environment and Setup Notes" may be omitted. Record environment variable names only, never their values.
- ## Environment and Setup Notes
+ If the user asks to hand off mid-task, save what is known so far and mark in-progress items clearly. An honest partial handoff beats waiting for a clean stopping point that never comes.
- [Only fill this if relevant — commands needed to run the project, env vars
- required, services that need to be running, etc. Skip if standard setup.]
+ ### 4. Verify the file
- [If none: omit this section entirely.]
+ ```bash
+ f="$HOME/.claude/sessions/<date>-<short-id>-session.tmp"
+ [[ "$(basename "$f")" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9-]{8,}-session\.tmp$ ]] && test -s "$f" && echo name-ok
+ grep -cE '^## (What We Are Building|What WORKED|What Did NOT Work|What Has NOT Been Tried Yet|Current State of Files|Decisions Made|Blockers and Open Questions|Exact Next Step)' "$f"
```
- ### Step 5: Show the file to the user
+ Expect `name-ok` and a count of `8`. On a lower count, add the missing sections and rerun. On a name failure, rename the file to a valid short-id and rerun.
- After writing, display the full contents and confirm the path:
+ ### 5. Show the file
+ Print the full contents, then the resolved path:
+
```
- Handoff saved to [actual resolved path to the session file]
+ Handoff saved to <resolved path>
```
- ### Step 6: Tell the user to leave — this is the whole point
+ ### 6. Tell the user to leave
- This is the last thing printed. Do not bury it, do not soften it, do not follow it with more discussion. Print exactly this, filled in:
+ This is the last thing printed. Do not bury it, soften it, or follow it with more discussion. Print exactly this, with the real path filled in:
```
════════════════════════════════════════════════
HANDOFF COMPLETE — START A NEW CHAT NOW
- This session's context is getting long enough that quality will
- start degrading if you keep working here. Open a NEW chat/session
- and run:
+ This session's context is long enough that quality will
+ start degrading if you keep working here. Open a new
+ chat/session and run:
- /ccc-resume-session [actual resolved path to the session file]
+ /ccc-resume-session <resolved path>
Do not continue this conversation for further work.
════════════════════════════════════════════════
```
- If invoked mid-orchestration (`/ccc-orchestrate` / `/ccc-plan-exec` in flight), add one line above the box: "Orchestration paused at [phase/step] — the fresh session will resume the Executor loop from there."
+ If an orchestration is in flight, print one line above the box: "Orchestration paused at <phase/step> — the fresh session will resume the executor loop from there."
- ---
+ ## Decision points
- ## Anti-Patterns
+ None. The skill does not ask before writing: it always creates a new file under `~/.claude/sessions/` and always ends with the instruction to leave. If the user wants to keep working here instead, that is their call after the box is printed; do not offer it as an option.
- - **Waiting until context is nearly full to run this.** By the time context pressure is obvious, quality has already degraded — that's the failure mode this skill exists to prevent. Run it early and often, not as a last resort.
- - **Skipping the "open a new chat now" instruction, or softening it into a suggestion.** The instruction to leave is not optional framing — it is the mechanism. A handoff file nobody acts on accomplishes nothing.
- - **Writing a shorter or lossier file "because this is meant to be frequent."** Frequency must come from how cheap and fast invocation is, not from truncating what gets preserved. Every section from `/ccc-save-session`'s format is still required, every time.
- - **Continuing to work in the same chat after writing the file** "just to finish one more thing." That one more thing is exactly what degraded context produces worse output for.
+ ## Done when
- ---
+ - Step 4 printed `name-ok` and a section count of `8`.
+ - The file contents and the resolved path were shown.
+ - The handoff box with the real `/ccc-resume-session <path>` line is the final output.
- ## Notes
+ ## Guardrails
- - Reuses `/ccc-save-session`'s exact file format and `~/.claude/sessions/` location — no second format, no compatibility shim needed for `/ccc-resume-session`.
- - Each invocation gets its own file — never append to a previous handoff's file, even if invoked twice in one session.
- - Ties into the Orchestrator/Executor model (`/ccc-orchestrate`, `/ccc-plan-exec`): long-running multi-step execution is exactly when this should fire mid-task, at natural phase boundaries — not only when the whole run finishes.
- - If the user asks to hand off mid-task, save what is known so far and mark in-progress items clearly — an honest partial handoff beats waiting for a "clean" stopping point that never comes.
+ - Never run this only when context is nearly full. By then quality has already degraded; run it early and often.
+ - Never skip or soften the "start a new chat now" instruction. A handoff file nobody acts on accomplishes nothing.
+ - Never write a shorter or lossier file because handoffs are frequent. Every section is required every time.
+ - Never continue working in the same chat after writing the file "to finish one more thing".
+ - Never overwrite or append to an existing session file.
+ - Never write secrets, tokens or credential values into the file; name the variable or secret reference instead.
+ - Writes only inside `~/.claude/sessions/`. It does not commit, push, post, or update trackers.
+
+ ## See also
+
+ - `/ccc-save-session` — same format, end-of-session cadence
+ - `/ccc-resume-session` — loads the handoff in the new chat
+ - `/ccc-orchestrate`, `/ccc-plan-exec` — long executor loops where mid-run handoffs matter most
---
> ⚙️ **Fable contract:** plan before build · verifier ≠ worker · prove before alarm · loops need gates · leave durable state — `rules/fable-method.md`