List, preview, and reversibly delete Claude Code sessions — from a CLI, a curses TUI, or a Claude Code plugin. Pure Python, zero runtime dependencies.
Claude Code stores every session on disk as a .jsonl file under
~/.claude/projects/. Over time they pile up, and there's no built-in way to
browse or prune them. claude-sessions gives you three ways to do it, all
backed by the same engine:
| Interface | Command | Best for |
|---|---|---|
| CLI | csm list … |
Quick look, scripting |
| TUI | claude-sessions |
Browsing / picking visually |
| Claude Code plugin | /sessions |
Doing it from inside claude |
- Three front-ends, one engine — identical listing & deletion behavior everywhere.
- Reversible by default — deleted sessions move to a trash folder
(
~/.claude/.session-trash/, 30-day retention) and can be restored. - Never deletes the running session — the current Claude Code session is
detected via
CLAUDE_CODE_SESSION_IDand protected. - Reads your real data — parses the actual
.jsonlformat; titles come from the first user message. - Zero runtime deps — standard library only (CLI + TUI). Nothing to
pip installto run it.
- Python ≥ 3.10
- Claude Code sessions under
~/.claude/projects/(the default location)
git clone https://github.com/scorpion-fish/claude-sessions.git claude-sessions
cd claude-sessions
# Option A — install onto PATH (enables `csm`, `claude-sessions`, and the plugin)
pip install -e .
# Option B — run without installing (zero deps)
PYTHONPATH=src python3 -m claude_sessions listVerify:
csm --version # csm 0.1.0
csm list # prints your sessionscsm list # all sessions, newest first
csm list --project -home-me-code-myapp # one project only
csm list --json # machine-readable
csm show 2 # preview the 2nd row (also accepts a uuid)
csm delete 2 # asks y/N, then moves to trash
csm delete 2 --yes # skip the prompt
csm restore <uuid> # undo a deletion
csm purge # permanently drop trash older than 30 days
csm purge --days 7 # custom retention
csm tui # launch the curses TUISample output:
# project last active (UTC) size title
1 -home-me-code-myapp 2026-06-29 09:07 120K *fix login redirect bug…
2 -home-me-code-api 2026-06-29 08:42 343K add retry to db client
3 -home-me-notes 2026-06-28 22:10 14K <无标题>
(* = current session, cannot be deleted)
show / delete accept either a uuid or a row number (2 or #2)
referring to the current csm list order.
A split-pane curses browser: sessions on the left, a live preview on the right.
┌ Claude Sessions ─────────────┬──────────────────────────┐
│ > * 06-29 05:07 标题一 │ # 标题一 │
│ 06-29 05:06 标题二 │ /home/me/code/myapp · 797K│
│ 06-29 04:25 <无标题> │ user: 第一个问题… │
│ │ assistant: 回答… │
├──────────────────────────────┴──────────────────────────┤
│ ↑↓/jk move · d delete · r refresh · / search · q quit │
└─────────────────────────────────────────────────────────┘
| Key | Action |
|---|---|
↑ ↓ / j k |
Move selection |
d |
Delete the highlighted session (prompts y/n) |
r |
Refresh the list from disk |
/ |
Search/filter (type to filter, Enter to commit) |
q / Esc |
Quit |
/plugin marketplace add /path/to/claude-sessions/plugin
/plugin install session-manage
Then inside claude:
> /sessions # numbered list, current session marked *
> 2 # preview session #2
> delete 2 # Claude asks: yes / no
> yes # deleted; refreshed list shown
The plugin simply drives csm, so behavior is identical to the CLI.
- Sessions are
~/.claude/projects/<encoded-project>/<uuid>.jsonl(one JSON object per line). A session may also have a same-named directory (<uuid>/subagents/…) — deleting a session removes both. - Project decoding:
/home/me/code/myappis stored as-home-me-code-myapp(slashes → dashes); the tool inverts this for display. - Title: the text of the first real user message, truncated to 60 chars.
- Deletion is a
mvinto the trash plus a<uuid>.meta.jsonsidecar recording the original paths and time — that's what makes it reversible and whatpurgeuses to enforce retention.
| Concern | Behavior |
|---|---|
| Accidental delete | Goes to trash first; csm restore <id> brings it back |
| Disk space | csm purge permanently clears old trash |
| Deleting the live session | Refused (detected via CLAUDE_CODE_SESSION_ID) |
| Tests / dev touching real data | Overridable via CSM_CLAUDE_DIR env var |
pip install -e ".[dev]" # installs pytest (optional)
PYTHONPATH=src python3 -m unittest discover -s tests # zero-dep test run
pytest # if pytest installedProject layout:
src/claude_sessions/
env.py # paths, current-session id, project-dir decode
parse.py # JSONL parsing, title + preview extraction
sessions.py # discover / get / preview sessions
trash.py # reversible delete / restore / purge
cli.py # `csm` (argparse)
tui/app.py # `claude-sessions` (curses)
tests/ # unittest specs mirroring src/, + cli + tui smoke tests
plugin/ # Claude Code plugin (manifest + /sessions command)
docs/ # design spec + implementation plan
See CONTRIBUTING.md for conventions, and CHANGELOG.md for changes.
MIT — see LICENSE.