Handoff revive
Skill sofumel/claude-handoff-revive/plugins/handoff-revive/skills/handoff-revive
Resume Claude Code work after rate/usage/context limits without replaying the prior transcript. Auto-saves at 90%/95% usage. Plugin-installable, 10 languages.
npx -y skills add sofumel/claude-handoff-revive --skill handoff-reviveAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Save a compact handoff checkpoint and resume work in a fresh session without replaying the entire transcript via `--resume`. SAVE trigger — the slash command `/handoff-revive:save` (carries forward still-relevant goal/decisions/lessons from any existing handoff, then runs a content-quality check). AUTO-SAVE trigger — when the UserPromptSubmit hook injects "5-hour usage at N%" context (run SAVE flow without asking, prepend brief notice). RESUME trigger — the slash command `/handoff-revive:resume`. Also use when the SessionStart hook surfaces an existing handoff at `.claude/handoff/current.md` — read that file instead of recommending `claude --resume`. Configuration via `/handoff-revive:auto on|off|status` (per-session toggle). Do NOT trigger on natural-language phrases like "save handoff" / "ハンドオフ保存して" / "続きから" — only the slash commands and hook contexts above.
SKILL.md
21.3 KB, as published. Nobody here has run it
handoff-revive
Save the minimum state needed to continue work later, so the next session can start fresh (NOT via --resume / -c) and reload only a small file.
Why not claude --resume
--resume and -c replay the entire prior transcript into context. For a typical session this costs tens of thousands of tokens (often 100k+ for long sessions) before the user even asks anything. A handoff file costs 1,000–3,000 tokens. Always prefer the handoff file when one exists.
Two modes
Mode 1: SAVE (/handoff-revive:save)
Triggered ONLY by:
- User runs the slash command
/handoff-revive:save - The UserPromptSubmit hook injects auto-save context (see Mode 1c below)
Do NOT trigger on natural-language phrases like "save handoff", "checkpoint", "ハンドオフ", "保存", "保存して中断". Users are expected to use the slash command. If a user types one of those phrases without the slash command, treat it as a regular message (gently remind them they can run /handoff-revive:save if they want to save).
Steps:
-
Detect language — read
.claude/handoff/langif it exists. Trim whitespace; the file holds a language code (one of:ja,en,zh(Simplified),zh-TW(Traditional),ko,es,pt,de,fr,tr) with no trailing newline. Otherwise detect from the user's most recent message:- Hiragana/Katakana →
ja - Hangul →
ko - Han characters: simplified markers (e.g. 这, 国, 学) →
zh; traditional markers (e.g. 這, 國, 學) →zh-TW - Cyrillic / Arabic → fall back to
en - Latin script: detect by common diacritics + words:
é à è ç+ words like fichier, avec, est →frä ö ü ß+ words like Datei, und, ist →deã õ ç+ words like arquivo, está, para →ptñ+ Spanish words (archivo, está, con) →esı ş ğ ç+ Turkish words (dosya, için, çalış) →tr- Otherwise →
en
When the message is mixed or ambiguous, default to
en. Write the chosen code to.claude/handoff/lang(no newline) using your file-write tool. Subsequent saves reuse the persisted value unless the user explicitly asks to switch language. - Hiragana/Katakana →
-
Carry forward, then fill the schema — if
.claude/handoff/current.mdalready exists, read it first and preserve anygoal,decisions, andlessons_learnedthat are still relevant (drop what is now obsolete). This matters in long sessions: details captured in an earlier save survive even if they have since scrolled out of your context. Then write the full handoff to.claude/handoff/current.mdusing the template below. All section keys stay in English (machine-readable); section values go in the user's language. If approaches were tried and abandoned this session, record them under## lessons_learned(attempted / why_abandoned / learned); omit the section if there were none.Overwrite guard: if
.claude/handoff/current.mdalready exists and itsbranch:metadata differs from the current git branch, it likely belongs to different work. Ask the user before overwriting it (e.g. "既存の handoff は別ブランチ (feature/x) の作業のものです。上書きしますか?"). In AUTO-SAVE mode (Mode 1c), do not ask — proceed, but mention the cross-branch overwrite in the notice. -
For
next_action: be executable. Not "continue refactoring auth" butEdit src/auth/login.ts:42 — replace the bcrypt.compare call with the timing-safe variant from line 88. Include the exact file:line and the exact next command/edit. The goal is zero "thinking time" on resume. -
For
touched_files: format aspath -- one-line reason. Use--(space, two dashes, space) as the separator, NOT:, because Windows absolute paths contain a colon (C:\...) and would break the schema. Always prefer project-relative paths with forward slashes (src/auth/login.ts); fall back to absolute paths only when the file is genuinely outside the project. No diffs, no line ranges — just enough to re-orient.Token-saving helper (recommended): instead of thinking through which files to list, run
extract-recent-filesto get a deterministic list fromgit status(orfind -mminif non-git). This saves ~200–500 tokens per save:- Linux/macOS/WSL/Git-Bash:
bash "${CLAUDE_PLUGIN_ROOT:-.claude}/skills/handoff-revive/scripts/extract-recent-files.sh" - Windows PowerShell:
$r = if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { ".claude" }; powershell -ExecutionPolicy Bypass -File "$r/skills/handoff-revive/scripts/extract-recent-files.ps1"
The script outputs
- <path> -- <reason>lines (max 20). Paste them under## touched_files, then refine reasons where the auto-generatedmodified/untrackeddoesn't capture intent (e.g. "needs rollback" / "validated; do not touch"). - Linux/macOS/WSL/Git-Bash:
-
Run
finalize-handoff— single zero-token call that does validate + cleanup + savings report. Path uses${CLAUDE_PLUGIN_ROOT:-.claude}so the same command works in plugin and standalone installs:-
Linux/macOS/WSL/Git-Bash:
bash "${CLAUDE_PLUGIN_ROOT:-.claude}/skills/handoff-revive/scripts/finalize-handoff.sh" -
Windows PowerShell:
$r = if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { ".claude" }; powershell -ExecutionPolicy Bypass -File "$r/skills/handoff-revive/scripts/finalize-handoff.ps1" -
Exit 0: handoff is valid and finalized. Stderr will show
[handoff-revive] OK Saved <path> (~N tokens). Estimated savings on next resume: tens of thousands of tokens (vs --resume replaying full prior context).Capture both lines and surface them to the user in step 7. -
Exit 1: validator failed. Stderr lists the issues. Read each, fix the corresponding fields in
.claude/handoff/current.md, then re-call. Maximum 2 retries — if still failing, stop and warn the user with remaining errors.
If the user explicitly sets
HANDOFF_SKIP_VALIDATE=1, skip this step. -
-
Content-quality pass (every save, including AUTO-SAVE).
finalize-handoffcatches structural issues for free; this adds the Claude-driven semantic checks: isgoalspecific enough? does eachdecisioninclude a real reason? are blockers phrased as answerable questions? doeswipsay enough to resume mid-edit? Rewrite vague fields and re-run finalize. For AUTO-SAVE, do a single quick pass — don't over-iterate near the rate limit. -
Confirm to user in their language. State the path saved, summarize
next_actionin 1 line, show the savings line from finalize's stderr (e.g. "節約見込み: 数万トークン"), and remind: "To resume, start a NEW session (do not useclaude --resume) and run/handoff-revive:resume."
Mode 1b: the content-quality checklist (step 6 above)
The deterministic validator (folded into finalize-handoff) handles all structural issues for free. The content-quality pass in step 6 adds the Claude-driven checks the validator cannot do:
- Is
goalspecific enough that someone with no context understands it? (Validator only checks non-empty.) - Does each entry in
decisionsinclude a real reason after the dash, not just the decision restated? - Are
blockersphrased as answerable questions, not vague worries? - Does
wipdescribe state precisely enough to resume mid-edit (e.g. "1/3 functions converted, line 42 next" — not "still working on auth")? - Does each
lessons_learnedentry describe a genuinely failed attempt (tried and abandoned), not just an option that wasn't chosen? Unchosen options belong indecisions.
If any of the above is weak, rewrite that field and save again. Validator re-runs automatically. Then confirm to user.
Mode 1c: AUTO-SAVE (triggered by hook, no user request)
Auto-save fires when the UserPromptSubmit hook injects additionalContext containing one of the directives below. The hook fires after the usage-monitor PostToolUse hook detected rate_limits.five_hour.used_percentage crossing a configured threshold (defaults: 90% / 95%).
You will see context like one of these in the user's prompt:
⚠️ 5-hour usage at 92%. Auto-save a handoff before answering the user. Run the SAVE flow (extract-recent-files → write handoff → finalize-handoff). Do NOT ask the user. After save, briefly notify them in their language…
🚨 CRITICAL: 5-hour usage at 96%. IMMEDIATELY auto-save a handoff before answering the user…
When you see this:
-
Do NOT ask permission. The user has implicitly opted in by leaving auto-save enabled (default). If they wanted to ask first, they would have run
/handoff-revive:auto off. -
Run the full SAVE flow steps 1–6 (detect lang → carry-forward + fill schema → executable next_action → fill touched_files → finalize-handoff → content-quality pass). Use
extract-recent-filesto populatetouched_files. Keep the quality pass to a single quick rewrite — you are near the rate limit, so don't over-iterate. -
Prepend a brief auto-save notice to your response in the user's language, then handle their actual request. Examples:
lang AUTO_SAVE notice (e.g. 92%) URGENT notice (e.g. 96%) ja ⚠️ 使用量 92% に到達したため、ハンドオフを自動保存しました (~N tokens)。 🚨 緊急: 使用量 96%、自動保存しました (~N tokens)。新規セッションで /handoff-revive:resumeを実行すれば再開できます。en ⚠️ Usage hit 92% — auto-saved handoff (~N tokens). 🚨 CRITICAL: usage at 96% — auto-saved (~N tokens). Start a new session and run /handoff-revive:resumeif rate-limited.zh ⚠️ 使用率达到 92%,已自动保存交接 (~N tokens)。 🚨 紧急: 使用率 96%,已自动保存。新会话运行 /handoff-revive:resume即可恢复。zh-TW ⚠️ 使用率達到 92%,已自動儲存交接 (~N tokens)。 🚨 緊急: 使用率 96%,已自動儲存。新會話執行 /handoff-revive:resume即可恢復。ko ⚠️ 사용량 92% 도달, 핸드오프 자동 저장 (~N tokens). 🚨 긴급: 사용량 96%, 자동 저장. 새 세션에서 /handoff-revive:resume실행.es ⚠️ Uso al 92% — handoff auto-guardado (~N tokens). 🚨 CRÍTICO: uso al 96% — auto-guardado. Inicia sesión nueva y ejecuta /handoff-revive:resume.pt ⚠️ Uso a 92% — handoff auto-guardado (~N tokens). 🚨 CRÍTICO: uso a 96% — auto-guardado. Inicia uma sessão nova e executa /handoff-revive:resume.de ⚠️ Nutzung bei 92% — Handoff automatisch gespeichert (~N tokens). 🚨 KRITISCH: Nutzung bei 96% — automatisch gespeichert. Starte neue Sitzung und führe /handoff-revive:resumeaus.fr ⚠️ Utilisation à 92% — handoff auto-sauvegardé (~N tokens). 🚨 CRITIQUE : utilisation à 96% — auto-sauvegardé. Lancez une nouvelle session et exécutez /handoff-revive:resume.tr ⚠️ Kullanım %92 — handoff otomatik kaydedildi (~N tokens). 🚨 KRİTİK: kullanım %96 — otomatik kaydedildi. Yeni oturum başlatın ve /handoff-revive:resumeçalıştırın. -
Add a separator (
────────) and continue with the user's actual request — do not let the auto-save interrupt the work. -
If
finalize-handofffails after 2 retries, warn the user briefly but proceed with their request anyway. Their work is more important than a clean handoff at this moment.
Mode 2: RESUME (new session, after limit reset)
Triggered ONLY by:
- User runs the slash command
/handoff-revive:resume - The SessionStart hook injected
additionalContextmentioning the existing.claude/handoff/current.mdAND the user then runs/handoff-revive:resume(the hook only proactively surfaces files modified withinHANDOFF_SURFACE_DAYS, default 7 — older handoffs are not auto-announced but are still usable via/handoff-revive:resume)
Do NOT trigger on natural-language phrases like "resume from handoff", "continue", "続きから", "继续", "계속", "reanudar". Users are expected to use the slash command. If you see one of those phrases without the slash command, gently remind the user they can run /handoff-revive:resume.
Note: skills cannot intercept the claude --resume / -c CLI flag (the flag is processed before the skill loads). The SessionStart hook is what differentiates a --resume session from a fresh start; if the user is in a --resume session and a handoff exists, you may briefly note that /handoff-revive:resume in a new session would have been cheaper, but proceed with their --resume flow.
Steps:
-
Read
.claude/handoff/current.md. Do not read prior session transcripts. -
Read
.claude/handoff/langand respond in that language. -
Resume receipt (zero tokens) — before editing, print a tiny receipt that proves the load boundary without echoing the handoff body or prior transcript:
- Linux/macOS/WSL/Git-Bash:
bash "${CLAUDE_PLUGIN_ROOT:-.claude}/skills/handoff-revive/scripts/resume-receipt.sh" - Windows PowerShell:
$r = if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { ".claude" }; powershell -ExecutionPolicy Bypass -File "$r/skills/handoff-revive/scripts/resume-receipt.ps1"
Show this receipt before any edits. It should say the session loaded
current.mdonly, did not load prior transcript/history snapshots, list section names/counts, reportnext_action_present, summarize freshness asokor warning count, and include privacy flags such ashandoff_body_echoed=false. - Linux/macOS/WSL/Git-Bash:
-
Freshness check (zero tokens) — compares the handoff's
base_commit/branchmetadata to the current git state:- Linux/macOS/WSL/Git-Bash:
bash "${CLAUDE_PLUGIN_ROOT:-.claude}/skills/handoff-revive/scripts/check-freshness.sh" - Windows PowerShell:
$r = if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { ".claude" }; powershell -ExecutionPolicy Bypass -File "$r/skills/handoff-revive/scripts/check-freshness.ps1"
No output = fresh, continue silently. If it prints warnings (file age / commits since save / branch mismatch / cannot verify), relay them to the user in their language at the top of your resume summary. Never refuse to resume because of a warning — it is information, not a gate. Legacy handoffs without metadata produce no output.
In the same step, count the resume for
/handoff-revive:stats(zero tokens, best-effort):- Linux/macOS/WSL/Git-Bash:
bash "${CLAUDE_PLUGIN_ROOT:-.claude}/skills/handoff-revive/scripts/stats-handoff.sh" record resume - Windows PowerShell:
$r = if ($env:CLAUDE_PLUGIN_ROOT) { $env:CLAUDE_PLUGIN_ROOT } else { ".claude" }; powershell -ExecutionPolicy Bypass -File "$r/skills/handoff-revive/scripts/stats-handoff.ps1" -Cmd record -Kind resume
- Linux/macOS/WSL/Git-Bash:
-
Read each file listed in
touched_filesonly if needed for the immediatenext_action. Do not preemptively read all of them. -
State the goal and
next_actionback to the user in 1–2 sentences and ask "Proceed?" before editing. -
After the user confirms or redirects, execute
next_action.
Schema (template)
Write to .claude/handoff/current.md:
---
schema_version: "1.0"
saved_at: {ISO-8601 timestamp}
lang: {ja|en|zh|zh-TW|ko|es|pt|de|fr|tr}
session_summary_tokens_estimated: {rough count}
---
## goal
{1 line: what is the user ultimately trying to accomplish}
## done
- {completed item}
- ...
## wip
- {currently in-progress item, with state}
## todo
- {not yet started}
- ...
## blockers
- {question or unknown that is blocking; omit section if none}
## next_action
{REQUIRED. file:line + exact command/edit. Must be executable without further thinking.}
## touched_files
- path/to/file.ts -- {one-line reason}
- ...
## decisions
- {decision}: {WHY — the reason behind it, not just what was decided}
- ...
## lessons_learned
- attempted: {approach that was tried}
why_abandoned: {why it failed or was dropped}
learned: {what to remember next time}
- ... (OPTIONAL section — omit entirely if there were no failed attempts)
Section headings use H2 (##) so the file renders cleanly on GitHub / VS Code preview while remaining unambiguous to parse.
Do not write author / author_email / branch / base_commit / created_at yourself — finalize-handoff injects them into the frontmatter automatically from git (and skips them outside a git repo). Set HANDOFF_HIDE_EMAIL=1 to omit the email.
blockers and lessons_learned are optional: omit them when empty (the cleanup pass strips them automatically).
Templates (optional): /handoff-revive:save --template=vacation-handover switches to the long-handover variant for handing work to another person across an absence. Read ${CLAUDE_PLUGIN_ROOT:-.claude}/skills/handoff-revive/templates/vacation-handover.md and follow it: the frontmatter gains template: "vacation-handover" and a non-empty ## handover_notes section (contact / deadline / watch_out) becomes REQUIRED — the validator enforces both. Without --template, nothing changes.
Referencing files that don't exist yet (TDD, planned work): the validator checks that referenced paths exist and warns about missing ones (informational; --strict turns them into errors). To reference a file you intend to create, mark it: in touched_files use - path/to/new.ts -- planned: will hold the new helper, and in next_action put # planned: on the line that mentions it. lessons_learned is for genuinely failed attempts — approaches that were tried and abandoned — not for options that were merely considered and not chosen (those belong in decisions with their WHY). Native /rewind erases failures; this section is how the next session keeps what the failure taught.
Hook setup
Plugin installs auto-activate hooks. Standalone installs need a settings.json snippet — see HOOK_SETUP.md at the repo root for the snippets and full details.
Multi-language
Confirmation messages and the next_action summary line are written in the user's language. Section keys (goal, done, etc.) stay in English so the schema is parseable across languages. Supported: ja, en, zh (Simplified), zh-TW (Traditional), ko, es, pt, de, fr, tr. For other languages, fall back to English keys + the user's language for values.
Example confirmation strings:
| lang | save confirmation |
|---|---|
| ja | ハンドオフ保存しました: .claude/handoff/current.md。再開時は新規セッションで /handoff-revive:resume を実行してください(claude --resume は使わない)。 |
| en | Handoff saved: .claude/handoff/current.md. To resume, start a new session and run /handoff-revive:resume (do NOT use claude --resume). |
| zh | 已保存交接文件: .claude/handoff/current.md。恢复时请新建会话并运行 /handoff-revive:resume(不要使用 claude --resume)。 |
| ko | 핸드오프 저장됨: .claude/handoff/current.md. 재개 시 새 세션에서 /handoff-revive:resume 를 실행하세요 (claude --resume 사용 금지). |
| es | Handoff guardado: .claude/handoff/current.md. Para reanudar, inicia una sesión nueva y ejecuta /handoff-revive:resume (NO uses claude --resume). |
Token budget
Net cost per save: ~300–1,400 tokens (incl. finalize-handoff overhead).
Net cost per resume: ~800–2,800 tokens.
Net cost per AUTO-SAVE event: ~500–1,500 tokens (one full save per threshold crossing, max 2 per session: AUTO_SAVE then URGENT).
claude --resume costs tens of thousands of tokens (often 100k+ for long sessions) for the same resumption.
Break-even: 1 resume per save. Saves only, never resume → only the SKILL.md load is wasted. Best case: ~10–100× cheaper than --resume (depends on prior session size).
finalize-handoff outputs Estimated savings on next resume: tens of thousands of tokens to stderr after each save. Surface that line to the user in the confirmation message.
Auto-save can be opted out per-session via /handoff-revive:auto off, or globally via HANDOFF_AUTO_SAVE_PERCENT=disabled and HANDOFF_URGENT_PERCENT=disabled.
Do NOT
- Do not read prior session transcripts on resume. The handoff file is the single source of truth.
- Do not silently auto-invoke save from a hook (burns tokens without user knowing). Hooks only nudge.
- Do not write the entire conversation into the handoff file. Only the schema fields.
- Do not use
--resume/-cif a current handoff file exists. Warn the user first. - Do not translate section keys. Keys stay in English; values go in user's language.