Neither wins outright, but they fail in different ways, so a rule of thumb helps.
Compaction keeps the session alive. The summary is lossy: exact file contents, the reasons behind a rejected approach, and small details often drop out. It is cheap, though, and it keeps the momentum of a task you're still inside.
A handoff is a deliberate curation. Writing the notes forces you (and Claude) to decide what matters, and a fresh session starts with a clean context, so old dead ends stop pulling the model back. It costs more effort and some re-reading.
Rule of thumb: Compact when you're in the middle of one task and the next step depends on what was just read or changed. Hand off when either (1) you've reached a natural boundary, like a finished feature or a closed bug, or (2) the session is cluttered with failed attempts and the model keeps repeating them. A useful test: if you can't describe the state of the work in five or six sentences, write a handoff file instead of compacting.
When you compact, say what to keep, for example "/compact keep the failing test names and the schema decision." For a handoff, ask Claude for the file before you clear, then start the new session by having it read that file first. The notes should cover the goal, what's done, what was tried and ruled out, and the very next step.
This is from how Claude Code has worked as I know it, and the commands and auto-compact behavior change between versions, so check the current Claude Code docs if a detail matters.
Also discussed here:
- Claude, can you give me sample code in C# for sending an email with…
- "Coded and Audited by AI," and the Longer Story Underneath That Sen…
If I go the handoff route, what belongs in a good handoff note? Give me a short template I can reuse, and tell me what people usually leave out that bites them later.
A handoff note works best when a fresh session can act on it without asking you anything. Here's a template you can reuse:
# Handoff: <project>, <date>
## Goal
One sentence on what finished looks like.
## Done
What's merged or verified, with file paths.
## Decisions and why
Each choice, plus the reason.
## Tried and ruled out
Approach, and why it failed.
## Current state
Tests passing or failing (names), uncommitted changes, branch.
## Next step
One concrete action, with the command to run.
## Assumptions to confirm
Anything you or Claude assumed but didn't check.
The gaps that bite people later:
- Rejected approaches without the reason. The new session can't tell a dead end from an untried idea, so it proposes the same fix again.
- Verification. Without the command that proves the work is correct, the next session may declare success too early.
- Git state. Which branch, what's uncommitted, and which files are half-edited.
- Environment details. Versions, required env variables (names only, never values), and the exact test command.
- Vague next steps. "Finish the parser" leaves room to guess. "Run
pytest tests/test_parser.pyand fix the failing case" doesn't. - No date on the note. Notes go stale, so tell the next session to check the notes against the code before acting on them.
This is practical experience rather than a controlled study, so treat the template as a starting point and adjust it to your project.