
session-closing
by spm1001
Behavioral skills for Claude Code: session lifecycle, utilities, and setup
SKILL.md
name: session-closing description: End-of-session ritual. Reflect while context is rich, then seal. Triggers on /close, 'wrap up', 'let's finish', or context nearly full. Pairs with /open. (user) user-invocable: false
/close
Capture learnings while context is rich, then commit and exit.
Structure
Prerequisites → Verify infrastructure
Pre-flight → Return to home directory
Gather → todos, beads, git, drift
Orient → Claude observes → User co-reflects → Claude answers
Decide → crystallize actions (STOP — present before executing)
Act → execute, write handoff, commit, clear todos
Remember → index session (background)
Prerequisites
Before running /close, verify infrastructure is healthy. Broken scripts mean lost handoffs.
| Check | How | If Broken |
|---|---|---|
| close-context.sh exists | [ -x ~/.claude/scripts/close-context.sh ] | Run claude-doctor.sh |
| check-home.sh exists | [ -x ~/.claude/scripts/check-home.sh ] | Fix symlinks |
| Handoffs dir writable | [ -d ~/.claude/handoffs ] | Create: mkdir -p ~/.claude/handoffs |
Quick pre-flight:
[ -x ~/.claude/scripts/close-context.sh ] && [ -x ~/.claude/scripts/check-home.sh ] && echo "OK" || echo "BROKEN"
If broken: STOP, diagnose, then write handoff manually rather than skipping closure entirely. See ~/Repos/claude-advanced/references/ERROR_PATTERNS.md.
Pre-flight: Return Home (MANDATORY)
You may have cd'd during work. Your system prompt contains Working directory: /path/... in the <env> block — this is immutable, where the session actually started.
- Extract that exact path from your system prompt
- Run:
~/.claude/scripts/check-home.sh "/that/path" - If
CD_REQUIRED=true, runcd <HOME_DIR>immediately
Do not skip. Do not trust pwd. Do not reason about whether you moved back. The script is authoritative.
Gather
~/.claude/scripts/close-context.sh
Script outputs: TIME, GIT, BEADS, LOCATION context.
Use TIME_OF_DAY for greetings. Use YEAR to anchor the handoff date.
Script Failure Handling
If the script fails (exit code 127 = file not found, or any error):
- STOP. Tell the user: "close-context.sh failed. Likely a broken symlink."
- Diagnose: Run
~/.claude/scripts/check-symlinks.sh - Fallback: If you can't fix it, write handoff manually to
~/.claude/handoffs/<encoded-path>/— don't skip closure entirely.
Why this matters: Broken scripts (Jan 3-10 2026) meant /close ran without proper context gathering. Never continue silently.
From script output, assess:
- TodoWrite — what's done, what's incomplete? (incomplete items surface in Decide)
- Beads — IN_PROGRESS items need notes or closure
- Git — UNCOMMITTED files? UNPUSHED commits?
- Drift — what did /open (or /ground) say we'd do vs what we did?
Surface stale artifacts: screenshots, temp files, old sketches, superseded plans.
Orient
This is THE reflection — complete it here. What emerges in Orient feeds into the handoff. There is no second reflection later.
Orient has three beats. All three must complete before moving to Decide.
Claude shares observations
Anti-pattern: Don't compress reflection into multiple-choice answers. The point is surfacing what YOU (Claude) noticed that the user might not have. Pre-baked options defeat this.
Share your observations directly:
"Before we wrap up, here's what stood out to me this session:
- [specific observation about the work]
- [pattern or connection you noticed]
- [something that felt unfinished or risky]
What resonates? What am I missing?"
User co-reflects + selects ritual
Immediately after sharing observations, present a combined AskUserQuestion. This captures which deeper reflections you should answer:
AskUserQuestion([
{
header: "Looking Back",
question: "Which backward reflections should I answer?",
multiSelect: true,
options: [
{ label: "All of these", description: "Full retrospective" },
{ label: "What did we forget?", description: "Dropped intentions" },
{ label: "What did we miss?", description: "Blind spots" },
{ label: "What could we have done better?", description: "Quality gaps" }
]
},
{
header: "Looking Ahead",
question: "Which forward reflections should I answer?",
multiSelect: true,
options: [
{ label: "All of these", description: "Full prospective" },
{ label: "What could go wrong?", description: "Risks, fragile bits" },
{ label: "What won't make sense later?", description: "Clarity gaps" },
{ label: "What will we wish we'd done?", description: "Missed opportunities" }
]
}
])
Option 3 ("Type something") for either question provides free text input.
Claude answers selected questions
Orient is not complete until this step finishes. Respond to the selected Looking Back/Looking Ahead questions genuinely — the user's selection transforms them into real asks, not template following.
Don't rush this. The reflection is where value compounds.
Decide
STOP. Do not proceed to Act without completing this phase.
From Gather + Orient, crystallize actions into two buckets.
Surfacing incomplete work
Before presenting options, check TodoWrite for incomplete items. Any todo not marked completed must appear in the Decide AskUserQuestion — either as a "Now" option (finish it) or "Next" option (create bead). Don't silently drop work.
Now vs Next
Now = actions that execute immediately, benefiting from current context:
- Incomplete todos that can be finished quickly
- Close a bead with resolution notes (context makes notes better)
- Update CLAUDE.md — Local (./CLAUDE.md) or Global (~/.claude/CLAUDE.md)
- Quick fixes (< 2 minutes, obvious how)
Next = deferrals that create work for a future session:
- Incomplete todos that need dedicated time
- Create a bead (by definition, you're deferring it)
- Anything needing "fresh thinking"
- Anything you're uncertain how to approach
The test: If it creates something for later, it's Next. If it completes something now, it's Now.
AskUserQuestion([
{
header: "Now",
question: "Execute now while context is fresh?",
multiSelect: true,
options: [
// Adapt to actual session:
// - Include incomplete todos as options
// - Include CLAUDE.md updates when insights emerged
{ label: "Finish [incomplete todo]", description: "Can complete quickly" },
{ label: "Close bead-xyz", description: "Add resolution notes" },
{ label: "Update Local CLAUDE.md", description: "Project-specific pattern" },
{ label: "Update Global CLAUDE.md", description: "Cross-project learning" },
{ label: "None", description: "Nothing needs immediate action" }
]
},
{
header: "Next",
question: "Create beads for future sessions?",
multiSelect: true,
options: [
// Adapt to actual session:
// - Include incomplete todos that need dedicated time
{ label: "[Incomplete todo]", description: "Needs dedicated time" },
{ label: "Investigate Y", description: "Needs dedicated exploration" },
{ label: "None", description: "Handoff captures everything needed" }
]
}
])
User gets explicit choice over timing. "Next" ≠ abandoned — it's queued with context.
After Decide completes: All incomplete todos have been addressed (user chose to finish, defer, or drop). The cleardown in Act is now safe.
Act
Execute in this order:
Execute "Now" items
Do the selected actions: finish incomplete todos, close beads with notes, update CLAUDE.md, quick fixes.
Create "Next" beads
For each selected deferral, create a bead with enough context that a future Claude can pick it up.
Clear TodoWrite
Clear the todo list with an empty array:
TodoWrite([])
This is safe because:
- Incomplete items were surfaced in Decide — user chose to finish, defer, or drop
- Items deferred are now in beads (persistent)
- Completed items are done
- Leaving stale todos confuses next session
Write handoff
Handoff location is non-negotiable. The script computes the path; you use it exactly.
~/.claude/scripts/close-context.sh | grep HANDOFF_DIR
| Rule | Why |
|---|---|
Write to {HANDOFF_DIR}/{session-id}.md | Central location, /open finds it |
Never write locally (.handoff.md in project) | /open won't find it — information becomes invisible |
| Never compute path yourself | Encoding differences cause folder fragmentation |
Why this matters (Jan 2026 incident): A Claude wrote to .handoff-kube-migration.md locally instead of the central location. The next session's /open couldn't find it — loaded a stale handoff instead. The information existed but was invisible.
Get session ID:
ls -t ~/.claude/projects/-$(pwd | tr '/' '-' | cut -c2-)/*.jsonl 2>/dev/null | grep -v agent | head -1 | xargs basename -s .jsonl
Use first 8 characters for filename.
Fallback: If SESSION_ID is empty (script failed), use timestamp: 2026-01-04-2215.md
Example: session 51d17dc5-b714-481c-9dfb-6d4128800e7b → filename 51d17dc5.md
Full path: {HANDOFF_DIR}/51d17dc5.md
# Handoff — {DATE}
session_id: {full uuid from above command}
purpose: {first Done bullet, truncated to ~60 chars}
## Done
- [Completions in verb form — include bead ID if closing a bead, e.g., "Fixed auth bug (claude-go-xyz)"]
## Gotchas
[What would trip up next Claude]
## Risks
[What could go wrong with what we built]
## Next
[Direction for next session]
## Artifacts
[Only if Google Drive work — see Knowledge Work section below]
## Commands
```bash
# Optional — verification or continuation that might help
Reflection
Claude observed: [Key observations from Orient] User noted: [What they added or emphasized]
#### Knowledge Work Context (Google Drive)
**When working in Google Drive (not ~/Repos):** Add an Artifacts section to the handoff.
You already know what you touched — you called MCP tools during the session. Recall:
- Which docs you read (`get_content`)
- Which docs you updated (`update_doc`, `append_to_doc`)
- Which folders you browsed (`list_files`)
```markdown
## Artifacts
Working folder: [Project Name](https://drive.google.com/drive/folders/xxx)
This session:
- Updated: [Contract Stewardship Doc](https://docs.google.com/.../d/yyy) — added supplier descriptions
- Created: [Q1 Review Notes](https://docs.google.com/.../d/zzz)
- Referenced: [Budget Template](https://docs.google.com/.../d/www) — read-only
Why this matters: Knowledge work doesn't have commits. This section is the equivalent — what changed, where.
Rehydration: Next Claude can get_content() on these links to pull current state. The links are stable; content is always fresh from source.
Purpose line is auto-generated from first Done bullet — enables claude -r style picker at /open.
Commit
If git dirty in the working directory (where you started):
- Stage relevant files (including handoff if in repo)
- Commit with standard message + co-authorship
- Push if user approves
Anti-pattern: Don't commit other repos. You may have seen dirty state in other repos during the session. That's not your concern — only commit where you're working. Being "helpful" by tidying other repos is unwanted.
Tell user to exit
Say: "Type /exit to close." Don't exit programmatically.
Remember
Automatic — handled by session-end hook. You don't invoke this; it happens when the user runs /exit.
The hook (~/.claude/hooks/session-end.sh) fires automatically and:
- Indexes the session transcript via
mem process - Scans handoffs and beads for memory
This enables future /mem search to find this session's content.
You don't need to do anything here — just tell the user to /exit and the hook takes care of the rest.
GODAR Reference
| Phase | /open | /ground | /close |
|---|---|---|---|
| Gather | Handoff, beads, script | Todos, beads, drift | Todos, beads, git, drift |
| Orient | "Where we left off" | "What's drifted" | Claude observes → User co-reflects → Claude answers |
| Decide | User picks direction | Continue or adjust | Crystallize actions (STOP) |
| Act | Draw-down → TodoWrite | Update beads, reset | Execute, handoff, commit, clear todos |
| Remember | — | Optional: memory skill | Index session (background) |
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です