A tmux-like terminal multiplexer written in Rust.
A background server owns sessions, windows, and panes; clients attach to it over a Unix socket, so sessions survive detach and terminal restarts. Panes run real shell PTYs with vte-based terminal emulation, scrollback, mouse selection, a cursor (copy) mode, a status line, and a window-tree sidebar that spans all sessions.
curl -fsSL https://github.com/aplio/spectra/raw/refs/heads/master/install.sh | sh- pin a version:
SPECTRA_VERSION=v0.2.0 sh - custom directory:
SPECTRA_BIN_DIR=$HOME/.bin sh - upgrade later with
spectra --update; a live handoff then automatically moves a running server onto the new binary without killing any pane process (refused while clients are attached — detach and runspectra server-handoffmanually; see docs/upgrade.md)
Or build from source: cargo install --path .
spectra # attach if a server is running, otherwise create one
spectra --attach dev # attach to a target: session[:window[.pane]]
spectra --cwd /path --shell /bin/zsh
spectra --remote user@host # attach to a server on another machine over ssh (experimental)Session management from the shell (spectra --help for the full list):
spectra ls
spectra new-session
spectra kill-session --target dev
spectra new-window --target dev
spectra split-window --vertical --target dev:1
spectra send-keys --target dev:1.2 "make test"The prefix is Ctrl+j. Press prefix ? for the full searchable cheat sheet.
| Key | Action |
|---|---|
Alt+Arrow |
focus pane in direction (no prefix; crosses windows/sessions at edges) |
prefix | / prefix " |
split vertical / horizontal |
prefix c / prefix n |
new window / new session |
prefix w |
tree popup (session → window → pane, / filters, r renames) |
prefix e |
toggle the window-tree sidebar |
prefix p |
command palette |
prefix z |
zoom active pane |
prefix H/J/K/L (or Shift+Arrow) |
swap pane in direction (split shape stays) |
prefix ! |
break the focused pane out into a new window |
prefix R |
sticky resize mode (arrows/hjkl resize, Esc exits) |
prefix [ |
cursor mode (vi-style movement, g chords gg/ge/gh/gl, v/y select and copy, / search) |
prefix / |
search scrollback (cursor mode with the / bar open; type to search, Enter confirm, n/N next/prev, Esc cancel) |
prefix y |
copy the mouse drag selection |
prefix v |
paste the clipboard image as a temp-file path (bridged from the local clipboard over --remote too) |
prefix d |
detach (server keeps running) |
prefix x |
close focused pane (closes the window, then the session, when it's the last one) |
prefix u |
restore the last closed pane (kept alive for [pane].undo_close_seconds, default 10s) |
prefix q |
quit (press again within 3s to confirm) |
With [mouse].enabled = true, click focuses panes, dragging on dividers resizes,
and dragging over text selects (double/triple click expands word → run → line).
Ctrl+click opens the path or URL under the cursor (ghostty-style cmd+click):
an existing directory opens as a new pane in that directory, and URLs open in
the browser. A clicked file opens by type: text and code open in the configured
editor (falling back to $EDITOR, then the first of gargo/vi/emacs/nano on
PATH, and jumping to a trailing :line), while documents, images, media and
archives (xlsx, docx, pdf, png, ...) go to the system opener (open /
xdg-open). [mouse.open_click_commands] overrides this per extension, e.g.
xlsx = "open ${PATH}", with "editor" and "system" as forcing special
values. The modifier is [mouse].open_click. Moving the mouse with the
modifier held underlines the target under the pointer, so clickable paths and
URLs are visible before the click.
~/.config/spectra/config.toml (or $XDG_CONFIG_HOME/spectra/config.toml).
All keys are optional; see docs/config.example.toml
for the annotated full reference.
prefix = "C-j"
[mouse]
enabled = true
[terminal]
scrollback_lines = 10000
[prefix_bindings]
N = "run: notify-send 'hello from spectra'"
[global_bindings]
"C-w" = "window-tree"Reload at runtime with prefix r. Runtime data (session logs, layouts, scrollback
dumps) lives under ~/.local/share/spectra.
A running server serves a JSON-RPC API over a second Unix socket. spectra api
sends one request and prints the result:
spectra api session.list
spectra api pane.read '{"pane_id":1,"lines":50}'
spectra api pane.send_keys '{"pane_id":1,"text":"ls\n"}'
spectra api pane.swap '{"direction":"left"}'
spectra api pane.move '{"pane_id":2,"to_window":1}' # or new_window / to_session
spectra api layout.export
spectra api layout.apply '{"layout":{"type":"split","axis":"vertical","ratio_percent":70,"first":{"type":"leaf","pane_id":1},"second":{"type":"leaf","pane_id":2}}}'
spectra api layout.set_split_ratio '{"pane_id":1,"ratio":70}'
spectra api --follow events.subscribe '{"events":["agent.changed"]}'On top of this sit two extension points:
- Plugins — a directory with a
spectra-plugin.tomlmanifest (any language, no SDK) can react to events, run a supervised background service, and ship agent-detection manifests. Place them under~/.config/spectra/plugins/<name>/;spectra api plugin.listshows what loaded. - Claude Code integration —
spectra integration install claudewires Claude Code's hooks to spectra's agent-state detection, so the sidebar and status line show whether an agent in a pane is working, blocked, or done. Uninstall withspectra integration uninstall claude.
cargo run # run from source (attach-or-create)
cargo fmt
cargo clippy --all-targets --all-features -- -D warnings
cargo testArchitecture notes and a module map live in docs/README.md. See docs/CONTRIBUTING.md for contribution guidelines.
Releases: bump version in Cargo.toml, tag vX.Y.Z, and push the tag — CI
builds Linux/macOS binaries and publishes them with checksums to a GitHub release.