| name | session-continuity |
| description | Manages a persistent, multi-session task workflow through a strict state machine backed by files in the project's .claude/ directory. Use when resuming work across sessions, when the user says "continue" or "create a plan"/"setup tasks", or when work must survive a session restart, context compaction, or handoff. Every message announces its state; tasks never auto-advance and TodoWrite is never used. |
| version | 2.1.0 |
Session Continuity
Overview
Persistent task workflow that survives session restarts. Sessions end, context windows compact, and agents hand off, but the work must continue where it left off. This skill externalizes all task state into versioned files in the project's .claude/ directory and drives execution through a strict state machine. State lives in files, not in the conversation, so any session can pick up the work by reading three files. The state machine prevents the two failure modes that destroy continuity: re-deriving progress by re-investigating the codebase (wasteful, the answer is already in session.md), and auto-advancing past tasks the user never approved.
When to Use
- Resuming work across sessions when the user says "continue"
- Starting a multi-task plan when the user says "create a plan" or "setup tasks"
- Work that must survive a session restart, context compaction, or agent handoff
- Any task list where the user wants explicit control over advancing and committing
When NOT to use: A single, self-contained change that completes within one session and needs no persistence. For breaking a spec into tasks before persisting them, see implementation-planning. For the verification gate this skill enforces in the VERIFY state, see verification-before-completion.
Related: implementation-planning, verification-before-completion, tdd-workflow, investigation-modes.
For multi-step and multi-agent coordination rules, see references/orchestration-patterns.md.
CRITICAL: STATE MACHINE GOVERNANCE
EVERY SINGLE MESSAGE MUST START WITH YOUR CURRENT STATE
Format:
CHECK_STATUS
WORKING
VERIFY
COMPLETE
AWAITING_COMMIT
MARK_COMPLETE
BLOCKED
NOT JUST THE FIRST MESSAGE. EVERY. SINGLE. MESSAGE.
When you read a file → prefix with state
When you run tests → prefix with state
When you explain results → prefix with state
When you ask a question → prefix with state
Example:
CHECK_STATUS
Reading session.md...
CHECK_STATUS
Status shows "in progress". Routing to WORKING.
TRANSITION: CHECK_STATUS → WORKING
WORKING
Reading requirements.md for task specs...
WORKING
Implementing getUser function with deps...
State Machine
user: "continue"
↓
┌────────────────┐
┌───│ CHECK_STATUS │←──────────┬──────────┐
│ │ Read session.md│ │ │
│ └────────┬───────┘ │ │
│ │ │ │
Status= │ │ Status= │ │
"Complete" │ │ "in progress" │ │
│ │ │ │
↓ ↓ │ │
┌───────────┐ ┌──────────────┐ │ │
│ AWAITING_ │ │ WORKING │←────┐ │ │
│ COMMIT │ │ │ │ │ │
│ │ │ Read: │ │ │ │
│ Ask │ │ requirements │ │ │ │
│ permission│ │ tasks.md │ │ │ │
│ STOP │ └──────┬───────┘ │ │ │
└─────┬─────┘ │ │ │ │
│ │ task done │ │ │
user: yes │ │ │ │ │
│ ↓ │ │ │
│ ┌──────────────┐ │ │ │
│ │ VERIFY │ │ │ │
│ │ │ │ │ │
│ │ Run steps │─────┘ │ │
│ │ from │ fail │ │
│ │ requirements │ │ │
│ └──────┬───────┘ │ │
│ │ │ │
│ │ pass │ │
│ │ │ │
│ ↓ │ │
│ ┌──────────────┐ │ │
│ │ COMPLETE │ │ │
│ │ │ │ │
│ │ Update: │ │ │
│ │ session.md │─────────┘ │
│ │ Status= │ │
│ │ "Complete" │ │
│ └──────────────┘ │
│ │
↓ │
┌──────────────────┐ │
│ MARK_COMPLETE │ │
│ │ │
│ Update: tasks [x]│ │
│ Update: session │──────────────────────────────┘
│ (next task) │
└──────────────────┘
Files
All files live in the project's .claude/ directory:
| File | Purpose |
|---|
.claude/tasks.md | Checklist of tasks |
.claude/requirements.md | Implementation specs, verification steps |
.claude/session.md | Current state for resume |
State: CHECK_STATUS
Prefix: CHECK_STATUS
Purpose: Read session.md and route based on Status field.
Actions
- Run
pwd to verify project directory
- Read
.claude/session.md
- Look at Status field
- Route:
- Status="Complete" or "ready to commit" → AWAITING_COMMIT
- Status="in progress" or missing → WORKING
- Status="blocked" → BLOCKED
Critical Rules
- ONLY read session.md and route
- DO NOT read other files, launch agents, or do anything else
- IF ERROR: STOP and tell user what failed
Transitions
- CHECK_STATUS → AWAITING_COMMIT (Status="complete")
- CHECK_STATUS → WORKING (Status="in progress")
- CHECK_STATUS → BLOCKED (Status="blocked")
State: AWAITING_COMMIT
Prefix: AWAITING_COMMIT
Purpose: Task is complete. Ask permission to mark done.
Actions
- Say: "Task X is complete. May I mark it as complete in tasks.md?"
- STOP - wait for user response
- If user says yes → MARK_COMPLETE
- If user says no → STOP, await instruction
Critical Rules
- ONLY ask permission and STOP
- DO NOT read files, launch agents, work on next task
- DO NOT do anything except ask and wait
Transitions
- AWAITING_COMMIT → MARK_COMPLETE (user says yes)
- AWAITING_COMMIT → STOP (user says no)
State: MARK_COMPLETE
Prefix: MARK_COMPLETE
Purpose: Update task files after user approval.
Actions
- Update tasks.md: Change
[ ] to [x] for current task
- Update session.md: Set to next task with Status="in progress"
- Go to CHECK_STATUS
Critical Rules
- ONLY update files and route
- DO NOT read other files or research next task
- IF CANNOT EDIT: Say "Cannot edit files: [reason]" and STOP
Transitions
- MARK_COMPLETE → CHECK_STATUS
State: WORKING
Prefix: WORKING
Purpose: Implement the current task.
Actions
- Read requirements.md for task specs
- Read tasks.md for task list
- Work on current task using patterns:
- fn(args, deps)
- Result types
- Zod at boundaries
- Update session.md after TDD cycles
- When task done → VERIFY
Session.md Updates
Update at these triggers:
| Trigger | Update |
|---|
| Start task | Status="in progress" |
| TDD cycle | Brief note in Notes |
| Hit blocker | Status="blocked", describe |
| Task done | → transition to VERIFY |
Critical Rules
- EVERY message must have state prefix
- DO NOT skip to next task
- DO NOT work on multiple tasks
- IF BLOCKED: Document in session.md, STOP
Transitions
- WORKING → VERIFY (task implementation done)
- WORKING → BLOCKED (hit blocker)
State: VERIFY
Prefix: VERIFY
Purpose: Run verification before claiming complete.
Actions
- Read Verification section from requirements.md
- Run ALL verification commands:
npm test
npm run lint
npm run build
- Show ALL output verbatim
- If all pass → COMPLETE
- If any fail → WORKING (treat as blocker)
Critical Rules
- EVERY message must have state prefix
- NEVER skip verification
- NEVER claim complete without running checks
- IF ERROR: STOP and tell user
Transitions
- VERIFY → COMPLETE (all pass)
- VERIFY → WORKING (any fail)
State: COMPLETE
Prefix: COMPLETE
Purpose: Update session.md to reflect completion.
Actions
- Update session.md: Set Status="Complete"
- Go to CHECK_STATUS
Critical Rules
- ONLY update session.md and route
- DO NOT ask permission (that's AWAITING_COMMIT)
- IF ERROR: STOP and tell user
Transitions
State: BLOCKED
Prefix: BLOCKED
Purpose: Cannot proceed, need user guidance.
Actions
- Explain blocking issue clearly
- Show what you tried
- STOP and wait for user guidance
Critical Rules
- NEVER improvise workarounds
- ALWAYS stop and wait for user
Transitions
- BLOCKED → [any state] (based on user guidance)
Setup: "Plan" or "Setup Tasks"
When user says "create a plan" or "setup tasks":
- Ask for task list
- Ask for verification commands
- Ask for constraints/patterns
- Create files:
.claude/tasks.md
- [ ] Task 1: [exact user wording]
- [ ] Task 2: [exact user wording]
.claude/requirements.md
## Verification
Before marking complete:
- `npm test` - all pass
- `npm run lint` - no errors
- `npm run build` - succeeds
## Task 1: [name]
- [specs from conversation]
- [constraints]
.claude/session.md
**Current:** Task 1
**Status:** in progress
## Done
(none yet)
## Notes
- [context for resume]
Anti-Patterns
WRONG: Investigating Codebase to Figure Out Progress
User: "continue"
Claude: *Reads tasks.md*
Claude: "Let me investigate the codebase to understand what's done"
Claude: *Searches 10+ files, runs git log*
Claude: *Wastes tokens figuring out state*
Problem: All that info is in session.md already.
RIGHT: Reading session.md First
User: "continue"
Claude: "CHECK_STATUS"
Claude: *Reads session.md*
Claude: "Status shows 'in progress'. Routing to WORKING."
Claude: "WORKING"
Claude: "Continuing Task 2..."
WRONG: Skipping Verification
Claude: *Completes implementation*
Claude: "Task 1 is complete!"
*User commits and pushes*
*CI fails - tests broken*
Problem: Skipped verification, introduced bugs.
RIGHT: Running Verification
Claude: "VERIFY"
Claude: *Runs npm test* → All pass
Claude: *Runs npm lint* → All pass
Claude: *Runs npm build* → Success
Claude: "COMPLETE"
Claude: "Task 1 complete, all verification passed."
WRONG: Creating Git Commits
Claude: *Completes task*
Claude: *Runs git add . && git commit*
Problem: User loses control over commits.
RIGHT: Handing Off to User
Claude: "Task complete, ready for you to commit."
Claude: "May I mark this task as complete?"
WRONG: Auto-Advancing Tasks
Claude: "Task 1 done. Starting Task 2..."
Claude: *Explores codebase for Task 2*
Problem: User didn't approve advancing.
RIGHT: Stopping After Complete
Claude: "Task 1 complete. May I mark it done?"
*Waits for user*
Never Use TodoWrite
This skill REPLACES Claude Code's built-in todos:
WRONG: TodoWrite tool
RIGHT: .claude/tasks.md file
WRONG: Internal todo state
RIGHT: Visible, editable files
Why: TodoWrite state is lost between sessions. Files persist.
Path Troubleshooting
Symptom: "File not found" on continue
Fix:
- Run
pwd
- Read from
./.claude/session.md (project root)
- NOT from skill directory
Quick Reference
| State | Prefix | Action | Exit |
|---|
| CHECK_STATUS | CHECK_STATUS | Read session.md, route | Status-based |
| AWAITING_COMMIT | AWAITING_COMMIT | Ask permission, STOP | User response |
| MARK_COMPLETE | MARK_COMPLETE | Update files | → CHECK_STATUS |
| WORKING | WORKING | Implement task | → VERIFY |
| VERIFY | VERIFY | Run verification | Pass/Fail |
| COMPLETE | COMPLETE | Update session.md | → CHECK_STATUS |
| BLOCKED | BLOCKED | Explain, STOP | User guidance |
Red Flags
- A message with no state prefix
- Investigating the codebase to figure out progress instead of reading
session.md
- Advancing to the next task without explicit user approval
- Claiming a task complete without running the VERIFY commands
- Using TodoWrite or any internal todo state instead of
.claude/ files
- Creating a git commit on the user's behalf
- Improvising a workaround from the BLOCKED state instead of stopping
- Reading files outside the current state's allowed actions (each state lists what it may touch)
Verification
Confirm before relying on this workflow: