If you use Claude Code daily, you know the problem: after a few weeks you have dozens of sessions scattered across every project you've touched. They live as JSONL files under ~/.claude/projects/
, named by UUID. Which one was the JWT refactor? Which one is still mid-task? claude --resume
shows you a picker for the current directory — but there's no overview of everything, no naming, no "this one matters, pin it".
So I built Claude Session Manager — a native Linux desktop app that gives Claude Code sessions a proper home.
GitHub: https://github.com/r4nd3l/claude-session-manager
claude --resume <id>
in the session's original project directory, inside your own shellImportantly: it never touches Claude Code's own data. Names, favorites, everything app-side lives in its own config file. Transcripts are read-only to this app (unless you explicitly trash one — and that goes to the system trash, recoverable).
I wanted a native app, and the deciding factor turned out to be one component: the terminal widget.
Claude Code is a heavy TUI — alternate screens, spinners, constant redraws. A half-baked terminal emulator widget will mangle it. On Linux there's exactly one production-grade embeddable terminal: VTE, the widget behind GNOME Terminal and Ptyxis. That decision cascaded into the rest of the stack:
AdwTabView
/AdwTabBar
gave me the tab system basically for free, AdwOverlaySplitView
the sidebar layout1. Some libadwaita types are final. class SessionSidebar(Adw.ToolbarView)
compiles fine and explodes at runtime with could not create new GType
. AdwToolbarView
can't be subclassed — wrap it in a Gtk.Box
instead.
2. GtkListBox headers belong to rows. I implemented collapsible project groups by filtering out the group's rows... and the group
3. Bind properties, don't rebuild lists. The first version rebuilt the whole sidebar on every change — fine at 10 sessions, scroll-position-destroying at 50+ with live file monitoring. The fix was a proper model layer: a GObject
item per session with bindable properties, reused across refreshes. Renames, stars and status dots now update in place, and the list is only re-spliced when the order actually changes.
sessions.py # transcript discovery + parsing (pure Python, fully testable)
state.py # app-side persistence (names, favorites, settings)
store.py # single source of truth: threaded scans, file monitors, diffing
sidebar.py # the session list widget
window.py # tabs + actions + composition
The data layer is GTK-free, which means the test suite runs on a bare python:3.12-slim
container in CI — no display server, no GTK packages.
There's a .deb
on the release page:
sudo apt install ./claude-session-manager_0.1.0_all.deb
Or run from source (Fedora/Arch package names in the README):
git clone https://github.com/r4nd3l/claude-session-manager.git
cd claude-session-manager
python3 -m claude_session_manager
It's GPL-3, unofficial, and not affiliated with Anthropic. Issues and PRs welcome — the next feature on my list is transcript peek: reading the last few messages of a session in the details dialog, so you can identify a session without resuming it.
If you try it, I'd genuinely like to know what breaks on your distro. 🐧
Enjoying the content? If you'd like to support my work and keep the ideas flowing, consider buying me a coffee! Your support means the world to me!