tmux
v0.1.1tmux as an iii worker — list, create, rename and kill sessions and windows, see which pane runs Claude Code or Codex (working, waiting for you, idle), which runs `iii compose` and every listening port by process and pane, plus a Console page whose terminal is a live tmux client.
Install
iii trigger compose::add worker=tmuxRun in your project with the iii engine running. Exact versions are immutable and digest-pinned.
- max_terminals: 8
poll_interval_ms: 1000
ports_interval_ms: 3000
terminal_idle_timeout_ms: 30000
tmux_binary: tmuxtmux
tmux as an iii worker. It lists every tmux session, window and pane on the
host, creates, renames and kills sessions and windows, and tells you what is
running where: which pane holds Claude Code or Codex and whether that agent is
working, waiting for you or idle, which pane runs iii compose and on which
port its engine listens, and every TCP port your processes listen on, traced
back to the pane that started them. Its Console page embeds a terminal that
is a real tmux client: what you type goes straight into the session, and the
screen updates as tmux draws it, the same way a second terminal attached with
tmux attach would.
Install
iii trigger compose::add worker=tmuxThe worker drives the tmux binary installed on the host (Linux or macOS) and
talks to the same tmux server you use from your terminal. Without tmux it still
starts and reports available: false.
Quickstart
Open the tmux page in the Console to browse sessions, open one in the terminal, and see the Ports tab. From code or an agent:
# Every session → window → pane, with agent / compose / port status
iii trigger tmux::sessions::list
# A new session running a dev server, then a second window in it
iii trigger tmux::sessions::create name=api cwd=~/code/api command="pnpm dev"
iii trigger tmux::windows::create session=api name=logs
# Who listens on which port, and which compose stacks are up
iii trigger tmux::ports::listA pane running an agent and a pane running iii compose look like this in
tmux::sessions::list:
{ "id": "%3", "command": "claude",
"agent": { "id": "claude", "label": "Claude Code", "state": "waiting", "since_ms": 1791936000000,
"title": "Fix the login redirect" } }
{ "id": "%7", "command": "iii:c:default",
"compose": { "namespace": "default", "pid": 2759592 },
"ports": [ { "port": 49135, "role": "engine", "process": "iii:e:default" },
{ "port": 3111, "role": "worker", "worker": "http" },
{ "port": 3114, "role": "worker", "worker": "ade" } ] }Agent state comes from the pane's last lines: a permission or choice prompt is
waiting, Claude Code's esc to interrupt line is working. The agent's
title is the session title it put on its pane (Claude Code's conversation
topic) without the ✳ or spinner in front; it is null while the pane shows
tmux's default title, the host name. Selecting a window
(tmux::windows::select) works like tmux itself: every client attached to
that session, your own terminal included, switches to it.
Panes work the same way. tmux::panes::select makes a pane active and, with
zoom: true, zooms the window on it the way prefix z does, for every client
looking at that window; zoom: false unzooms. tmux::panes::capture returns a
pane's visible screen with its colour escapes, its size and cursor:
iii trigger tmux::panes::select pane=%3 zoom=true
iii trigger tmux::panes::capture pane=%3Configuration
tmux_binary: tmux # name on PATH or absolute path (never this worker's own binary)
socket_name: null # tmux -L <name>; null = your default tmux server
socket_path: null # tmux -S <path>; wins over socket_name
poll_interval_ms: 1000 # live feed cadence for sessions and agent state
ports_interval_ms: 3000 # process and listening-port re-scan cadence
busy_window_ms: 2000 # agents without working patterns: "working" while the pane changed this recently
command_timeout_ms: 5000 # one tmux command
max_terminals: 8 # concurrent Console terminals (each one is a tmux client)
terminal_idle_timeout_ms: 30000 # detach a Console terminal its page stopped heart-beating
agents: # first match wins; patterns are case-insensitive regexes over the pane's last lines
- id: claude
label: Claude Code
process: [claude]
working_patterns: ["esc to interrupt"]
waiting_patterns: ["❯\\s*1\\.\\s*Yes", "Do you want to proceed\\?", "Enter to select"]The built-in list also recognises codex, opencode and gemini; see
src/config.rs. Edit the configuration from the page's
settings action or with configuration::set.
Custom trigger types
| Trigger type | Fires when | Payload to subscribers |
|---|---|---|
tmux::changed |
Once when bound, then whenever sessions, windows, panes, agent states, compose stacks or listening ports change | { sessions, ports } — the same shapes tmux::sessions::list and tmux::ports::list return |
Bind it with config: {}. The worker only polls tmux while at least one
binding exists.