| name | dev-checkpoint |
| description | Save progress and generate a continuation prompt. Updates PRD status markers, captures git state, and writes checkpoint.md for the next session. Use at the end of a session or before switching context. |
| argument-hint | <feature name> |
| allowed-tools | Bash(bash:*) Bash(node:*) Bash(git add:*) Bash(git commit:*) Bash(git log:*) Bash(git status:*) Bash(rm:*) Read Write |
Checkpoint Current Session
Review the current session and create a continuation prompt for the next session.
SAVE-ONLY MODE
This skill analyzes and saves. It does NOT fix, investigate, or implement anything.
- Do NOT investigate bugs or errors mentioned during the session
- Do NOT start implementing fixes or next steps
- Do NOT move to the next phase or task
- If the user mentions bugs during confirmation (Step 4), note them in
<blockers> or <notes> but do NOT attempt to fix them
Why commit-first ordering
The branch/worktree decision and the optional commit happen before PRD markers are updated and the checkpoint is written. This way the saved checkpoint records the branch and commit the session actually ends on — a branch created after the checkpoint would make the next /dev-resume report drifted. The PRD-marker edits and checkpoint.md/session-log.md written after the commit are honestly recorded as uncommittedChanges: true; they get swept into the next session's commit.
Step 0: Discover Project Root
Run the discovery script:
bash "$DISCOVER" root
Where $DISCOVER is the absolute path to scripts/discover.sh within this skill's directory.
Path safety — shell state does not persist between tool calls, so you must provide full script paths on each call:
- Use
$HOME instead of the literal home directory (e.g., bash "$HOME/code/…/discover.sh", not bash "/Users/name/…/discover.sh"). This prevents username hallucination.
- Copy values from tool output. When reusing a value returned by a previous command (like
$PROJECT_ROOT), copy it verbatim from that command's output. Never retype a path from memory.
- Verify on first call: if a script call fails with "No such file", the path is wrong — STOP and re-derive from the skill-loading context.
- Never ignore a non-zero exit. If any script in this skill fails, stop and report the error before continuing.
Store the output as $PROJECT_ROOT. If the command fails, inform the user and stop.
Step 1: Identify the Active Feature
Run the discovery script to find features:
bash "$DISCOVER" features "$PROJECT_ROOT" "$ARGUMENTS"
Pass $ARGUMENTS as the third argument only if the user provided one; omit it otherwise.
- If the script exits non-zero (no
.dev/ directory): ask the user to specify the feature name.
- If output is empty: no features found, ask the user to specify the feature name.
- If one line: use as
$FEATURE_PATH.
- If multiple lines: ask which feature to checkpoint.
Never use raw $ARGUMENTS directly in shell commands or paths.
Validate with the validation script. Where $VALIDATE is the absolute path to scripts/validate.sh within this skill's directory. Apply the path safety rules from Step 0 ($HOME, copy from output).
If using an existing feature (a $FEATURE_PATH was matched):
bash "$VALIDATE" feature-path "$FEATURE_PATH" "$PROJECT_ROOT"
If creating a new feature (no match, normalizing user input):
bash "$VALIDATE" normalize "$USER_INPUT"
Outputs $FEATURE_NAME on success; on failure, STOP and report the error.
Set $FEATURE_DIR to $PROJECT_ROOT/.dev/$FEATURE_NAME. The checkpoint will be saved to $FEATURE_DIR/checkpoint.md. (If a worktree is set up in Step 6, both $PROJECT_ROOT and $FEATURE_DIR are retargeted there.)
Step 2: Gather Feature State via CLI
Run the CLI to get structured progress and gate data:
node "$CLI" progress-summary --json --dir "$FEATURE_DIR"
node "$CLI" gate-check --json --dir "$FEATURE_DIR"
Where $CLI is the absolute path to scripts/dev-workflow.cjs within this skill's directory. Apply the path safety rules from Step 0 ($HOME, copy from output).
Parse the JSON output:
- progress-summary returns:
feature, overall {done, total, percent}, phases[] {number, title, done, total, status}, subPrds[] {id, title, done, total, status}
- gate-check returns:
feature, atGate, completedPhase, nextPhase, allComplete
From the CLI output, determine:
- Current phase: the first phase with status
in-progress, or the next not-started phase if at a gate
- Overall progress:
overall.done/overall.total (overall.percent%)
Step 3: Analyze Session Context
Review the current conversation to extract:
- Completed items — what was accomplished this session (to mark
⬜ → ✅)
- Decisions made — architectural choices, trade-offs
- Blockers encountered — issues, workarounds, gotchas
Cross-reference with the CLI progress data to verify accuracy. The CLI provides the ground truth for PRD status markers; your session review adds decisions, blockers, and context that only the conversation contains.
Step 4: Confirm Session Context
Present the agent's findings (decisions, blockers, notes) and end with an explicit question:
"Does this look right? Reply yes to continue, or tell me what to add or change."
If a category is empty, omit it.
The completed items and current phase confirmed here anchor the commit message composed in Step 7 — note them.
STOP. Wait for explicit confirmation before proceeding to Step 5. If the user mentions new bugs or issues during this step, add them to the checkpoint notes — do NOT investigate or fix them.
Step 5: Determine First-Checkpoint Status
Check whether $FEATURE_DIR/checkpoint.md already exists. Set $IS_FIRST_CHECKPOINT to true if the file does NOT exist, false if it does.
This must be evaluated now, before any branch/worktree setup or checkpoint write — later steps create checkpoint.md (and, for a worktree, move the feature directory), so the existence check is only meaningful before they run.
Step 6: Workflow Setup (First Checkpoint Only)
REQUIRED CHECK: Evaluate $IS_FIRST_CHECKPOINT (set in Step 5).
- If
$IS_FIRST_CHECKPOINT is true (no checkpoint.md existed): execute this step.
- If
$IS_FIRST_CHECKPOINT is false (a checkpoint already exists): skip to Step 7.
This step offers the user a worktree or branch for the feature. Follow the instructions in worktree-guide.md.
Use $WORKTREE as the absolute path to scripts/worktree-setup.sh within this skill's directory. Apply the path safety rules from Step 0.
The branch/worktree offer runs before the commit (Step 7) so the commit lands on the new branch or worktree.
If the user chooses Worktree — the worktree is created before checkpoint.md exists, and worktree-setup.sh execute moves $PROJECT_ROOT/.dev/$FEATURE_NAME into the worktree. So you must retarget every subsequent path:
- Run
worktree-setup.sh execute per the guide; capture the worktree location from its worktree:<path> output as $WORKTREE_PATH.
- Retarget: set
$PROJECT_ROOT ← $WORKTREE_PATH and $FEATURE_DIR ← $WORKTREE_PATH/.dev/$FEATURE_NAME. Every later step — the commit (7), PRD updates (8), git-state capture (9), and checkpoint write (11) — operates on the worktree. Run git against it (git -C "$WORKTREE_PATH" …) and run cwd-based scripts from it (cd "$WORKTREE_PATH" && …).
- Defer the restart instruction: do NOT yet tell the user to end the session and
cd into the worktree. The checkpoint must be written first. That instruction is reported in the Step 13 summary.
If the user chooses Branch — worktree-setup.sh branch creates and switches to feature/$FEATURE_NAME in the current directory. No retargeting needed: the commit (7) lands on it and Step 9 records it.
If the user chooses Skip or declines — stay on the current branch and continue to Step 7.
Step 7: Optional Commit
Skip this step entirely if ANY of these are true:
- This is not a git repository
- A fresh
git status --porcelain is empty (no uncommitted changes)
Run git status --porcelain fresh here (in the worktree case, git -C "$WORKTREE_PATH" status --porcelain) — do NOT reuse any earlier result.
If there are uncommitted changes, generate a commit message from the Step 3 session analysis as confirmed in Step 4 (completed items + current phase):
- Format:
<Summary of what was accomplished this session>
- One concise sentence, under 72 characters if possible
- Per repo conventions: no AI attribution, no emojis
STOP. Present the following to the user and wait for their response:
Ready to commit your changes:
<output of `git status --short`>
Proposed commit message:
<generated commit message>
Commit these changes?
If the user declines: leave the working tree as-is and continue to Step 8 — the checkpoint is still saved (it will record the uncommitted state).
If the user accepts, run (prefix git with -C "$WORKTREE_PATH" in the worktree case):
git add -u
git commit -m "<generated commit message>"
Confirm with git log -1 --oneline and report the commit hash. Then continue to Step 8.
Step 8: Update PRD Status Markers (REQUIRED)
For each completed item identified in Step 3, run the CLI:
node "$CLI" status-update --phase N --step M --marker done --dir "$FEATURE_DIR"
Where $CLI is the absolute path to scripts/dev-workflow.cjs within this skill's directory. Apply the path safety rules from Step 0 ($HOME, copy from output). $FEATURE_DIR is $PROJECT_ROOT/.dev/$FEATURE_NAME (retargeted to the worktree if Step 6 set one up).
--phase N — the phase number containing the completed step
--step M — the step number within that phase (omit for phase-level markers)
--marker done — marks the step as ✅ complete
The CLI reports { changed, line, file } as JSON when --json is passed, or a text summary otherwise. Track these results for the Step 13 summary. If changed is false, the marker was already ✅.
Check the exit code. A non-zero exit code means the command failed (e.g., phase not found, invalid path). Never ignore a non-zero exit — if a status-update call fails, stop and report the error before continuing.
If nothing was completed, state: "No PRD updates needed."
Do NOT manually edit PRD files — the status-update CLI ensures format compatibility with the parser.
Step 9: Capture Git State
Run the git state script:
bash "$GIT_STATE" full
Where $GIT_STATE is the absolute path to scripts/git-state.sh within this skill's directory. Apply the path safety rules from Step 0 ($HOME, copy from output).
This runs after the commit (Step 7) and the PRD-marker updates (Step 8), so branch and lastCommit reflect the final state and the status: lines correctly show the fresh .dev/ edits as uncommitted.
git-state.sh reads the current working directory. In the worktree case, run it from the worktree so it reports the worktree's state: cd "$WORKTREE_PATH" && bash "$GIT_STATE" full.
Parse the output lines:
git:false → not a git repo; omit branch, lastCommit, uncommittedChanges from the checkpoint JSON.
branch:<name> → store for checkpoint JSON branch field
commit:<oneline> → store as checkpoint JSON lastCommit field
status:<line> → each is one line of git status --short; if no status: lines, set uncommittedChanges to false (otherwise true)
Step 10: Compose Checkpoint Data
Rules:
- Always include
context, currentState, nextAction, keyFiles. Omit decisions, blockers, notes if empty (empty arrays, not omitted keys).
- No absolute paths with usernames → use relative paths. No secrets/credentials → use placeholders.
- The
prdFiles array lists PRD files in the feature directory (e.g. ["00-master-plan.md"]).
Construct a JSON object matching the CheckpointWriteInput schema:
{
"branch": "<from git state>",
"lastCommit": "<from git state>",
"uncommittedChanges": <true|false>,
"prdFiles": ["00-master-plan.md"],
"context": "## Context\n\n**Goal**: ...\n**Current phase**: ...\n**Key completions**: ...",
"currentState": "## Current Progress\n\n- ✅ Phase 1: ...\n- ⬜ Phase 2: ...",
"nextAction": "## Next Steps\n\n1. First task\n2. Second task",
"keyFiles": "## Key Files\n\n- Master PRD: path\n- Key file: path",
"decisions": ["Decision 1", "Decision 2"],
"blockers": ["Blocker 1"],
"notes": ["Note 1"],
"continuationPrompt": "Please continue with ..."
}
The LLM composes the content (decisions, blockers, context — this requires judgment). The CLI handles YAML frontmatter, XML section formatting, file writing, and session-log appending. Do not format as markdown or write YAML frontmatter manually.
Reference the checkpoint-template.md for the semantic structure of each section, but let the CLI handle the formatting.
Step 11: Save Checkpoint via CLI
Use --input-file, not echo | --stdin. Multi-line JSON string values (the context, currentState, etc. sections contain \n) cannot be piped reliably through echo '...' — unescaped literal newlines in the shell become real U+000A bytes inside JSON string literals and JSON.parse rejects them as "Bad control character". Write the JSON to a file, then pass the path to the CLI.
-
Write the Step 10 JSON to $FEATURE_DIR/.checkpoint-input.json using the Write tool. The file can contain real newlines — Write is not a shell and does not mangle the content.
-
Run the CLI against that file (pass --json so the consolidation signal can be read reliably in Step 12):
node "$CLI" checkpoint-write --json --dir "$FEATURE_DIR" --input-file "$FEATURE_DIR/.checkpoint-input.json"
-
Delete the input file once the CLI reports success:
rm -f "$FEATURE_DIR/.checkpoint-input.json"
Where $CLI is the absolute path to scripts/dev-workflow.cjs within this skill's directory. Apply the path safety rules from Step 0 ($HOME, copy from output). $FEATURE_DIR is $PROJECT_ROOT/.dev/$FEATURE_NAME (the worktree path if Step 6 set one up).
The CLI will:
- Read the existing
checkpoint.md (if it exists) and append it to session-log.md as a session entry
- Write the new
checkpoint.md with proper YAML frontmatter and XML section formatting
- Return
{ success, file, sessionCount, consolidationDue } — sessionCount is the number of sessions now in session-log.md; consolidationDue is true when the history has grown enough (≥10 sessions past the last digest) to warrant consolidation. Capture both for Step 12.
Check the exit code. A non-zero exit code means the command failed (e.g., invalid JSON, missing required fields, directory not found). Never ignore a non-zero exit — if checkpoint-write fails, stop and report the error. The checkpoint was NOT saved, and .checkpoint-input.json is left on disk for inspection (do not delete it on failure).
Do NOT manually write checkpoint.md or session-log.md — the CLI ensures format compatibility and handles session-log accumulation automatically.
Step 12: Consolidate Session History (When Due)
This step keeps /dev-resume bounded on long-running features by distilling the older session tail into a compact digest — modeled on /dev-wrapup's feedback compaction. It runs only when Step 11 reported consolidationDue: true.
If consolidationDue is false (the common case — fewer than 10 sessions, or the last digest is still recent): skip this step silently. Do not mention it. Behavior is identical to before.
If consolidationDue is true:
-
Read $FEATURE_DIR/session-log.md with the Read tool. It holds every archived session (## Session N — <date> blocks) — the full raw history.
-
Compose a two-tier digest (the LLM step — this requires judgment, mirroring /dev-wrapup's { aggregate, recent } split):
aggregate — a distilled narrative (a few short paragraphs) of the feature's arc across the older sessions: what was built, the phases completed, major pivots, and persistent constraints. The most recent sessions stay raw in session-log.md and are re-surfaced by /dev-resume separately, so emphasize the older tail rather than re-narrating the latest work.
decisions — a bounded, deduplicated set of decisions that are still relevant going forward. Drop superseded, reversed, or obsolete decisions. This is the curated set /dev-resume carries forward in place of every raw <decisions> bullet ever recorded.
-
Set the numeric fields from the Step 11 result:
sessionCount — the sessionCount value returned by checkpoint-write (total sessions now in the log). The engine compares against this to decide when the next consolidation is due (re-fires every +10 sessions), so it must be the current count, not a smaller number.
consolidatedThrough — the highest session number folded into the aggregate. Normally equal to sessionCount (consolidate the whole arc); the recent raw sessions re-surface independently at resume.
-
Write the digest JSON to $FEATURE_DIR/.session-digest-input.json with the Write tool (real newlines are fine — Write is not a shell), matching the SessionDigestWriteInput schema:
{
"sessionCount": 12,
"consolidatedThrough": 12,
"aggregate": "## Feature Arc\n\nPhases 1–3 delivered ...\n\nKey pivots: ...",
"decisions": ["Still-relevant decision 1", "Still-relevant decision 2"]
}
-
Run the WRITE-only consolidate command:
node "$CLI" session-consolidate --dir "$FEATURE_DIR" --input-file "$FEATURE_DIR/.session-digest-input.json"
-
Delete the input file once the CLI reports success:
rm -f "$FEATURE_DIR/.session-digest-input.json"
Where $CLI is the absolute path to scripts/dev-workflow.cjs within this skill's directory. Apply the path safety rules from Step 0 ($HOME, copy from output). $FEATURE_DIR is the worktree path if Step 6 set one up.
Check the exit code. A non-zero exit means the write failed (e.g., invalid JSON, missing aggregate/sessionCount/consolidatedThrough). Never ignore a non-zero exit — stop and report; leave .session-digest-input.json on disk for inspection (do not delete it on failure).
The digest is written to its own session-digest.md file. session-log.md is never edited to hold a digest block — a ## Session N heading there would inflate the session counter and be mis-parsed by the session-log parser. The session-consolidate CLI enforces this (it only ever writes session-digest.md); never hand-write a digest into the log, and never hand-write session-digest.md directly — the CLI guarantees format compatibility with the parser.
Step 13: Summary
Report:
- Which feature was checkpointed
- PRD updates made (list each file and what was changed, or state "No updates needed")
- Whether a commit was made (and its hash), or that the commit was skipped/declined
- Whether session history was consolidated into
session-digest.md (only when Step 12 ran; omit this line when consolidation was not due)
- What the next steps are
- Confirm the checkpoint location
If a worktree was set up in Step 6, end the summary with the deferred restart instruction:
Worktree ready at <$WORKTREE_PATH> on branch feature/$FEATURE_NAME, and this checkpoint was saved inside it.
Next: End this session, then start a new one in the worktree:
cd "<$WORKTREE_PATH>" && claude
Wrap-Up Suggestion
After the checkpoint is complete (whether or not a commit was made), suggest:
Before ending your session, consider running /dev-wrapup to review learnings worth persisting and identify self-improvement signals.