Skip to content

Commit f72fdf6

Browse files
authored
feat(tmux-agent-comms): open new sessions in app terminal tabs by default (#76)
* feat(tmux-agent-comms): open new sessions in app terminal tabs by default Make visible app-integrated terminal tabs the default spawn path while preserving autonomous readiness checks and detached fallback for background fleets or environments without a tab facility. * fix(tmux-agent-comms): align spawn evals with app-tab default * fix(tmux-agent-comms): multi-word agent_cmd + split detached fallback Unquote TAC_AGENT_CMD after tmux -- so multi-word launches expand to argv, and only print the attach/open-tab command when the app has no terminal-tab facility — not for explicit background fleets.
1 parent 4bfeafa commit f72fdf6

6 files changed

Lines changed: 71 additions & 33 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
| Skill | Version Change |
1414
|-------|----------------|
1515
| docs-generator → doc-manager | 1.2.5 → 2.0.1 |
16-
| tmux-agent-comms | 1.3.0 → 1.8.1 (observability + terminal option) |
16+
| tmux-agent-comms | 1.3.0 → 1.9.0 (observability + app terminal tabs by default) |
1717
| landing-page-generator | 1.1.4 → 1.2.0 (absorbs README-to-landing as Mode B) |
1818
| code-review | 1.2.0 → 2.0.0 (merge code-optimizer + clean-code + slop-cleanup as modes) |
1919
| drawio-generator | 1.2.2 → 1.2.3 (nested under diagram-generator umbrella) |

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ Adjacent skills: **test-coverage** (generate tests for untested branches) · **d
238238
| [**ollama-optimizer**](skills/ollama-optimizer/) | 1.0.4 | medium | Hardware-aware Ollama tuning |
239239
| [**install-script-generator**](skills/install-script-generator/) | 2.1.0 | high | Cross-platform install.sh with env detection |
240240
| [**opencode-runner**](skills/opencode-runner/) | 1.4.0 | medium | Delegate work to opencode free cloud models |
241-
| [**tmux-agent-comms**](skills/tmux-agent-comms/) | 1.3.0 | medium | Spawn, message, read CLI agents in tmux |
241+
| [**tmux-agent-comms**](skills/tmux-agent-comms/) | 1.9.0 | medium | Spawn, message, read CLI agents in tmux |
242242

243243
---
244244

skills/tmux-agent-comms/SKILL.md

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
---
22
name: tmux-agent-comms
3-
description: "Manage AI agents in tmux: spawn, status/inspect, message, read replies, or kill sessions via send-keys/capture-pane. Use to launch fleets or talk to running agents. Don't use for SSH, GNU screen, or GUI apps."
3+
description: "Manage AI agents in tmux: spawn sessions in current app terminal tabs by default; message CLI agents via send-keys/capture-pane; read replies; kill sessions. Use to launch fleets or talk to running agents. Don't use for SSH, screen, or GUI apps."
44
license: MIT
55
effort: medium
66
metadata:
7-
version: 1.8.1
7+
version: 1.9.0
88
author: "Luong NGUYEN <luongnv89@gmail.com>"
99
---
1010

1111
# Tmux Agent Comms
1212

1313
Manage and talk to AI agents (another Claude Code, Gemini CLI, Codex, pi-agent, or any CLI) running in separate tmux sessions: **create** sessions, **send** messages, **wait** for the agent to finish, **capture** replies, **check status**, **inspect** sessions, and **tear down** when done.
1414

15+
Default spawn behavior: each new tmux session opens in a **new terminal tab inside the current app/environment** where this skill is invoked. The tab is a visible terminal attached to that tmux session; it is not an external Terminal.app/iTerm/xterm window unless the user explicitly asks.
16+
1517
Mental model: each tmux session is one agent. You orchestrate from outside by writing to its input and reading its pane — what a human does by switching windows, but scripted. Your context budget is finite, so relay each agent's answer, not its whole screen (the bundled helper extracts just the reply delta).
1618

1719
## When to Use
@@ -45,8 +47,8 @@ Six phases, in order: discover/spawn a session, resolve the exact target, send t
4547
2. **Verify the target before sending.** Resolve the exact session with `has-session` first (Phase 2) — a typo sends keystrokes nowhere or to the wrong agent.
4648
3. **Wait for the agent, don't race it.** Sending a follow-up while it's still working corrupts input. Wait until the pane settles (Phase 4) before reading or sending again.
4749
4. **Escape what you send.** `send-keys` and the shell both interpret special characters. Follow the escaping rules in Phase 3 or messages get mangled — or worse, execute.
48-
5. **Attaching is opt-in, not a replacement.** Showing an agent's terminal (Phase 1) is for a human to drive by hand; it never replaces the default detached, scripted workflow.
49-
6. **Default startup is autonomous and non-blocking.** Spawn detached sessions and continue with readiness checks; don't wait at startup for a human unless the user explicitly asks for interactive mode.
50+
5. **New sessions open visibly by default.** Spawn new agent sessions in a fresh terminal tab provided by the current app/environment, attached to the tmux session. If the environment cannot open an app terminal tab, create the session detached and print the exact attach command for the user; never run `attach-session` yourself from a non-TTY shell.
51+
6. **Default startup is autonomous and non-blocking.** Opening a visible app tab is for human observation; the orchestrator still continues with readiness checks and scripted messaging. Don't wait at startup for a human unless the user explicitly asks for interactive mode.
5052

5153
## Phase 1: Create or Discover Sessions
5254

@@ -56,29 +58,53 @@ tmux list-sessions 2>/dev/null || echo "no tmux server running yet"
5658

5759
Match the target against this list (Phase 2). New sessions use the predictable pattern **`<folder>-<short-task-name>`**: folder is the current project/workspace folder, and short task is a concise slug like `reviewer`, `tests`, or `docs`. This keeps `status`, `inspect`, and attach commands grep-friendly.
5860

59-
To spawn: `tmux new-session` **fails if the name is taken** (exit 1), so check first, create **detached** (`-d -s <name>`), then launch the agent in a second step:
61+
To spawn, resolve a free name first because `tmux new-session` **fails if the name is taken** (exit 1):
6062

6163
```bash
6264
slug() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-|-$//g'; }
6365
folder="$(slug "$(basename "$PWD")")"
6466
task="$(slug "${short_task_name:-reviewer}")"
6567
name="${folder}-${task}"
68+
project_dir="$PWD"
69+
agent_cmd="${TAC_AGENT_CMD:-claude}"
6670
tmux has-session -t "$name" 2>/dev/null && name="${name}-$(date +%s)" # avoid collision
67-
tmux new-session -d -s "$name" -c "$PWD"
68-
tmux send-keys -t "$name" "${TAC_AGENT_CMD:-claude}" Enter
6971
```
7072

71-
**Startup mode:** autonomous/non-blocking is the default for pi-agent, Claude, Codex, Gemini, and other CLIs. Use `TAC_STARTUP_MODE=autonomous|interactive` as the global default when present; a per-launch user request like `--interactive` or "show me the setup first" overrides it. In autonomous mode, use a detached launch command (`TAC_AGENT_CMD`, or the user's requested command) and immediately continue to readiness checks; never park the orchestrator on an interactive startup question. In interactive mode, print the attach command and stop before scripted sends.
73+
**Default: open a new app terminal tab.** Use the terminal-tab facility of the current app/environment where the skill is running (IDE terminal tab, coding-agent terminal tab, or equivalent). The new tab's command should create/attach the tmux session and launch the agent there:
74+
75+
```bash
76+
# $agent_cmd is intentionally unquoted so multi-word TAC_AGENT_CMD values
77+
# (e.g. claude --permission-mode bypassPermissions) expand to separate argv.
78+
cd "$project_dir" && exec tmux new-session -s "$name" -c "$project_dir" -- $agent_cmd
79+
```
80+
81+
The tab itself is the live terminal for that session. Do **not** open an external OS terminal app unless the user explicitly requests it, and do not confuse this with creating a tmux window/tab inside an existing session.
82+
83+
**Detached fallback** — create the session detached, then branch on *why* you fell back:
84+
85+
```bash
86+
tmux new-session -d -s "$name" -c "$project_dir"
87+
# send-keys types the command line, so multi-word TAC_AGENT_CMD is fine as one string.
88+
tmux send-keys -t "$name" "$agent_cmd" Enter
89+
```
90+
91+
- **No app-tab facility** (environment cannot open an integrated terminal tab): also print the exact command for the user to open a tab themselves:
92+
```bash
93+
printf 'Open a new terminal tab in this app and run: cd %q && tmux attach-session -t %q\n' "$project_dir" "$name"
94+
```
95+
- **Explicit background/detached request** (user asked for a background fleet / no visible tabs): stop after the detached spawn — do **not** print an open-tab/attach instruction.
96+
97+
**Startup mode:** autonomous/non-blocking is the default for pi-agent, Claude, Codex, Gemini, and other CLIs. Use `TAC_STARTUP_MODE=autonomous|interactive` as the global default when present; a per-launch user request like `--interactive` or "show me the setup first" overrides it. In autonomous mode, open the visible app tab when available (or the matching detached fallback above), then immediately continue to readiness checks — never park the orchestrator on an interactive startup question. In interactive mode, ensure the session is visible (app tab, or printed attach command when the tab facility is missing) and stop before scripted sends.
7298

7399
**"Spawned" ≠ "ready"** — a fresh agent often boots through a trust/auth prompt. Don't send blind; run the wait helper (Phase 4): exit `0` means ready, exit `3` means it's parked on a prompt to surface to the user rather than type into.
74100

75101
```bash
76102
python3 scripts/wait_for_idle.py "$name" --timeout 30 --no-print; echo "ready=$?"
77103
```
78104

79-
For a **fleet**, repeat with distinct task slugs under the same folder prefix (`myrepo-reviewer`, `myrepo-tests`, `myrepo-docs`).
105+
For a **fleet**, repeat with distinct task slugs under the same folder prefix (`myrepo-reviewer`, `myrepo-tests`, `myrepo-docs`). The visible-tab default applies to each newly spawned session unless the user asks for a detached/background fleet.
80106

81-
**Showing the agent's terminal** (optional, human-only): `tmux attach-session -t "$name"` or `tmux switch-client -t "$name"`, run by the human in their own interactive terminal — the agent invoking either itself will fail (no TTY / no attached client). Detach with `Ctrl-b d` to return control without killing the session. See `references/tmux-recipes.md` ("Showing an agent's live terminal") for the when-to-use table and worked example.
107+
**Showing an existing agent's terminal** (human-only): if a session already exists without a visible tab, the human can run `tmux attach-session -t "$name"` or `tmux switch-client -t "$name"` from an interactive terminal. The agent invoking either itself will fail (no TTY / no attached client). Detach with `Ctrl-b d` to return control without killing the session. See `references/tmux-recipes.md` ("Showing an agent's live terminal") for the when-to-use table and worked example.
82108

83109
## Phase 2: Resolve the Exact Target
84110

@@ -202,14 +228,14 @@ Relay that answer to the user. If the read starts mid-sentence, widen to `-S -80
202228
- **Trust/auth dialog**`wait_for_idle.py` returns exit 3, not 0. Never send a message (would be read as menu input); surface the dialog.
203229
- **Reply ends in a numbered list** ("1. yes 2. no") — not mistaken for a prompt; block detection uses only verified dialog strings.
204230
- **Duplicate session name**`tmux new-session` exits 1; resolve a free name first (Phase 1).
205-
- **Interactive startup would hang the run** — default to autonomous detached startup; only enter interactive mode when the user explicitly opts in, then print an attach command instead of blocking the orchestrator.
231+
- **Interactive startup would hang the run** — default to autonomous startup (visible app tab when available, otherwise detached fallback) and continue readiness checks; only enter interactive mode when the user explicitly opts in, then ensure the session is visible and stop before scripted sends.
206232
- **Status cannot identify an agent** — list it as `unknown` rather than guessing; `inspect` must resolve the exact session before printing an attach command.
207233
- **Reply text contains "running"/"loading"** — busy detection scans only spinner chrome, never reply prose.
208234
- **Message never landed** — Phase 3's post-send-activity check catches this before waiting and reports `NOT-DELIVERED`; send a lone `Enter`, re-check, re-type if still nothing.
209235
- **Agent stalled** (unchanged pane, no spinner, no completion) — distinct from "still working" or a dropped delivery; surface it, don't silently re-wait.
210236
- **Re-wait/re-send loop won't terminate** — enforce the overall budget (Phase 4); escalate rather than poll indefinitely.
211237
- **Capped-tail capture starts mid-sentence** — reply is longer than ~40 lines; widen stepwise, only reach for unbounded `-S -` if a wide tail still truncates.
212-
- **Returning to orchestrator control after attaching** — detach with `Ctrl-b d`; never `kill-session` just to "get back."
238+
- **Returning to orchestrator control after attaching**if the human attached manually, detach with `Ctrl-b d`; never `kill-session` just to "get back." A visible app tab can stay open while the orchestrator continues scripted send/wait/capture.
213239

214240
## Reference
215241

skills/tmux-agent-comms/docs/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@
77

88
# Tmux Agent Comms
99

10-
> Spawn, manage, and talk to AI agents running in separate tmux sessions — agent-to-agent communication over `send-keys` and `capture-pane`.
10+
> Spawn, manage, and talk to AI agents running in separate tmux sessions — new sessions open in an app terminal tab by default, with agent-to-agent communication over `send-keys` and `capture-pane`.
1111
1212
## Highlights
1313

14-
- **Launch a fleet** — create predictable, detached tmux sessions (`<folder>-<short-task-name>`) and boot an agent (Claude Code, Gemini CLI, Codex, pi-agent, any CLI) inside each.
15-
- **Start non-blocking by default**use autonomous detached startup, with `TAC_STARTUP_MODE` or a per-launch request to opt into interactive startup only when needed.
14+
- **Launch sessions** — create predictable tmux sessions (`<folder>-<short-task-name>`) and boot an agent (Claude Code, Gemini CLI, Codex, pi-agent, any CLI) inside each, opening new sessions in a terminal tab inside the current app by default.
15+
- **Start non-blocking by default**open a visible app tab when available, then continue readiness checks; use `TAC_STARTUP_MODE` or a per-launch request to opt into interactive-only startup when needed.
1616
- **Message any agent** — send a prompt to a target session with proper escaping, including the separate-`Enter` gotcha for stubborn TUIs.
1717
- **Read replies reliably** — a bundled `wait_for_idle.py` polls the pane until output settles instead of guessing with a fixed `sleep`, then returns the answer.
1818
- **Broadcast & collect** — fan one instruction out to several agents and gather each reply, with periodic fleet status during long-running work.
1919
- **Status & inspect** — list every managed agent in a table, inspect one agent, and get the exact attach command for a human terminal.
20-
- **Show an agent's terminal on demand**attach to (or switch to) a spawned agent's session to see its live CLI and type into it directly, for trust prompts, debugging, or hands-on steering, without giving up the default detached workflow.
20+
- **Keep agents visible**new sessions attach to a fresh terminal tab in the current app by default; detached mode remains available for background fleets or environments without a terminal-tab facility.
2121
- **Safe teardown** — kill individual sessions (or the whole server) behind explicit user confirmation, so no agent's work is lost by accident.
2222

2323
## When to Use
2424

2525
| Say this... | Skill will... |
2626
|---|---|
27-
| "Launch three Claude agents in tmux for reviewer, tests, and docs" | Create three named detached sessions and start an agent in each |
27+
| "Launch three Claude agents in tmux for reviewer, tests, and docs" | Create three named sessions (app terminal tabs by default) and start an agent in each |
2828
| "Send 'summarize src/' to the reviewer agent and show me its reply" | Send the message, wait for the pane to settle, capture and relay the answer |
2929
| "Ask all my agents to pull the latest main" | Broadcast the message to every session and collect each response |
3030
| "Show status for my tmux agents" | Print a table with state, progress, start time, and working directory |
@@ -75,7 +75,7 @@ Spin up several agents, each scoped to a job, and kick them all off at once.
7575
/tmux-agent-comms launch three Claude agents in tmux named reviewer, tests, and docs in this repo, then ask each to report what it would work on first
7676
```
7777

78-
The skill creates three predictably named detached sessions (for example, `myrepo-reviewer`, `myrepo-tests`, `myrepo-docs`), boots an agent in each, waits for each to clear its boot/trust prompt, then messages them. The `<folder>-<short-task-name>` convention keeps later status, inspect, and attach commands self-documenting.
78+
The skill creates three predictably named sessions (for example, `myrepo-reviewer`, `myrepo-tests`, `myrepo-docs`) in app terminal tabs by default, boots an agent in each, waits for each to clear its boot/trust prompt, then messages them. The `<folder>-<short-task-name>` convention keeps later status, inspect, and attach commands self-documenting.
7979

8080
### 3. Broadcast one instruction to the whole fleet
8181

skills/tmux-agent-comms/evals/evals.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
},
1010
{
1111
"id": 2,
12-
"prompt": "Spin up two tmux agents for me one named 'tests' and one named 'docs' and launch claude in each, in the current project directory.",
13-
"expected_output": "Creates two detached sessions using the <folder>-<short-task-name> convention (e.g. <folder>-tests and <folder>-docs), uses -c for the project directory, launches the agent in non-blocking/autonomous mode by default, and waits for each to finish booting before considering them ready. No destructive commands.",
12+
"prompt": "Spin up two tmux agents for me \u2014 one named 'tests' and one named 'docs' \u2014 and launch claude in each, in the current project directory.",
13+
"expected_output": "Creates two sessions using the <folder>-<short-task-name> convention (e.g. <folder>-tests and <folder>-docs), opens each by default in a visible app/IDE terminal tab attached to the tmux session (detached only if no app-tab facility exists \u2014 then print the attach command \u2014 or the user asks for background, with no open-tab instruction), uses the project directory, launches the agent in non-blocking/autonomous mode by default, and waits for each to finish booting before considering them ready. No destructive commands.",
1414
"files": []
1515
},
1616
{
@@ -22,7 +22,7 @@
2222
{
2323
"id": 4,
2424
"prompt": "Launch three tmux agents for this repo (reviewer, tests, docs) and keep me updated while they work for a while.",
25-
"expected_output": "Creates detached sessions using the <folder>-<short-task-name> naming convention, honors TAC_STARTUP_MODE/per-launch interactive overrides while defaulting to non-blocking/autonomous startup, waits without serializing the fleet, and emits read-only fleet status reports about every 5 minutes showing each agent's state, task/progress, start time, and working directory without sending extra keys to working agents.",
25+
"expected_output": "Creates sessions using the <folder>-<short-task-name> naming convention and opens each by default in a visible app/IDE terminal tab attached to the tmux session (detached only if no app-tab facility exists \u2014 then print the attach command \u2014 or the user asks for a background fleet, with no open-tab instruction), honors TAC_STARTUP_MODE/per-launch interactive overrides while defaulting to non-blocking/autonomous startup, waits without serializing the fleet, and emits read-only fleet status reports about every 5 minutes showing each agent's state, task/progress, start time, and working directory without sending extra keys to working agents.",
2626
"files": []
2727
},
2828
{

0 commit comments

Comments
 (0)