---
name: ayf:cmux
description: |
  Real parallel agent spawning via cmux terminal orchestration.
  Use to launch multiple Claude Code agents simultaneously in isolated workspaces,
  monitor their state, answer their permission prompts, and coordinate their work
  from one conductor session.
tags: [multi-agent, parallel, orchestration, cmux, swarm]
requires: cmux (cmux.app running)
---

# AY Framework × cmux — Real Parallel Agents

cmux turns ay-framework's "one Claude wearing hats" into a real multi-agent swarm.
Each agent runs as its own Claude Code process in its own cmux workspace. This skill
teaches the **conductor** (you) how to spawn, drive, monitor, and coordinate them.

Everything below uses only commands verified against the live `cmux` CLI. When in
doubt, run `cmux --help` or `cmux <command> --help`.

> **Tip:** `cmux` prints a one-line deprecation notice for some legacy aliases (e.g.
> `list-workspaces`). Set `CMUX_QUIET=1` in your environment to silence those notices
> so they don't pollute `read-screen` parsing.

## 1. Prerequisites — is cmux up?

```bash
cmux ping              # → "PONG" when the cmux daemon is running
cmux list-workspaces   # list every workspace (alias for `cmux workspace list`)
```

- `cmux ping` returns **`PONG`** (not "OK"). Any other output / non-zero exit → cmux.app
  is not running; open it before spawning anything.
- `cmux list-workspaces` prints one row per workspace. The current one is marked `*`:

  ```
    workspace:2  loops
    workspace:3  tasks
  * workspace:9  ay-framework  [selected]
  ```

  Parse the `workspace:N` **ref** from column 1 — that ref is what every other command
  takes via `--workspace`.

## 2. Launch an agent in a new workspace

Spawn a workspace that boots straight into Claude with `--command 'claude'`. Use
`--cwd` so the agent starts in the repo, and `--focus false` so spawning doesn't steal
your screen. `new-workspace` prints `OK workspace:N` on stdout — capture the ref:

```bash
spawn_agent() {                     # spawn_agent <task-num> <slug> [color]
  local task_num="$1" slug="$2" color="${3:-Green}"
  local out ws
  out="$(CMUX_QUIET=1 cmux new-workspace \
           --name "task-${task_num}-${slug}" \
           --cwd "$(pwd)" \
           --command 'claude' \
           --focus false)"
  ws="$(printf '%s' "$out" | grep -oE 'workspace:[0-9]+' | head -1)"
  [ -n "$ws" ] || { echo "spawn failed: $out" >&2; return 1; }

  cmux workspace-action --action set-color --color "$color" --workspace "$ws"
  echo "$ws"
}

WS=$(spawn_agent 51 review-pack Green)
```

Wait for Claude to finish booting before sending a prompt — **poll, never blind-sleep**:

```bash
for _ in 1 2 3 4 5 6 7 8; do
  sleep 2
  cmux read-screen --workspace "$WS" --lines 6 | grep -qE 'for shortcuts|Welcome|❯|>' && break
done
```

## 3. Send prompts to an agent

Claude Code needs the text delivered, **then** a separate Enter keypress to submit.
`send` types text; `send-key enter` submits it:

```bash
cmux send     --workspace "$WS" "/task-start 51"
sleep 0.3                                   # let the TUI register the text
cmux send-key --workspace "$WS" enter       # submit
sleep 3
cmux read-screen --workspace "$WS" --lines 12   # confirm a spinner/response appeared
```

Always `read-screen` after submitting to confirm the agent accepted the prompt — do not
assume it landed.

## 4. Read agent state — the classification table

`cmux read-screen --workspace <ws> --lines <n>` returns the tail of the agent's screen.
Classify what the agent is doing from that text:

| Screen shows | State | Your action |
|---|---|---|
| `✻ Working…` / `✶ Thinking…` + elapsed timer | **WORKING** | Leave it alone |
| `Do you want to proceed?` + `1. Yes  2. No` | **BLOCKED — permission** | Send the digit as text (§5) |
| `Do you want to make this edit?` + `2. Yes, allow all` | **BLOCKED — edit approval** | Send `2` as text (§5) |
| bare `❯` / `>` prompt after final output, no spinner | **DONE / IDLE** | Read result, send next step |
| dimmed/greyed text sitting in the input line, no spinner | **GHOST SUGGESTION** | See the trap in §6 |
| timer frozen, buffer not advancing | **STALE SURFACE** | Recover via §8 |

Read a few lines (`--lines 6`) for a quick status poll; read more (`--lines 40`) or add
`--scrollback` when you need the full picture of what an agent decided.

## 5. Answer permission prompts — digits are TEXT, not keys

When an agent stops on a `1. Yes / 2. No` menu, you answer by sending the **digit as
text** with `send`, then Enter. Do **not** use `send-key` for digits — `send-key` is for
named keys (enter, up, escape…) and rejects digits.

```bash
# CORRECT — the choice is text, submitted with a separate Enter:
cmux send     --workspace "$WS" "2"
sleep 0.3
cmux send-key --workspace "$WS" enter

# WRONG — send-key treats "2" as a key name and errors / misfires:
cmux send-key --workspace "$WS" "2"     # ✗ do not do this
```

Rule of thumb: **content** (prompts, menu choices, numbers) → `send`.
**Control keys** (enter, escape, up/down, ctrl-c) → `send-key`.

## 6. The ghost-suggestion trap ⚠️

Claude Code shows a dimmed **ghost suggestion** (autocomplete-style greyed text) in the
input line. It is **not** something the agent typed and **not** submitted — it is a
placeholder hint.

The trap: if you `send-key enter` on a workspace showing only a ghost suggestion, you may
submit that ghost text (or an empty line), firing an action you never intended — a wrong
command, a blank prompt, or an accidental confirmation.

**Guard against it:**
- Never send a bare `enter` to "nudge" an agent. Enter is only ever the second half of
  *your own* `send` → `send-key enter` pair.
- Before submitting, `read-screen` and confirm the input line contains **your** text (full
  brightness), not a dimmed ghost.
- If you see only a ghost suggestion and want the agent to do something, type the real
  instruction yourself with `send`, then submit.

## 7. Fleet monitoring pattern — `/loop` + `read-screen`

Don't babysit agents synchronously. Register the fleet, then let a recurring loop scan
every workspace and surface only what needs you. Drive the cadence with Claude Code's
`/loop`:

```
/loop 60s scan the cmux fleet: for each ay-framework agent workspace, read-screen and
classify it (WORKING / BLOCKED / DONE / STALE). Answer any BLOCKED permission prompts per
the cmux skill. Report only agents that changed state or need me. Stop when all are DONE.
```

The scan the loop runs each tick:

```bash
# Fleet = workspaces named "task-*". Discover them fresh each tick.
for ws in $(CMUX_QUIET=1 cmux list-workspaces | grep -oE 'workspace:[0-9]+'); do
  name=$(CMUX_QUIET=1 cmux list-workspaces | grep "$ws" | sed -E 's/^[* ]*workspace:[0-9]+  //')
  case "$name" in task-*) ;; *) continue ;; esac

  screen=$(cmux read-screen --workspace "$ws" --lines 8)
  if printf '%s' "$screen" | grep -qE '1\. Yes|Do you want to (proceed|make this edit)'; then
    echo "🔴 $ws ($name) BLOCKED — needs an answer"
    # auto-approve safe prompts: cmux send --workspace "$ws" "2"; cmux send-key --workspace "$ws" enter
  elif printf '%s' "$screen" | grep -qE '✻|✶|Working|Thinking'; then
    echo "🟢 $ws ($name) working"
  else
    echo "⚪ $ws ($name) idle/done — collect result"
  fi
done
```

Pair this with cmux desktop signals so blocked agents pull your attention:

```bash
cmux trigger-flash --workspace "$WS"                              # flash the tab
cmux notify --title "Agent blocked" --body "task-51 needs approval" --workspace "$WS"
```

## Coordinating the swarm (the conductor loop)

The conductor is your main session. It:

1. Reads `.ay/tracking/BOARD.md` for READY tasks whose blockers are all DONE.
2. Spawns one agent per independent task (§2), color-coded and named `task-N-slug`.
3. Runs the `/loop` fleet monitor (§7) to watch every agent at once.
4. Answers permission prompts (§5) and heeds the ghost-suggestion trap (§6).
5. Collects results — agents write to `.ay/tracking/HANDOFFS.md` per the agent protocol,
   so the conductor just reads that one file:

   ```bash
   cat .ay/tracking/HANDOFFS.md      # every agent's output in one place
   ```
6. Dispatches dependent tasks once their blockers flip to DONE on the board.

## 8. Recovery — stale surfaces

If `read-screen` returns a frozen buffer (timer not advancing), the surface may be
detached. Re-select it, then restore your own view:

```bash
cmux surface-health --workspace "$WS"       # inspect; look for a detached/false surface
CUR=$(cmux current-workspace)               # remember where you are
cmux select-workspace --workspace "$WS"     # reattach the stale one
# ...it repaints; read-screen again...
cmux select-workspace --workspace "$CUR"    # put the human's view back
```

## Cleanup

```bash
# Mark done and archive visually, or close entirely:
cmux workspace-action --action set-color --color Charcoal --workspace "$WS"
cmux workspace-action --action set-description --description "done: task-51 shipped" --workspace "$WS"
cmux close-workspace --workspace "$WS"
```

## Colour conventions for ay-framework agents

| Colour | Meaning |
|---|---|
| Green | Agent working (IN PROGRESS) |
| Amber | Agent waiting on a human answer |
| Red | Agent blocked / errored |
| Blue | Agent idle / researching |
| Charcoal | Task done, workspace archived |
| Purple | The conductor (orchestrating) session |

## Command quick-reference (all verified)

| Need | Command |
|---|---|
| Is cmux up? | `cmux ping` → `PONG` |
| List workspaces | `cmux list-workspaces` |
| Spawn agent | `cmux new-workspace --name <n> --cwd <dir> --command 'claude' --focus false` |
| Type a prompt | `cmux send --workspace <ws> "<text>"` |
| Submit it | `cmux send-key --workspace <ws> enter` |
| Read agent screen | `cmux read-screen --workspace <ws> --lines <n>` |
| Answer a menu | `cmux send --workspace <ws> "2"` then `send-key … enter` |
| Colour a tab | `cmux workspace-action --action set-color --color <c> --workspace <ws>` |
| Flash a tab | `cmux trigger-flash --workspace <ws>` |
| Notify human | `cmux notify --title <t> --body <b> --workspace <ws>` |
| Reattach stale | `cmux select-workspace --workspace <ws>` |
| Close workspace | `cmux close-workspace --workspace <ws>` |

This is how ay-framework becomes a real parallel swarm: one conductor, many Claude agents,
coordinated through cmux and `.ay/tracking/`.
