runpane cli
the cli that lets agents use pane
runpane installs Pane and gives agents the commands they need to create panes, read terminal output, and send input. It works on Windows, WSL, macOS, Linux, local machines, and remote hosts.
every os, first-class
Windows and WSL aren't afterthoughts. The same workflow runs on macOS, Linux, VMs, and remote hosts too.
npm, pnpm, and pypi
Start with npx, pnpm dlx, pipx, or install globally when agents need runpane on PATH.
agents can control pane
Any agent that runs shell commands can add repos, create panes, check terminal output, and send input.
built for agent loops
Your agents can use Pane as the workspace they manage. No hosted scheduler, no special SDK. Just terminal commands.
install
For a one-time install or update, use a runner. It'll run the latest CLI without a global CLI install. In a terminal, these commands open the setup wizard. Pane stays installed after setup:
npx --yes runpane@latest
pnpm dlx runpane@latest
pipx run runpaneFor agents or scripts that call runpane repeatedly, install it globally:
npm i -g runpane
runpane setup
python -m pip install runpane
python -m runpane setupwhy a cli instead of mcp
MCP is great for external tools. Agents can use MCP for GitHub, Linear, Jira, Slack, and anything else. Pane doesn't replace those.
But every agent already has a terminal. A CLI works in Codex, Claude Code, Aider, Goose, OpenCode, shell scripts, cron, and CI. No extra server to install, no per-agent setup.
It's lightweight by default. runpane agent-context prints a short summary. Agents only load full command details when they actually need them.
Agents can read it before installing. The full command list is public at /runpane-cli-contract.json.
The full workflow is open source. The Codex and Claude Code orchestrator skills handle the full issue-to-PR loop.
One CLI for both humans and agents. Installing, updating, diagnostics, creating panes, reading output, sending input. It's all the same runpane command.
the core loop commands
- Open Pane first. Install your coding agent and sign in to it before you start.
- Add your repo. In the example below,
activemeans the repo selected in Pane. Select the repo you just added, or replaceactivewith therepo.idreturned by the add command. - Create a pane. It gets its own branch, safely isolated. From the successful JSON result, use
items[0].paneIdfor<pane-id>anditems[0].panelIdfor<panel-id>. - Check the terminal output before sending more text.
panels submitsends your text and presses Enter. Usepanels submit-composeronly when you want to submit text already in the input box.
runpane doctor --json
runpane agent-context
runpane agent-context --command "panels wait" --json
runpane repos list --json
runpane repos add --path "$PWD" --yes --json
runpane agents doctor --agent codex --repo active --json
runpane panes create --repo active --name "issue-252" --agent codex --prompt "Plan this issue" --source agent --wait-ready --yes --json
runpane panes list --repo active --json
runpane panels list --pane <pane-id> --json
runpane panels wait --panel <panel-id> --for ready --json
runpane panels screen --panel <panel-id> --limit 80 --json
runpane panels output --panel <panel-id> --limit 200 --json
runpane panels submit --panel <panel-id> --text "Continue" --yes --jsonwsl and windows
If your agent runs inside WSL but Pane is installed on Windows, call the Windows wrapper through PowerShell:
powershell.exe -NoProfile -Command \
'Set-Location $env:TEMP; runpane repos list --json'For a repo inside WSL, add it through Pane first. Use its saved name or ID from the list above in later commands. Run agents doctor for that repo to check where your agent will run. The WSL walkthrough shows how to create a pane through the Windows wrapper.
where to go next
- Set up your first AI agent loop
- Read the runpane CLI reference
- See the full CLI command list
- Use the RunPane Orchestrator skill for Codex
See the full CLI command list
Open a command to see its usage and flags. This English reference comes straight from Pane's CLI. For a guided walkthrough, start with the CLI docs.
greenfield-inc/Pane @d0c2ad10d696
runpane help
Show help for runpane or a specific command.
runpane help [command]command <command>- Optional command topic such as "panes create".
runpane helprunpane help panes createrunpane setup
Open the guided setup wizard for install, remote host setup, update, and diagnostics.
runpane setuprunpane setuprunpane install
Install Pane on this machine or configure this machine as a remote daemon host.
runpane install [client|daemon] [options]target <client|daemon>- Install the desktop client or configure a remote daemon host.
--version <latest|vX.Y.Z>- Pane release to install.
--format <auto|appimage|deb|dmg|zip|exe>- Release artifact format.
--yes- Skip interactive prompts where possible.
runpane install clientrunpane install daemon --label "My Server"runpane update
Update the Pane desktop app using the same artifact path as install client.
runpane update [options]--version <latest|vX.Y.Z>- Pane release to update to.
--format <auto|appimage|deb|dmg|zip|exe>- Release artifact format.
--dry-run- Print the update plan without downloading.
runpane updaterunpane update --version latestrunpane version
Print the runpane wrapper version without contacting, launching, or focusing Pane.
runpane version
runpane --version--pane-path <path>- Ignored for version; retained only for parser compatibility.
runpane versionrunpane --versionrunpane doctor
Run platform, release, installed Pane, daemon reachability, and remote setup diagnostics.
runpane doctor [--json] [--pane-dir <path>] [--pane-path <path>] [--format <format>] [--verbose]
runpane doctor --report [--title <text>] --body-file <path|-> [--yes] [--json]--json- Print a machine-readable environment report.
--pane-dir <path>- Connect to a specific Pane data directory.
--pane-path <path>- Inspect a specific Pane executable.
--format <format>- Release artifact format to inspect.
--verbose- Print extra diagnostics.
--report- Prepare a redacted, inspectable diagnostic report.
--body-file <path|->- Read report evidence from a file or stdin.
--title <text>- Report title.
--yes- Confirm creating exactly one dcouple/Pane issue.
runpane doctor --jsonrunpane doctorrunpane doctor --report --title "runpane watch failed" --body-file ./watch.txt --jsonrunpane daemon repair
Repair and restart the managed remote-daemon launcher without changing pairing or tunnel configuration.
runpane daemon repair [--pane-dir <path>] [--pane-path <path>] [--yes] [--json]--pane-dir <path>- Remote daemon data directory; defaults to ~/.pane_remote.
--pane-path <path>- Existing Pane executable used to perform repair.
--yes- Skip the service restart confirmation.
--json- Print one machine-readable repair result.
runpane daemon repair --pane-dir ~/.pane_remote --yes --jsonrunpane agents doctor
Diagnose whether a built-in agent command is available in a Pane repository environment.
runpane agents doctor --agent <codex|claude|cursor> [--repo <selector>] [--json]--agent <codex|claude|cursor>- Built-in agent command to diagnose.
--repo <selector>- Repository selector; defaults to the active Pane repo.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane agents doctor --agent <agent> --repo active --jsonrunpane agent-context
Print token-efficient Pane command context for coding agents.
runpane agent-context [--json]
runpane agent-context --command <command> [--json]--command <command>- Print the detailed definition for one command, for example "panes create".
--json- Print machine-readable output.
runpane agent-contextrunpane agent-context --command "panes create" --jsonrunpane repos list
List repositories saved in the running Pane app.
runpane repos list [--json] [--pane-dir <path>]--json- Print machine-readable repository records.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane repos list --jsonrunpane repos add
Register an existing git repository with the running Pane app.
runpane repos add --path <path> [--name <name>] [--json] [--yes]--path <path>- Existing git repository path to register with Pane.
--name <name>- Saved repository name; defaults to the directory name.
--yes- Skip confirmation for mutating commands.
--json- Print machine-readable output.
--dry-run- Validate and preview without adding the repo.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane repos add --path /path/to/repo --yes --jsonrunpane panes list
List Pane sessions in a saved repository.
runpane panes list [--repo <selector>] [--json]--repo <selector>- Optional repository selector: active, id, exact path, or saved repository name.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane panes list --repo active --jsonrunpane panes cost
Report estimated token cost per Pane, with per-model breakdown and cache efficiency.
runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]--repo <selector>- Optional repository selector: active, id, exact path, or saved repository name.
--pane <pane-id>- Return only the selected Pane.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane panes cost --pane <pane-id> --jsonrunpane workspace state
Read one workspace snapshot of every Pane and CLI panel.
runpane workspace state [--repo <selector>] [--json]--repo <selector>- Optionally limit the snapshot to one saved repository.
--json- Print machine-readable output.
runpane workspace state --jsonrunpane watch
Wait for workspace agent and Pane transitions using a daemon-held cursor.
runpane watch [--as <name>|--since <generation>] [--follow] [--format <lines|json>] [--heartbeat <seconds>] [--idle-after <ms>] [--settle <ms>] [--blocked-settle <ms>] [--min-interval <ms>] [--idle-backoff] [--all-managed|--pane <id>] [--include-shells] [--self-test] [--kinds <kind,...>] [--repo <selector>] [--name-contains <text>] [--timeout-ms <ms>] [--from <now|earliest>] [--json]You can watch agent terminals in visible, unarchived panes. Ordinary shell tabs are excluded by default when you follow events.
READY means the agent looks idle. BLOCKED means it needs attention. UNKNOWN means Pane can't tell its state. STUCK means there's text waiting in its input box. Check the terminal before acting on a state.
A named cursor saves your place in the event stream. The next request with that name acknowledges the previous batch. A following watcher makes those requests automatically; it doesn't wait for your script to finish its work. Make your actions safe to repeat. For processing you need to resume reliably, save your own progress after each batch.
runpane watch --follow is the responsive monitor: lines, 60-second heartbeats, IDLE every 10 minutes, managed-agent scope, redacted STUCK detection, no settle, no batching, all kinds. Expensive consumers (one wake-up per line) opt into the cadence flags. Pane Chat arms them automatically through its pane-orchestrator skill; only your own scripts need to pass them. Named cursors persist in the Pane data directory.
--as <consumer-name>- Use a persisted named cursor (at-least-once delivery). Default: PANE_PANEL_ID under --follow when set, otherwise anonymous.
--since <generation>- Use an explicit generation cursor instead of a name. Cannot be combined with --as, or with --settle, --blocked-settle, --min-interval.
--from <now|earliest>- Starting point for a new named cursor. Default now (silent baseline); earliest replays the journal.
--follow- Continue waiting until interrupted. Required by every cadence flag.
--format <lines|json>- Output format. Default lines in every mode; --json selects json.
--heartbeat <seconds>- Healthy-silence bound; a HEARTBEAT line proves the watcher is alive. Default 60 under --follow, 0 otherwise. Filter it out of any monitor that wakes an agent.
--idle-after <milliseconds>- IDLE fires after a READY panel has stayed idle this long, then re-fires every multiple. Default 600000 under --follow, 0 otherwise.
--settle <milliseconds>- Opt-in (follow only): emit READY only after the panel stays idle this long; a BUSY, BLOCKED, UNKNOWN, EXIT, or GONE inside the window cancels it silently. Default 0. Use when a pane flips idle/working while it waits on subagents; the orchestrator value is 180000.
--blocked-settle <milliseconds>- Opt-in (follow only): emit BLOCKED only after this window; an in-pane answer inside it cancels the line. Default 0. The orchestrator value is 30000.
--min-interval <milliseconds>- Opt-in (follow only): hold READY, IDLE, NEW, GONE, EXIT, and UNKNOWN lines and flush them together at most once per interval; BLOCKED bypasses it and carries the held lines with it. Default 0. The orchestrator value is 600000.
--idle-backoff- Opt-in (follow only): IDLE fires at --idle-after, then 30m, 1h, 3h, then daily per panel; any activity resets the schedule. Default off (fixed multiples of --idle-after).
--kinds <kind,...>- Limit event kinds: agent.ready, agent.busy, agent.blocked, agent.unknown, agent.idle, pane.created, pane.gone, panel.exited. Default all. Drop agent.busy for any consumer that acts on lines; BUSY carries no action.
--pane <pane-id>- Limit to a Pane; repeatable. Default all managed panes.
--exclude-pane <pane-id>- Exclude a Pane; repeatable.
--repo <selector>- Limit to a saved repository (active, id, path, or name). Default all repositories.
--name-contains <text>- Limit by Pane name substring.
--agents-only- Limit to CLI agent panels. Default on under --follow.
--all-managed- Explicit spelling for the all-managed default scope.
--include-shells- Include ordinary shell panels.
--timeout-ms <milliseconds>- Wait timeout per request; 0 polls once. Default 60000, capped at 120000 (the follow loop re-issues requests).
--limit <count>- Maximum entries per response. Default 256.
--ack-now- At-most-once named-cursor delivery (advance before you act). Default at-least-once.
--include-held-input- Include up to 120 characters of unsubmitted composer text in JSON entries. Default off (presence only).
--no-held-input- Disable redacted STUCK detection in lines follow mode.
--self-test- Probe the watch path anonymously without advancing a named cursor; run it before arming --follow.
--json- Emit structured NDJSON; held-input content remains opt-in.
runpane watch --self-testrunpane watch --followrunpane watch --as monitor --follow --jsonrunpane watch --follow --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoffDefaults stay responsive: no settle, no batching, all kinds, IDLE every --idle-after. Cadence flags are opt-in for expensive consumers and require --follow.
Recommended orchestrator invocation (what Pane Chat arms automatically): runpane watch --self-test, then runpane watch --follow --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff. Budget: about 6 wake-ups per active pane per hour worst case, usually 1-3.
BUSY carries no action; drop it with --kinds. HEARTBEAT is client-side proof of life, is never shaped by cadence flags, and should be filtered out of any monitor that wakes an agent.
STUCK means real unsubmitted composer text. An agent prompt suggestion (for example a grey Try "..." hint) never counts.
Dead watch: judge death by a non-zero exit or a WATCH ERROR line, not by silence. Re-arm once; if it dies again, file runpane doctor --report.
Cadence state is held per named consumer; an anonymous --follow with a cadence flag names itself follow-<pid>. Held lines survive a reconnect of the same consumer; a changed filter re-delivers them under the new filter.
Journal loss is surfaced through reset and dropped metadata.
The daemon treats omitted idleAfterMs as disabled so older clients never receive agent.idle unexpectedly.
runpane panes create
Create user-visible Panes (Pane sessions) backed by Pane-managed worktrees for feature/PR work and open terminal-backed tool tabs.
runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] [options]
runpane panes create --from-json <path|-> [--yes] [--json]--repo <selector>- Repository selector: active, id, exact path, or saved repository name.
--name <name>- Pane/session name.
--agent <codex|claude|cursor>- Built-in agent terminal template to open.
--tool-command <command>- Custom terminal command to run instead of a built-in agent.
--prompt <text>- Alias for --initial-input; sends text after the command is ready.
--initial-input-file <path|->- Read initial input from a file or stdin.
--from-json <path|->- Read a full panes.create request JSON payload.
--source <user|agent>- Mutation source; agent implies background/no-focus creation.
--no-focus- Create the pane in the background without stealing focus.
--focus- Explicitly focus the created pane.
--pinned- Accepted for backward compatibility and now a no-op;
panes createalready pins by default. --no-pinned- Create the pane unpinned instead of the default pinned (the Pane UI's favorite/pin star). Pinning never implies focus.
--yes- Skip confirmation for mutating commands.
--dry-run- Validate and preview without mutating.
--json- Print machine-readable output.
--wait-ready- Wait for each created terminal panel to be ready before returning.
--ready-timeout-ms <ms>- Readiness timeout per pane; defaults to 30000.
--concurrency <count>- Accepted for compatibility. Pane currently serializes multi-pane session creation so queued jobs do not time out before starting.
runpane panes create --repo active --name issue-257 --agent <agent> --prompt "Plan this issue" --source agent --no-focus --wait-ready --yes --jsonrunpane panes create --from-json panes.json --yes --jsonrunpane panes create --repo active --name issue-123 --agent <agent> --prompt "Plan this issue" --source agent --no-focus --wait-ready --yes --jsonrunpane panes adopt
Adopt an existing externally managed git worktree as a Pane without changing the worktree.
runpane panes adopt --repo <selector> --path <dir> --name <name> --agent <codex|claude|cursor> [--resume <id>] [--folder <name>] [--launch] [--no-pinned] [--dry-run] [--yes] [--json]--repo <selector>- Saved repository selector.
--path <dir>- Existing git worktree path.
--name <name>- Pane name.
--agent <codex|claude|cursor>- Agent whose terminal to create.
--resume <id>- Persist this agent session id and stage its resume command.
--folder <name>- Top-level sidebar folder.
--launch- Run the resume command immediately.
--no-pinned- Do not pin the adopted pane.
--dry-run- Validate and preview only.
--yes- Skip confirmation.
--json- Print machine-readable output.
runpane panes adopt --repo active --path /path/to/worktree --name imported --agent codex --resume <id> --yes --jsonrunpane panes archive
Archive a Pane (session) exactly like the UI Archive action, including safe removal of its Pane-managed git worktree.
runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--dry-run] --yes [--json]If you adopted an existing worktree, archiving its pane leaves that directory in place. Pane only cleans up worktrees it owns.
--pane <pane-id>- Pane/session id to archive.
--source <user|agent>- Mutation source; does not change archive safety behavior.
--force- Archive even if the pane's branch has uncommitted, untracked, or unpushed changes.
--yes- Skip confirmation for mutating commands.
--dry-run- Refresh and print archive safety evidence without archiving.
--json- Print machine-readable output.
runpane panes archive --pane <pane-id> --source agent --yes --jsonrunpane panes archive --pane <pane-id> --dry-run --jsonrunpane panes archive --pane <pane-id> --force --yes --jsonrunpane panes pin
Declaratively pin a Pane; pinned is the Pane UI's favorite/pin star and repeated requests are idempotent.
runpane panes pin --pane <pane-id> --yes [--dry-run] [--json]--pane <pane-id>- Pane/session id to pin.
--yes- Skip confirmation for mutating commands.
--dry-run- Validate and preview without mutating.
--json- Print machine-readable output.
runpane panes pin --pane <pane-id> --yes --jsonrunpane panes pin --pane <pane-id> --dry-run --jsonrunpane panes unpin
Declaratively unpin a Pane; pinned is the Pane UI's favorite/pin star and repeated requests are idempotent.
runpane panes unpin --pane <pane-id> --yes [--dry-run] [--json]--pane <pane-id>- Pane/session id to unpin.
--yes- Skip confirmation for mutating commands.
--dry-run- Validate and preview without mutating.
--json- Print machine-readable output.
runpane panes unpin --pane <pane-id> --yes --jsonrunpane panes unpin --pane <pane-id> --dry-run --jsonrunpane panes rename
Rename a Pane without changing its worktree, branch, panels, or focus.
runpane panes rename --pane <pane-id> --name <new-name> --yes [--dry-run] [--json]--pane <pane-id>- Pane/session id to rename.
--name <new-name>- New non-empty Pane/session name; surrounding whitespace is trimmed.
--yes- Skip confirmation for mutating commands.
--dry-run- Validate and return the projected updated pane without mutating.
--json- Print machine-readable output including the updated pane.
runpane panes rename --pane <pane-id> --name issue-393 --yes --jsonrunpane panes rename --pane <pane-id> --name issue-393 --dry-run --jsonrunpane panels create
Create a terminal-backed tool panel inside an existing Pane session.
runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] [--wait-ready] --yes [--json]
runpane panels create --pane <pane-id> --tool-command <command> [--title <title>] [--focus|--no-focus] --yes [--json]--pane <pane-id>- Existing Pane session id to add the panel to.
--agent <codex|claude|cursor>- Built-in agent command template to launch.
--tool-command <command>- Custom terminal command to launch instead of a built-in agent.
--title <title>- Panel title override.
--initial-input <text>- Initial input to send after the tool starts.
--initial-input-file <path|->- Read initial input from a file or stdin.
--source <user|agent>- Mutation source; agent implies background creation.
--no-focus- Create the panel in the background without changing active panel.
--focus- Explicitly focus the created panel.
--wait-ready- Wait until the terminal tool is ready.
--ready-timeout-ms <ms>- Readiness wait timeout.
--yes- Skip confirmation for this mutating command.
--json- Print machine-readable output.
runpane panels create --pane <pane-id> --agent <agent> --source agent --no-focus --wait-ready --yes --jsonrunpane panels create --pane <pane-id> --tool-command <command> --title <title> --source agent --no-focus --wait-ready --yes --jsonrunpane panels list
List tool panels inside a Pane session.
runpane panels list --pane <pane-id> [--json]--pane <pane-id>- Pane/session id.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane panels list --pane <pane-id> --jsonrunpane panels output
Read recent terminal output from a panel.
runpane panels output --panel <panel-id> [--limit <count>] [--json]--panel <panel-id>- Tool panel id.
--limit <count>- Maximum recent output lines or records to read. Defaults to 200.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane panels output --panel <panel-id> --limit 200 --jsonrunpane panels screen
Read a compact current-screen view from a terminal panel.
runpane panels screen --panel <panel-id> [--limit <count>] [--json]--panel <panel-id>- Terminal panel id.
--limit <count>- Maximum lines to return; defaults to 80.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane panels screen --panel <panel-id> --limit 80 --jsonrunpane panels input
Send input bytes to a terminal panel.
runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]--panel <panel-id>- Terminal panel id.
--text <text>- Text bytes to send.
--input-file <path|->- Read input from a file or stdin.
--yes- Skip confirmation for this mutating command.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
printf 'Continue\n' | runpane panels input --panel <panel-id> --input-file - --yesprintf '\003' | runpane panels input --panel <panel-id> --input-file - --yesrunpane panels input --panel <panel-id> --text "simple text" --yes --jsonrunpane panels submit
Send and submit text to a terminal panel, including idle agent composers.
runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]--panel <panel-id>- Terminal panel id.
--text <text>- Text to submit before Enter.
--input-file <path|->- Read text from a file or stdin before Enter.
--yes- Skip confirmation for this mutating command.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane panels submit --panel <panel-id> --text "2" --yes --jsonprintf "echo hello" | runpane panels submit --panel <panel-id> --input-file - --yes --jsonrunpane panels submit-composer
Submit an agent composer using the panel-appropriate key sequence.
runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter] --yes [--json]--panel <panel-id>- Terminal panel id.
--strategy <auto|codex-ctrl-enter|enter>- Composer submit key sequence strategy.
--yes- Skip confirmation for this mutating command.
--json- Print machine-readable output.
runpane panels submit-composer --panel <codex-panel-id> --strategy auto --yes --jsonrunpane panels submit-composer --panel <panel-id> --strategy enter --yes --jsonrunpane panels wait
Wait for a terminal panel to initialize, become ready/idle, or contain text.
runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--contains <text>] [--timeout-ms <ms>] [--interval-ms <ms>] [--json]--panel <panel-id>- Terminal panel id.
--for <initialized|ready|idle|text>- Condition to wait for. Defaults to ready for CLI panels and idle otherwise.
--contains <text>- Text required for --for text; implies --for text when --for is omitted.
--timeout-ms <ms>- Wait timeout; defaults to 30000.
--interval-ms <ms>- Polling interval; defaults to 500.
--json- Print machine-readable output.
--pane-dir <path>- Connect to a specific Pane data directory.
runpane panels wait --panel <panel-id> --for ready --timeout-ms 30000 --jsonrunpane panels wait --panel <panel-id> --contains "Ready" --json