Summarize & export a Claude Code session into one clean handoff.md for Gemini, GPT, or another Claude. Zero deps, single file, post-hoc.
claude-handoff
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
**Turn any Claude Code session — even a crashed one — into a clean handoff.md another AI can continue from. And give Claude Code permanent project memory, distilled from your own history.**
That's it. Your latest session becomes handoff.md: the conversation without
the noise, the files that changed, the commands that ran — opening with
instructions to the receiving assistant, so you can paste it straight into
Gemini, GPT, claude.ai, or a fresh Claude Code session with zero extra
prompting.
Claude Code stores every session locally as JSONL
(~/.claude/projects/…/*.jsonl), full of tool calls, tool results, thinking
blocks and system reminders. Existing exporters dump all of that into
markdown. claude-handoff instead produces a **handoff document** — and,
since it can read your *entire* history, a **project memory brief** too.
- **Zero dependencies.** Stdlib only, Python 3.9+. A nine-module package —
also shipped as a generated single-file script you can curl and audit.
- **Deterministic by default.** No API call, no cost, works offline.
- **--llm when you want a real summary.** Claude, OpenAI or Gemini via
your own API key — or --llm claude-cli, which runs your locally-installed
Claude Code CLI on your existing Pro/Max plan: **no API key at all**.
- **Noise-free.** Drops tool results, thinking blocks, system reminders,
subagent chatter, slash-command envelopes. Keeps user intent, assistant
answers, files modified, commands run — including the files and commands
of subagents (agent-*.jsonl), whose full transcripts stay behind
--include-sidechains.
- **Project memory.** chf --brief distills a project's ENTIRE session
history into one living brief — what this is, where things stand,
decisions, fixes, conventions, and an ordered resume plan of open
threads, every claim citing its session; --install-brief-hook injects
it into every new Claude Code session, so Claude starts already knowing
the project.
- **Safe to paste.** Secret-looking strings (API keys, tokens,
password=…) are redacted from every output — the handoff you paste into
a web chat is egress too. --anonymize goes further for public sharing.
---
Prerequisites
| Requirement | Minimum | Check | Notes |
|---|---|---|---|
| Python | 3.9+ | python3 --version | The only hard requirement |
| Claude Code | any | claude --version | Only for --llm claude-cli (uses your Pro/Max login) |
| pipx *(recommended)* | any | pipx --version | pip install pipx — or use brew / plain pip |
No third-party Python packages, ever — everything runs on the standard library.
Install
Installing the package gives you two identical commands: claude-handoff
and the short alias **chf**. Tab completion:
---
60 seconds: pick your situation
**A session crashed, hit the usage limit, or you closed the terminal:**
…then paste into claude.ai, ChatGPT, Gemini — or a fresh claude session.
Works on any old session; nothing needed to be installed *before* the crash.
**Moving work from Claude Code to another model:**
**"Which session was it where we talked about CORS?"**
**Give Claude Code permanent memory of this project:**
**A real summary instead of the transcript (goal / decisions / state / next):**
**A claude.ai or ChatGPT web chat instead of a terminal session:**
---
Project memory (--brief)
Claude Code forgets everything between sessions — but the whole history is
on your disk. chf --brief reads **every** session of the current project
and writes one memory document to ~/.claude/briefs/ .md:
- a factual **session timeline** + most-touched files (deterministic, free);
- with --llm, a **distilled memory** that opens with *what this is*
(product, stack, current state) and *where things stand* (done / in
flight / not started), then decisions with their why, fixed bugs,
conventions — and *open threads* as an ordered resume plan, each with
its concrete next action and a [in flight] / [blocked] /
[not started] tag. Every bullet cites the session id it came from
(chf --name opens the source).
Per-session notes are cached, so refreshing after new sessions only pays
for the new ones — and a monster session (beyond ~120k chars) is
map-reduced *inside* the note, so the memory path never truncates:
nothing is silently dropped, at any size.
You can also curate what feeds the memory: --exclude leaves a
session out (a duplicate, an experiment — bare --exclude opens a
numbered picker that remembers: the stored exclusions arrive