DEV Community

Cover image for A native Linux app to manage Claude Code sessions
Matt Miller
Matt Miller

Posted on

A native Linux app to manage Claude Code sessions

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

What it does

  • Every session on your machine in one sidebar, grouped by project, newest first, with the first prompt as a preview
  • Custom names and favorites — star the sessions you keep coming back to, rename "a3b2152e" to "JWT auth"
  • Click to resume — each session opens in an embedded terminal tab, running claude --resume <id> in the session's original project directory, inside your own shell
  • Attention indicators — working in one tab while Claude finishes in another? The background tab and its sidebar entry light up
  • Live updates — start a session anywhere in any terminal, and it appears in the sidebar seconds later
  • Bulk operations — multi-select to open, star, hide, or trash many sessions at once
  • Session details — message counts, models used, token totals parsed straight from the transcript

Importantly: 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).

The stack: why Python + GTK4, not Electron

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:

  • GTK4 + libadwaitaAdwTabView/AdwTabBar gave me the tab system basically for free, AdwOverlaySplitView the sidebar layout
  • Python + PyGObject — the whole app is plain Python, no build step; contributors need nothing but distro packages
  • Qt was out — PySide6 has no maintained terminal widget, and the workarounds (X11 window embedding) die on Wayland
  • Electron/Tauri + xterm.js would have worked — but for a tool that spawns local processes and reads local files, a native app with zero IPC layers is simply the better fit

Three GTK lessons I learned the hard way

1. 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 header vanished with them, because headers are decorations attached to the first visible row of a group. The fix: make headers real rows in the list, so they survive when their children are hidden.

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.

Architecture in five files

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
Enter fullscreen mode Exit fullscreen mode

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.

Try it

There's a .deb on the release page:

sudo apt install ./claude-session-manager_0.1.0_all.deb
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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!

Buy Me A Coffee

Top comments (0)