checkpoint: reset the context, keep the thread
Long sessions get expensive: every turn re-sends the whole history. A checkpoint writes down
just enough for a fresh session to pick up exactly where this one stopped, so you can clear the
context (/clear in Claude Code; every tool has its own fresh-session command) and continue at
a fraction of the token cost. The fresh session already reads STATE.md first
(AGENTS.md session protocol, step 1), so the handoff has one home: STATE.md. Do not create a
second document.
This is the light sibling of handover. handover transfers the project to a stranger at a
milestone and runs a full audit. checkpoint just parks the current train of work so you can
resume it yourself in a clean session. If the work is actually being handed to someone else or a
milestone is closing, use handover instead.
When to fire
- Roughly 15% of the context window is spent in this session, or the session is long and
every turn feels heavy. Fire before the harness auto-summarizes, so the handoff is yours and
accurate, not a lossy machine summary.
- The user asks for it, or is about to clear the context.
- Do not fire for a two-message session: there is nothing to save and the checkpoint itself costs
tokens.
The 15% mark is the activation point: propose the checkpoint there by default. Stretching past it
to at most ~40% is the user's call, and only when finishing the current unit of work first is
clearly better than parking it. Past ~40%, always checkpoint: advise it urgently, before quality
degrades and the handoff turns lossy. Suggest, do not force, and never clear the context on the
user's behalf. A tool that supports lifecycle hooks can surface this reminder automatically once
context crosses the threshold; such a hook only ever suggests.
Cheaper than a checkpoint, and what costs more
A checkpoint is the middle of a ladder, and the rungs below it are free:
- Keep the log out of the context. A test run, a build or a log enters the conversation as its
counts and its failures (the shell's tail and grep, or a subagent that reads it and returns two
lines), never whole. File reads dominate a long session; read the range, not the file.
- Rewind instead of summarizing when a path is abandoned: going back to the turn before it keeps
the cached prefix, while a summary throws the cache away and keeps the dead end in it.
- When the tool offers manual compaction, do it at a natural break with an instruction, and say
what survives: the files changed this session, the commands that run the checks and tests, and
the Now line. The tool's automatic summary keeps what it finds important, not what you do.
- After two failed corrections on the same problem, a fresh session that starts from what was
learned, written down, beats a third attempt in a context full of the first two.
- Nothing mid-session that invalidates the cache wholesale: a model or effort switch, a tool
server connected or disconnected, a plugin toggled. Each re-reads the whole history at full
price, so each belongs at a session boundary (
calibrate).
The method (do it from context you already have; do not re-read the repo)
The whole point is to spend few tokens. Write from what is already in this conversation. Only
open a file if a fact is genuinely missing.
- Update the handoff block at the top of
docs/state/STATE.md so it is literally true right
now. Every field earns its place:
- Status / Phase / Branch / HEAD current.
- Gates: the real state (checks, tests, CI), with the number. "checks green, tests 42/42".
- Now ▶ the single exact next action, concrete enough to start cold. Not "continue work"
but "wire the Stop hook into settings.json per the plan in the log entry below".
- Blocked on: anything waiting on the user or an external thing, else clear it.
- Add one dated Log entry (newest first) with, tight and skimmable:
- Done: what changed this session, in a few bullets.
- Docs touched: the files a resumer must open first, as links. Point, do not restate.
- Lessons / gotchas: only what a fresh session would otherwise rediscover the hard way
(a dead end tried, a non-obvious constraint, a decision and its reason). Skip the obvious.
- Stopped at: the precise point work paused, mirroring Now ▶.
- Route facts to their owner, not into the checkpoint. A real decision goes to
docs/decisions/; deferred work gets a defer: marker plus a line in docs/state/DEBT.md;
new scope goes to docs/state/INTAKE.md. STATE.md links to them; it does not absorb them.
A lesson that outlives this session goes to INTAKE.md as well, as an improvement row: a
correction the user had to give twice, a fix applied more than once, an insight about how this
project actually works. Name the candidate fix and leave it a candidate: scope triages the
row, and skill-author §1's ladder decides whether it becomes a doc line, a gate, or a skill.
- Keep STATE.md under its 150-line budget. If the Log overflows, move the oldest entries to
docs/state/log/YYYY-MM.md (the existing manifest pattern), do not trim the new entry.
- Sanitize. STATE.md is tracked and travels with the repo: keep secrets, tokens, URLs with
embedded credentials, and personal data out of the handoff. Name where a credential lives
(keychain, untracked
.env), never its value.
- Run
node checks/check.mjs so you never hand off a repo that is already red.
Then hand control back to the user
End your turn with a short block the user can act on without thinking:
One line confirming the handoff is written to STATE.md.
The literal command to start fresh, named for the tool in use: /clear in Claude Code,
the equivalent elsewhere. "Start a fresh session" without the exact keystroke is not an
instruction; the user must never have to guess what to type.
The resume prompt to paste into that session, in a code block so it copies in one click:
Read docs/state/STATE.md and continue from the Now ▶ action.
(The session protocol reads STATE.md anyway; the paste just makes it explicit and works even in
a tool that does not auto-load AGENTS.md.)
Do not clear the context yourself and do not delete anything. Clearing is the user's call.
Relation to the automated gates and the rest of the system
A checkpoint is a discipline, not a check. checks/check.mjs only enforces that STATE.md stays
under budget and the prose stays clean; it cannot judge whether Now ▶ is truly resumable. That
judgment is this skill's job. A checkpoint that leaves Now ▶ vague has failed even with all gates
green. When the fresh session starts, it should need this file and nothing from the old chat. ⚓
1---2name: checkpoint3description: Flush a lean mid-session handoff into STATE.md so the context can be cleared and the same work resumed in a fresh, cheap session. Load at roughly 15% of the context window (urgent past 40%), when a session feels long or slow, or when the user says "checkpoint", "handoff", "save tokens", "fresh session" or "/clear and continue". Transfer to another person is `handover`.4---56# checkpoint: reset the context, keep the thread78Long sessions get expensive: every turn re-sends the whole history. A checkpoint writes down9just enough for a fresh session to pick up exactly where this one stopped, so you can clear the10context (`/clear` in Claude Code; every tool has its own fresh-session command) and continue at11a fraction of the token cost. The fresh session already reads STATE.md first12(AGENTS.md session protocol, step 1), so the handoff has one home: STATE.md. Do not create a13second document.1415This is the *light* sibling of `handover`. `handover` transfers the project to a stranger at a16milestone and runs a full audit. `checkpoint` just parks the current train of work so you can17resume it yourself in a clean session. If the work is actually being handed to someone else or a18milestone is closing, use `handover` instead.1920## When to fire2122- Roughly 15% of the context window is spent in this session, or the session is long and23 every turn feels heavy. Fire *before* the harness auto-summarizes, so the handoff is yours and24 accurate, not a lossy machine summary.25- The user asks for it, or is about to clear the context.26- Do not fire for a two-message session: there is nothing to save and the checkpoint itself costs27 tokens.2829The 15% mark is the activation point: propose the checkpoint there by default. Stretching past it30to at most ~40% is the user's call, and only when finishing the current unit of work first is31clearly better than parking it. Past ~40%, always checkpoint: advise it urgently, before quality32degrades and the handoff turns lossy. Suggest, do not force, and never clear the context on the33user's behalf. A tool that supports lifecycle hooks can surface this reminder automatically once34context crosses the threshold; such a hook only ever suggests.3536## Cheaper than a checkpoint, and what costs more3738A checkpoint is the middle of a ladder, and the rungs below it are free:3940- Keep the log out of the context. A test run, a build or a log enters the conversation as its41 counts and its failures (the shell's tail and grep, or a subagent that reads it and returns two42 lines), never whole. File reads dominate a long session; read the range, not the file.43- Rewind instead of summarizing when a path is abandoned: going back to the turn before it keeps44 the cached prefix, while a summary throws the cache away and keeps the dead end in it.45- When the tool offers manual compaction, do it at a natural break with an instruction, and say46 what survives: the files changed this session, the commands that run the checks and tests, and47 the Now line. The tool's automatic summary keeps what it finds important, not what you do.48- After two failed corrections on the same problem, a fresh session that starts from what was49 learned, written down, beats a third attempt in a context full of the first two.50- Nothing mid-session that invalidates the cache wholesale: a model or effort switch, a tool51 server connected or disconnected, a plugin toggled. Each re-reads the whole history at full52 price, so each belongs at a session boundary (`calibrate`).5354## The method (do it from context you already have; do not re-read the repo)5556The whole point is to spend few tokens. Write from what is already in this conversation. Only57open a file if a fact is genuinely missing.58591. **Update the handoff block at the top of `docs/state/STATE.md`** so it is literally true right60 now. Every field earns its place:61 - **Status / Phase / Branch / HEAD** current.62 - **Gates:** the real state (checks, tests, CI), with the number. "checks green, tests 42/42".63 - **Now ▶** the single exact next action, concrete enough to start cold. Not "continue work"64 but "wire the Stop hook into settings.json per the plan in the log entry below".65 - **Blocked on:** anything waiting on the user or an external thing, else clear it.662. **Add one dated Log entry** (newest first) with, tight and skimmable:67 - **Done:** what changed this session, in a few bullets.68 - **Docs touched:** the files a resumer must open first, as links. Point, do not restate.69 - **Lessons / gotchas:** only what a fresh session would otherwise rediscover the hard way70 (a dead end tried, a non-obvious constraint, a decision and its reason). Skip the obvious.71 - **Stopped at:** the precise point work paused, mirroring Now ▶.723. **Route facts to their owner, not into the checkpoint.** A real decision goes to73 `docs/decisions/`; deferred work gets a `defer:` marker plus a line in `docs/state/DEBT.md`;74 new scope goes to `docs/state/INTAKE.md`. STATE.md links to them; it does not absorb them.75 A lesson that outlives this session goes to INTAKE.md as well, as an improvement row: a76 correction the user had to give twice, a fix applied more than once, an insight about how this77 project actually works. Name the candidate fix and leave it a candidate: `scope` triages the78 row, and `skill-author` §1's ladder decides whether it becomes a doc line, a gate, or a skill.794. **Keep STATE.md under its 150-line budget.** If the Log overflows, move the oldest entries to80 `docs/state/log/YYYY-MM.md` (the existing manifest pattern), do not trim the new entry.815. **Sanitize.** STATE.md is tracked and travels with the repo: keep secrets, tokens, URLs with82 embedded credentials, and personal data out of the handoff. Name where a credential lives83 (keychain, untracked `.env`), never its value.846. **Run `node checks/check.mjs`** so you never hand off a repo that is already red.8586## Then hand control back to the user8788End your turn with a short block the user can act on without thinking:8990- One line confirming the handoff is written to STATE.md.91- The **literal command** to start fresh, named for the tool in use: `/clear` in Claude Code,92 the equivalent elsewhere. "Start a fresh session" without the exact keystroke is not an93 instruction; the user must never have to guess what to type.94- The resume prompt to paste into that session, **in a code block** so it copies in one click:9596 ```97 Read docs/state/STATE.md and continue from the Now ▶ action.98 ```99100 (The session protocol reads STATE.md anyway; the paste just makes it explicit and works even in101 a tool that does not auto-load AGENTS.md.)102103Do not clear the context yourself and do not delete anything. Clearing is the user's call.104105## Relation to the automated gates and the rest of the system106107A checkpoint is a discipline, not a check. `checks/check.mjs` only enforces that STATE.md stays108under budget and the prose stays clean; it cannot judge whether Now ▶ is truly resumable. That109judgment is this skill's job. A checkpoint that leaves Now ▶ vague has failed even with all gates110green. When the fresh session starts, it should need this file and nothing from the old chat. ⚓