Skip to content

Instantly share code, notes, and snippets.

@jbasdf
Created March 12, 2026 02:19
Show Gist options
  • Select an option

  • Save jbasdf/2f31c6fc12dea4f739543ad41f564c86 to your computer and use it in GitHub Desktop.

Select an option

Save jbasdf/2f31c6fc12dea4f739543ad41f564c86 to your computer and use it in GitHub Desktop.
setup-cmux skill - Configure cmux terminal multiplexer workspaces for Claude Code projects
name description
setup-cmux
Configure cmux terminal multiplexer workspaces for a project by generating .vscode/terminals.json with AI Workflow tabs, App workspace, and development terminals. Use when the user says "setup cmux", "configure cmux", "add cmux workspaces", "setup terminals", "setup ai workflow", "add workflow tabs", "configure make cmux", or wants to set up their terminal workspace layout for development with Claude agents, or when starting a new project that needs terminal multiplexer configuration. Also use when the user wants to add or modify cmux workspaces, tabs, or browser panes.

Setup cmux

Configure cmux terminal multiplexer workspaces for any project by generating or updating .vscode/terminals.json. This creates a complete development environment with AI workflow tabs, application servers, and development terminals — all launchable via make cmux.

Announce at start: "I'm using the setup-cmux skill to configure your cmux terminal workspace."

How cmux Works

cmux reads .vscode/terminals.json to create terminal workspaces with tabs. Each workspace appears as a sidebar entry, and tabs within it can be terminals or browser surfaces. A Python script (scripts/cmux.py) processes the config and creates everything via the cmux CLI.

The config has two sections:

  • terminals — legacy flat list (iTerm2 fallback)
  • cmux — structured workspaces with tabs, browser panes, health checks, and auto-input

The cmux section is what we configure. The terminals section is optional but useful as a fallback for environments without cmux.

Step 1: Detect Project Context

Before configuring anything, understand the project:

# Project name and directory
basename $(pwd)

# Current git branch
git rev-parse --abbrev-ref HEAD 2>/dev/null

# Check for existing terminals.json
cat .vscode/terminals.json 2>/dev/null | head -5

# Check for Makefile targets
grep -E '^(dev|serve|start|test|cmux|tree|terms):' Makefile 2>/dev/null

# Check for package.json scripts
cat package.json 2>/dev/null | jq '.scripts | keys' 2>/dev/null

# Check for .env with URLs and ports
grep -E '^(PUBLIC_URL|PORT|BACKEND_PORT|VITE_PORT|DATABASE_URL)=' .env 2>/dev/null

# Detect tech stack
ls Cargo.toml package.json pyproject.toml go.mod 2>/dev/null

Store:

  • PROJECT_NAME — directory name or repo name
  • PREFIX — short uppercase prefix for tab names (e.g., "AR" for atomic-reactor, "GS" for grade-sync). Derive from project name or ask user.
  • TECH_STACK — rust, node, python, go, etc.
  • HAS_FRONTEND — does the project have a separate frontend dev server?
  • HAS_BACKEND — does the project have a backend server?
  • PUBLIC_URL — from .env if available
  • HAS_DOCKER — uses docker-compose for services?

Step 2: Ask User What They Need

Present the detected context and ask which workspace configurations they want. Offer these workspace templates:

## Project: {PROJECT_NAME} ({TECH_STACK})

I can set up these cmux workspaces for you:

### 1. AI Workflow (recommended)
8 numbered step tabs named after the skill/command they run, plus console, reminder, and plans tabs:
plan-stories → plan-sweep → review-open-prs → fix-pr-issues → merge-approved-prs → cleanup-merged → docs-maintain → status + Console + Reminder + Plans

### 2. App
Application servers, database, tests, and optionally a browser pane.
Configured based on your tech stack ({TECH_STACK}).

### 3. Development
Multiple Claude sessions + a console tab for ad-hoc work.

Which would you like? (e.g., "all", "1 and 2", "just the AI workflow")

Adapt workspace suggestions based on detected stack. For example:

  • No Makefile targets for backend? Skip the App workspace backend tab.
  • No frontend? Skip the frontend tab and browser pane.
  • Simple project? Maybe just Development + AI Workflow.

Step 3: Derive Configuration

Project Prefix

The prefix keeps tab names scannable across multiple projects in cmux. Derive it from the project name:

Project Name Prefix
atomic-reactor AR
grade-sync GS
my-cool-app MCA
api-server AS

Rules:

  • Take first letter of each hyphen/underscore-separated word
  • Uppercase
  • 2-3 characters max
  • Ask user to confirm: "I'll use {PREFIX} as your tab prefix. OK?"

Tab Naming Convention

AI Workflow step tabs use: {N} {skill-name} (number + the actual skill/command name) Other tabs use: {PREFIX} {Purpose}

Examples with prefix "GS":

  • 1 plan-stories, 2 plan-sweep, 3 review-open-prs, ..., 8 status
  • GS Backend, GS Frontend, GS Console
  • GS Claude 1, GS Claude 2

Step 4: Generate the Configuration

AI Workflow Workspace

This is the development lifecycle pipeline. Each tab is user-controlled — the prompt is pre-typed into Claude's input but NOT submitted. The user decides when to kick off each step by pressing Enter.

Each tab has two layers:

  1. /rename — sent via input.lines after Claude initializes (submitted with Enter automatically).
  2. Task prompt — sent via input.lines as an object with "submit": false, so it appears in Claude's input buffer but waits for the user to press Enter.

Step descriptions live in the "notes" field (documentation-only) and are available via make remind in the Reminder tab. Do NOT add echo banners to tab commands — they clutter the terminal.

IMPORTANT: Claude CLI does NOT have a --prompt flag. The prompt is a positional argument (claude 'text'), but for the AI Workflow we don't use it — we want user-controlled execution via input.lines with "submit": false.

The "notes" field provides human-readable context (what step, when to run, dependencies). It is documentation-only and not processed by cmux.

{
  "workspace": "AI Workflow",
  "tabs": [
    {
      "name": "1 plan-stories",
      "commands": [
        "cd [workspaceFolder]",
        "claude --dangerously-skip-permissions"
      ],
      "input": {
        "delay": 8,
        "lines": [
          "/rename {PREFIX} Intake [BRANCH]",
          {"text": "/plan-stories work", "delay": 2, "submit": false}
        ]
      },
      "notes": "STEP 1: Story Intake. Pulls stories from the GitHub Projects board and generates implementation plans in docs/plans/. Run /plan-stories work to start. Re-run anytime new stories are assigned."
    },
    {
      "name": "2 plan-sweep",
      "commands": [
        "cd [workspaceFolder]",
        "claude --dangerously-skip-permissions"
      ],
      "input": {
        "delay": 8,
        "lines": [
          "/rename {PREFIX} Execute [BRANCH]",
          {"text": "/plan-sweep", "delay": 2, "submit": false}
        ]
      },
      "notes": "STEP 2: Plan Execution. Discovers plans in docs/plans/, analyzes dependencies, then executes them in parallel tiers using worktrees. Run /plan-sweep to start. Wait for step 1 to produce plans first."
    },
    {
      "name": "3 review-open-prs",
      "commands": [
        "cd [workspaceFolder]",
        "claude --dangerously-skip-permissions"
      ],
      "input": {
        "delay": 8,
        "lines": [
          "/rename {PREFIX} Review [BRANCH]",
          {"text": "Review all open PRs on this repo. Use the review-open-prs skill.", "delay": 2, "submit": false}
        ]
      },
      "notes": "STEP 3: PR Review. Reviews all open PRs for code quality, test coverage, and adherence to project standards. Run after step 2 creates PRs. Re-run after fix-pr-issues pushes fixes."
    },
    {
      "name": "4 fix-pr-issues",
      "commands": [
        "cd [workspaceFolder]",
        "claude --dangerously-skip-permissions"
      ],
      "input": {
        "delay": 8,
        "lines": [
          "/rename {PREFIX} Fix [BRANCH]",
          {"text": "Fix issues identified in PR reviews. Use the fix-pr-issues skill.", "delay": 2, "submit": false}
        ]
      },
      "notes": "STEP 4: Fix PR Issues. Reads review comments from open PRs and dispatches agents to fix them in worktrees. Run after step 3 leaves review comments. May need to cycle back to step 3."
    },
    {
      "name": "5 merge-approved-prs",
      "commands": [
        "cd [workspaceFolder]",
        "claude --dangerously-skip-permissions"
      ],
      "input": {
        "delay": 8,
        "lines": [
          "/rename {PREFIX} Merge [BRANCH]",
          {"text": "Merge all approved GitHub PRs in optimal order. Use the merge-approved-prs skill.", "delay": 2, "submit": false}
        ]
      },
      "notes": "STEP 5: Merge PRs. Merges all approved PRs in dependency order with automatic conflict resolution. Run after PRs are approved (step 3/4 cycle complete)."
    },
    {
      "name": "6 cleanup-merged",
      "commands": [
        "cd [workspaceFolder]",
        "claude --dangerously-skip-permissions"
      ],
      "input": {
        "delay": 8,
        "lines": [
          "/rename {PREFIX} Cleanup [BRANCH]",
          {"text": "Clean up git worktrees and branches that have been merged into main. Use the cleanup-merged skill.", "delay": 2, "submit": false}
        ]
      },
      "notes": "STEP 6: Cleanup. Removes worktrees and branches that have been merged into main. Safe — verifies each branch is fully merged before deleting. Run after step 5 merges PRs."
    },
    {
      "name": "7 docs-maintain",
      "commands": [
        "cd [workspaceFolder]",
        "claude --dangerously-skip-permissions"
      ],
      "input": {
        "delay": 8,
        "lines": [
          "/rename {PREFIX} Docs [BRANCH]",
          {"text": "Update project documentation to reflect recent code changes. Use the docs-maintain skill.", "delay": 2, "submit": false}
        ]
      },
      "notes": "STEP 7: Documentation. Updates project docs to reflect recent code changes, audits for broken links, and archives completed plans. Run after merges land on main."
    },
    {
      "name": "8 status",
      "commands": [
        "cd [workspaceFolder]",
        "claude --dangerously-skip-permissions"
      ],
      "input": {
        "delay": 8,
        "lines": [
          "/rename {PREFIX} Status [BRANCH]",
          {"text": "Give me a development lifecycle status overview: 1) Plans in docs/plans/ (count and status), 2) Open PRs (count, review status), 3) Approved PRs ready to merge, 4) Merged branches needing cleanup, 5) Active worktrees. Present this as a dashboard.", "delay": 2, "submit": false}
        ]
      },
      "notes": "STATUS: Dashboard. Shows the full lifecycle overview — plans, PRs, merges, worktrees. Run anytime to see where things stand and which step to run next."
    },
    {
      "name": "console",
      "focus": true,
      "commands": ["cd [workspaceFolder]"]
    },
    {
      "name": "{PREFIX} Reminder",
      "commands": ["cd [workspaceFolder]", "make remind"]
    },
    {
      "name": "{PREFIX} Plans",
      "commands": ["cd [workspaceFolder]/docs/plans"]
    },
    {
      "name": "{PREFIX} Claude Plans",
      "commands": ["cd [workspaceFolder]/docs/plans", "claude --dangerously-skip-permissions"],
      "input": { "delay": 5, "lines": ["/rename {PREFIX} Claude Plans [BRANCH]"] }
    }
  ]
}

App Workspace

Adapt based on tech stack. Here are templates for common stacks:

Rust + Node Frontend (e.g., Actix/Axum + Vite)

{
  "workspace": "App",
  "tabs": [
    {
      "name": "{PREFIX} Backend",
      "commands": ["cd [workspaceFolder]", "{backend_cmd}"],
      "healthCheck": { "wait": 5, "expect": "listening" }
    },
    {
      "name": "{PREFIX} Frontend",
      "commands": ["cd [workspaceFolder]", "{frontend_cmd}"]
    },
    {
      "name": "{PREFIX} Database",
      "commands": ["cd [workspaceFolder]", "{db_cmd}"]
    },
    {
      "name": "{PREFIX} Backend Tests",
      "commands": ["cd [workspaceFolder]", "{backend_test_cmd}"]
    },
    {
      "name": "{PREFIX} Frontend Tests",
      "commands": ["cd [workspaceFolder]", "{frontend_test_cmd}"]
    },
    {
      "name": "{PREFIX} Browser",
      "type": "browser",
      "urls": [
        { "name": "{PROJECT_NAME}", "url": "{PUBLIC_URL}" }
      ]
    }
  ]
}

Node Only (e.g., Next.js, Express)

{
  "workspace": "App",
  "tabs": [
    {
      "name": "{PREFIX} Dev",
      "commands": ["cd [workspaceFolder]", "npm run dev"],
      "healthCheck": { "wait": 3, "expect": "ready" }
    },
    {
      "name": "{PREFIX} Tests",
      "commands": ["cd [workspaceFolder]", "npm test"]
    },
    {
      "name": "{PREFIX} Browser",
      "type": "browser",
      "urls": [
        { "name": "{PROJECT_NAME}", "url": "http://localhost:3000" }
      ]
    }
  ]
}

Python (e.g., Django, FastAPI)

{
  "workspace": "App",
  "tabs": [
    {
      "name": "{PREFIX} Server",
      "commands": ["cd [workspaceFolder]", "{server_cmd}"],
      "healthCheck": { "wait": 3, "expect": "Uvicorn running" }
    },
    {
      "name": "{PREFIX} Tests",
      "commands": ["cd [workspaceFolder]", "{test_cmd}"]
    }
  ]
}

Detect the right commands from the Makefile or package.json. Common patterns:

What Makefile package.json Fallback
Backend make dev-backend npm run dev cargo run / python manage.py runserver
Frontend make dev-frontend npm run dev:frontend npm run dev
Backend tests make test npm test cargo test / pytest
Frontend tests npm run test npm test npx jest / npx vitest
Database make db-console psql / docker-compose up -d postgres

Development Workspace

Multiple Claude sessions for general-purpose work:

{
  "workspace": "{PROJECT_NAME}",
  "tabs": [
    {
      "name": "{PREFIX} Claude 1",
      "commands": ["cd [workspaceFolder]", "claude --dangerously-skip-permissions"],
      "input": { "delay": 5, "lines": ["/rename {PREFIX} Claude [BRANCH] 1"] }
    },
    {
      "name": "{PREFIX} Claude 2",
      "commands": ["cd [workspaceFolder]", "claude --dangerously-skip-permissions"],
      "input": { "delay": 5, "lines": ["/rename {PREFIX} Claude [BRANCH] 2"] }
    },
    {
      "name": "{PREFIX} Claude 3",
      "commands": ["cd [workspaceFolder]", "claude --dangerously-skip-permissions"],
      "input": { "delay": 5, "lines": ["/rename {PREFIX} Claude [BRANCH] 3"] }
    },
    {
      "name": "{PREFIX} Claude 4",
      "commands": ["cd [workspaceFolder]", "claude --dangerously-skip-permissions"],
      "input": { "delay": 5, "lines": ["/rename {PREFIX} Claude [BRANCH] 4"] }
    },
    {
      "name": "{PREFIX} Console",
      "focus": true,
      "commands": ["cd [workspaceFolder]"]
    }
  ]
}

Step 5: Write the File

If .vscode/terminals.json exists

Read the existing file, preserve the terminals array (legacy section), and merge the new cmux.workspaces entries. If a workspace with the same name already exists, ask whether to replace or skip it.

If .vscode/terminals.json does not exist

Create the full file with both sections:

{
  "autorun": true,
  "autokill": true,
  "terminals": [],
  "cmux": {
    "notify": true,
    "workspaces": [
      // ... generated workspaces
    ]
  }
}

Ensure .vscode/ exists

mkdir -p .vscode

Step 6: Ensure Makefile Targets Exist

make cmux — Open workspaces

Check the Makefile for a cmux target. If missing, offer to add one:

cmux: ## Open cmux workspaces from .vscode/terminals.json
	@./scripts/cmux.py

Also check for scripts/cmux.py. If missing, search for it in sibling projects and offer to copy it:

# Search common locations for cmux.py
find ~/projects -maxdepth 3 -name "cmux.py" -path "*/scripts/*" 2>/dev/null | head -5

If found, offer to copy it:

mkdir -p scripts
cp <found_path> scripts/cmux.py
chmod +x scripts/cmux.py

If not found anywhere, tell the user: "Your project needs scripts/cmux.py to process the terminals.json config. You can copy it from a project that has it, or install it from the cmux documentation."

make remind — Show AI Workflow steps

Check the Makefile for a remind target. If missing, offer to add one that prints all AI Workflow step names and prompts:

remind: ## Show AI Workflow steps and prompts
	@echo ""
	@echo "AI Workflow Steps"
	@echo "================="
	@echo ""
	@echo "Step 1: plan-stories"
	@echo "  Prompt: /plan-stories work"
	@echo "  Pulls stories from GitHub Projects board, generates plans in docs/plans/"
	@echo ""
	# ... one block per step ...
	@echo "All prompts are pre-typed but not submitted — press Enter to run each step."
	@echo ""

This target is displayed in the Reminder tab so users can quickly reference which step does what without switching tabs.

make close — Close all workspaces

Check the Makefile for a close target. If missing, offer to add one. This is the counterpart to make cmux — it closes all cmux workspaces except the one you're in:

close: ## Close all cmux workspaces except the current one
	@if ! command -v cmux &> /dev/null; then \
		echo "$(RED)✗ cmux is not installed$(NC)"; \
		exit 1; \
	fi
	@echo "$(BLUE)Closing all cmux workspaces except current...$(NC)"; \
	cmux list-workspaces 2>/dev/null | while read -r line; do \
		if echo "$$line" | grep -q '\[selected\]'; then continue; fi; \
		WS=$$(echo "$$line" | grep -o 'workspace:[0-9]*'); \
		if [ -n "$$WS" ]; then \
			echo "  Closing $$WS..."; \
			cmux close-workspace --workspace "$$WS" 2>/dev/null; \
		fi; \
	done; \
	echo "$(GREEN)✓ All other workspaces closed$(NC)"

Also add close to the .PHONY list.

Note: The cmux list-workspaces output format is:

  workspace:18  Skills
* workspace:1   MyProject  [selected]
  workspace:52  AI Workflow

The * prefix and [selected] suffix mark the current workspace. The grep -o 'workspace:[0-9]*' pattern reliably extracts the workspace ID regardless of field position.

Step 7: Update CLAUDE.md with Terminal Interaction Instructions

After writing .vscode/terminals.json, generate (or update) a ## cmux Terminal Interaction section in the project's CLAUDE.md. This teaches agents how to find and interact with the App workspace surfaces — restarting services, running tests, checking health, etc.

Why This Matters

Agents running in cmux need to know:

  • What terminal surfaces exist and what they're named
  • How to find a surface by name (IDs are dynamic)
  • How to restart a service (Ctrl+C + re-send command)
  • How to read output to verify status
  • Best practices to avoid breaking things

What to Generate

Read the App workspace tabs from the config you just wrote. For each tab, extract:

  • Surface Name — the name field (e.g., {PREFIX} Backend)
  • Command — the shell command(s) from commands (e.g., make dev-backend)
  • Purpose — infer from the command and tab name

Then generate the following section and insert/replace it in CLAUDE.md:

## cmux Terminal Interaction

When running inside cmux, agents can interact with other terminals to manage the development environment. Always check for cmux availability first: `command -v cmux &>/dev/null`.

**IMPORTANT:** All cmux commands must be run from the **original terminal window** where `make cmux` (or `cmux`) was launched. cmux commands will not work from terminals spawned by cmux itself (e.g., Claude sessions, app servers). If you need to run cmux commands, use the console tab or a shell that is in the original cmux window.

### App Workspace Surfaces

The **App** workspace contains these surfaces (tab names from `.vscode/terminals.json`):

| Surface Name | Command | Purpose |
|---|---|---|
| `{PREFIX} Backend` | `make dev-backend` | Rust backend via `cargo watch -x run` |
| `{PREFIX} Frontend` | `make dev-frontend` | Vite dev server for React SPA |
| ... (one row per App workspace tab) |

### Finding a Surface

```bash
# List all panels to find surface IDs by name
cmux list-panels --json 2>/dev/null | grep "{PREFIX} Backend"
# Example output: surface:325  terminal  "{PREFIX} Backend"

# Or search by content visible on screen
cmux find-window --content "listening" --select

Restarting a Service

To restart a service, send Ctrl+C to stop it, then re-send the start command:

# Find the surface ID
SURFACE=$(cmux list-panels --json 2>/dev/null | grep '"{PREFIX} Backend"' | grep -o 'surface:[0-9]*')

# Restart: Ctrl+C then re-run
cmux send --surface "$SURFACE" "\x03"      # Ctrl+C to stop
sleep 1
cmux send --surface "$SURFACE" "{backend_command}\n"

# Verify it restarted
sleep 3
cmux read-screen --surface "$SURFACE" --scrollback --lines 20

(Include a "Common restart scenarios" list with one entry per long-running service tab — Backend, Frontend, Tunnel, etc. — showing what triggers a restart and the exact command.)

Running Tests in Dedicated Surfaces

(One example per test tab, showing how to find the surface and re-trigger tests.)

Checking Service Health

# Read the last 20 lines of a surface to check if a service is running
SURFACE=$(cmux list-panels --json 2>/dev/null | grep '"{PREFIX} Backend"' | grep -o 'surface:[0-9]*')
cmux read-screen --surface "$SURFACE" --scrollback --lines 20
# Look for "{healthCheck.expect}" to confirm it's up

Best Practices for Agents

  1. Run cmux commands from the original window only — cmux commands must be executed from the terminal window where make cmux was launched, not from terminals spawned by cmux (Claude sessions, servers, etc.)
  2. Find surfaces by name — Surface IDs are dynamic; always look them up by name before interacting
  3. Read before acting — Use cmux read-screen to check current state before restarting
  4. Wait after restart — Services take time to compile/start; read screen to confirm readiness
  5. Use sidebar for progress — For long operations, use cmux set-progress and cmux log
  6. Notify on completion — Use cmux notify for long ops
  7. Don't create duplicate surfaces — Check if a surface already exists before creating new ones

### How to Insert/Update

1. Read the project's `CLAUDE.md`
2. If a `## cmux Terminal Interaction` section already exists, replace it entirely (from `## cmux Terminal Interaction` up to the next `##` heading or end of file)
3. If it doesn't exist, append it at the end of `CLAUDE.md`
4. Adapt the content to the actual tabs configured — don't include tabs that weren't set up (e.g., if no Tunnel tab, skip the tunnel restart example)
5. Use the actual `{PREFIX}` and command values from the generated config

### Adaptation Rules

- **Only document App workspace tabs** — AI Workflow and Development workspace tabs don't need terminal interaction instructions (agents don't restart Claude sessions)
- **Include browser tabs only if relevant** — mention the browser surface name so agents know it exists, but don't include restart instructions for it
- **Match healthCheck.expect values** — if a tab has a healthCheck, use its `expect` string in the "Checking Service Health" example
- **Include tunnel/infrastructure tabs** — these are common restart targets, always include them with explicit restart instructions
- **Tech-stack-specific health signals** — use appropriate health check strings (e.g., "listening" for Rust/Node servers, "Uvicorn running" for Python, "ready" for Vite)

## Step 8: Present Summary

After writing the configuration, show a summary table per workspace:

cmux Configuration Complete

Workspaces Created

AI Workflow (12 tabs)

Tab Name Purpose
1 1 plan-stories /plan-stories work
2 2 plan-sweep /plan-sweep
3 3 review-open-prs review-open-prs
4 4 fix-pr-issues fix-pr-issues
5 5 merge-approved-prs merge-approved-prs
6 6 cleanup-merged cleanup-merged
7 7 docs-maintain docs-maintain
8 8 status status dashboard
9 console General-purpose shell (focused)
10 GS Reminder make remind — step reference
11 GS Plans Shell in docs/plans/
12 GS Claude Plans Claude session for plan work

App (6 tabs)

Tab Name Command
1 GS Backend make dev-backend
2 GS Frontend make dev-frontend
...

CLAUDE.md Updated

  • Added ## cmux Terminal Interaction section with surface names, restart commands, and health checks
  • Agents can now find and interact with App workspace terminals

Next Steps

  • Run make cmux to launch all workspaces
  • Or run ./scripts/cmux.py directly

## Updating Existing Configuration

If the user asks to modify an existing setup (add tabs, change commands, rename prefix):

1. Read the current `.vscode/terminals.json`
2. Identify the workspace/tab to modify
3. Make the change using the Edit tool (prefer surgical edits over full rewrites)
4. Show the before/after for the affected section

## Configuration Reference

### Tab Fields

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | yes | Tab title displayed in cmux |
| `commands` | string[] | yes | Shell commands to execute |
| `type` | string | no | `"terminal"` (default) or `"browser"` |
| `execute` | bool | no | Auto-run commands on creation (default true) |
| `focus` | bool | no | Set as focused tab after creation |
| `notes` | string | no | Human-readable description of what this tab does, when to run it, and dependencies. Documentation-only field — not processed by cmux. |
| `input.delay` | number | no | Seconds to wait before sending first input line |
| `input.lines` | (string\|object)[] | no | Lines to send to the running process. Strings are submitted with Enter. Objects support: `{"text": "...", "submit": false, "delay": 2}` — `submit` (default true) controls whether Enter is pressed, `delay` (default 0) adds a pause in seconds before sending that line. |
| `healthCheck.wait` | number | no | Seconds to wait before checking |
| `healthCheck.expect` | string | no | Text pattern to match in output |
| `split.type` | string | no | `"browser"` or `"terminal"` for split pane |
| `split.direction` | string | no | `"right"` or `"down"` |
| `urls` | array | no | For browser tabs: `[{name, url}]` |

### AI Workflow Tab Startup Sequence

Each AI Workflow step tab uses two mechanisms in order:

| Step | Mechanism | Purpose |
|------|-----------|---------|
| 1 | `claude --dangerously-skip-permissions` in `commands` | Start Claude (bare, no positional prompt) |
| 2 | String in `input.lines` | `/rename` — sent with Enter after `input.delay` seconds |
| 3 | Object in `input.lines` with `"submit": false` | Task prompt — typed into input but NOT submitted. User presses Enter when ready. |

**Why user-controlled?** The workflow is sequential (intake → execute → review → fix → merge → cleanup → docs). Each step should only run when the previous step is done. By pre-typing the prompt without submitting, the user sees what will run and decides when to trigger it.

**Why no echo banners?** Step descriptions live in the `"notes"` field and are available via the Reminder tab (`make remind`). Echo banners clutter the terminal and are redundant.

**IMPORTANT:** Claude CLI does NOT have a `--prompt` flag. Do not use `--prompt`. The prompt is a positional argument (`claude 'text'`), but for the AI Workflow we use `input.lines` with `"submit": false` instead so the user controls execution.

### AI Workflow Utility Tabs

In addition to the 8 step tabs, the AI Workflow workspace includes:

| Tab | Purpose |
|-----|---------|
| `console` | Focused by default. General-purpose shell for ad-hoc commands. |
| `{PREFIX} Reminder` | Runs `make remind` to display all step names, prompts, and descriptions. |
| `{PREFIX} Plans` | Shell opened in `docs/plans/` for browsing implementation plans. |
| `{PREFIX} Claude Plans` | Claude session in `docs/plans/` for plan-related work. |

### Placeholders

| Placeholder | Replaced With |
|------------|---------------|
| `[workspaceFolder]` | Project root directory |
| `[workspaceFolderBasename]` | Directory name only |
| `[BRANCH]` | Current git branch |
| `[ENV_VAR]` | Value from `.env` file |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment