My Mac hard-crashed with seven Claude Code sessions open across five repos. The built-in recovery, claude --resume, lists only the directory you run it from — and takes over that shell. The fix is one script over files Claude already writes: every session, every project, one list, Enter to resume.
cs OPENS, AND WHAT ENTER DOES WITH THE HIGHLIGHTED ROWPoint fzf at the session store
Claude Code stores every session as plain JSONL — one file per session, one folder per project, at ~/.claude/projects/<encoded-project-path>/<session-id>.jsonl. The early lines of each file carry the session id, the working directory, the git branch, and your opening message: a complete cross-project session index, already sitting on disk.
$ ls ~/.claude/projects | head -3 -Users-dg -Users-dg-dashboard -Users-dg-GitHub-D4G4
That encoding is reversible, which is all the picker needs to cd you back to the right place.
One list, Enter to resume
Running claude-sessions opens fzf over every session from every project, newest first, with a live preview of the conversation. Sessions spawned by agent teams carry a ⛭ tag with the agent's name; ctrl-a hides them.
cd <project> && claude --resume <session-id>
The new tab lands in the right directory and Claude's own summary-or-full-session prompt appears there, while the picker stays open for the next one. Restoring my seven sessions was Enter, seven times — about ten seconds.
Install it
Needs fzf and python3. Tab-opening is macOS (iTerm2 or Terminal); inside tmux it works on Linux too.
$ curl -fsSL https://raw.githubusercontent.com/DenverLifeSciences/claude-sessions/main/claude-sessions -o /usr/local/bin/claude-sessions $ chmod +x /usr/local/bin/claude-sessions
One caveat, stated plainly: the session storage format is undocumented and could change under any Claude Code release. The script treats it as read-only and never writes a byte back — the worst a format change can do is empty the list.