# Session End

> Close out the CURRENT Claude Code session before archiving it: file durable outcomes to the notes tree, capture action items to the task manager, write a handoff note if work is unfinished, then archive. Use when the user says "end this session", "close this session", "wrap this up", "run session-end", or is reducing the number of open sessions. Current session only; archiving ends the conversation, and is only possible at all in a desktop-app session.

- Skill: `campbellsmurphy/session-end` (Agent Skill)
- Install (CLI): `npx skillmds@latest add campbellsmurphy/session-end`
- Raw SKILL.md: https://api.skillmd.com/api/skills/campbellsmurphy/session-end/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: campbellsmurphy (https://skillmd.com/u/campbellsmurphy)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/campbellsmurphy/session-end

---


# Session end

The proactive half of session capture: close a session properly so nothing durable is lost when it goes away. Scope is the CURRENT session only. Closing other sessions would mean parsing their transcripts, which is a different job.

**Adapt before use.** Two things here are local to a setup: where notes live, and which task manager gets action items. Set them once:

```
VAULT=~/vault                  # the notes tree
TASKS=$VAULT/02-areas/claude-code/tasks.md   # a markdown mirror of the task manager, or drop it
```

Capture is split-destination, never one dump file:

- durable life or project facts go to the owning page under `01-projects/`, `02-areas/` or `03-resources/`, plus that folder's `index.md`
- reusable operational knowledge about the harness itself goes to one place you can grep later
- outstanding action items go to the task manager, plus the markdown mirror if you keep one
- unfinished work goes to a handoff note under `reports/`
- collaboration-pattern corrections go to memory or CLAUDE.md, never the notes tree (write errors into CLAUDE.md or skills, not chat corrections)
- everything else is dropped. Selective beats complete: "nothing worth keeping, just archive" is a valid outcome, not a failure.

## Procedure

1. **Sweep.** Re-read the whole session from context, never the raw JSONL transcript (internal format, and the session is already in front of you). Collect: outcomes shipped, decisions made with rationale AND rejected alternatives, what failed and why, gotchas learned, state changes to systems outside the notes tree, corrections the user gave, action items still open, threads left dangling. If a repo was touched, anchor with `git status` and `git log` instead of narrating from memory. Never fabricate: a session with no story has no story, and gaps stay TBC.

2. **Review gate.** ONE terse message: proposed writes (path plus one-line gist each), tasks to create or complete, handoff note or not, memory writes if any. Then ask for the go. Items the user declines are dropped; if they decline everything, treat it as the no-write path in step 6. On the go, run steps 3 to 6 straight through.

3. **Tasks, task manager side first.** Route each approved action item by ownership: things the user must do, and things the agent should do next time. Whichever tool you use, create the task first and keep the returned id for the mirror. Complete the tasks this session finished. If the task manager is unreachable (a headless or scheduled session often has no MCP), write the mirror line WITHOUT an id and with a note saying it still needs pushing; a later session picks it up.

4. **Write the notes, one batch.** ALL writes in a single Bash call: a `python3` heredoc for the pages, with the activity-log append as a shell redirect in the same command. On a synced store (iCloud, Dropbox) the contract is write once, verify from what you wrote in memory, and never immediately re-read from disk.

   The batch covers: durable pages filed straight to final destinations (never the inbox, never the daily folder); each owning `index.md` updated; the status line or TL;DR of any project index this session moved; the task mirror lines appended; and the file's `updated:` frontmatter bumped. Mirror line shape, if you keep a mirror:

   ```
   - [ ] <text> [priority] [date] → [[<relative-path>|<Label>]] ^<task-id>
   	- Context: 1 to 3 lines of real context, which is the whole point of an agent-captured task
   ```

   Handoff note ONLY if work is genuinely unfinished: `reports/YYYY-MM-DD-session-end-<slug>.md`, 50 lines or fewer, written for the next context window rather than as a diary of this one. Skeleton: Goal, Done, Decisions (including rejected), What failed, Next steps (specific start-here item first, phrased as verifiable criteria), Resume (exact commands, paths, session id).

5. **Memory.** Collaboration-pattern learnings only, per whatever memory rules your CLAUDE.md sets.

6. **Archive, strictly last, after the writes have landed.** Branch on **which surface is hosting the session**. That, not whether the user is at their desk, is what decides whether the archive tool exists at all:

   - **Desktop-app session.** The session-management MCP tools are present. Put any final words in the SAME message as the tool call, then archive with a short reason. The tool prompts the user; on approval the session archives and the conversation ends. If they reject the prompt, the session stays open. Stop there.
   - **Cloud session.** Running on the provider's infrastructure, with no session-management tools at all: the MCP server lives in the desktop app binary, and there is no desktop app in that container to attach it to. Finish steps 1 to 5, then say in ONE line that it can be archived from the session list in the web UI or the desktop sidebar. Do not raise a task for it; it is one click in the UI they are already looking at.
   - **CLI session.** Headless, scheduled, or bridged. Same absence, plus a harder wall: CLI sessions are never registered with the desktop app, so they cannot be opened there and cannot be archived later from anywhere. There is nothing to archive and nothing to defer. Say so in one line and stop.

## Trust posture

- Review gate before any write; nothing lands without the go, including project notes created only to anchor a task mirror.
- Never touch: the daily folder, the inbox, filed sources, generated data namespaces, or generated index files.
- Sensitive-flagged notes keep their existing handling; nothing is surfaced unprompted.
- Archiving is reversible from the app, but it stops the session's process and ends the conversation, so it still goes strictly last. Capture first, archive last, never the reverse.

## Gotchas (learned the hard way)

- **Two separate session stores, and only one of them can be archived.** Desktop-app sessions are `local_<uuid>`, stored as JSON under `~/Library/Application Support/Claude/claude-code-sessions/`. CLI sessions are bare `<uuid>.jsonl` under `~/.claude/projects/<slug>/`. Neither store sees the other: the session-management tools return "not found" for every CLI uuid. So "resume it in the desktop app and archive it there" is NOT a real recovery path for a CLI session, and must never be written into a task.
- **Archive is a cliff.** Nothing can be said after the archive call; the conversation ends on the tool result.
- **A task without its mirror line drifts.** If you keep a markdown mirror reconciled by a script, a task created without its id in the mirror gets re-imported later as a duplicate with invented context. Always write both sides, task manager first, because the mirror needs the returned id.
- **If you have an automated audit of uncaptured sessions**, record a decision for sessions you deliberately close without writing anything, or the audit will resurface them forever.

Prior art that shaped this: Boris Cherny's clean-slate handoff brief, and iannuttall's `/session-end`.

