Skip to content

GeoffChurch/shpool-table

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

shpool-table

A lightweight TUI for managing shpool sessions.

screenshot

shpool-table is not a shpool session itself — it's a standalone process that owns your terminal, shows your sessions in a navigable list, and spawns shpool attach when you pick one. When you detach from a session (via shpool's detach keybinding), you land back in the manager's menu. It requires zero changes to shpool — the daemon doesn't know the manager exists.

Installation

Requires shpool and a Rust toolchain (1.85+).

cargo install --git https://github.com/GeoffChurch/shpool-table

To hack on it locally instead:

git clone https://github.com/GeoffChurch/shpool-table
cd shpool-table
cargo build --release
# binary at target/release/shpool-table

Usage

shpool-table
Key Action
Up / Down or k / j Move selection
Enter Attach to the selected session
n Create a new session (prompts for name)
d Kill the selected session (confirms first)
q / Ctrl-C Quit

The TUI footer is the canonical source for key bindings — the table above is a convenience snapshot.

When you attach, shpool attach <name> takes over the terminal. Detach with shpool's keybinding (default Ctrl-Space Ctrl-q, configurable in ~/.config/shpool/config.toml) and you're back in the manager.

As an SSH entry-point

Set your SSH config to land directly in the manager:

Host myserver
    Hostname remote.example.com
    RemoteCommand bash -lc "shpool-table"
    RequestTTY yes

The bash -lc wrapper runs a login shell so ~/.cargo/bin gets added to PATH via your shell's profile scripts. Without it, SSH invokes a non-interactive non-login shell, which doesn't source .bashrc or .profile and so shpool-table isn't found. Skip the wrapper only if you've put the binary on the system PATH some other way.

Alongside tmux or other multiplexers

shpool-table handles session navigation, not terminal multiplexing. If you want split panes or tiled windows, run your multiplexer as the outer layer and shpool-table inside each pane:

  • tmux / zellij: each pane runs shpool-table, you pick a shpool session per pane. Your multiplexer layout persists independently from your shpool sessions — detaching from shpool drops you back to the manager in that pane, not out of the multiplexer.
  • dtach / abduco: same idea — these handle persistence at the multiplexer level while shpool handles it at the shell level.
  • Tiling window managers (sway, i3, etc.): each terminal window runs shpool-table directly.

Multiplexing and previews

shpool-table doesn't currently multiplex (show multiple sessions side-by-side). This is possible in principle — shpool continuously maintains an in-memory virtual terminal render of every session (via shpool_vt100), so a future version could display live previews or a split view by requesting snapshots from the daemon. This would require a small upstream addition to shpool (e.g., a shpool peek <name> subcommand). See Future directions below.

Architecture

The manager shells out to the shpool CLI rather than using shpool-protocol directly. Per shpool's version policy, the CLI is a public, semver-stable interface while the wire protocol is explicitly not — shelling out means shpool-table survives shpool upgrades without breakage, and inherits autodaemonization, socket discovery, and version negotiation for free.

Code layout

File Role
src/main.rs Entry point, fetch_sessions, TUI orchestration
src/session.rs Serde types for shpool list --json output
src/tui.rs Model, input parser, render — pure logic, tested
src/tty.rs Unsafe libc wrappers: raw mode, tty size, alt screen

All unsafe code is isolated in tty.rs behind RAII (RawMode guard). The pure state-transition and input-parsing logic in tui.rs has unit tests; no trait-based mocking layer — direct style, small enough to refactor if needed.

Testing

cargo test

The test suite covers:

  • JSON schema compatibility. Deserializes representative shpool list --json output (including extra fields) to catch serde drift without needing a running daemon.
  • Selection state. Wrap-around for up/down, empty-list edge case.
  • Input parsing. Escape-sequence state machine for arrow keys, Enter, quit keys, and unknown sequences.
  • Input→action dispatch. process_input is extracted from the event loop as a pure function: given a byte buffer, a Model, and an InputParser, it returns an optional LoopAction. Tests verify multi-key sequences like "Down, Down, Enter → Attach third session" without any terminal I/O.

End-to-end tests against a real shpool daemon are feasible (create sessions with shpool attach -b, assert on output, clean up with shpool kill) but not yet wired up. The main consideration is test isolation — each test needs its own daemon socket and config to avoid cross-test pollution and sensitivity to the host's shpool config.

Dependencies

Minimal by design:

  • anyhow — error handling
  • libc — termios raw mode, ioctl(TIOCGWINSZ), isatty
  • serde + serde_json — parsing shpool list --json

No TUI framework (ratatui, crossterm, etc.) — the interface is small enough that hand-rolled ANSI escape sequences are simpler than a dependency.

Future directions

  • Session previews. The cleanest path is a shpool peek <name> upstream subcommand that prints the daemon's in-memory screen snapshot as ANSI. shpool-table could then show a preview pane without leaving the CLI-only, shell-out architecture.
  • Resize handling. Redraw the manager's own menu on SIGWINCH (currently redraws on next keypress).
  • System hygiene. Automatically rename any installed shpiel (a waddling abomination that chose the path of smugness over usefulness) to "shpaghetti".

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages