Summary
Create a kolu-tmux CLI shim that implements the subset of tmux commands used by AI coding tools (Claude Code, etc.), translating them to Kolu HTTP RPC calls.
Depends on #184 (plain-text screen capture API) for capture-pane support.
Motivation
AI tools like Claude Code use tmux as a standard interface to discover, read, and write to terminals. A shim lets these tools work with Kolu without upstream changes.
Scope
Shim binary (kolu-tmux)
Parses tmux subcommands and flags, dispatches to Kolu's existing HTTP RPC (/rpc/*).
Commands to support:
| Command |
Maps to |
-V (version) |
Return fake version string |
has-session -t name |
/api/health |
list-sessions [-F fmt] |
Single "kolu" session |
list-windows [-t session] [-F fmt] |
terminal.list(), top-level only |
list-panes [-t window] [-F fmt] |
terminal.list(), filter by parentId |
capture-pane -p [-t target] [-S start] [-E end] [-J] |
terminal.screenText (#184) |
send-keys [-t target] [-l] text [key...] |
terminal.sendInput |
new-session -s name [-c path] |
terminal.create |
new-window [-t session] [-c path] |
terminal.create |
split-window [-t window] [-h|-v] [-c path] |
terminal.create({ parentId }) |
kill-pane -t target |
terminal.kill |
resize-pane -t target -x W -y H |
terminal.resize |
break-pane / join-pane |
terminal.setParent |
show-options -g prefix |
Return synthetic prefix |
set-option (pane border colors, etc.) |
No-op (acknowledge silently) |
select-layout |
No-op (Kolu sub-terminals are tabs, not spatial) |
Target resolution
Resolve tmux-style targets (session:window.pane, %pane-id, numeric indices) to Kolu terminal UUIDs. Window index = position in terminal.list() order; pane index = sub-terminal order within parent.
-F format string evaluator
Support the format variables Claude Code actually uses: #{session_name}, #{window_index}, #{window_name}, #{pane_id}, #{pane_pid}, #{pane_current_path}, #{pane_active}, etc.
Environment injection
- Set
$TMUX in PTY shells (format: <socket>,<pid>,0) so tools detect multiplexer presence
- Set
$TMUX_PANE to a unique synthetic pane ID per terminal (e.g. %0, %1, %2... derived from terminal index) — this is how Claude Code identifies its "leader pane" and scopes teammate operations
- Put
kolu-tmux on $PATH as tmux within Kolu shells (symlink or wrapper)
Multi-instance isolation
A user may run Claude Code in N different Kolu terminals simultaneously (each in a different repo). Each instance must be isolated:
$TMUX_PANE per terminal — Claude Code reads $TMUX_PANE at startup to identify its leader pane. Each Kolu terminal gets a unique pane ID, so each Claude Code instance knows which pane is "self".
split-window without -t — must create a sub-terminal under the calling terminal (resolved from the caller's $TMUX_PANE). The shim needs to accept $TMUX_PANE from the calling environment to determine context.
- Kolu's concept mapping — 1 Kolu server = 1 tmux session; N top-level terminals = N tmux windows; sub-terminals = panes within a window. Each Claude Code instance lives in its own window and creates teammate panes (sub-terminals) within that window only.
-L <socket> flag — Claude Code uses per-PID socket names for isolation in "external session" mode. Inside tmux (our case), it uses the existing session, so this is less critical. The shim should accept and ignore -L.
Claude Code integration
Once implemented, Claude Code's multi-agent (teammate/swarm) feature will work inside Kolu terminals with zero user configuration. Here's how:
How it works (automatic)
Claude Code detects tmux at startup via two checks:
$TMUX env var — if set, Claude Code knows it's "inside tmux" and uses its TmuxBackend for teammate pane management
tmux -V — checks if the tmux binary is available (the shim responds to this)
Since Kolu injects both $TMUX and the shim binary into PTY shells, Claude Code will automatically detect tmux support and use it. No settings changes needed.
What Claude Code uses tmux for
Claude Code does not use tmux for its own command execution (the Bash tool spawns processes directly). tmux is used exclusively for:
- Agent teams:
split-window to create teammate panes, send-keys to dispatch commands, kill-pane to clean up
- Pane management:
break-pane/join-pane to hide/show teammate panes, pane border colors for visual identification
- Worktree sessions:
--tmux -w flag creates a tmux session per worktree
Relevant Claude Code settings
| Setting |
Values |
Effect |
teammateMode |
"auto" (default), "tmux", "in-process" |
"auto" auto-detects tmux; "tmux" forces it; "in-process" disables pane creation |
preferTmuxOverIterm2 |
true/false |
Irrelevant in Kolu (no iTerm2) |
Users can override per-session with --teammate-mode tmux or --teammate-mode in-process.
Verifying it works
Inside a Kolu terminal:
# Should return the shim's version string
tmux -V
# Should show the kolu session
tmux list-sessions
# Launch Claude Code with teammates — panes appear as Kolu sub-terminals
claude --tmux -w
Additional shim commands for Claude Code teammate support
Beyond the basic tmux subset, Claude Code's TmuxBackend also uses:
select-layout — pane layout (main-vertical, tiled) — no-op in Kolu (sub-terminals are tabs, not spatial)
set-option pane-border-style — teammate color coding — no-op (Kolu could map to per-terminal theme accents in the future)
Non-goals
- Full tmux protocol compatibility (only the subset AI tools use)
- tmux control mode (
-CC)
- Copy mode / key bindings / status bar emulation
Summary
Create a
kolu-tmuxCLI shim that implements the subset of tmux commands used by AI coding tools (Claude Code, etc.), translating them to Kolu HTTP RPC calls.Depends on #184 (plain-text screen capture API) for
capture-panesupport.Motivation
AI tools like Claude Code use tmux as a standard interface to discover, read, and write to terminals. A shim lets these tools work with Kolu without upstream changes.
Scope
Shim binary (
kolu-tmux)Parses tmux subcommands and flags, dispatches to Kolu's existing HTTP RPC (
/rpc/*).Commands to support:
-V(version)has-session -t name/api/healthlist-sessions [-F fmt]list-windows [-t session] [-F fmt]terminal.list(), top-level onlylist-panes [-t window] [-F fmt]terminal.list(), filter by parentIdcapture-pane -p [-t target] [-S start] [-E end] [-J]terminal.screenText(#184)send-keys [-t target] [-l] text [key...]terminal.sendInputnew-session -s name [-c path]terminal.createnew-window [-t session] [-c path]terminal.createsplit-window [-t window] [-h|-v] [-c path]terminal.create({ parentId })kill-pane -t targetterminal.killresize-pane -t target -x W -y Hterminal.resizebreak-pane/join-paneterminal.setParentshow-options -g prefixset-option(pane border colors, etc.)select-layoutTarget resolution
Resolve tmux-style targets (
session:window.pane,%pane-id, numeric indices) to Kolu terminal UUIDs. Window index = position interminal.list()order; pane index = sub-terminal order within parent.-Fformat string evaluatorSupport the format variables Claude Code actually uses:
#{session_name},#{window_index},#{window_name},#{pane_id},#{pane_pid},#{pane_current_path},#{pane_active}, etc.Environment injection
$TMUXin PTY shells (format:<socket>,<pid>,0) so tools detect multiplexer presence$TMUX_PANEto a unique synthetic pane ID per terminal (e.g.%0,%1,%2... derived from terminal index) — this is how Claude Code identifies its "leader pane" and scopes teammate operationskolu-tmuxon$PATHastmuxwithin Kolu shells (symlink or wrapper)Multi-instance isolation
A user may run Claude Code in N different Kolu terminals simultaneously (each in a different repo). Each instance must be isolated:
$TMUX_PANEper terminal — Claude Code reads$TMUX_PANEat startup to identify its leader pane. Each Kolu terminal gets a unique pane ID, so each Claude Code instance knows which pane is "self".split-windowwithout-t— must create a sub-terminal under the calling terminal (resolved from the caller's$TMUX_PANE). The shim needs to accept$TMUX_PANEfrom the calling environment to determine context.-L <socket>flag — Claude Code uses per-PID socket names for isolation in "external session" mode. Inside tmux (our case), it uses the existing session, so this is less critical. The shim should accept and ignore-L.Claude Code integration
Once implemented, Claude Code's multi-agent (teammate/swarm) feature will work inside Kolu terminals with zero user configuration. Here's how:
How it works (automatic)
Claude Code detects tmux at startup via two checks:
$TMUXenv var — if set, Claude Code knows it's "inside tmux" and uses itsTmuxBackendfor teammate pane managementtmux -V— checks if the tmux binary is available (the shim responds to this)Since Kolu injects both
$TMUXand the shim binary into PTY shells, Claude Code will automatically detect tmux support and use it. No settings changes needed.What Claude Code uses tmux for
Claude Code does not use tmux for its own command execution (the Bash tool spawns processes directly). tmux is used exclusively for:
split-windowto create teammate panes,send-keysto dispatch commands,kill-paneto clean upbreak-pane/join-paneto hide/show teammate panes, pane border colors for visual identification--tmux -wflag creates a tmux session per worktreeRelevant Claude Code settings
teammateMode"auto"(default),"tmux","in-process""auto"auto-detects tmux;"tmux"forces it;"in-process"disables pane creationpreferTmuxOverIterm2true/falseUsers can override per-session with
--teammate-mode tmuxor--teammate-mode in-process.Verifying it works
Inside a Kolu terminal:
Additional shim commands for Claude Code teammate support
Beyond the basic tmux subset, Claude Code's
TmuxBackendalso uses:select-layout— pane layout (main-vertical,tiled) — no-op in Kolu (sub-terminals are tabs, not spatial)set-option pane-border-style— teammate color coding — no-op (Kolu could map to per-terminal theme accents in the future)Non-goals
-CC)