Checkpoint System
How Han's checkpoint system brings focused, incremental validation by only checking code you actually modified.
Han's checkpoint system applies the Boy Scout Rule to code validation: leave the code better than you found it, but don't demand perfection on day one.
The Problem
Without checkpoints, validation hooks run against your entire codebase. Install a linting plugin on a legacy project with 500 pre-existing issues, and you're immediately overwhelmed with problems you didn't create.
This leads to:
- Developers disabling hooks in frustration
- Validation abandoned entirely
- Net result: worse quality, not better
The Solution: Session-Scoped Validation
Checkpoints capture file states when your session starts. When hooks run, they only validate files you actually modified during that session.
Session Start (t0):
├─ Checkpoint created
├─ File hashes captured for all project files
Your Work (t0 → t1):
├─ Modified: components/Button.tsx
├─ Untouched: utils/format.ts (has lint errors)
Session Stop (t1):
├─ Hook runs
├─ Filters to: components/Button.tsx only
└─ Pre-existing issues in utils/format.ts: not your problem today
How Checkpoints Work
Session Checkpoints
Created automatically at SessionStart:
- Captures SHA-256 hashes of all tracked files
- Stored in
~/.claude/projects/{slug}/han/checkpoints/session_{id}.json - Used by
Stophooks to filter validation scope - Cleaned up after 24 hours
Agent Checkpoints
For complex workflows with subagents:
- Created at
SubagentStartfor each spawned agent - Stored as
agent_{agent_id}.json - Each agent's work is validated independently
- Prevents cross-contamination between parallel work
Main Session (session_abc):
├─ Checkpoint: session_abc.json
├─ Spawns Subagent 1 (agent_xyz):
│ ├─ Checkpoint: agent_xyz.json
│ └─ Works on feature-a/
└─ Spawns Subagent 2 (agent_def):
├─ Checkpoint: agent_def.json
└─ Works on feature-b/
When Subagent 1 finishes, SubagentStop hooks only validate its changes. Subagent 2's work is isolated.
Configuration
Checkpoints are enabled by default. All settings default to true as of v2.0.0.
Disable Checkpoints
For intentional full-codebase validation:
# han.yml
hooks:
checkpoints: false # Validate all changed files, not just your session's
Or via environment variable:
HAN_NO_CHECKPOINTS=1 han hook run jutsu-biome lint
Or via CLI flag:
han hook run jutsu-biome lint --no-checkpoints
When to Disable
- Tech debt sprints: When deliberately addressing accumulated issues
- CI pipelines: Merge gates should validate the full codebase
- Initial cleanup: First-time adoption with planned fix-all session
Most day-to-day development should keep checkpoints enabled.
CLI Commands
Manage checkpoints directly with the CLI:
Capture a Checkpoint
# Automatic (reads stdin from hook payload)
han checkpoint capture
# Manual with explicit options
han checkpoint capture --type session --id my-session-123
han checkpoint capture --type agent --id agent-xyz
List Active Checkpoints
han checkpoint list
Output:
Active Checkpoints
==================
Session Checkpoints:
- abc123 (captured 2 hours ago)
- def456 (captured 1 day ago)
Agent Checkpoints:
- agent-xyz (captured 5 minutes ago)
Total: 3 checkpoints
Clean Stale Checkpoints
# Remove checkpoints older than 24 hours (default)
han checkpoint clean
# Custom age threshold
han checkpoint clean --max-age 48
Integration with Hooks
Hooks automatically use checkpoints when available:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{ "type": "command", "command": "han checkpoint capture" }
]
}
],
"Stop": [
{
"hooks": [
{ "type": "command", "command": "han hook run jutsu-biome lint" }
]
}
]
}
}
The Stop hook automatically filters to files changed since the session checkpoint.
The Boy Scout Philosophy
The checkpoint system embodies incremental improvement:
- Touch a file → that file gets validated
- Fix issues in code you're already changing
- Over time, frequently-touched code gets cleaner
- Rarely-touched code stays as-is until relevant
This is sustainable. Demanding perfection on day one isn't.
What Checkpoints Don't Do
Hide problems: Pre-existing issues still exist. They surface when you touch those files.
Replace CI: Your CI should validate the full codebase. Checkpoints optimize the developer feedback loop.
Persist across sessions: Each session starts fresh. Old checkpoints are cleaned up automatically.
Technical Details
Checkpoint Storage
~/.claude/projects/{project-slug}/han/checkpoints/
├── session_abc123.json
├── session_def456.json
└── agent_xyz789.json
Checkpoint Format
{
"type": "session",
"id": "session_abc123",
"timestamp": "2025-12-13T08:00:00Z",
"files": {
"src/index.ts": "sha256:abc...",
"src/utils.ts": "sha256:def..."
}
}
Graceful Degradation
- Missing checkpoint? Normal hook behavior (validates all changed files)
- Corrupted checkpoint? Falls back gracefully
- Never silently skips validation
Debugging
Checkpoint capture fails silently by default to avoid blocking hooks. To see error messages:
HAN_VERBOSE=1 han checkpoint capture --type session --id test-123
The HAN_VERBOSE=1 environment variable enables detailed error output for troubleshooting.
Next Steps
- Learn about smart caching for faster hook execution
- Explore hook configuration for fine-tuning
- Read about SubagentStart/Stop hooks for agent lifecycle