Maestro CLI

One binary, one socket. maestro talks to the running app over its control socket — the same verbs drive the UI, your scripts, and the agents themselves. Everything you can click, an agent can run.

Concepts

Every maestro-managed terminal runs inside a session (a tab in the app). Sessions form a tree — a session can have child sessions — and windows hold session trees. The env var $MAESTRO_SESSION_ID holds the current session's id; "this session"/"this tab" means that id.

Get the CLI

Sessions spawned by Maestro already have a maestro shim on their PATH. For a global command in your own shells, symlink the launcher out of the app bundle:

ln -sf /Applications/Maestro.app/Contents/Resources/bin/maestro /usr/local/bin/maestro

Targeting

<target> is a session-id prefix (e.g. 3f2a) or a unique title substring (case-insensitive). Run maestro list to see ids and titles; use "$MAESTRO_SESSION_ID" to target the current session.

Sessions

maestro list [--closed]

All sessions as JSON (id, title, kind, status, cwd, parentId, windowId). --closed lists recently-closed sessions (tombstones) instead, newest first.

maestro list | jq '.[] | {id, title, status}'

maestro open --kind <claude|codex|shell> [--child|--sibling] [--cwd <dir>] [--parent <id>] [--title <t>]

Open a new session.

  • --kind claude, codex, or shell (default shell)
  • --child / --sibling place relative to the FOCUSED session (parent and cwd resolved server-side)
  • --parent <id> nests under a specific session
  • --cwd <dir> working directory
  • --title <t> tab title
maestro open --kind claude --child --title "api tests"

maestro focus <target> | --back | --forward

Focus a session (bring its tab to front), or move back/forward through this window's focus history.

maestro focus "api tests"
maestro focus --back

maestro send <target> "<text>"

Type text into a session's terminal. Does not press Enter — follow with send-key enter.

maestro send "api tests" "npm test" && maestro send-key "api tests" enter

maestro send-key <target> <enter|escape|ctrl-c|tab>

Send a key press to a session.

maestro send-key "api tests" ctrl-c

maestro close <target> [--instant] [--discard] [--stash] [--force] [--cascade]

Close a session and its subtree. Archives by default (closed history; restore via unarchive), respecting the close countdown unless --instant.

  • --cascade closes the whole subtree, children first
  • --instant skips the close countdown
  • --discard destroys to Recently-Closed instead of archiving
  • --stash sends it to the visible Stash shelf
  • --force bypasses the busy/dirty guard
maestro close "$MAESTRO_SESSION_ID" --cascade --force

Layout & windows

maestro split <target> [--down]

Split a tab into panes (tmux-style): spawns a shell pane beside <target> (below with --down).

maestro split "$MAESTRO_SESSION_ID" --down

maestro move <target> [up|down] [--before <id>] [--after <id>] [--child-of <id>] [--promote] [--to-window <id>] [--new-window] [--project <dir>]

Reorder or re-parent a session, or move it to another/new window.

  • --promote lifts it to root level
  • --child-of <id> re-parents under another session
  • --to-window <id> / --new-window moves it across windows
  • --project <dir> regroups it under a project (clears the manual pin)
maestro move "$MAESTRO_SESSION_ID" --new-window

maestro move-project <dir> [up|down] [--before <dir>] [--after <dir>] [--first] [--last] [--window <id>]

Reorder a project group in the sidebar (per window, custom sort). Dirs resolve to their project root; defaults to the focused window.

maestro move-project ~/dev/api --first

maestro duplicate-window [--window <id>]

Open a new window viewing the same workspace (same sessions, independent focus). Defaults to the focused window.

maestro duplicate-window

Lifecycle

maestro rename <target> "<title>" | --clear

Set a session's custom title. --clear (or an empty title) reverts to the auto-derived one.

maestro rename "$MAESTRO_SESSION_ID" "api tests"

maestro reveal <target> <finder|terminal|editor>

Open the session's cwd in Finder, a new Terminal, or your editor.

maestro reveal "api tests" editor

maestro popup <target>

Open a compact popup window showing a live duplicate of a session's terminal — the same window that auto-appears when a session needs input.

maestro popup "refactor auth"

maestro reopen [<target>]

Reopen a closed session (see list --closed). <target> matches a closed session by id-prefix or title; omit it to reopen the most-recently-closed one.

maestro reopen

maestro stash <target>  ·  maestro unstash <target>

stash shelves a session and its subtree — same as archive, but it stays visible in the sidebar Stashed section. unstash restores it; agents resume lazily on focus.

maestro stash "docs sweep"
maestro unstash "docs sweep"

maestro unarchive <target>

Restore an archived session (and its subtree) to the sidebar; agents resume lazily on focus.

maestro unarchive "refactor auth"

Agents & settings

maestro swap <target> --resume <agentSessionId> | [--to claude|codex] [--model <m>] [--handoff <file>] [--force]

Replace the agent running in a tab in place (same tab id/position). --resume <id> continues an existing claude/codex conversation; otherwise a fresh agent boots — --to picks the provider, --model the model, --handoff <file> seeds its first prompt. The outgoing conversation is tombstoned (reopen / ⌘Z restores it). --force bypasses the busy guard.

maestro swap "api tests" --to codex --model gpt-5

maestro settings <list [group] | get <key> | set <key> <value>>

Read or change maestro settings. list writes the full settings catalog (keys, labels, descriptions, current values) to a file and prints its path — read that file to find the right key, then get/set it.

maestro settings list
maestro settings set terminal.fontSize 14

maestro status-set <target> <status> [--reason <text>]

Manually override a session's status (e.g. working, waiting, idle). Mostly for scripting and testing.

maestro status-set "api tests" waiting --reason "needs review"

maestro help

Print the built-in help. Bare maestro with no verb launches (or focuses) the app.

Examples

# claude session nested under the focused one
maestro open --kind claude --child --title "api tests"

# shell tab next to the focused session
maestro open --kind shell --sibling

# run the tests in it
maestro send "api tests" "npm test" && maestro send-key "api tests" enter

# pop this session out into its own window
maestro move "$MAESTRO_SESSION_ID" --new-window

# swap this tab's agent for codex, keeping the tab in place
maestro swap "$MAESTRO_SESSION_ID" --to codex

# close this session and its whole subtree
maestro close "$MAESTRO_SESSION_ID" --cascade --force