Skip to content

wired/claude-spaces

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

134 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

claude-spaces

Tests AUR

Session management for Claude Code.

claude-spaces-v0 9 0

Claude Code tracks sessions but gives you no way to see them. No list, no switching, no way to tell what's running in the background. claude-spaces adds all of that — a persistent tmux side panel that shows every session across every project, with instant switching and background activity alerts.

+------------------------------------+------------------------------+
|                                    | ~wired/                      |
|  Active claude session             | write a wrapper...       5m  |
|  or welcome screen                 | sessions                14h  |
|                                    | configure verbose...     4h  |
|                                    |                              |
|                                    |      ─ other projects ─      |
|                                    | on-point-camera              |
|                                    |   test-framework          2h |
|                                    |   camera firmware         3h |
|                                    |                              |
|                                    | old-webapp                   |
|                                    |   fix route bug           1d |
|                                    |                              |
|                                    |         ─ inactive ─         |
|                                    | old-project                  |
|                                    |                              |
|                                    | : menu  / search             |
|                                    | Q:detach  ?:help             |
|                                    | claude-spaces v0.9.10-dev     |
+------------------------------------+------------------------------+
         left slot                    picker (30 cols default)

WARNING

claude-spaces avoids altering Claude Code's internal files. We only read from ~/.claude and write all state to claude-spaces-specific directories.

That said, this is a hobby project and Claude was involved with most of the code, so I encourage caution. Test it out before using it with valuable projects.

Install

brew tap wired/tap && brew install claude-spaces    # macOS / Homebrew
yay -S claude-spaces                                # Arch (AUR)
make install                                        # /usr/local/bin (may need sudo)
PREFIX=~/.local make install                        # ~/.local/bin

You can also just clone and run directly if all dependencies are met. It will warn you.

Requires bash 4.3+, tmux 3.0+, jq.

Quick Start

claude-spaces              # launch
claude-spaces --restart    # restart the server (e.g. to apply an update)
claude-spaces --reset      # kill all managed panes, clear state
claude-spaces --help

Run it from any project directory. It creates a dedicated tmux server, opens a session picker on the right, and launches Claude Code on the left.

Prefix key

claude-spaces inherits your tmux prefix from tmux.conf and works with any prefix. That said, the keybindings are designed around ` (backtick):

  • prefix + ` — smart terminal toggle (open, then toggle focus)
  • prefix + a — sends a literal ` (so you don't lose the character)

If you'd like to try it, add to your ~/.tmux.conf:

set-option -g prefix `
bind-key a send-prefix

Or, to only use ` as prefix inside claude-spaces, add to ~/.config/claude-spaces/config:

prefix=`

All prefix bindings are configurable via the same config file (see Configuration).

Features

Session picker — all sessions for the current project in a persistent side panel. Navigate with j/k, jump with 1-0, search with /. You can also use the tmux prefix for even faster navigation

Cross-project discovery — sessions from other running projects appear automatically. Hit Enter to switch. Inactive projects (not currently running) are discovered and can be resumed.

This allows you to use claude-spaces with worktrees as well, you just have to create them yourself.

Project names — when multiple projects share the same directory name, the picker automatically disambiguates them with minimal path suffixes. You can also set custom names via prefix + p or the : command menu — useful for worktrees or any project where the directory name isn't descriptive enough.

Bell detection — when Claude finishes in a background session, the picker highlights it in red. Never miss a completed task again.

Per-session terminal — each session gets its own shell pane, either below it (prefix + `) or to the side (prefix + Tab). Both open the terminal and toggle focus between it and the Claude pane. prefix + t toggles terminal visibility on/off. Resize freely — size is saved per-session.

Search and filter — type / to filter sessions by name across all sections. Matches update as you type.

Isolated per-project servers — each project gets its own tmux server. No cross-contamination of keybindings, window state, or bell hooks.

Keybinds

claude-spaces takes full ownership of the tmux prefix key table on its dedicated server. Stock tmux bindings are disabled. Your tmux.conf is sourced for visuals (colors, mouse, status) but all keybindings are managed by claude-spaces.

Picker pane (direct keys)

Key Action
j / k / / Move cursor (skips headers)
1-9, 0 Jump to Nth session (0 = 10th) + focus
Enter Load + focus session (remote/inactive: switch project)
Space Load session (stay in picker)
H / L Load + focus session
a / i Focus Claude pane
h / l / / Move between panes
/ Search/filter sessions
: Command menu (new, fork, rename, close, hide, shutdown)
? Show help screen
Q Detach (exit)
R Reload picker in-place (picks up code changes) — see note below

Note on R after an update. Most updates hot-reload in place. If an update changes the session layout, the new picker can't run against the running server — R stops it instead, and tells you to run claude-spaces again. Your sessions restart, but conversations are not lost: they come straight back in the picker, resumable. claude-spaces --restart does the same thing without going through the picker. Running claude-spaces while such an update is pending prints a notice and leaves the server alone, so nothing is ever restarted behind your back.

Prefix key bindings (from any pane)

Key Action
prefix + Enter / prefix + i Focus Claude pane
prefix + Space Toggle picker / Claude pane
prefix + ` Smart terminal — bottom (open/focus toggle)
prefix + Tab Smart terminal — side (open/focus toggle)
prefix + t Toggle terminal on/off (unconditional)
prefix + a Literal grave (`)
prefix + h / prefix + ← / prefix + S-← Select pane left
prefix + j / prefix + ↓ Select pane down
prefix + k / prefix + ↑ Select pane up
prefix + l / prefix + → / prefix + S-→ Select pane right
prefix + J / prefix + S-↓ Next session + focus
prefix + K / prefix + S-↑ Prev session + focus
prefix + 1-9, 0 Jump to Nth session + focus
prefix + / Focus picker + search
prefix + c New session
prefix + f Fork session (with confirm)
prefix + x Close session (with confirm)
prefix + r Rename session
prefix + p Rename project
prefix + H Hide session (with confirm)
prefix + s Shutdown (kill server)
prefix + R Reload picker
prefix + z Zoom/maximize pane
prefix + [ Copy mode
prefix + ] Paste buffer
prefix + PgUp Copy mode + scroll up
prefix + d Detach
prefix + : Command menu
prefix + ? Show help screen
prefix + + Refresh/rescan
prefix + F12 tmux command prompt (escape hatch)
prefix + M-↑/↓/←/→ Resize pane (2 cells)
prefix + C-↑/↓/←/→ Resize pane (5 cells)
Bell Detection

Background sessions that finish can ring the terminal bell, highlighting them in red in the picker. Add a Claude Code Stop hook to ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "printf '\\a' | jq -Rsc '{terminalSequence: .}'"
          }
        ]
      }
    ]
  }
}

Claude Code runs hooks without a controlling terminal (v2.1.139+), so the older printf '\a' > /dev/tty recipe now fails with No such device or address. Returning the bell in the terminalSequence field instead makes Claude Code emit it through its own terminal, where tmux sees it. Requires Claude Code v2.1.141+. Bell state clears when the session is brought to the foreground.

Rendering (recommended: tui: fullscreen)

Recommended when using Claude Code under claude-spaces. In ~/.claude/settings.json:

{
  "tui": "fullscreen"
}

By default Claude Code draws into the terminal's normal buffer, so its output lands in tmux's scrollback. tmux reflows scrollback whenever a pane's width changes — so resizing your terminal (or opening a side terminal) can mangle the history, with parts of the transcript doubled or tripled.

tui: fullscreen moves Claude onto the alternate screen, which tmux never writes into scrollback and never reflows, so the mangling cannot occur.

Switching sessions does not resize the Claude pane — the picker moves, not Claude — so swapping between sessions is already reflow-free either way.

Trade-off: you lose tmux-native scrollback and copy-mode for the Claude pane — use Claude's own scrolling instead. The picker and terminal panes are unaffected.

Configuration

Config file: ~/.config/claude-spaces/config (created on first run with commented defaults; respects $XDG_CONFIG_HOME).

# Picker pane width: characters (e.g. 30) or percentage (e.g. 20%)
# picker_width=30

# Picker pane position: "right" (default) or "left"
# picker_side=right

# Sessions modified within this many minutes sort at the top (running sessions
# first, then by name); older sessions sort by most recent first below them.
# recent_threshold=10

# Max length for tmux window names
# window_name_len=12

# Path to tmux.conf to source on dedicated server (empty = don't source)
# tmux_conf=~/.tmux.conf

# Directory for runtime state. Defaults to $XDG_RUNTIME_DIR/claude-spaces, or
# /tmp/claude-spaces-$UID when that is unset. Set this if your /tmp is reaped
# while sessions are still live. Must be an absolute path (~/ is expanded).
# A persistent location means state survives reboot and keeps a small entry per
# project; `claude-spaces --reset` clears the current project's.
# state_root=~/.local/state/claude-spaces

# Terminal pane height: characters (e.g. 15) or percentage (e.g. 35%)
# terminal_height=35%

# Terminal pane width (side orientation): characters or percentage
# terminal_width=45%

# Minimum Claude pane width when side terminal is open (characters)
# min_claude_width=10

# Minimum Claude pane height when bottom terminal is open (characters)
# min_claude_height=10

# Show jump index next to first 10 local sessions
# show_index=1

# Override tmux prefix key (default: inherited from tmux.conf)
# prefix=C-a

# Keybinding overrides (comma-separated for multiple keys)
# bind_terminal=`
# bind_side_terminal=Tab
# bind_toggle_terminal=t
# bind_focus_claude=Enter,i
# bind_nav_next=J,S-Down
# bind_nav_prev=K,S-Up
# bind_pane_left=h,Left,S-Left
# bind_pane_right=l,Right,S-Right
# bind_pane_up=k,Up
# bind_pane_down=j,Down
# bind_focus_picker=Space
# bind_detach=d
# bind_zoom=z
# bind_copy_mode=[
# bind_paste=]
# bind_search=/
# bind_new_session=c
# bind_fork=f
# bind_close=x
# bind_rename=r
# bind_rename_project=p
# bind_hide=H
# bind_shutdown=s
# bind_reload=R
# bind_refresh=+
# bind_menu=:

Custom session names: ~/.local/share/claude-spaces/names (session_id=name; respects $XDG_DATA_HOME) Hidden sessions: ~/.local/share/claude-spaces/hidden (one ID per line; respects $XDG_DATA_HOME)

License

MIT

About

Session management for Claude Code using tmux.

Resources

License

Stars

3 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors