runpane 2.3.7__tar.gz → 2.3.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {runpane-2.3.7 → runpane-2.3.8}/PKG-INFO +1 -1
- {runpane-2.3.7 → runpane-2.3.8}/pyproject.toml +1 -1
- runpane-2.3.8/src/runpane/__init__.py +1 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/cli.py +60 -0
- runpane-2.3.8/src/runpane/generated_contract.py +4 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/local_control.py +139 -7
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/telemetry.py +8 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane.egg-info/PKG-INFO +1 -1
- runpane-2.3.7/src/runpane/__init__.py +0 -1
- runpane-2.3.7/src/runpane/generated_contract.py +0 -4
- {runpane-2.3.7 → runpane-2.3.8}/README.md +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/setup.cfg +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/__main__.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/agent_context.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/daemon_client.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/doctor.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/download.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/installers.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/platforms.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/releases.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane/version.py +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane.egg-info/SOURCES.txt +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane.egg-info/dependency_links.txt +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane.egg-info/entry_points.txt +0 -0
- {runpane-2.3.7 → runpane-2.3.8}/src/runpane.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.3.8"
|
|
@@ -18,9 +18,13 @@ from .installers import (
|
|
|
18
18
|
spawn_pane,
|
|
19
19
|
)
|
|
20
20
|
from .local_control import (
|
|
21
|
+
run_agents_doctor,
|
|
21
22
|
run_panels_input,
|
|
22
23
|
run_panels_list,
|
|
23
24
|
run_panels_output,
|
|
25
|
+
run_panels_screen,
|
|
26
|
+
run_panels_submit,
|
|
27
|
+
run_panels_wait,
|
|
24
28
|
run_panes_create,
|
|
25
29
|
run_panes_list,
|
|
26
30
|
run_repos_add,
|
|
@@ -96,7 +100,13 @@ class ParsedArgs:
|
|
|
96
100
|
panel_input_file: Optional[str] = None
|
|
97
101
|
from_json: Optional[str] = None
|
|
98
102
|
timeout_ms: Optional[float] = None
|
|
103
|
+
wait_ready: bool = False
|
|
104
|
+
ready_timeout_ms: Optional[float] = None
|
|
105
|
+
concurrency: Optional[int] = None
|
|
99
106
|
limit: Optional[int] = None
|
|
107
|
+
wait_condition: Optional[str] = None
|
|
108
|
+
contains: Optional[str] = None
|
|
109
|
+
interval_ms: Optional[float] = None
|
|
100
110
|
help_topic: Optional[str] = None
|
|
101
111
|
remote_setup_args: List[str] = field(default_factory=list)
|
|
102
112
|
|
|
@@ -155,6 +165,14 @@ def dispatch_parsed_command(parsed: ParsedArgs, telemetry_context: WrapperTeleme
|
|
|
155
165
|
return run_panels_output(parsed)
|
|
156
166
|
if parsed.command == "panels input":
|
|
157
167
|
return run_panels_input(parsed)
|
|
168
|
+
if parsed.command == "panels screen":
|
|
169
|
+
return run_panels_screen(parsed)
|
|
170
|
+
if parsed.command == "panels submit":
|
|
171
|
+
return run_panels_submit(parsed)
|
|
172
|
+
if parsed.command == "panels wait":
|
|
173
|
+
return run_panels_wait(parsed)
|
|
174
|
+
if parsed.command == "agents doctor":
|
|
175
|
+
return run_agents_doctor(parsed)
|
|
158
176
|
if parsed.command in {"install", "update"}:
|
|
159
177
|
return install_or_update(parsed, telemetry_context)
|
|
160
178
|
print(help_text(None))
|
|
@@ -409,6 +427,9 @@ def parse_local_boolean_flag(parsed: ParsedArgs, flag: str) -> None:
|
|
|
409
427
|
if flag == "--json":
|
|
410
428
|
parsed.json = True
|
|
411
429
|
return
|
|
430
|
+
if flag == "--wait-ready":
|
|
431
|
+
parsed.wait_ready = True
|
|
432
|
+
return
|
|
412
433
|
raise ValueError(f"Unknown option for {parsed.command}: {flag}")
|
|
413
434
|
|
|
414
435
|
|
|
@@ -472,6 +493,24 @@ def parse_local_value_flag(parsed: ParsedArgs, flag: str, value: str) -> None:
|
|
|
472
493
|
raise ValueError("--timeout-ms must be a positive number.")
|
|
473
494
|
parsed.timeout_ms = timeout_ms
|
|
474
495
|
return
|
|
496
|
+
if flag == "--ready-timeout-ms":
|
|
497
|
+
try:
|
|
498
|
+
ready_timeout_ms = float(value)
|
|
499
|
+
except ValueError as error:
|
|
500
|
+
raise ValueError("--ready-timeout-ms must be a positive number.") from error
|
|
501
|
+
if ready_timeout_ms <= 0:
|
|
502
|
+
raise ValueError("--ready-timeout-ms must be a positive number.")
|
|
503
|
+
parsed.ready_timeout_ms = ready_timeout_ms
|
|
504
|
+
return
|
|
505
|
+
if flag == "--concurrency":
|
|
506
|
+
try:
|
|
507
|
+
concurrency = int(value)
|
|
508
|
+
except ValueError as error:
|
|
509
|
+
raise ValueError("--concurrency must be a positive integer.") from error
|
|
510
|
+
if concurrency <= 0:
|
|
511
|
+
raise ValueError("--concurrency must be a positive integer.")
|
|
512
|
+
parsed.concurrency = concurrency
|
|
513
|
+
return
|
|
475
514
|
if flag == "--limit":
|
|
476
515
|
try:
|
|
477
516
|
limit = int(value)
|
|
@@ -481,6 +520,23 @@ def parse_local_value_flag(parsed: ParsedArgs, flag: str, value: str) -> None:
|
|
|
481
520
|
raise ValueError("--limit must be a positive integer.")
|
|
482
521
|
parsed.limit = limit
|
|
483
522
|
return
|
|
523
|
+
if flag == "--for":
|
|
524
|
+
if value not in {"initialized", "ready", "idle", "text"}:
|
|
525
|
+
raise ValueError("--for must be one of: initialized, ready, idle, text.")
|
|
526
|
+
parsed.wait_condition = value
|
|
527
|
+
return
|
|
528
|
+
if flag == "--contains":
|
|
529
|
+
parsed.contains = value
|
|
530
|
+
return
|
|
531
|
+
if flag == "--interval-ms":
|
|
532
|
+
try:
|
|
533
|
+
interval_ms = float(value)
|
|
534
|
+
except ValueError as error:
|
|
535
|
+
raise ValueError("--interval-ms must be a positive number.") from error
|
|
536
|
+
if interval_ms <= 0:
|
|
537
|
+
raise ValueError("--interval-ms must be a positive number.")
|
|
538
|
+
parsed.interval_ms = interval_ms
|
|
539
|
+
return
|
|
484
540
|
raise ValueError(f"Unknown option for {parsed.command}: {flag}")
|
|
485
541
|
|
|
486
542
|
|
|
@@ -493,6 +549,10 @@ def is_runpane_local_command(command: str) -> bool:
|
|
|
493
549
|
"panels list",
|
|
494
550
|
"panels output",
|
|
495
551
|
"panels input",
|
|
552
|
+
"panels screen",
|
|
553
|
+
"panels submit",
|
|
554
|
+
"panels wait",
|
|
555
|
+
"agents doctor",
|
|
496
556
|
}
|
|
497
557
|
|
|
498
558
|
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Generated by scripts/generate-runpane-contract.js. Do not edit by hand.
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
RUNPANE_CONTRACT = json.loads("{\n \"$schema\": \"./schema.json\",\n \"schemaVersion\": 1,\n \"name\": \"runpane\",\n \"description\": \"Thin installer and local control CLI for Pane\",\n \"packageInstallPolicy\": [\n \"The packages must not download, install, or configure Pane during package installation.\",\n \"Work starts only when a user runs `runpane ...`.\"\n ],\n \"compatibility\": {\n \"node\": \">=18.17.0\",\n \"python\": \">=3.8\"\n },\n \"terminology\": {\n \"repo\": \"Saved Pane repository/project record\",\n \"pane\": \"User-visible Pane session\",\n \"tool\": \"Terminal-backed tab\",\n \"agent\": \"Built-in agent command template\"\n },\n \"defaults\": {\n \"target\": \"client\",\n \"paneVersion\": \"latest\",\n \"channel\": \"stable\",\n \"format\": \"auto\",\n \"dryRun\": false,\n \"yes\": false,\n \"verbose\": false\n },\n \"enums\": {\n \"installTargets\": [\n \"client\",\n \"daemon\"\n ],\n \"artifactFormats\": [\n \"auto\",\n \"appimage\",\n \"deb\",\n \"dmg\",\n \"zip\",\n \"exe\"\n ],\n \"channels\": [\n \"stable\",\n \"nightly\"\n ],\n \"agents\": [\n \"codex\",\n \"claude\"\n ]\n },\n \"agentTemplates\": {\n \"codex\": {\n \"title\": \"Codex\",\n \"command\": \"codex --yolo\",\n \"description\": \"Open a Codex terminal tab and allow the initial input to drive the agent.\"\n },\n \"claude\": {\n \"title\": \"Claude Code\",\n \"command\": \"claude --dangerously-skip-permissions\",\n \"description\": \"Open a Claude Code terminal tab and allow the initial input to drive the agent.\"\n }\n },\n \"commands\": [\n {\n \"name\": \"help\",\n \"summary\": \"Show help for runpane or a specific command.\",\n \"usage\": [\n \"runpane help [command]\"\n ]\n },\n {\n \"name\": \"setup\",\n \"summary\": \"Open the guided setup wizard for install, remote host setup, update, and diagnostics.\",\n \"usage\": [\n \"runpane setup\"\n ],\n \"interactiveEntrypoint\": true\n },\n {\n \"name\": \"install\",\n \"summary\": \"Install Pane on this machine or configure this machine as a remote daemon host.\",\n \"usage\": [\n \"runpane install [client|daemon] [options]\"\n ],\n \"defaultTarget\": \"client\",\n \"targets\": [\n \"client\",\n \"daemon\"\n ],\n \"unknownDaemonFlagsForwarded\": true\n },\n {\n \"name\": \"update\",\n \"summary\": \"Update the Pane desktop app using the same artifact path as install client.\",\n \"usage\": [\n \"runpane update [options]\"\n ],\n \"target\": \"client\"\n },\n {\n \"name\": \"version\",\n \"summary\": \"Print the runpane wrapper version and installed Pane version when detectable.\",\n \"usage\": [\n \"runpane version\",\n \"runpane --version\"\n ]\n },\n {\n \"name\": \"doctor\",\n \"summary\": \"Run platform, release, installed Pane, and remote setup diagnostics.\",\n \"usage\": [\n \"runpane doctor\"\n ]\n },\n {\n \"name\": \"agents doctor\",\n \"summary\": \"Diagnose whether a built-in agent command is available in a Pane repository environment.\",\n \"usage\": [\n \"runpane agents doctor --agent <codex|claude> [--repo <selector>] [--json]\"\n ],\n \"jsonSchemas\": [\n \"agentDoctorResult\"\n ]\n },\n {\n \"name\": \"agent-context\",\n \"summary\": \"Print token-efficient Pane command context for coding agents.\",\n \"usage\": [\n \"runpane agent-context [--json]\",\n \"runpane agent-context --command <command> [--json]\"\n ],\n \"jsonSchemas\": [\n \"agentContextBriefResult\",\n \"agentContextCommandResult\"\n ]\n },\n {\n \"name\": \"repos list\",\n \"summary\": \"List repositories saved in the running Pane app.\",\n \"usage\": [\n \"runpane repos list [--json] [--pane-dir <path>]\"\n ],\n \"jsonSchemas\": [\n \"repoListResult\"\n ]\n },\n {\n \"name\": \"repos add\",\n \"summary\": \"Register an existing git repository with the running Pane app.\",\n \"usage\": [\n \"runpane repos add --path <path> [--name <name>] [--json] [--yes]\"\n ],\n \"mutates\": true,\n \"jsonSchemas\": [\n \"repoAddRequest\",\n \"repoAddResult\"\n ]\n },\n {\n \"name\": \"panes list\",\n \"summary\": \"List Pane sessions in a saved repository.\",\n \"usage\": [\n \"runpane panes list [--repo <selector>] [--json]\"\n ],\n \"jsonSchemas\": [\n \"paneListResult\"\n ]\n },\n {\n \"name\": \"panes create\",\n \"summary\": \"Create one or more Pane sessions in a saved repository and open a terminal-backed tool tab.\",\n \"usage\": [\n \"runpane panes create --repo <selector> --name <name> --agent <codex|claude> [options]\",\n \"runpane panes create --from-json <path|-> [--yes] [--json]\"\n ],\n \"mutates\": true,\n \"jsonSchemas\": [\n \"paneCreateRequest\",\n \"paneCreateResult\"\n ]\n },\n {\n \"name\": \"panels list\",\n \"summary\": \"List tool panels inside a Pane session.\",\n \"usage\": [\n \"runpane panels list --pane <pane-id> [--json]\"\n ],\n \"jsonSchemas\": [\n \"panelListResult\"\n ]\n },\n {\n \"name\": \"panels output\",\n \"summary\": \"Read recent terminal output from a panel.\",\n \"usage\": [\n \"runpane panels output --panel <panel-id> [--limit <count>] [--json]\"\n ],\n \"jsonSchemas\": [\n \"panelOutputResult\"\n ]\n },\n {\n \"name\": \"panels screen\",\n \"summary\": \"Read a compact current-screen view from a terminal panel.\",\n \"usage\": [\n \"runpane panels screen --panel <panel-id> [--limit <count>] [--json]\"\n ],\n \"jsonSchemas\": [\n \"panelScreenResult\"\n ]\n },\n {\n \"name\": \"panels input\",\n \"summary\": \"Send input bytes to a terminal panel.\",\n \"usage\": [\n \"runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\"\n ],\n \"mutates\": true,\n \"jsonSchemas\": [\n \"panelInputRequest\",\n \"panelInputResult\"\n ]\n },\n {\n \"name\": \"panels submit\",\n \"summary\": \"Send text to a terminal panel and append a terminal Enter byte.\",\n \"usage\": [\n \"runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\"\n ],\n \"mutates\": true,\n \"jsonSchemas\": [\n \"panelSubmitRequest\",\n \"panelSubmitResult\"\n ]\n },\n {\n \"name\": \"panels wait\",\n \"summary\": \"Wait for a terminal panel to initialize, become ready/idle, or contain text.\",\n \"usage\": [\n \"runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--contains <text>] [--timeout-ms <ms>] [--interval-ms <ms>] [--json]\"\n ],\n \"jsonSchemas\": [\n \"panelWaitResult\"\n ]\n }\n ],\n \"flags\": {\n \"wrapper\": [\n {\n \"name\": \"--version\",\n \"value\": \"<latest|vX.Y.Z>\",\n \"description\": \"Pane release to install or inspect.\"\n },\n {\n \"name\": \"--download-dir\",\n \"value\": \"<path>\",\n \"description\": \"Directory for downloaded Pane release artifacts.\"\n },\n {\n \"name\": \"--pane-path\",\n \"value\": \"<path>\",\n \"description\": \"Use or inspect an existing Pane executable.\"\n },\n {\n \"name\": \"--format\",\n \"value\": \"<auto|appimage|deb|dmg|zip|exe>\",\n \"description\": \"Pane release artifact format.\"\n },\n {\n \"name\": \"--dry-run\",\n \"description\": \"Print the plan without downloading or installing.\"\n },\n {\n \"name\": \"--yes\",\n \"aliases\": [\n \"-y\"\n ],\n \"description\": \"Skip interactive prompts where possible.\"\n },\n {\n \"name\": \"--verbose\",\n \"description\": \"Print extra diagnostics.\"\n }\n ],\n \"remoteValue\": [\n {\n \"name\": \"--label\",\n \"value\": \"<name>\"\n },\n {\n \"name\": \"--prefer-tunnel\",\n \"value\": \"<tailscale|ssh|manual|auto>\"\n },\n {\n \"name\": \"--channel\",\n \"value\": \"<stable|nightly>\"\n },\n {\n \"name\": \"--base-url\",\n \"value\": \"<url>\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\"\n },\n {\n \"name\": \"--listen-port\",\n \"value\": \"<port>\"\n },\n {\n \"name\": \"--port\",\n \"value\": \"<port>\"\n },\n {\n \"name\": \"--repo-ref\",\n \"value\": \"<ref>\"\n }\n ],\n \"remoteBoolean\": [\n {\n \"name\": \"--auto-listen-port\"\n },\n {\n \"name\": \"--interactive-tailscale-setup\"\n },\n {\n \"name\": \"--no-install-service\"\n },\n {\n \"name\": \"--no-tailscale-serve\"\n },\n {\n \"name\": \"--print-only\"\n }\n ],\n \"localValue\": [\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"description\": \"Connect to a Pane daemon using this Pane data directory.\"\n },\n {\n \"name\": \"--repo\",\n \"value\": \"<selector>\",\n \"description\": \"Repository selector: active, id, exact path, or saved repository name.\"\n },\n {\n \"name\": \"--pane\",\n \"value\": \"<pane-id>\",\n \"description\": \"Pane/session id to inspect.\"\n },\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"description\": \"Tool panel id to inspect or control.\"\n },\n {\n \"name\": \"--path\",\n \"value\": \"<path>\",\n \"description\": \"Existing git repository path to register with Pane.\"\n },\n {\n \"name\": \"--name\",\n \"value\": \"<name>\",\n \"description\": \"Name for the registered repository or created pane/session.\"\n },\n {\n \"name\": \"--worktree-name\",\n \"value\": \"<name>\",\n \"description\": \"Worktree name to request. Defaults to --name.\"\n },\n {\n \"name\": \"--base-branch\",\n \"value\": \"<branch>\",\n \"description\": \"Base branch for the created worktree.\"\n },\n {\n \"name\": \"--agent\",\n \"value\": \"<codex|claude>\",\n \"description\": \"Built-in agent terminal template to open.\"\n },\n {\n \"name\": \"--tool-command\",\n \"value\": \"<command>\",\n \"description\": \"Custom terminal command to run instead of a built-in agent.\"\n },\n {\n \"name\": \"--title\",\n \"value\": \"<title>\",\n \"description\": \"Terminal tab title. Defaults to the selected agent title or Terminal.\"\n },\n {\n \"name\": \"--initial-input\",\n \"value\": \"<text>\",\n \"aliases\": [\n \"--prompt\"\n ],\n \"description\": \"Text to send to the terminal after the command is ready. --prompt is an alias.\"\n },\n {\n \"name\": \"--initial-input-file\",\n \"value\": \"<path|->\",\n \"description\": \"Read initial input from a file or stdin.\"\n },\n {\n \"name\": \"--from-json\",\n \"value\": \"<path|->\",\n \"description\": \"Read a full panes.create request JSON payload from a file or stdin.\"\n },\n {\n \"name\": \"--timeout-ms\",\n \"value\": \"<milliseconds>\",\n \"description\": \"Maximum time to wait for each pane creation job.\"\n },\n {\n \"name\": \"--ready-timeout-ms\",\n \"value\": \"<milliseconds>\",\n \"description\": \"Readiness wait timeout for panes create --wait-ready.\"\n },\n {\n \"name\": \"--concurrency\",\n \"value\": \"<count>\",\n \"description\": \"Accepted for forward compatibility. Pane currently serializes multi-pane session creation so queued jobs do not time out before starting.\"\n },\n {\n \"name\": \"--limit\",\n \"value\": \"<count>\",\n \"description\": \"Maximum recent output lines or records to read.\"\n },\n {\n \"name\": \"--for\",\n \"value\": \"<initialized|ready|idle|text>\",\n \"description\": \"Panel wait condition.\"\n },\n {\n \"name\": \"--contains\",\n \"value\": \"<text>\",\n \"description\": \"Text to wait for with panels wait --for text.\"\n },\n {\n \"name\": \"--interval-ms\",\n \"value\": \"<milliseconds>\",\n \"description\": \"Polling interval for panels wait.\"\n },\n {\n \"name\": \"--text\",\n \"value\": \"<text>\",\n \"description\": \"Text bytes to send to a terminal panel.\"\n },\n {\n \"name\": \"--input-file\",\n \"value\": \"<path|->\",\n \"description\": \"Read panel input from a file or stdin.\"\n }\n ],\n \"localBoolean\": [\n {\n \"name\": \"--json\",\n \"description\": \"Print machine-readable JSON output.\"\n },\n {\n \"name\": \"--wait-ready\",\n \"description\": \"Wait for created terminal panels to be ready before returning.\"\n }\n ]\n },\n \"help\": {\n \"npm\": {\n \"default\": [\n \"Usage:\",\n \" runpane\",\n \" runpane setup\",\n \" runpane install [client|daemon] [options]\",\n \" runpane update [options]\",\n \" runpane version\",\n \" runpane doctor\",\n \" runpane agent-context [--json]\",\n \" runpane agents doctor --agent <codex|claude> [--repo <selector>] [--json]\",\n \" runpane repos list [--json]\",\n \" runpane repos add --path <path> [--name <name>]\",\n \" runpane panes list [--repo <selector>] [--json]\",\n \" runpane panes create --repo <selector> --name <name> --agent <codex|claude> [--wait-ready]\",\n \" runpane panels list --pane <pane-id> [--json]\",\n \" runpane panels output --panel <panel-id> [--limit <count>] [--json]\",\n \" runpane panels screen --panel <panel-id> [--limit <count>] [--json]\",\n \" runpane panels input --panel <panel-id> --input-file <path|-> --yes\",\n \" runpane panels submit --panel <panel-id> --text <text> --yes\",\n \" runpane panels wait --panel <panel-id> [--for ready|idle|text] [--json]\",\n \" runpane help [command]\",\n \"\",\n \"Quick start:\",\n \" npx --yes runpane@latest\",\n \" npm i -g runpane && runpane setup\",\n \"\",\n \"Advanced examples:\",\n \" npx --yes runpane@latest install client\",\n \" npx --yes runpane@latest install daemon --label \\\"My Server\\\"\",\n \" pnpm dlx runpane@latest\",\n \"\",\n \"Run \\\"runpane agent-context\\\" when an agent needs Pane command context.\",\n \"Run \\\"runpane help panes create\\\" for pane orchestration options.\"\n ],\n \"install\": [\n \"Usage:\",\n \" runpane install [client|daemon] [options]\",\n \"\",\n \"Examples:\",\n \" npx --yes runpane@latest install client\",\n \" npx --yes runpane@latest install daemon --label \\\"My Server\\\"\",\n \" pnpm dlx runpane@latest install daemon --prefer-tunnel ssh --label \\\"VM\\\"\",\n \"\",\n \"Wrapper options:\",\n \" --version <latest|vX.Y.Z> Pane release to install\",\n \" --format <auto|appimage|deb|dmg|zip|exe>\",\n \" --download-dir <path>\",\n \" --pane-path <path> Use an existing Pane executable\",\n \" --dry-run Print the plan without downloading\",\n \" --yes Skip interactive prompts where possible\",\n \" --verbose\",\n \"\",\n \"Daemon passthrough options:\",\n \" --label <name>\",\n \" --prefer-tunnel <tailscale|ssh|manual|auto>\",\n \" --channel <stable|nightly>\",\n \" --base-url <url>\",\n \" --pane-dir <path>\",\n \" --listen-port <port> / --port <port>\",\n \" --auto-listen-port\",\n \" --interactive-tailscale-setup\",\n \" --no-install-service\",\n \" --no-tailscale-serve\",\n \" --print-only\",\n \" --repo-ref <ref>\"\n ],\n \"setup\": [\n \"Usage:\",\n \" runpane setup\",\n \"\",\n \"Opens the guided setup for desktop install, remote host setup, update, and diagnostics.\",\n \"\",\n \"Quick start:\",\n \" npx --yes runpane@latest\",\n \" npm i -g runpane && runpane setup\"\n ],\n \"update\": [\n \"Usage:\",\n \" runpane update [options]\",\n \"\",\n \"Updates Pane using the same artifact selection as \\\"runpane install client\\\".\",\n \"\",\n \"Options:\",\n \" --version <latest|vX.Y.Z>\",\n \" --format <auto|appimage|deb|dmg|zip|exe>\",\n \" --download-dir <path>\",\n \" --pane-path <path>\",\n \" --dry-run\",\n \" --yes\",\n \" --verbose\"\n ],\n \"version\": [\n \"Usage:\",\n \" runpane version\",\n \" runpane --version\"\n ],\n \"doctor\": [\n \"Usage:\",\n \" runpane doctor [--pane-path <path>] [--format <format>] [--verbose]\"\n ],\n \"repos list\": [\n \"Usage:\",\n \" runpane repos list [--json] [--pane-dir <path>]\",\n \"\",\n \"Lists repositories saved in the running Pane app.\",\n \"\",\n \"Options:\",\n \" --json Print machine-readable output\",\n \" --pane-dir <path> Connect to a specific Pane data directory\"\n ],\n \"repos add\": [\n \"Usage:\",\n \" runpane repos add --path <path> [--name <name>] [--json] [--yes]\",\n \"\",\n \"Registers an existing git repository with the running Pane app.\",\n \"\",\n \"Options:\",\n \" --path <path> Existing git repository path\",\n \" --name <name> Saved repository name; defaults to the directory name\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --dry-run Validate and preview without adding the repo\",\n \" --yes Skip confirmation for mutating commands\"\n ],\n \"panes list\": [\n \"Usage:\",\n \" runpane panes list [--repo <selector>] [--json]\",\n \"\",\n \"Lists Pane sessions. Pass --repo to limit results to one saved repository.\",\n \"\",\n \"Options:\",\n \" --repo <selector> active, id, exact path, or saved repository name\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panes create\": [\n \"Usage:\",\n \" runpane panes create --repo <selector> --name <name> --agent <codex|claude> [options]\",\n \" runpane panes create --from-json <path|-> [--yes] [--json]\",\n \"\",\n \"Creates Pane sessions in a saved repository and opens a terminal-backed tool tab.\",\n \"\",\n \"Options:\",\n \" --repo <selector> active, id, exact path, or saved repository name\",\n \" --name <name> Pane/session name\",\n \" --worktree-name <name> Worktree name; defaults to --name\",\n \" --base-branch <branch> Base branch for the worktree\",\n \" --agent <codex|claude> Built-in terminal template\",\n \" --tool-command <command> Custom terminal command\",\n \" --title <title> Terminal tab title\",\n \" --initial-input <text> Text sent after the command is ready\",\n \" --prompt <text> Alias for --initial-input\",\n \" --initial-input-file <path|-> Read initial input from a file or stdin\",\n \" --from-json <path|-> Read a full request payload\",\n \" --timeout-ms <milliseconds> Pane creation timeout\",\n \" --wait-ready Wait for terminal readiness before returning\",\n \" --ready-timeout-ms <ms> Readiness wait timeout; defaults to 30000\",\n \" --concurrency <count> Accepted; creation is currently serialized\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --dry-run Validate and preview without creating panes\",\n \" --yes Skip confirmation for mutating commands\"\n ],\n \"panels list\": [\n \"Usage:\",\n \" runpane panels list --pane <pane-id> [--json]\",\n \"\",\n \"Lists tool panels in a Pane session.\",\n \"\",\n \"Options:\",\n \" --pane <pane-id> Pane/session id\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panels output\": [\n \"Usage:\",\n \" runpane panels output --panel <panel-id> [--limit <count>] [--json]\",\n \"\",\n \"Reads bounded recent terminal output from a panel.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Tool panel id\",\n \" --limit <count> Maximum recent output lines or records to read\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panels input\": [\n \"Usage:\",\n \" runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\",\n \"\",\n \"Sends exact input bytes to a terminal panel. Include a newline in the input when you mean Enter.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Terminal panel id\",\n \" --text <text> Text bytes to send\",\n \" --input-file <path|-> Read input from a file or stdin\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --yes Skip confirmation for mutating commands\"\n ],\n \"agent-context\": [\n \"Usage:\",\n \" runpane agent-context [--json]\",\n \" runpane agent-context --command <command> [--json]\",\n \"\",\n \"Prints Pane command context for coding agents without requiring a running Pane app.\",\n \"\",\n \"Options:\",\n \" --command <command> Print the full definition for one runpane command\",\n \" --json Print machine-readable output\",\n \"\",\n \"Examples:\",\n \" runpane agent-context\",\n \" runpane agent-context --json\",\n \" runpane agent-context --command \\\"panes create\\\"\",\n \" runpane agent-context --command \\\"panes create\\\" --json\"\n ],\n \"agents doctor\": [\n \"Usage:\",\n \" runpane agents doctor --agent <codex|claude> [--repo <selector>] [--json]\",\n \"\",\n \"Diagnoses whether Codex or Claude is available in the same repository environment Pane will use.\",\n \"\",\n \"Options:\",\n \" --agent <codex|claude> Built-in agent command to diagnose\",\n \" --repo <selector> active, id, exact path, or saved repository name; defaults to active\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panels screen\": [\n \"Usage:\",\n \" runpane panels screen --panel <panel-id> [--limit <count>] [--json]\",\n \"\",\n \"Reads a compact current-screen view from a terminal panel. Prefers alternate-screen/TUI output and falls back to recent scrollback.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Terminal panel id\",\n \" --limit <count> Maximum lines to return; defaults to 80\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panels submit\": [\n \"Usage:\",\n \" runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\",\n \"\",\n \"Sends text to a terminal panel and normalizes the final terminal Enter to CR. Use this for ordinary prompt answers and shell commands.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Terminal panel id\",\n \" --text <text> Text to submit before Enter\",\n \" --input-file <path|-> Read text from a file or stdin before Enter\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --yes Skip confirmation for this mutating command\"\n ],\n \"panels wait\": [\n \"Usage:\",\n \" runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--contains <text>] [--timeout-ms <ms>] [--interval-ms <ms>] [--json]\",\n \"\",\n \"Polls a terminal panel until it is initialized, ready, idle, or contains text. Output is intentionally small and includes next-step guidance.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Terminal panel id\",\n \" --for <condition> initialized, ready, idle, or text; defaults to ready for CLI panels and idle otherwise\",\n \" --contains <text> Text required for --for text; implies --for text when omitted\",\n \" --timeout-ms <milliseconds> Wait timeout; defaults to 30000\",\n \" --interval-ms <milliseconds> Poll interval; defaults to 500\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ]\n },\n \"pip\": {\n \"default\": [\n \"Usage:\",\n \" runpane\",\n \" runpane setup\",\n \" runpane install [client|daemon] [options]\",\n \" runpane update [options]\",\n \" runpane version\",\n \" runpane doctor\",\n \" runpane agent-context [--json]\",\n \" runpane agents doctor --agent <codex|claude> [--repo <selector>] [--json]\",\n \" runpane repos list [--json]\",\n \" runpane repos add --path <path> [--name <name>]\",\n \" runpane panes list [--repo <selector>] [--json]\",\n \" runpane panes create --repo <selector> --name <name> --agent <codex|claude> [--wait-ready]\",\n \" runpane panels list --pane <pane-id> [--json]\",\n \" runpane panels output --panel <panel-id> [--limit <count>] [--json]\",\n \" runpane panels screen --panel <panel-id> [--limit <count>] [--json]\",\n \" runpane panels input --panel <panel-id> --input-file <path|-> --yes\",\n \" runpane panels submit --panel <panel-id> --text <text> --yes\",\n \" runpane panels wait --panel <panel-id> [--for ready|idle|text] [--json]\",\n \" runpane help [command]\",\n \"\",\n \"Quick start:\",\n \" pipx run runpane\",\n \" python -m pip install runpane && python -m runpane setup\",\n \"\",\n \"Advanced examples:\",\n \" pipx run runpane install client\",\n \" pipx run runpane install daemon --label \\\"My Server\\\"\",\n \" uvx runpane@latest\",\n \"\",\n \"Run \\\"runpane agent-context\\\" when an agent needs Pane command context.\",\n \"Run \\\"runpane help panes create\\\" for pane orchestration options.\"\n ],\n \"install\": [\n \"Usage:\",\n \" runpane install [client|daemon] [options]\",\n \"\",\n \"Examples:\",\n \" npx --yes runpane@latest install daemon --label \\\"My Server\\\"\",\n \" pnpm dlx runpane@latest install daemon --prefer-tunnel ssh --label \\\"VM\\\"\",\n \" pipx run runpane install daemon --label \\\"My Server\\\"\",\n \"\",\n \"Wrapper options:\",\n \" --version <latest|vX.Y.Z>\",\n \" --format <auto|appimage|deb|dmg|zip|exe>\",\n \" --download-dir <path>\",\n \" --pane-path <path>\",\n \" --dry-run\",\n \" --yes\",\n \" --verbose\",\n \"\",\n \"Daemon passthrough options:\",\n \" --label <name>\",\n \" --prefer-tunnel <tailscale|ssh|manual|auto>\",\n \" --channel <stable|nightly>\",\n \" --base-url <url>\",\n \" --pane-dir <path>\",\n \" --listen-port <port> / --port <port>\",\n \" --auto-listen-port\",\n \" --interactive-tailscale-setup\",\n \" --no-install-service\",\n \" --no-tailscale-serve\",\n \" --print-only\",\n \" --repo-ref <ref>\"\n ],\n \"setup\": [\n \"Usage:\",\n \" runpane setup\",\n \"\",\n \"Opens the guided setup for desktop install, remote host setup, update, and diagnostics.\",\n \"\",\n \"Quick start:\",\n \" pipx run runpane\",\n \" python -m pip install runpane && python -m runpane setup\"\n ],\n \"update\": [\n \"Usage:\",\n \" runpane update [--version <latest|vX.Y.Z>] [--dry-run] [--yes]\"\n ],\n \"version\": [\n \"Usage:\",\n \" runpane version\",\n \" runpane --version\"\n ],\n \"doctor\": [\n \"Usage:\",\n \" runpane doctor [--pane-path <path>] [--format <format>] [--verbose]\"\n ],\n \"repos list\": [\n \"Usage:\",\n \" runpane repos list [--json] [--pane-dir <path>]\",\n \"\",\n \"Lists repositories saved in the running Pane app.\",\n \"\",\n \"Options:\",\n \" --json\",\n \" --pane-dir <path>\"\n ],\n \"repos add\": [\n \"Usage:\",\n \" runpane repos add --path <path> [--name <name>] [--json] [--yes]\",\n \"\",\n \"Registers an existing git repository with the running Pane app.\",\n \"\",\n \"Options:\",\n \" --path <path>\",\n \" --name <name>\",\n \" --pane-dir <path>\",\n \" --json\",\n \" --dry-run\",\n \" --yes\"\n ],\n \"panes list\": [\n \"Usage:\",\n \" runpane panes list [--repo <selector>] [--json]\",\n \"\",\n \"Lists Pane sessions. Pass --repo to limit results to one saved repository.\",\n \"\",\n \"Options:\",\n \" --repo <selector>\",\n \" --pane-dir <path>\",\n \" --json\"\n ],\n \"panes create\": [\n \"Usage:\",\n \" runpane panes create --repo <selector> --name <name> --agent <codex|claude> [options]\",\n \" runpane panes create --from-json <path|-> [--yes] [--json]\",\n \"\",\n \"Creates Pane sessions in a saved repository and opens a terminal-backed tool tab.\",\n \"\",\n \"Options:\",\n \" --repo <selector> active, id, exact path, or saved repository name\",\n \" --name <name> Pane/session name\",\n \" --worktree-name <name> Worktree name; defaults to --name\",\n \" --base-branch <branch> Base branch for the worktree\",\n \" --agent <codex|claude> Built-in terminal template\",\n \" --tool-command <command> Custom terminal command\",\n \" --title <title> Terminal tab title\",\n \" --initial-input <text> Text sent after the command is ready\",\n \" --prompt <text> Alias for --initial-input\",\n \" --initial-input-file <path|-> Read initial input from a file or stdin\",\n \" --from-json <path|-> Read a full request payload\",\n \" --timeout-ms <milliseconds> Pane creation timeout\",\n \" --wait-ready Wait for terminal readiness before returning\",\n \" --ready-timeout-ms <ms> Readiness wait timeout; defaults to 30000\",\n \" --concurrency <count> Accepted; creation is currently serialized\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --dry-run Validate and preview without creating panes\",\n \" --yes Skip confirmation for mutating commands\"\n ],\n \"panels list\": [\n \"Usage:\",\n \" runpane panels list --pane <pane-id> [--json]\",\n \"\",\n \"Lists tool panels in a Pane session.\",\n \"\",\n \"Options:\",\n \" --pane <pane-id>\",\n \" --pane-dir <path>\",\n \" --json\"\n ],\n \"panels output\": [\n \"Usage:\",\n \" runpane panels output --panel <panel-id> [--limit <count>] [--json]\",\n \"\",\n \"Reads recent terminal output records from a panel.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id>\",\n \" --limit <count>\",\n \" --pane-dir <path>\",\n \" --json\"\n ],\n \"panels input\": [\n \"Usage:\",\n \" runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\",\n \"\",\n \"Sends exact input bytes to a terminal panel. Include a newline in the input when you mean Enter.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id>\",\n \" --text <text>\",\n \" --input-file <path|->\",\n \" --pane-dir <path>\",\n \" --json\",\n \" --yes\"\n ],\n \"agent-context\": [\n \"Usage:\",\n \" runpane agent-context [--json]\",\n \" runpane agent-context --command <command> [--json]\",\n \"\",\n \"Prints Pane command context for coding agents without requiring a running Pane app.\",\n \"\",\n \"Options:\",\n \" --command <command>\",\n \" --json\",\n \"\",\n \"Examples:\",\n \" runpane agent-context\",\n \" runpane agent-context --json\",\n \" runpane agent-context --command \\\"panes create\\\"\",\n \" runpane agent-context --command \\\"panes create\\\" --json\"\n ],\n \"agents doctor\": [\n \"Usage:\",\n \" runpane agents doctor --agent <codex|claude> [--repo <selector>] [--json]\",\n \"\",\n \"Diagnoses whether Codex or Claude is available in the same repository environment Pane will use.\",\n \"\",\n \"Options:\",\n \" --agent <codex|claude> Built-in agent command to diagnose\",\n \" --repo <selector> active, id, exact path, or saved repository name; defaults to active\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panels screen\": [\n \"Usage:\",\n \" runpane panels screen --panel <panel-id> [--limit <count>] [--json]\",\n \"\",\n \"Reads a compact current-screen view from a terminal panel. Prefers alternate-screen/TUI output and falls back to recent scrollback.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Terminal panel id\",\n \" --limit <count> Maximum lines to return; defaults to 80\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panels submit\": [\n \"Usage:\",\n \" runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\",\n \"\",\n \"Sends text to a terminal panel and normalizes the final terminal Enter to CR. Use this for ordinary prompt answers and shell commands.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Terminal panel id\",\n \" --text <text> Text to submit before Enter\",\n \" --input-file <path|-> Read text from a file or stdin before Enter\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --yes Skip confirmation for this mutating command\"\n ],\n \"panels wait\": [\n \"Usage:\",\n \" runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--contains <text>] [--timeout-ms <ms>] [--interval-ms <ms>] [--json]\",\n \"\",\n \"Polls a terminal panel until it is initialized, ready, idle, or contains text. Output is intentionally small and includes next-step guidance.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Terminal panel id\",\n \" --for <condition> initialized, ready, idle, or text; defaults to ready for CLI panels and idle otherwise\",\n \" --contains <text> Text required for --for text; implies --for text when omitted\",\n \" --timeout-ms <milliseconds> Wait timeout; defaults to 30000\",\n \" --interval-ms <milliseconds> Poll interval; defaults to 500\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ]\n }\n },\n \"docs\": {\n \"maintainerRules\": [\n \"Treat `contracts/runpane/contract.json` as the source of truth for both wrapper packages and generated docs.\",\n \"Every command, flag, platform default, artifact-selection rule, and attribution rule change must be reflected in the contract.\",\n \"The npm and PyPI wrappers must expose the same command behavior unless the contract explicitly documents a package-manager-specific difference.\",\n \"Root `README.md` and package READMEs should lead with one guided quick-start command. Explicit commands, package-manager variants, and flags belong in an Advanced section.\",\n \"Release version bumps must keep root `package.json`, `packages/runpane`, and `packages/runpane-py` versions in sync. Run `pnpm run check:runpane-package-versions` before release.\",\n \"`pnpm run test:runpane-contract` must pass before changing wrapper command parsing, help output, platform defaults, release asset selection, or generated contract artifacts.\",\n \"Token-based npm or PyPI publishing is a temporary fallback. Prefer trusted publishing once the package names are reserved and trusted publishers are configured.\"\n ],\n \"recommendedQuickStarts\": [\n \"npx --yes runpane@latest\",\n \"npm i -g runpane && runpane setup\",\n \"pipx run runpane\",\n \"python -m pip install runpane && python -m runpane setup\"\n ],\n \"npmCommands\": [\n \"npx --yes runpane@latest\",\n \"npx --yes runpane@latest setup\",\n \"npx --yes runpane@latest install client\",\n \"npx --yes runpane@latest install daemon --label \\\"My Server\\\"\",\n \"pnpm dlx runpane@latest\",\n \"pnpm dlx runpane@latest install daemon --label \\\"My Server\\\"\",\n \"npm i -g runpane && runpane\",\n \"npm i -g runpane && runpane setup\",\n \"npm i -g runpane && runpane install daemon --label \\\"My Server\\\"\",\n \"pnpm add -g runpane && runpane\",\n \"pnpm add -g runpane && runpane setup\",\n \"pnpm add -g runpane && runpane install daemon --label \\\"My Server\\\"\",\n \"yarn dlx runpane@latest install daemon --label \\\"My Server\\\"\",\n \"bunx runpane@latest install daemon --label \\\"My Server\\\"\"\n ],\n \"pythonCommands\": [\n \"pipx run runpane\",\n \"pipx run runpane setup\",\n \"python -m pip install runpane\",\n \"runpane\",\n \"runpane setup\",\n \"python -m runpane setup\",\n \"runpane install daemon --label \\\"My Server\\\"\",\n \"pipx install runpane\",\n \"runpane\",\n \"runpane setup\",\n \"pipx run runpane install daemon --label \\\"My Server\\\"\",\n \"uvx runpane@latest\",\n \"uvx runpane@latest setup\",\n \"uvx runpane@latest install daemon --label \\\"My Server\\\"\",\n \"python -m runpane install daemon --label \\\"My Server\\\"\"\n ],\n \"packageManagerNotes\": [\n \"Use `pnpm dlx` for one-shot pnpm execution and `pnpm add -g` for persistent CLI installation.\",\n \"Do not document `pnpm install runpane` as the public CLI install path.\"\n ],\n \"commandUsages\": [\n \"runpane\",\n \"runpane setup\",\n \"runpane install\",\n \"runpane install client\",\n \"runpane install daemon\",\n \"runpane update\",\n \"runpane version\",\n \"runpane doctor\",\n \"runpane agent-context\",\n \"runpane agent-context --command \\\"panes create\\\" --json\",\n \"runpane repos list --json\",\n \"runpane repos add --path /path/to/repo --name Pane --yes --json\",\n \"runpane panes list --repo active --json\",\n \"runpane panes create --repo active --name issue-252 --agent codex --prompt \\\"Kick off the discussion skill for issue 252\\\" --yes\",\n \"runpane panes create --from-json panes.json --yes --json\",\n \"runpane panels list --pane <pane-id> --json\",\n \"runpane panels output --panel <panel-id> --limit 200 --json\",\n \"printf 'Continue\\\\n' | runpane panels input --panel <panel-id> --input-file - --yes --json\",\n \"runpane help\",\n \"runpane <command> --help\"\n ],\n \"commandDescriptions\": [\n \"`runpane` with no arguments and `runpane setup` open an interactive wizard when stdin and stdout are TTYs. In non-interactive shells or CI, both forms must print help and exit successfully instead of waiting for input.\",\n \"`runpane install` is an alias for `runpane install client`.\",\n \"`runpane install client` downloads the selected Pane desktop artifact and installs, opens, or launches it for the current platform.\",\n \"`runpane install daemon` downloads or installs Pane, resolves a stable Pane executable path, and spawns `<pane executable> --remote-setup <forwarded remote setup args>`.\",\n \"The wrapper must stream Pane stdout/stderr without reformatting because `pane --remote-setup` prints the one-time `pane-remote://...` connection code.\",\n \"`runpane update` uses the same release resolution and installer path as `install client`.\",\n \"`runpane version` prints the wrapper package version, the installed Pane version when detectable, and the latest GitHub release version when reachable.\",\n \"`runpane doctor` checks platform support, release metadata reachability, download URL selection, installed Pane detection, and remote-daemon hints.\",\n \"`runpane agent-context` prints a brief, token-efficient command schema for coding agents without connecting to the Pane daemon.\",\n \"`runpane agent-context --command \\\"panes create\\\"` prints the detailed definition for one command. Add `--json` for machine-readable output.\",\n \"`runpane repos list` connects to the running local Pane daemon and prints saved repository records.\",\n \"`runpane repos add` registers an existing git repository with the running local Pane daemon. It does not create directories or initialize git repositories by default.\",\n \"`runpane panes list` lists Pane sessions, optionally scoped to one saved repository.\",\n \"`runpane panes create` connects to the running local Pane daemon, resolves the requested repository, creates Pane sessions, opens terminal-backed tool tabs, and optionally sends initial input to the started tool.\",\n \"`runpane panels list` lists tool panels inside one Pane session.\",\n \"`runpane panels output` reads bounded recent terminal output from one panel and strips common terminal control noise for agent use.\",\n \"`runpane panels input` sends exact input bytes to one terminal panel. Prefer `--input-file` for newlines, Ctrl-C, quotes, or shell-sensitive text.\",\n \"`runpane panes create --prompt` is an alias for `--initial-input`; request JSON and daemon payloads should use the canonical `initialInput` field.\",\n \"When running from WSL while Pane is installed on Windows, the Linux wrapper may look for a missing `/tmp/pane-daemon.../daemon.sock` or resolve to a Windows shim such as Volta. In that case invoke the Windows wrapper through PowerShell from a Windows cwd, for example `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane repos list --json'`.\"\n ],\n \"wrapperFlagNote\": \"The top-level `runpane --version` form prints the wrapper version. The install subcommand form `runpane install --version vX.Y.Z` selects a Pane release.\",\n \"localControlFlagNote\": \"`runpane repos list`, `runpane panes list`, `runpane panes create`, and `runpane panels ...` commands use the local framed daemon socket/pipe for a running Pane app. `--pane-dir` points the wrapper at a non-default Pane data directory, such as `PANE_DIR=~/.pane_test` in development. `runpane agent-context` is local/offline and can be used before Pane is running. From WSL, if the user runs Windows Pane, call the Windows wrapper through `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane ...'` so the command can reach the Windows named-pipe daemon and avoid UNC cwd issues.\",\n \"daemonFlagNote\": \"Unknown daemon flags should be forwarded rather than dropped so newer Pane versions can extend `--remote-setup` without requiring an immediate wrapper release. Unknown flags for non-daemon commands should fail clearly.\",\n \"downloadAttribution\": [\n \"The npm package uses `source=npm` for all npm-registry consumers, including `npx`, `pnpm dlx`, `yarn dlx`, `bunx`, and global npm/pnpm installs.\",\n \"The PyPI package uses `source=pip` for all Python consumers, including pip, pipx, uvx, and `python -m runpane`.\",\n \"Wrappers should prefer `https://runpane.com/api/download?platform=<platform>&arch=<arch>&format=<format>&version=<version>&channel=<channel>&source=<npm|pip>`.\",\n \"If the website route cannot satisfy the download, wrappers may fall back to the matching GitHub release asset and print a warning that website attribution may be incomplete for that run.\",\n \"Wrappers also emit best-effort lifecycle telemetry to `https://runpane.com/api/runpane/telemetry` for command start/success/failure, download request/success/failure, and GitHub fallback usage.\",\n \"Wrapper telemetry uses a persisted anonymous `install_id` in the form `install_<uuid>` and PostHog `distinct_id = install:<install_id>` so distinct wrapper users can be counted with `count(DISTINCT properties.install_id)`.\",\n \"Wrapper telemetry must be disabled in CI and when `RUNPANE_TELEMETRY_DISABLED` is set, and must not include raw paths, labels, prompts, raw error text, or environment values.\"\n ],\n \"publishingCredentials\": [\n \"Local implementation, build, and dry-run validation do not need npm or PyPI API tokens.\",\n \"Release publishing should prefer npm Trusted Publishing and PyPI Trusted Publishing from GitHub Actions.\",\n \"Fallback `NPM_TOKEN` or `PYPI_API_TOKEN` credentials may be used for first package reservation or manual publication only. They must be supplied through local environment variables or GitHub Actions secrets, never committed, and revoked or rotated after use.\"\n ]\n },\n \"testFixtures\": {\n \"parserSamples\": [\n [\n \"setup\"\n ],\n [\n \"install\"\n ],\n [\n \"install\",\n \"client\",\n \"--version\",\n \"v2.2.8\",\n \"--format\",\n \"dmg\",\n \"--download-dir\",\n \"/tmp/pane-downloads\",\n \"--dry-run\",\n \"--yes\"\n ],\n [\n \"install\",\n \"daemon\",\n \"--label\",\n \"VM\",\n \"--prefer-tunnel\",\n \"ssh\",\n \"--channel\",\n \"nightly\",\n \"--base-url\",\n \"https://example.test\",\n \"--pane-dir\",\n \"/tmp/pane\",\n \"--listen-port\",\n \"4555\",\n \"--auto-listen-port\",\n \"--print-only\",\n \"--repo-ref\",\n \"main\",\n \"--unknown-future-flag\",\n \"future-value\",\n \"--dry-run\",\n \"--verbose\"\n ],\n [\n \"update\",\n \"--version\",\n \"latest\",\n \"--format\",\n \"appimage\",\n \"--pane-path\",\n \"/usr/bin/pane\",\n \"--dry-run\"\n ],\n [\n \"doctor\",\n \"--pane-path\",\n \"/usr/bin/pane\",\n \"--format\",\n \"zip\",\n \"--verbose\"\n ],\n [\n \"agent-context\"\n ],\n [\n \"agent-context\",\n \"--command\",\n \"panes create\",\n \"--json\"\n ],\n [\n \"repos\",\n \"list\",\n \"--json\",\n \"--pane-dir\",\n \"/tmp/pane\"\n ],\n [\n \"repos\",\n \"add\",\n \"--path\",\n \"/tmp/repo\",\n \"--name\",\n \"Repo\",\n \"--dry-run\",\n \"--yes\",\n \"--json\",\n \"--pane-dir\",\n \"/tmp/pane\"\n ],\n [\n \"panes\",\n \"list\",\n \"--repo\",\n \"active\",\n \"--json\"\n ],\n [\n \"panes\",\n \"create\",\n \"--repo\",\n \"active\",\n \"--name\",\n \"issue-252\",\n \"--agent\",\n \"codex\",\n \"--prompt\",\n \"Kick off discussion\",\n \"--dry-run\",\n \"--yes\",\n \"--json\"\n ],\n [\n \"panes\",\n \"create\",\n \"--from-json\",\n \"-\",\n \"--yes\",\n \"--json\"\n ],\n [\n \"panels\",\n \"list\",\n \"--pane\",\n \"session-1\",\n \"--json\"\n ],\n [\n \"panels\",\n \"output\",\n \"--panel\",\n \"panel-1\",\n \"--limit\",\n \"200\",\n \"--json\"\n ],\n [\n \"panels\",\n \"input\",\n \"--panel\",\n \"panel-1\",\n \"--text\",\n \"Continue\\\\n\",\n \"--yes\",\n \"--json\"\n ],\n [\n \"--version\"\n ],\n [\n \"agents\",\n \"doctor\",\n \"--agent\",\n \"codex\",\n \"--repo\",\n \"active\",\n \"--json\"\n ],\n [\n \"panes\",\n \"create\",\n \"--from-json\",\n \"-\",\n \"--wait-ready\",\n \"--ready-timeout-ms\",\n \"45000\",\n \"--concurrency\",\n \"2\",\n \"--yes\",\n \"--json\"\n ],\n [\n \"panels\",\n \"screen\",\n \"--panel\",\n \"panel-1\",\n \"--limit\",\n \"80\",\n \"--json\"\n ],\n [\n \"panels\",\n \"submit\",\n \"--panel\",\n \"panel-1\",\n \"--text\",\n \"2\",\n \"--yes\",\n \"--json\"\n ],\n [\n \"panels\",\n \"wait\",\n \"--panel\",\n \"panel-1\",\n \"--for\",\n \"text\",\n \"--contains\",\n \"ready\",\n \"--timeout-ms\",\n \"30000\",\n \"--interval-ms\",\n \"500\",\n \"--json\"\n ]\n ],\n \"topLevelHelpIncludes\": [\n \"runpane setup\",\n \"runpane install\",\n \"runpane update\",\n \"runpane version\",\n \"runpane doctor\",\n \"runpane agent-context\",\n \"runpane repos list\",\n \"runpane repos add\",\n \"runpane panes list\",\n \"runpane panes create\",\n \"runpane panels list\",\n \"runpane panels output\",\n \"runpane panels input\",\n \"runpane agents doctor\",\n \"runpane panels screen\",\n \"runpane panels submit\",\n \"runpane panels wait\"\n ],\n \"npmHelpIncludes\": [\n \"pnpm dlx runpane@latest\",\n \"npx --yes runpane@latest\"\n ],\n \"pipHelpIncludes\": [\n \"pipx run runpane\",\n \"python -m pip install runpane && python -m runpane setup\"\n ],\n \"installHelpIncludes\": [\n \"--version <latest|vX.Y.Z>\",\n \"--format <auto|appimage|deb|dmg|zip|exe>\",\n \"--download-dir <path>\",\n \"--pane-path <path>\",\n \"--label <name>\",\n \"--prefer-tunnel <tailscale|ssh|manual|auto>\",\n \"--repo-ref <ref>\"\n ]\n },\n \"jsonSchemas\": {\n \"error\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"error\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": false\n },\n \"error\": {\n \"type\": \"object\",\n \"required\": [\n \"message\"\n ],\n \"properties\": {\n \"message\": {\n \"type\": \"string\"\n },\n \"code\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n },\n \"repoListResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"repos\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"repos\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"id\",\n \"name\",\n \"path\",\n \"active\",\n \"sessionCount\"\n ],\n \"properties\": {\n \"id\": {\n \"type\": \"number\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"active\": {\n \"type\": \"boolean\"\n },\n \"environment\": {\n \"type\": \"string\"\n },\n \"sessionCount\": {\n \"type\": \"number\"\n }\n },\n \"additionalProperties\": false\n }\n }\n },\n \"additionalProperties\": false\n },\n \"repoAddRequest\": {\n \"type\": \"object\",\n \"required\": [\n \"path\"\n ],\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"dryRun\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n },\n \"repoAddResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"created\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"created\": {\n \"type\": \"boolean\"\n },\n \"dryRun\": {\n \"type\": \"boolean\"\n },\n \"repo\": {\n \"$ref\": \"#/jsonSchemas/repoListResult/properties/repos/items\"\n },\n \"preview\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"path\",\n \"alreadyExists\",\n \"wouldCreate\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"alreadyExists\": {\n \"type\": \"boolean\"\n },\n \"wouldCreate\": {\n \"type\": \"boolean\"\n },\n \"environment\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n },\n \"paneCreateRequest\": {\n \"type\": \"object\",\n \"required\": [\n \"repo\",\n \"panes\"\n ],\n \"properties\": {\n \"repo\": {\n \"oneOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"number\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"active\": {\n \"const\": true\n }\n },\n \"additionalProperties\": false\n }\n ]\n },\n \"panes\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"tool\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"worktreeName\": {\n \"type\": \"string\"\n },\n \"baseBranch\": {\n \"type\": \"string\"\n },\n \"sessionPrompt\": {\n \"type\": \"string\"\n },\n \"tool\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"required\": [\n \"agent\"\n ],\n \"properties\": {\n \"agent\": {\n \"enum\": [\n \"codex\",\n \"claude\"\n ]\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"initialInput\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"required\": [\n \"command\"\n ],\n \"properties\": {\n \"command\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"initialInput\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n ]\n }\n },\n \"additionalProperties\": false\n }\n },\n \"dryRun\": {\n \"type\": \"boolean\"\n },\n \"timeoutMs\": {\n \"type\": \"number\"\n },\n \"waitReady\": {\n \"type\": \"boolean\"\n },\n \"readyTimeoutMs\": {\n \"type\": \"number\"\n },\n \"concurrency\": {\n \"type\": \"number\"\n }\n },\n \"additionalProperties\": false\n },\n \"paneCreateResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"repo\",\n \"items\"\n ],\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\"\n },\n \"repo\": {\n \"$ref\": \"#/jsonSchemas/repoListResult/properties/repos/items\"\n },\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"index\",\n \"name\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"index\": {\n \"type\": \"number\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"sessionId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"worktreePath\": {\n \"type\": \"string\"\n },\n \"nextCommand\": {\n \"type\": \"string\"\n },\n \"tool\": {\n \"type\": \"object\",\n \"required\": [\n \"title\",\n \"command\"\n ],\n \"properties\": {\n \"title\": {\n \"type\": \"string\"\n },\n \"command\": {\n \"type\": \"string\"\n },\n \"agent\": {\n \"enum\": [\n \"codex\",\n \"claude\"\n ]\n }\n },\n \"additionalProperties\": false\n },\n \"readiness\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"condition\",\n \"matched\",\n \"timedOut\",\n \"elapsedMs\",\n \"state\"\n ],\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\"\n },\n \"condition\": {\n \"enum\": [\n \"initialized\",\n \"ready\",\n \"idle\",\n \"text\"\n ]\n },\n \"matched\": {\n \"type\": \"boolean\"\n },\n \"timedOut\": {\n \"type\": \"boolean\"\n },\n \"elapsedMs\": {\n \"type\": \"number\"\n },\n \"state\": {\n \"type\": \"object\",\n \"required\": [\n \"initialized\"\n ],\n \"properties\": {\n \"initialized\": {\n \"type\": \"boolean\"\n },\n \"isAlternateScreen\": {\n \"type\": \"boolean\"\n },\n \"activityStatus\": {\n \"enum\": [\n \"active\",\n \"idle\"\n ]\n },\n \"isCliReady\": {\n \"type\": \"boolean\"\n },\n \"isCliPanel\": {\n \"type\": \"boolean\"\n },\n \"agentType\": {\n \"enum\": [\n \"codex\",\n \"claude\"\n ]\n },\n \"lastActivity\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"blocked\": {\n \"type\": \"object\",\n \"required\": [\n \"kind\",\n \"message\"\n ],\n \"properties\": {\n \"kind\": {\n \"enum\": [\n \"codex-update\",\n \"agent-prompt\",\n \"unknown\"\n ]\n },\n \"message\": {\n \"type\": \"string\"\n },\n \"suggestedCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"nextCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"index\",\n \"error\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": false\n },\n \"index\": {\n \"type\": \"number\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"error\": {\n \"type\": \"object\",\n \"required\": [\n \"message\"\n ],\n \"properties\": {\n \"message\": {\n \"type\": \"string\"\n },\n \"code\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n }\n ]\n }\n }\n },\n \"additionalProperties\": false\n },\n \"paneListResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panes\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"repo\": {\n \"$ref\": \"#/jsonSchemas/repoListResult/properties/repos/items\"\n },\n \"panes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"id\",\n \"paneId\",\n \"name\",\n \"status\",\n \"worktreePath\",\n \"repoId\",\n \"panelCount\"\n ],\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"type\": \"string\"\n },\n \"worktreePath\": {\n \"type\": \"string\"\n },\n \"repoId\": {\n \"type\": \"number\"\n },\n \"repoName\": {\n \"type\": \"string\"\n },\n \"panelCount\": {\n \"type\": \"number\"\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"lastActivity\": {\n \"type\": \"string\"\n },\n \"archived\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n }\n }\n },\n \"additionalProperties\": false\n },\n \"panelListResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"paneId\",\n \"panels\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"panels\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"id\",\n \"panelId\",\n \"paneId\",\n \"type\",\n \"title\",\n \"active\"\n ],\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"active\": {\n \"type\": \"boolean\"\n },\n \"initialized\": {\n \"type\": \"boolean\"\n },\n \"agentType\": {\n \"type\": \"string\"\n },\n \"isCliPanel\": {\n \"type\": \"boolean\"\n },\n \"position\": {\n \"type\": \"number\"\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"lastActiveAt\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n }\n },\n \"additionalProperties\": false\n },\n \"panelOutputResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panelId\",\n \"limit\",\n \"returnedCount\",\n \"hasMore\",\n \"outputs\",\n \"text\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"limit\": {\n \"type\": \"number\"\n },\n \"returnedCount\": {\n \"type\": \"number\"\n },\n \"hasMore\": {\n \"type\": \"boolean\"\n },\n \"outputs\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n \"data\",\n \"timestamp\"\n ],\n \"properties\": {\n \"type\": {\n \"type\": \"string\"\n },\n \"data\": {},\n \"timestamp\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"text\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"panelInputRequest\": {\n \"type\": \"object\",\n \"required\": [\n \"panelId\",\n \"input\"\n ],\n \"properties\": {\n \"panelId\": {\n \"type\": \"string\"\n },\n \"input\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"panelInputResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panelId\",\n \"inputBytes\",\n \"sentAt\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"inputBytes\": {\n \"type\": \"number\"\n },\n \"sentAt\": {\n \"type\": \"string\"\n },\n \"nextCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"agentContextBriefResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"mode\",\n \"source\",\n \"summary\",\n \"rules\",\n \"tools\",\n \"detailCommand\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"mode\": {\n \"const\": \"brief\"\n },\n \"source\": {\n \"const\": \"runpane-contract\"\n },\n \"summary\": {\n \"type\": \"string\"\n },\n \"rules\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"tools\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"summary\",\n \"arguments\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"summary\": {\n \"type\": \"string\"\n },\n \"arguments\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"additionalProperties\": false\n }\n },\n \"detailCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"agentContextCommandResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"mode\",\n \"source\",\n \"command\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"mode\": {\n \"const\": \"command\"\n },\n \"source\": {\n \"const\": \"runpane-contract\"\n },\n \"command\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"summary\",\n \"details\",\n \"arguments\",\n \"examples\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"summary\": {\n \"type\": \"string\"\n },\n \"details\": {\n \"type\": \"string\"\n },\n \"requiresPaneDaemon\": {\n \"type\": \"boolean\"\n },\n \"mutates\": {\n \"type\": \"boolean\"\n },\n \"arguments\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\"\n }\n },\n \"examples\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"jsonSchemas\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"notes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n },\n \"panelScreenResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panelId\",\n \"source\",\n \"limit\",\n \"returnedLineCount\",\n \"hasMore\",\n \"text\",\n \"state\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"source\": {\n \"enum\": [\n \"alternateScreen\",\n \"scrollback\",\n \"persistedOutput\",\n \"empty\"\n ]\n },\n \"limit\": {\n \"type\": \"number\"\n },\n \"returnedLineCount\": {\n \"type\": \"number\"\n },\n \"hasMore\": {\n \"type\": \"boolean\"\n },\n \"text\": {\n \"type\": \"string\"\n },\n \"state\": {\n \"type\": \"object\",\n \"required\": [\n \"initialized\"\n ],\n \"properties\": {\n \"initialized\": {\n \"type\": \"boolean\"\n },\n \"isAlternateScreen\": {\n \"type\": \"boolean\"\n },\n \"activityStatus\": {\n \"enum\": [\n \"active\",\n \"idle\"\n ]\n },\n \"isCliReady\": {\n \"type\": \"boolean\"\n },\n \"isCliPanel\": {\n \"type\": \"boolean\"\n },\n \"agentType\": {\n \"enum\": [\n \"codex\",\n \"claude\"\n ]\n },\n \"lastActivity\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"nextCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"panelSubmitRequest\": {\n \"type\": \"object\",\n \"required\": [\n \"panelId\",\n \"input\"\n ],\n \"properties\": {\n \"panelId\": {\n \"type\": \"string\"\n },\n \"input\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"panelSubmitResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panelId\",\n \"inputBytes\",\n \"enter\",\n \"sentAt\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"inputBytes\": {\n \"type\": \"number\"\n },\n \"enter\": {\n \"const\": \"cr\"\n },\n \"sentAt\": {\n \"type\": \"string\"\n },\n \"nextCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"panelWaitResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panelId\",\n \"condition\",\n \"matched\",\n \"timedOut\",\n \"elapsedMs\",\n \"state\",\n \"screen\"\n ],\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\"\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"condition\": {\n \"enum\": [\n \"initialized\",\n \"ready\",\n \"idle\",\n \"text\"\n ]\n },\n \"matched\": {\n \"type\": \"boolean\"\n },\n \"timedOut\": {\n \"type\": \"boolean\"\n },\n \"elapsedMs\": {\n \"type\": \"number\"\n },\n \"state\": {\n \"type\": \"object\",\n \"required\": [\n \"initialized\"\n ],\n \"properties\": {\n \"initialized\": {\n \"type\": \"boolean\"\n },\n \"isAlternateScreen\": {\n \"type\": \"boolean\"\n },\n \"activityStatus\": {\n \"enum\": [\n \"active\",\n \"idle\"\n ]\n },\n \"isCliReady\": {\n \"type\": \"boolean\"\n },\n \"isCliPanel\": {\n \"type\": \"boolean\"\n },\n \"agentType\": {\n \"enum\": [\n \"codex\",\n \"claude\"\n ]\n },\n \"lastActivity\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"blocked\": {\n \"type\": \"object\",\n \"required\": [\n \"kind\",\n \"message\"\n ],\n \"properties\": {\n \"kind\": {\n \"enum\": [\n \"codex-update\",\n \"agent-prompt\",\n \"unknown\"\n ]\n },\n \"message\": {\n \"type\": \"string\"\n },\n \"suggestedCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"screen\": {\n \"type\": \"object\",\n \"required\": [\n \"source\",\n \"text\",\n \"hasMore\"\n ],\n \"properties\": {\n \"source\": {\n \"enum\": [\n \"alternateScreen\",\n \"scrollback\",\n \"persistedOutput\",\n \"empty\"\n ]\n },\n \"text\": {\n \"type\": \"string\"\n },\n \"hasMore\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n },\n \"nextCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"agentDoctorResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"agent\",\n \"command\",\n \"available\",\n \"checks\"\n ],\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\"\n },\n \"agent\": {\n \"enum\": [\n \"codex\",\n \"claude\"\n ]\n },\n \"command\": {\n \"type\": \"string\"\n },\n \"repo\": {\n \"$ref\": \"#/jsonSchemas/repoListResult/properties/repos/items\"\n },\n \"environment\": {\n \"enum\": [\n \"wsl\",\n \"windows\",\n \"linux\",\n \"macos\"\n ]\n },\n \"available\": {\n \"type\": \"boolean\"\n },\n \"executablePath\": {\n \"type\": \"string\"\n },\n \"version\": {\n \"type\": \"string\"\n },\n \"checks\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"ok\",\n \"message\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"ok\": {\n \"type\": \"boolean\"\n },\n \"message\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"warnings\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"additionalProperties\": false\n }\n },\n \"agentContext\": {\n \"brief\": {\n \"title\": \"Pane agent context\",\n \"summary\": \"Pane lets a developer manage repositories and user-visible terminal panes. Agents can use runpane to create panes, inspect compact terminal state, wait for readiness, and submit interactive input.\",\n \"rules\": [\n \"Start with `runpane repos list --json` to find the saved repository when unsure.\",\n \"If WSL cannot reach Pane or `runpane` resolves to a broken Windows shim, the user may be running Windows Pane; try `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane repos list --json'`.\",\n \"If the repository exists on disk but is not saved in Pane, use `runpane repos add --path <repo> --yes --json` before creating panes.\",\n \"Use `runpane agents doctor --agent <codex|claude> --repo <selector> --json` when agent availability differs across host, Windows, WSL, or repo environments.\",\n \"Use `runpane panes create --wait-ready` to create panes and validate initial terminal readiness in one call.\",\n \"Use `runpane panels screen` for compact current state, `panels wait` for readiness/text checks, and `panels submit` for ordinary Enter-submitted input.\",\n \"Use `runpane panels input` only when exact bytes are required, such as Ctrl-C or handcrafted terminal input.\",\n \"After creating panes or sending terminal input, validate with `panels wait` or bounded `panels screen` before reporting success.\",\n \"Use `runpane agent-context --command <command>` for detailed command definitions only when needed.\"\n ],\n \"detailCommand\": \"runpane agent-context --command <command> [--json]\",\n \"tools\": [\n {\n \"name\": \"agent-context\",\n \"summary\": \"Print token-efficient Pane command context for coding agents.\",\n \"arguments\": [\n \"--command <command>\",\n \"--json\"\n ]\n },\n {\n \"name\": \"agents doctor\",\n \"summary\": \"Check whether Codex or Claude is available in the repo environment Pane will use.\",\n \"arguments\": [\n \"--agent <codex|claude>\",\n \"--repo <selector>\",\n \"--json\"\n ]\n },\n {\n \"name\": \"repos list\",\n \"summary\": \"List repositories saved in the running Pane app.\",\n \"arguments\": [\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"repos add\",\n \"summary\": \"Register an existing git repository with the running Pane app.\",\n \"arguments\": [\n \"--path <path>\",\n \"--name <name>\",\n \"--yes\",\n \"--json\",\n \"--dry-run\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panes list\",\n \"summary\": \"List Pane sessions, optionally scoped to a saved repository.\",\n \"arguments\": [\n \"--repo <selector>\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panes create\",\n \"summary\": \"Create one or more Pane sessions in a saved repository and open a terminal-backed tool tab.\",\n \"arguments\": [\n \"--repo <selector>\",\n \"--name <name>\",\n \"--agent <codex|claude>\",\n \"--tool-command <command>\",\n \"--prompt <text>\",\n \"--initial-input-file <path|->\",\n \"--from-json <path|->\",\n \"--wait-ready\",\n \"--ready-timeout-ms <ms>\",\n \"--concurrency <count>\",\n \"--yes\",\n \"--json\"\n ]\n },\n {\n \"name\": \"panels list\",\n \"summary\": \"List tool panels inside a Pane session.\",\n \"arguments\": [\n \"--pane <pane-id>\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panels output\",\n \"summary\": \"Read recent terminal output from a panel.\",\n \"arguments\": [\n \"--panel <panel-id>\",\n \"--limit <count>\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panels screen\",\n \"summary\": \"Read a compact current-screen view from a terminal panel.\",\n \"arguments\": [\n \"--panel <panel-id>\",\n \"--limit <count>\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panels input\",\n \"summary\": \"Send input bytes to a terminal panel.\",\n \"arguments\": [\n \"--panel <panel-id>\",\n \"--text <text>\",\n \"--input-file <path|->\",\n \"--yes\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panels submit\",\n \"summary\": \"Send text plus terminal Enter to a terminal panel.\",\n \"arguments\": [\n \"--panel <panel-id>\",\n \"--text <text>\",\n \"--input-file <path|->\",\n \"--yes\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panels wait\",\n \"summary\": \"Wait for terminal initialized, ready, idle, or text state with compact output.\",\n \"arguments\": [\n \"--panel <panel-id>\",\n \"--for <condition>\",\n \"--contains <text>\",\n \"--timeout-ms <ms>\",\n \"--interval-ms <ms>\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n }\n ]\n },\n \"commands\": {\n \"help\": {\n \"name\": \"help\",\n \"summary\": \"Show help for runpane or a specific command.\",\n \"details\": \"Use this when you need human-readable usage text for a command.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"command\",\n \"value\": \"<command>\",\n \"required\": false,\n \"description\": \"Optional command topic such as \\\"panes create\\\".\"\n }\n ],\n \"examples\": [\n \"runpane help\",\n \"runpane help panes create\"\n ],\n \"notes\": [\n \"Help text is generated from the runpane contract.\"\n ]\n },\n \"setup\": {\n \"name\": \"setup\",\n \"summary\": \"Open the guided setup wizard for install, remote host setup, update, and diagnostics.\",\n \"details\": \"Use this for a human-driven Pane setup flow, not for unattended agent orchestration.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [],\n \"examples\": [\n \"runpane setup\"\n ],\n \"notes\": [\n \"In non-interactive shells, setup prints help and exits successfully.\"\n ]\n },\n \"install\": {\n \"name\": \"install\",\n \"summary\": \"Install Pane on this machine or configure this machine as a remote daemon host.\",\n \"details\": \"Installs or launches Pane release artifacts at command runtime. `install daemon` forwards remote setup flags to Pane.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"target\",\n \"value\": \"<client|daemon>\",\n \"required\": false,\n \"description\": \"Install the desktop client or configure a remote daemon host.\"\n },\n {\n \"name\": \"--version\",\n \"value\": \"<latest|vX.Y.Z>\",\n \"required\": false,\n \"description\": \"Pane release to install.\"\n },\n {\n \"name\": \"--format\",\n \"value\": \"<auto|appimage|deb|dmg|zip|exe>\",\n \"required\": false,\n \"description\": \"Release artifact format.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip interactive prompts where possible.\"\n }\n ],\n \"examples\": [\n \"runpane install client\",\n \"runpane install daemon --label \\\"My Server\\\"\"\n ],\n \"notes\": [\n \"Package install itself is inert; work begins only when runpane is executed.\"\n ]\n },\n \"update\": {\n \"name\": \"update\",\n \"summary\": \"Update the Pane desktop app using the same artifact path as install client.\",\n \"details\": \"Resolves and installs the selected Pane client release.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--version\",\n \"value\": \"<latest|vX.Y.Z>\",\n \"required\": false,\n \"description\": \"Pane release to update to.\"\n },\n {\n \"name\": \"--format\",\n \"value\": \"<auto|appimage|deb|dmg|zip|exe>\",\n \"required\": false,\n \"description\": \"Release artifact format.\"\n },\n {\n \"name\": \"--dry-run\",\n \"required\": false,\n \"description\": \"Print the update plan without downloading.\"\n }\n ],\n \"examples\": [\n \"runpane update\",\n \"runpane update --version latest\"\n ],\n \"notes\": [\n \"Equivalent artifact selection to `runpane install client`.\"\n ]\n },\n \"version\": {\n \"name\": \"version\",\n \"summary\": \"Print the runpane wrapper version and installed Pane version when detectable.\",\n \"details\": \"Use this for diagnostics or to confirm which wrapper is available.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--pane-path\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Inspect a specific Pane executable.\"\n }\n ],\n \"examples\": [\n \"runpane version\",\n \"runpane --version\"\n ],\n \"notes\": []\n },\n \"doctor\": {\n \"name\": \"doctor\",\n \"summary\": \"Run platform, release, installed Pane, and remote setup diagnostics.\",\n \"details\": \"Use this when runpane install/update behavior needs environment diagnostics.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--pane-path\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Use an existing Pane executable for diagnostics.\"\n },\n {\n \"name\": \"--verbose\",\n \"required\": false,\n \"description\": \"Print extra diagnostics.\"\n }\n ],\n \"examples\": [\n \"runpane doctor\",\n \"runpane doctor --verbose\"\n ],\n \"notes\": []\n },\n \"agent-context\": {\n \"name\": \"agent-context\",\n \"summary\": \"Print token-efficient Pane command context for coding agents.\",\n \"details\": \"Use this first when an agent needs to discover Pane primitives. It is local/offline and does not require a running Pane app.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--command\",\n \"value\": \"<command>\",\n \"required\": false,\n \"description\": \"Print the detailed definition for one command, for example \\\"panes create\\\".\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n }\n ],\n \"examples\": [\n \"runpane agent-context\",\n \"runpane agent-context --command \\\"panes create\\\" --json\"\n ],\n \"jsonSchemas\": [\n \"agentContextBriefResult\",\n \"agentContextCommandResult\"\n ],\n \"notes\": [\n \"Default output is brief so AGENTS.md can point here without bloating context.\"\n ]\n },\n \"repos list\": {\n \"name\": \"repos list\",\n \"summary\": \"List repositories saved in the running Pane app.\",\n \"details\": \"Use this to find the right Pane-managed repository before creating panes. If the repo is missing, use `repos add` first.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable repository records.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane repos list --json\"\n ],\n \"jsonSchemas\": [\n \"repoListResult\"\n ],\n \"notes\": [\n \"Requires a running Pane app or daemon for the selected Pane data directory.\",\n \"If this fails from WSL with a missing `/tmp/pane-daemon.../daemon.sock`, `volta: command not found`, or a Windows shim error, the user may be running Windows Pane. Retry via `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane repos list --json'`.\",\n \"When using PowerShell from WSL, set a Windows cwd such as `$env:TEMP` or `$env:USERPROFILE` before running runpane to avoid UNC cwd issues.\"\n ]\n },\n \"repos add\": {\n \"name\": \"repos add\",\n \"summary\": \"Register an existing git repository with the running Pane app.\",\n \"details\": \"Use this when the repository exists on disk but is not saved in Pane yet. It validates the path as a git repository.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--path\",\n \"value\": \"<path>\",\n \"required\": true,\n \"description\": \"Existing git repository path to register with Pane.\"\n },\n {\n \"name\": \"--name\",\n \"value\": \"<name>\",\n \"required\": false,\n \"description\": \"Saved repository name; defaults to the directory name.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip confirmation for mutating commands.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--dry-run\",\n \"required\": false,\n \"description\": \"Validate and preview without adding the repo.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane repos add --path /path/to/repo --yes --json\"\n ],\n \"jsonSchemas\": [\n \"repoAddRequest\",\n \"repoAddResult\"\n ],\n \"notes\": [\n \"It does not create directories or initialize git repositories by default.\",\n \"For a Windows Pane app managing WSL repositories, prefer a saved WSL repo from `repos list` when possible. Adding a brand-new WSL repo from Windows may require WSL-aware path handling.\"\n ]\n },\n \"panes list\": {\n \"name\": \"panes list\",\n \"summary\": \"List Pane sessions, optionally scoped to a saved repository.\",\n \"details\": \"Use this after selecting a repository to find existing Pane sessions and their ids before inspecting panels.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--repo\",\n \"value\": \"<selector>\",\n \"required\": false,\n \"description\": \"Optional repository selector: active, id, exact path, or saved repository name.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panes list --repo active --json\"\n ],\n \"jsonSchemas\": [\n \"paneListResult\"\n ],\n \"notes\": [\n \"Without --repo, this lists sessions across saved Pane repositories.\"\n ]\n },\n \"panes create\": {\n \"name\": \"panes create\",\n \"summary\": \"Create one or more Pane sessions in a saved repository and open a terminal-backed tool tab.\",\n \"details\": \"Use this to set up user-visible panes for work. Select a saved repository, choose a built-in agent or custom terminal command, and optionally send initial input after the tool starts. For multi-step shell setup, pass a shell command through --tool-command rather than adding a new runpane primitive.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--repo\",\n \"value\": \"<selector>\",\n \"required\": true,\n \"description\": \"Repository selector: active, id, exact path, or saved repository name.\"\n },\n {\n \"name\": \"--name\",\n \"value\": \"<name>\",\n \"required\": true,\n \"description\": \"Pane/session name.\"\n },\n {\n \"name\": \"--agent\",\n \"value\": \"<codex|claude>\",\n \"required\": false,\n \"description\": \"Built-in agent terminal template to open.\"\n },\n {\n \"name\": \"--tool-command\",\n \"value\": \"<command>\",\n \"required\": false,\n \"description\": \"Custom terminal command to run instead of a built-in agent.\"\n },\n {\n \"name\": \"--prompt\",\n \"value\": \"<text>\",\n \"required\": false,\n \"description\": \"Alias for --initial-input; sends text after the command is ready.\"\n },\n {\n \"name\": \"--initial-input-file\",\n \"value\": \"<path|->\",\n \"required\": false,\n \"description\": \"Read initial input from a file or stdin.\"\n },\n {\n \"name\": \"--from-json\",\n \"value\": \"<path|->\",\n \"required\": false,\n \"description\": \"Read a full panes.create request JSON payload.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip confirmation for mutating commands.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--wait-ready\",\n \"required\": false,\n \"description\": \"Wait for each created terminal panel to be ready before returning.\"\n },\n {\n \"name\": \"--ready-timeout-ms\",\n \"value\": \"<ms>\",\n \"required\": false,\n \"description\": \"Readiness timeout per pane; defaults to 30000.\"\n },\n {\n \"name\": \"--concurrency\",\n \"value\": \"<count>\",\n \"required\": false,\n \"description\": \"Accepted for compatibility. Pane currently serializes multi-pane session creation so queued jobs do not time out before starting.\"\n }\n ],\n \"examples\": [\n \"runpane panes create --repo active --name issue-257 --agent codex --prompt \\\"Plan this issue\\\" --yes\",\n \"runpane panes create --from-json panes.json --yes --json\",\n \"runpane panes create --repo active --name issue-123 --agent codex --prompt \\\"Plan this issue\\\" --wait-ready --yes --json\"\n ],\n \"jsonSchemas\": [\n \"paneCreateRequest\",\n \"paneCreateResult\"\n ],\n \"notes\": [\n \"At least one of --agent or --tool-command is required unless --from-json is used.\",\n \"The built-in agent templates come from the runpane contract; custom terminal commands can pass agent-specific flags when requested by the user.\",\n \"Use --initial-input-file for multi-line prompts or shell-sensitive initial input.\",\n \"When the JSON result includes nextCommand, run it to validate that the terminal produced output before reporting success.\",\n \"Multi-pane requests are created sequentially today. The --concurrency flag is accepted for compatibility, but agents should not rely on parallel creation.\",\n \"For POSIX or WSL command chaining, use a custom terminal command like `bash -lc 'cmd1 && cmd2 && cmd3'`.\",\n \"For Windows PowerShell command chaining, use a custom terminal command like `powershell -NoProfile -Command \\\"cmd1; if ($LASTEXITCODE) { exit $LASTEXITCODE }; cmd2\\\"`.\",\n \"From WSL with Windows Pane, invoke through PowerShell and select the saved WSL repo by name or id, for example `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane panes create --repo \\\"WSL Pane\\\" --name issue-123 --agent codex --prompt \\\"Plan this issue\\\" --yes --json'`.\",\n \"Use --wait-ready when an agent needs to verify that an agent terminal started instead of only creating a pane.\",\n \"If readiness returns blocked, inspect blocked.suggestedCommand rather than guessing which prompt to answer.\"\n ]\n },\n \"panels list\": {\n \"name\": \"panels list\",\n \"summary\": \"List tool panels inside a Pane session.\",\n \"details\": \"Use this to find the terminal panel id to inspect or control after creating or selecting a Pane session.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--pane\",\n \"value\": \"<pane-id>\",\n \"required\": true,\n \"description\": \"Pane/session id.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panels list --pane <pane-id> --json\"\n ],\n \"jsonSchemas\": [\n \"panelListResult\"\n ],\n \"notes\": [\n \"The ids returned here are stable inputs for `panels output` and `panels input`.\"\n ]\n },\n \"panels output\": {\n \"name\": \"panels output\",\n \"summary\": \"Read recent terminal output from a panel.\",\n \"details\": \"Use this to inspect recent terminal output from a terminal-backed panel without loading the full history by default. Live terminal scrollback is returned as bounded recent lines; persisted output fallback is returned as bounded records. Terminal control noise is stripped before returning text.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"required\": true,\n \"description\": \"Tool panel id.\"\n },\n {\n \"name\": \"--limit\",\n \"value\": \"<count>\",\n \"required\": false,\n \"description\": \"Maximum recent output lines or records to read. Defaults to 200.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panels output --panel <panel-id> --limit 200 --json\"\n ],\n \"jsonSchemas\": [\n \"panelOutputResult\"\n ],\n \"notes\": [\n \"Default output is bounded to the latest 200 lines or records. Use a larger --limit only when hasMore is true and more history is needed.\",\n \"Use --json when an agent needs timestamps, record types, returnedCount, or hasMore.\",\n \"The output is intended to be agent-readable, but terminal prompts and shell echoes may still appear; use the newest relevant lines before concluding success.\",\n \"Prefer `panels screen` for a smaller current-state read before increasing output limits.\"\n ]\n },\n \"panels input\": {\n \"name\": \"panels input\",\n \"summary\": \"Send input bytes to a terminal panel.\",\n \"details\": \"Use this to answer prompts or continue an agent inside an existing Pane terminal panel. Input is byte-oriented; choose --input-file for exact control over newlines and control characters.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"required\": true,\n \"description\": \"Terminal panel id.\"\n },\n {\n \"name\": \"--text\",\n \"value\": \"<text>\",\n \"required\": false,\n \"description\": \"Text bytes to send.\"\n },\n {\n \"name\": \"--input-file\",\n \"value\": \"<path|->\",\n \"required\": false,\n \"description\": \"Read input from a file or stdin.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip confirmation for this mutating command.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"printf 'Continue\\\\n' | runpane panels input --panel <panel-id> --input-file - --yes\",\n \"printf '\\\\003' | runpane panels input --panel <panel-id> --input-file - --yes\",\n \"runpane panels input --panel <panel-id> --text \\\"simple text\\\" --yes --json\"\n ],\n \"jsonSchemas\": [\n \"panelInputRequest\",\n \"panelInputResult\"\n ],\n \"notes\": [\n \"Input is sent exactly as provided. Include a real newline byte when the terminal should receive Enter; across shells, `--input-file` is safer than `--text \\\"...\\\\n\\\"`.\",\n \"Use `--input-file -` or a temp file for multi-line input, quotes, Ctrl-C, or shell-sensitive text.\",\n \"If interrupting a running process, send Ctrl-C first, validate/read output, then send the next command in a separate `panels input` call so bytes are not dropped.\",\n \"After sending input, validate with `runpane panels output --panel <panel-id> --json` before reporting success.\",\n \"Runpane records action metadata and errors for observability, but should not log full input text by default.\",\n \"For ordinary text plus Enter, prefer `panels submit` so the terminal receives a CR Enter byte.\"\n ]\n },\n \"agents doctor\": {\n \"name\": \"agents doctor\",\n \"summary\": \"Diagnose whether a built-in agent command is available in a Pane repository environment.\",\n \"details\": \"Use this before creating Codex or Claude panes when PATH may differ between macOS/Linux/Windows/WSL or between the wrapper shell and Pane. The check runs through Pane project context, not the wrapper process.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--agent\",\n \"value\": \"<codex|claude>\",\n \"required\": true,\n \"description\": \"Built-in agent command to diagnose.\"\n },\n {\n \"name\": \"--repo\",\n \"value\": \"<selector>\",\n \"required\": false,\n \"description\": \"Repository selector; defaults to the active Pane repo.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane agents doctor --agent codex --repo active --json\"\n ],\n \"jsonSchemas\": [\n \"agentDoctorResult\"\n ],\n \"notes\": [\n \"For WSL repos, install the agent inside the WSL distro Pane uses, not only on Windows.\",\n \"This diagnoses built-in Codex/Claude templates only; custom commands should be validated by creating a pane and reading its screen.\"\n ]\n },\n \"panels screen\": {\n \"name\": \"panels screen\",\n \"summary\": \"Read a compact current-screen view from a terminal panel.\",\n \"details\": \"Use this for token-safe current terminal state. It prefers active alternate-screen/TUI output, then live scrollback, then persisted output. Default output is bounded to 80 lines.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"required\": true,\n \"description\": \"Terminal panel id.\"\n },\n {\n \"name\": \"--limit\",\n \"value\": \"<count>\",\n \"required\": false,\n \"description\": \"Maximum lines to return; defaults to 80.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panels screen --panel <panel-id> --limit 80 --json\"\n ],\n \"jsonSchemas\": [\n \"panelScreenResult\"\n ],\n \"notes\": [\n \"Use this before `panels output` when an agent only needs the latest visible/current state.\",\n \"If hasMore is true and context is missing, rerun with a larger --limit or use `panels output`.\"\n ]\n },\n \"panels submit\": {\n \"name\": \"panels submit\",\n \"summary\": \"Send text to a terminal panel and append a terminal Enter byte.\",\n \"details\": \"Use this for ordinary interactive submissions. The daemon normalizes a final LF or CRLF to CR, or appends CR if no newline is present. Exact byte workflows remain on `panels input`.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"required\": true,\n \"description\": \"Terminal panel id.\"\n },\n {\n \"name\": \"--text\",\n \"value\": \"<text>\",\n \"required\": false,\n \"description\": \"Text to submit before Enter.\"\n },\n {\n \"name\": \"--input-file\",\n \"value\": \"<path|->\",\n \"required\": false,\n \"description\": \"Read text from a file or stdin before Enter.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip confirmation for this mutating command.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panels submit --panel <panel-id> --text \\\"2\\\" --yes --json\",\n \"printf \\\"echo hello\\\" | runpane panels submit --panel <panel-id> --input-file - --yes --json\"\n ],\n \"jsonSchemas\": [\n \"panelSubmitRequest\",\n \"panelSubmitResult\"\n ],\n \"notes\": [\n \"The response includes nextCommand for validation. Run it before reporting that the input worked.\",\n \"Use `panels input` for Ctrl-C, escape sequences, or any workflow requiring exact bytes.\"\n ]\n },\n \"panels wait\": {\n \"name\": \"panels wait\",\n \"summary\": \"Wait for a terminal panel to initialize, become ready/idle, or contain text.\",\n \"details\": \"Use this to validate asynchronous terminal behavior without pulling large scrollback. It returns brief readiness state, blocker hints, a compact screen, and a next command.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"required\": true,\n \"description\": \"Terminal panel id.\"\n },\n {\n \"name\": \"--for\",\n \"value\": \"<initialized|ready|idle|text>\",\n \"required\": false,\n \"description\": \"Condition to wait for. Defaults to ready for CLI panels and idle otherwise.\"\n },\n {\n \"name\": \"--contains\",\n \"value\": \"<text>\",\n \"required\": false,\n \"description\": \"Text required for --for text; implies --for text when --for is omitted.\"\n },\n {\n \"name\": \"--timeout-ms\",\n \"value\": \"<ms>\",\n \"required\": false,\n \"description\": \"Wait timeout; defaults to 30000.\"\n },\n {\n \"name\": \"--interval-ms\",\n \"value\": \"<ms>\",\n \"required\": false,\n \"description\": \"Polling interval; defaults to 500.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panels wait --panel <panel-id> --for ready --timeout-ms 30000 --json\",\n \"runpane panels wait --panel <panel-id> --contains \\\"Ready\\\" --json\"\n ],\n \"jsonSchemas\": [\n \"panelWaitResult\"\n ],\n \"notes\": [\n \"If blocked is present, do not assume success. Use blocked.suggestedCommand or inspect `panels screen`.\",\n \"The default timeout and screen are intentionally small for agent context safety.\"\n ]\n }\n },\n \"managedBlock\": [\n \"## Pane\",\n \"\",\n \"The developer is using Pane for this repository. Pane can manage saved repositories and create user-visible panes with terminal-backed tools for planning, discussion, implementation, and review work.\",\n \"\",\n \"Use `runpane agent-context` for a brief Pane command schema. Use `runpane agent-context --command \\\"panels wait\\\"` or another command name for detailed schema only when needed.\",\n \"\",\n \"Default to context-safe validation: after creating panes or sending terminal input, run `runpane panels wait` or `runpane panels screen` before reporting success. Prefer `runpane panels submit` for normal text plus Enter; use `runpane panels input` only for exact bytes such as Ctrl-C or escape sequences.\",\n \"\",\n \"Common commands:\",\n \"- `runpane repos list --json`\",\n \"- `runpane repos add --path <repo> --yes --json`\",\n \"- `runpane agents doctor --agent codex --repo active --json`\",\n \"- `runpane panes create --repo active --name <name> --agent codex --prompt \\\"<task>\\\" --wait-ready --yes --json`\",\n \"- `runpane panels list --pane <pane-id> --json`\",\n \"- `runpane panels screen --panel <panel-id> --limit 80 --json`\",\n \"- `runpane panels wait --panel <panel-id> --for ready --timeout-ms 30000 --json`\",\n \"- `runpane panels submit --panel <panel-id> --text \\\"<answer>\\\" --yes --json`\",\n \"- `runpane panels input --panel <panel-id> --input-file <path|-> --yes --json`\",\n \"\",\n \"WSL note: if `runpane repos list` cannot find `/tmp/pane-daemon.../daemon.sock` or `runpane` resolves to a broken Windows shim, Pane may be running on Windows. Try `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane repos list --json'`, then create panes through the same PowerShell form using the saved WSL repo name or id. Use `runpane agents doctor --agent codex --repo <selector> --json` to diagnose the repo environment Pane will actually use.\"\n ]\n }\n}")
|
|
@@ -61,7 +61,7 @@ def run_panes_create(parsed: Any) -> int:
|
|
|
61
61
|
"runpane:panes:create",
|
|
62
62
|
[request],
|
|
63
63
|
pane_dir=parsed.pane_dir,
|
|
64
|
-
timeout_ms=(parsed.timeout_ms or 120_000) + 10_000,
|
|
64
|
+
timeout_ms=(parsed.timeout_ms or 120_000) + (parsed.ready_timeout_ms or 30_000) + 10_000,
|
|
65
65
|
)
|
|
66
66
|
|
|
67
67
|
if parsed.json:
|
|
@@ -123,6 +123,77 @@ def run_panels_input(parsed: Any) -> int:
|
|
|
123
123
|
return 0
|
|
124
124
|
|
|
125
125
|
|
|
126
|
+
def run_panels_screen(parsed: Any) -> int:
|
|
127
|
+
if not parsed.panel_id:
|
|
128
|
+
raise ValueError("runpane panels screen requires --panel.")
|
|
129
|
+
|
|
130
|
+
result = invoke_daemon("runpane:panels:screen", [{
|
|
131
|
+
"panelId": parsed.panel_id,
|
|
132
|
+
"limit": parsed.limit,
|
|
133
|
+
}], pane_dir=parsed.pane_dir)
|
|
134
|
+
|
|
135
|
+
if parsed.json:
|
|
136
|
+
print_json(result)
|
|
137
|
+
return 0
|
|
138
|
+
|
|
139
|
+
text = result.get("text") or ""
|
|
140
|
+
sys.stdout.write(text)
|
|
141
|
+
if text and not text.endswith("\n"):
|
|
142
|
+
sys.stdout.write("\n")
|
|
143
|
+
return 0
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def run_panels_submit(parsed: Any) -> int:
|
|
147
|
+
request = build_panel_input_request(parsed, "submit")
|
|
148
|
+
confirm_panel_input(parsed, request, "submit")
|
|
149
|
+
result = invoke_daemon("runpane:panels:submit", [request], pane_dir=parsed.pane_dir)
|
|
150
|
+
|
|
151
|
+
if parsed.json:
|
|
152
|
+
print_json(result)
|
|
153
|
+
else:
|
|
154
|
+
input_bytes = result.get("inputBytes", 0)
|
|
155
|
+
suffix = "" if input_bytes == 1 else "s"
|
|
156
|
+
print(f"Submitted {input_bytes} byte{suffix} with Enter to panel {result.get('panelId')}.")
|
|
157
|
+
if result.get("nextCommand"):
|
|
158
|
+
print(f"Next: {result.get('nextCommand')}")
|
|
159
|
+
return 0
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def run_panels_wait(parsed: Any) -> int:
|
|
163
|
+
if not parsed.panel_id:
|
|
164
|
+
raise ValueError("runpane panels wait requires --panel.")
|
|
165
|
+
|
|
166
|
+
result = invoke_daemon("runpane:panels:wait", [{
|
|
167
|
+
"panelId": parsed.panel_id,
|
|
168
|
+
"condition": parsed.wait_condition,
|
|
169
|
+
"contains": parsed.contains,
|
|
170
|
+
"timeoutMs": parsed.timeout_ms,
|
|
171
|
+
"intervalMs": parsed.interval_ms,
|
|
172
|
+
}], pane_dir=parsed.pane_dir, timeout_ms=(parsed.timeout_ms or 30_000) + 5_000)
|
|
173
|
+
|
|
174
|
+
if parsed.json:
|
|
175
|
+
print_json(result)
|
|
176
|
+
else:
|
|
177
|
+
print_panel_wait_result(result)
|
|
178
|
+
return 0 if result.get("ok") else 1
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def run_agents_doctor(parsed: Any) -> int:
|
|
182
|
+
if not parsed.agent:
|
|
183
|
+
raise ValueError("runpane agents doctor requires --agent codex|claude.")
|
|
184
|
+
|
|
185
|
+
result = invoke_daemon("runpane:agents:doctor", [{
|
|
186
|
+
"agent": parsed.agent,
|
|
187
|
+
"repo": parsed.repo,
|
|
188
|
+
}], pane_dir=parsed.pane_dir)
|
|
189
|
+
|
|
190
|
+
if parsed.json:
|
|
191
|
+
print_json(result)
|
|
192
|
+
else:
|
|
193
|
+
print_agent_doctor_result(result)
|
|
194
|
+
return 0 if result.get("ok") else 1
|
|
195
|
+
|
|
196
|
+
|
|
126
197
|
def build_repo_add_request(parsed: Any) -> Dict[str, Any]:
|
|
127
198
|
if not parsed.repo_path:
|
|
128
199
|
raise ValueError("runpane repos add requires --path.")
|
|
@@ -134,13 +205,13 @@ def build_repo_add_request(parsed: Any) -> Dict[str, Any]:
|
|
|
134
205
|
}
|
|
135
206
|
|
|
136
207
|
|
|
137
|
-
def build_panel_input_request(parsed: Any) -> Dict[str, Any]:
|
|
208
|
+
def build_panel_input_request(parsed: Any, command: str = "input") -> Dict[str, Any]:
|
|
138
209
|
if not parsed.panel_id:
|
|
139
|
-
raise ValueError("runpane panels
|
|
210
|
+
raise ValueError(f"runpane panels {command} requires --panel.")
|
|
140
211
|
if parsed.panel_input is not None and parsed.panel_input_file:
|
|
141
212
|
raise ValueError("Use either --text or --input-file, not both.")
|
|
142
213
|
if parsed.panel_input is None and not parsed.panel_input_file:
|
|
143
|
-
raise ValueError("runpane panels
|
|
214
|
+
raise ValueError(f"runpane panels {command} requires --text or --input-file.")
|
|
144
215
|
|
|
145
216
|
return {
|
|
146
217
|
"panelId": parsed.panel_id,
|
|
@@ -157,6 +228,12 @@ def build_pane_create_request(parsed: Any) -> Dict[str, Any]:
|
|
|
157
228
|
payload["dryRun"] = True
|
|
158
229
|
if parsed.timeout_ms is not None:
|
|
159
230
|
payload["timeoutMs"] = parsed.timeout_ms
|
|
231
|
+
if parsed.wait_ready:
|
|
232
|
+
payload["waitReady"] = True
|
|
233
|
+
if parsed.ready_timeout_ms is not None:
|
|
234
|
+
payload["readyTimeoutMs"] = parsed.ready_timeout_ms
|
|
235
|
+
if parsed.concurrency is not None:
|
|
236
|
+
payload["concurrency"] = parsed.concurrency
|
|
160
237
|
return payload
|
|
161
238
|
|
|
162
239
|
if not parsed.repo:
|
|
@@ -174,6 +251,9 @@ def build_pane_create_request(parsed: Any) -> Dict[str, Any]:
|
|
|
174
251
|
}],
|
|
175
252
|
**optional_value("dryRun", True if parsed.dry_run else None),
|
|
176
253
|
**optional_value("timeoutMs", parsed.timeout_ms),
|
|
254
|
+
**optional_value("waitReady", True if parsed.wait_ready else None),
|
|
255
|
+
**optional_value("readyTimeoutMs", parsed.ready_timeout_ms),
|
|
256
|
+
**optional_value("concurrency", parsed.concurrency),
|
|
177
257
|
}
|
|
178
258
|
|
|
179
259
|
|
|
@@ -238,15 +318,17 @@ def confirm_pane_create(parsed: Any, request: Dict[str, Any]) -> None:
|
|
|
238
318
|
raise ValueError("Cancelled.")
|
|
239
319
|
|
|
240
320
|
|
|
241
|
-
def confirm_panel_input(parsed: Any, request: Dict[str, Any]) -> None:
|
|
321
|
+
def confirm_panel_input(parsed: Any, request: Dict[str, Any], command: str = "input") -> None:
|
|
242
322
|
if parsed.yes:
|
|
243
323
|
return
|
|
244
324
|
if not is_interactive_shell():
|
|
245
|
-
raise ValueError("runpane panels
|
|
325
|
+
raise ValueError(f"runpane panels {command} mutates a Pane terminal. Rerun with --yes in non-interactive shells.")
|
|
246
326
|
|
|
247
327
|
input_bytes = len(request.get("input", "").encode("utf-8"))
|
|
248
328
|
suffix = "" if input_bytes == 1 else "s"
|
|
249
|
-
|
|
329
|
+
verb = "Submit" if command == "submit" else "Send"
|
|
330
|
+
enter_suffix = " plus Enter" if command == "submit" else ""
|
|
331
|
+
answer = input(f"{verb} {input_bytes} byte{suffix}{enter_suffix} to panel {request.get('panelId')}? [y/N] ").strip().lower()
|
|
250
332
|
if answer not in {"y", "yes"}:
|
|
251
333
|
raise ValueError("Cancelled.")
|
|
252
334
|
|
|
@@ -314,11 +396,61 @@ def print_pane_create_result(result: Dict[str, Any]) -> None:
|
|
|
314
396
|
if item.get("ok"):
|
|
315
397
|
worktree = f" at {item.get('worktreePath')}" if item.get("worktreePath") else ""
|
|
316
398
|
print(f"Created {name}: session {item.get('sessionId', 'unknown')} panel {item.get('panelId', 'unknown')}{worktree}")
|
|
399
|
+
readiness = item.get("readiness")
|
|
400
|
+
if readiness:
|
|
401
|
+
ready_state = "yes" if readiness.get("ok") else "timed out" if readiness.get("timedOut") else "blocked"
|
|
402
|
+
print(f" Ready: {ready_state} after {readiness.get('elapsedMs')}ms")
|
|
403
|
+
blocked = readiness.get("blocked")
|
|
404
|
+
if blocked:
|
|
405
|
+
print(f" Blocked: {blocked.get('message')}")
|
|
406
|
+
if item.get("nextCommand"):
|
|
407
|
+
print(f" Next: {item.get('nextCommand')}")
|
|
317
408
|
else:
|
|
318
409
|
error = item.get("error") or {}
|
|
319
410
|
print(f"Failed {name}: {error.get('message', 'unknown error')}", file=sys.stderr)
|
|
320
411
|
|
|
321
412
|
|
|
413
|
+
def print_panel_wait_result(result: Dict[str, Any]) -> None:
|
|
414
|
+
condition = result.get("condition")
|
|
415
|
+
panel_id = result.get("panelId")
|
|
416
|
+
elapsed = result.get("elapsedMs")
|
|
417
|
+
if result.get("ok"):
|
|
418
|
+
print(f"Matched {condition} for panel {panel_id} after {elapsed}ms.")
|
|
419
|
+
elif result.get("blocked"):
|
|
420
|
+
print(f"Blocked waiting for {condition} on panel {panel_id}: {result['blocked'].get('message')}")
|
|
421
|
+
elif result.get("timedOut"):
|
|
422
|
+
print(f"Timed out waiting for {condition} on panel {panel_id} after {elapsed}ms.")
|
|
423
|
+
else:
|
|
424
|
+
print(f"Did not match {condition} for panel {panel_id}.")
|
|
425
|
+
|
|
426
|
+
state = result.get("state") or {}
|
|
427
|
+
status_parts = [
|
|
428
|
+
"initialized" if state.get("initialized") else "not-initialized",
|
|
429
|
+
state.get("activityStatus"),
|
|
430
|
+
None if state.get("isCliReady") is None else "cli-ready" if state.get("isCliReady") else "cli-not-ready",
|
|
431
|
+
state.get("agentType"),
|
|
432
|
+
]
|
|
433
|
+
status = ", ".join(part for part in status_parts if part)
|
|
434
|
+
if status:
|
|
435
|
+
print(f"State: {status}")
|
|
436
|
+
if result.get("nextCommand"):
|
|
437
|
+
print(f"Next: {result.get('nextCommand')}")
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def print_agent_doctor_result(result: Dict[str, Any]) -> None:
|
|
441
|
+
repo = f" in {result['repo'].get('name')}" if result.get("repo") else ""
|
|
442
|
+
environment = f" ({result.get('environment')})" if result.get("environment") else ""
|
|
443
|
+
print(f"{result.get('agent')}: {'available' if result.get('available') else 'not available'}{repo}{environment}")
|
|
444
|
+
if result.get("executablePath"):
|
|
445
|
+
print(f"Path: {result.get('executablePath')}")
|
|
446
|
+
if result.get("version"):
|
|
447
|
+
print(f"Version: {result.get('version')}")
|
|
448
|
+
for check in result.get("checks", []):
|
|
449
|
+
print(f"{'OK' if check.get('ok') else 'FAIL'} {check.get('name')}: {check.get('message')}")
|
|
450
|
+
for warning in result.get("warnings") or []:
|
|
451
|
+
print(f"Warning: {warning}")
|
|
452
|
+
|
|
453
|
+
|
|
322
454
|
def print_panel_list_result(result: Dict[str, Any]) -> None:
|
|
323
455
|
panels = result.get("panels", [])
|
|
324
456
|
pane_id = result.get("paneId")
|
|
@@ -39,6 +39,8 @@ def create_initial_telemetry_context(argv: Optional[List[str]] = None) -> Wrappe
|
|
|
39
39
|
return {"command": "version"}
|
|
40
40
|
if first == "agent-context":
|
|
41
41
|
return {"command": "agent-context"}
|
|
42
|
+
if first == "agents":
|
|
43
|
+
return {"command": "agents doctor" if len(args) > 1 and args[1] == "doctor" else "unknown"}
|
|
42
44
|
if first == "repos":
|
|
43
45
|
return {"command": "repos add" if len(args) > 1 and args[1] == "add" else "repos list"}
|
|
44
46
|
if first == "panes":
|
|
@@ -48,6 +50,12 @@ def create_initial_telemetry_context(argv: Optional[List[str]] = None) -> Wrappe
|
|
|
48
50
|
return {"command": "panels output"}
|
|
49
51
|
if len(args) > 1 and args[1] == "input":
|
|
50
52
|
return {"command": "panels input"}
|
|
53
|
+
if len(args) > 1 and args[1] == "screen":
|
|
54
|
+
return {"command": "panels screen"}
|
|
55
|
+
if len(args) > 1 and args[1] == "submit":
|
|
56
|
+
return {"command": "panels submit"}
|
|
57
|
+
if len(args) > 1 and args[1] == "wait":
|
|
58
|
+
return {"command": "panels wait"}
|
|
51
59
|
return {"command": "panels list"}
|
|
52
60
|
return {"command": "unknown"}
|
|
53
61
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.3.7"
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
# Generated by scripts/generate-runpane-contract.js. Do not edit by hand.
|
|
2
|
-
import json
|
|
3
|
-
|
|
4
|
-
RUNPANE_CONTRACT = json.loads("{\n \"$schema\": \"./schema.json\",\n \"schemaVersion\": 1,\n \"name\": \"runpane\",\n \"description\": \"Thin installer and local control CLI for Pane\",\n \"packageInstallPolicy\": [\n \"The packages must not download, install, or configure Pane during package installation.\",\n \"Work starts only when a user runs `runpane ...`.\"\n ],\n \"compatibility\": {\n \"node\": \">=18.17.0\",\n \"python\": \">=3.8\"\n },\n \"terminology\": {\n \"repo\": \"Saved Pane repository/project record\",\n \"pane\": \"User-visible Pane session\",\n \"tool\": \"Terminal-backed tab\",\n \"agent\": \"Built-in agent command template\"\n },\n \"defaults\": {\n \"target\": \"client\",\n \"paneVersion\": \"latest\",\n \"channel\": \"stable\",\n \"format\": \"auto\",\n \"dryRun\": false,\n \"yes\": false,\n \"verbose\": false\n },\n \"enums\": {\n \"installTargets\": [\n \"client\",\n \"daemon\"\n ],\n \"artifactFormats\": [\n \"auto\",\n \"appimage\",\n \"deb\",\n \"dmg\",\n \"zip\",\n \"exe\"\n ],\n \"channels\": [\n \"stable\",\n \"nightly\"\n ],\n \"agents\": [\n \"codex\",\n \"claude\"\n ]\n },\n \"agentTemplates\": {\n \"codex\": {\n \"title\": \"Codex\",\n \"command\": \"codex --yolo\",\n \"description\": \"Open a Codex terminal tab and allow the initial input to drive the agent.\"\n },\n \"claude\": {\n \"title\": \"Claude Code\",\n \"command\": \"claude --dangerously-skip-permissions\",\n \"description\": \"Open a Claude Code terminal tab and allow the initial input to drive the agent.\"\n }\n },\n \"commands\": [\n {\n \"name\": \"help\",\n \"summary\": \"Show help for runpane or a specific command.\",\n \"usage\": [\n \"runpane help [command]\"\n ]\n },\n {\n \"name\": \"setup\",\n \"summary\": \"Open the guided setup wizard for install, remote host setup, update, and diagnostics.\",\n \"usage\": [\n \"runpane setup\"\n ],\n \"interactiveEntrypoint\": true\n },\n {\n \"name\": \"install\",\n \"summary\": \"Install Pane on this machine or configure this machine as a remote daemon host.\",\n \"usage\": [\n \"runpane install [client|daemon] [options]\"\n ],\n \"defaultTarget\": \"client\",\n \"targets\": [\n \"client\",\n \"daemon\"\n ],\n \"unknownDaemonFlagsForwarded\": true\n },\n {\n \"name\": \"update\",\n \"summary\": \"Update the Pane desktop app using the same artifact path as install client.\",\n \"usage\": [\n \"runpane update [options]\"\n ],\n \"target\": \"client\"\n },\n {\n \"name\": \"version\",\n \"summary\": \"Print the runpane wrapper version and installed Pane version when detectable.\",\n \"usage\": [\n \"runpane version\",\n \"runpane --version\"\n ]\n },\n {\n \"name\": \"doctor\",\n \"summary\": \"Run platform, release, installed Pane, and remote setup diagnostics.\",\n \"usage\": [\n \"runpane doctor\"\n ]\n },\n {\n \"name\": \"agent-context\",\n \"summary\": \"Print token-efficient Pane command context for coding agents.\",\n \"usage\": [\n \"runpane agent-context [--json]\",\n \"runpane agent-context --command <command> [--json]\"\n ],\n \"jsonSchemas\": [\n \"agentContextBriefResult\",\n \"agentContextCommandResult\"\n ]\n },\n {\n \"name\": \"repos list\",\n \"summary\": \"List repositories saved in the running Pane app.\",\n \"usage\": [\n \"runpane repos list [--json] [--pane-dir <path>]\"\n ],\n \"jsonSchemas\": [\n \"repoListResult\"\n ]\n },\n {\n \"name\": \"repos add\",\n \"summary\": \"Register an existing git repository with the running Pane app.\",\n \"usage\": [\n \"runpane repos add --path <path> [--name <name>] [--json] [--yes]\"\n ],\n \"mutates\": true,\n \"jsonSchemas\": [\n \"repoAddRequest\",\n \"repoAddResult\"\n ]\n },\n {\n \"name\": \"panes list\",\n \"summary\": \"List Pane sessions in a saved repository.\",\n \"usage\": [\n \"runpane panes list [--repo <selector>] [--json]\"\n ],\n \"jsonSchemas\": [\n \"paneListResult\"\n ]\n },\n {\n \"name\": \"panes create\",\n \"summary\": \"Create one or more Pane sessions in a saved repository and open a terminal-backed tool tab.\",\n \"usage\": [\n \"runpane panes create --repo <selector> --name <name> --agent <codex|claude> [options]\",\n \"runpane panes create --from-json <path|-> [--yes] [--json]\"\n ],\n \"mutates\": true,\n \"jsonSchemas\": [\n \"paneCreateRequest\",\n \"paneCreateResult\"\n ]\n },\n {\n \"name\": \"panels list\",\n \"summary\": \"List tool panels inside a Pane session.\",\n \"usage\": [\n \"runpane panels list --pane <pane-id> [--json]\"\n ],\n \"jsonSchemas\": [\n \"panelListResult\"\n ]\n },\n {\n \"name\": \"panels output\",\n \"summary\": \"Read recent terminal output from a panel.\",\n \"usage\": [\n \"runpane panels output --panel <panel-id> [--limit <count>] [--json]\"\n ],\n \"jsonSchemas\": [\n \"panelOutputResult\"\n ]\n },\n {\n \"name\": \"panels input\",\n \"summary\": \"Send input bytes to a terminal panel.\",\n \"usage\": [\n \"runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\"\n ],\n \"mutates\": true,\n \"jsonSchemas\": [\n \"panelInputRequest\",\n \"panelInputResult\"\n ]\n }\n ],\n \"flags\": {\n \"wrapper\": [\n {\n \"name\": \"--version\",\n \"value\": \"<latest|vX.Y.Z>\",\n \"description\": \"Pane release to install or inspect.\"\n },\n {\n \"name\": \"--download-dir\",\n \"value\": \"<path>\",\n \"description\": \"Directory for downloaded Pane release artifacts.\"\n },\n {\n \"name\": \"--pane-path\",\n \"value\": \"<path>\",\n \"description\": \"Use or inspect an existing Pane executable.\"\n },\n {\n \"name\": \"--format\",\n \"value\": \"<auto|appimage|deb|dmg|zip|exe>\",\n \"description\": \"Pane release artifact format.\"\n },\n {\n \"name\": \"--dry-run\",\n \"description\": \"Print the plan without downloading or installing.\"\n },\n {\n \"name\": \"--yes\",\n \"aliases\": [\n \"-y\"\n ],\n \"description\": \"Skip interactive prompts where possible.\"\n },\n {\n \"name\": \"--verbose\",\n \"description\": \"Print extra diagnostics.\"\n }\n ],\n \"remoteValue\": [\n {\n \"name\": \"--label\",\n \"value\": \"<name>\"\n },\n {\n \"name\": \"--prefer-tunnel\",\n \"value\": \"<tailscale|ssh|manual|auto>\"\n },\n {\n \"name\": \"--channel\",\n \"value\": \"<stable|nightly>\"\n },\n {\n \"name\": \"--base-url\",\n \"value\": \"<url>\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\"\n },\n {\n \"name\": \"--listen-port\",\n \"value\": \"<port>\"\n },\n {\n \"name\": \"--port\",\n \"value\": \"<port>\"\n },\n {\n \"name\": \"--repo-ref\",\n \"value\": \"<ref>\"\n }\n ],\n \"remoteBoolean\": [\n {\n \"name\": \"--auto-listen-port\"\n },\n {\n \"name\": \"--interactive-tailscale-setup\"\n },\n {\n \"name\": \"--no-install-service\"\n },\n {\n \"name\": \"--no-tailscale-serve\"\n },\n {\n \"name\": \"--print-only\"\n }\n ],\n \"localValue\": [\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"description\": \"Connect to a Pane daemon using this Pane data directory.\"\n },\n {\n \"name\": \"--repo\",\n \"value\": \"<selector>\",\n \"description\": \"Repository selector: active, id, exact path, or saved repository name.\"\n },\n {\n \"name\": \"--pane\",\n \"value\": \"<pane-id>\",\n \"description\": \"Pane/session id to inspect.\"\n },\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"description\": \"Tool panel id to inspect or control.\"\n },\n {\n \"name\": \"--path\",\n \"value\": \"<path>\",\n \"description\": \"Existing git repository path to register with Pane.\"\n },\n {\n \"name\": \"--name\",\n \"value\": \"<name>\",\n \"description\": \"Name for the registered repository or created pane/session.\"\n },\n {\n \"name\": \"--worktree-name\",\n \"value\": \"<name>\",\n \"description\": \"Worktree name to request. Defaults to --name.\"\n },\n {\n \"name\": \"--base-branch\",\n \"value\": \"<branch>\",\n \"description\": \"Base branch for the created worktree.\"\n },\n {\n \"name\": \"--agent\",\n \"value\": \"<codex|claude>\",\n \"description\": \"Built-in agent terminal template to open.\"\n },\n {\n \"name\": \"--tool-command\",\n \"value\": \"<command>\",\n \"description\": \"Custom terminal command to run instead of a built-in agent.\"\n },\n {\n \"name\": \"--title\",\n \"value\": \"<title>\",\n \"description\": \"Terminal tab title. Defaults to the selected agent title or Terminal.\"\n },\n {\n \"name\": \"--initial-input\",\n \"value\": \"<text>\",\n \"aliases\": [\n \"--prompt\"\n ],\n \"description\": \"Text to send to the terminal after the command is ready. --prompt is an alias.\"\n },\n {\n \"name\": \"--initial-input-file\",\n \"value\": \"<path|->\",\n \"description\": \"Read initial input from a file or stdin.\"\n },\n {\n \"name\": \"--from-json\",\n \"value\": \"<path|->\",\n \"description\": \"Read a full panes.create request JSON payload from a file or stdin.\"\n },\n {\n \"name\": \"--timeout-ms\",\n \"value\": \"<milliseconds>\",\n \"description\": \"Maximum time to wait for each pane creation job.\"\n },\n {\n \"name\": \"--limit\",\n \"value\": \"<count>\",\n \"description\": \"Maximum recent output lines or records to read.\"\n },\n {\n \"name\": \"--text\",\n \"value\": \"<text>\",\n \"description\": \"Text bytes to send to a terminal panel.\"\n },\n {\n \"name\": \"--input-file\",\n \"value\": \"<path|->\",\n \"description\": \"Read panel input from a file or stdin.\"\n }\n ],\n \"localBoolean\": [\n {\n \"name\": \"--json\",\n \"description\": \"Print machine-readable JSON output.\"\n }\n ]\n },\n \"help\": {\n \"npm\": {\n \"default\": [\n \"Usage:\",\n \" runpane\",\n \" runpane setup\",\n \" runpane install [client|daemon] [options]\",\n \" runpane update [options]\",\n \" runpane version\",\n \" runpane doctor\",\n \" runpane agent-context [--json]\",\n \" runpane repos list [--json]\",\n \" runpane repos add --path <path> [--name <name>]\",\n \" runpane panes list [--repo <selector>] [--json]\",\n \" runpane panes create --repo <selector> --name <name> --agent <codex|claude>\",\n \" runpane panels list --pane <pane-id> [--json]\",\n \" runpane panels output --panel <panel-id> [--limit <count>] [--json]\",\n \" runpane panels input --panel <panel-id> --input-file <path|-> --yes\",\n \" runpane help [command]\",\n \"\",\n \"Quick start:\",\n \" npx --yes runpane@latest\",\n \" npm i -g runpane && runpane setup\",\n \"\",\n \"Advanced examples:\",\n \" npx --yes runpane@latest install client\",\n \" npx --yes runpane@latest install daemon --label \\\"My Server\\\"\",\n \" pnpm dlx runpane@latest\",\n \" pipx run runpane\",\n \"\",\n \"Run \\\"runpane agent-context\\\" when an agent needs Pane command context.\",\n \"Run \\\"runpane help panes create\\\" for pane orchestration options.\"\n ],\n \"install\": [\n \"Usage:\",\n \" runpane install [client|daemon] [options]\",\n \"\",\n \"Examples:\",\n \" npx --yes runpane@latest install client\",\n \" npx --yes runpane@latest install daemon --label \\\"My Server\\\"\",\n \" pnpm dlx runpane@latest install daemon --prefer-tunnel ssh --label \\\"VM\\\"\",\n \"\",\n \"Wrapper options:\",\n \" --version <latest|vX.Y.Z> Pane release to install\",\n \" --format <auto|appimage|deb|dmg|zip|exe>\",\n \" --download-dir <path>\",\n \" --pane-path <path> Use an existing Pane executable\",\n \" --dry-run Print the plan without downloading\",\n \" --yes Skip interactive prompts where possible\",\n \" --verbose\",\n \"\",\n \"Daemon passthrough options:\",\n \" --label <name>\",\n \" --prefer-tunnel <tailscale|ssh|manual|auto>\",\n \" --channel <stable|nightly>\",\n \" --base-url <url>\",\n \" --pane-dir <path>\",\n \" --listen-port <port> / --port <port>\",\n \" --auto-listen-port\",\n \" --interactive-tailscale-setup\",\n \" --no-install-service\",\n \" --no-tailscale-serve\",\n \" --print-only\",\n \" --repo-ref <ref>\"\n ],\n \"setup\": [\n \"Usage:\",\n \" runpane setup\",\n \"\",\n \"Opens the guided setup for desktop install, remote host setup, update, and diagnostics.\",\n \"\",\n \"Quick start:\",\n \" npx --yes runpane@latest\",\n \" npm i -g runpane && runpane setup\"\n ],\n \"update\": [\n \"Usage:\",\n \" runpane update [options]\",\n \"\",\n \"Updates Pane using the same artifact selection as \\\"runpane install client\\\".\",\n \"\",\n \"Options:\",\n \" --version <latest|vX.Y.Z>\",\n \" --format <auto|appimage|deb|dmg|zip|exe>\",\n \" --download-dir <path>\",\n \" --pane-path <path>\",\n \" --dry-run\",\n \" --yes\",\n \" --verbose\"\n ],\n \"version\": [\n \"Usage:\",\n \" runpane version\",\n \" runpane --version\"\n ],\n \"doctor\": [\n \"Usage:\",\n \" runpane doctor [--pane-path <path>] [--format <format>] [--verbose]\"\n ],\n \"repos list\": [\n \"Usage:\",\n \" runpane repos list [--json] [--pane-dir <path>]\",\n \"\",\n \"Lists repositories saved in the running Pane app.\",\n \"\",\n \"Options:\",\n \" --json Print machine-readable output\",\n \" --pane-dir <path> Connect to a specific Pane data directory\"\n ],\n \"repos add\": [\n \"Usage:\",\n \" runpane repos add --path <path> [--name <name>] [--json] [--yes]\",\n \"\",\n \"Registers an existing git repository with the running Pane app.\",\n \"\",\n \"Options:\",\n \" --path <path> Existing git repository path\",\n \" --name <name> Saved repository name; defaults to the directory name\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --dry-run Validate and preview without adding the repo\",\n \" --yes Skip confirmation for mutating commands\"\n ],\n \"panes list\": [\n \"Usage:\",\n \" runpane panes list [--repo <selector>] [--json]\",\n \"\",\n \"Lists Pane sessions. Pass --repo to limit results to one saved repository.\",\n \"\",\n \"Options:\",\n \" --repo <selector> active, id, exact path, or saved repository name\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panes create\": [\n \"Usage:\",\n \" runpane panes create --repo <selector> --name <name> --agent <codex|claude> [options]\",\n \" runpane panes create --from-json <path|-> [--yes] [--json]\",\n \"\",\n \"Creates Pane sessions in a saved repository and opens a terminal-backed tool tab.\",\n \"\",\n \"Options:\",\n \" --repo <selector> active, id, exact path, or saved repository name\",\n \" --name <name> Pane/session name\",\n \" --worktree-name <name> Worktree name; defaults to --name\",\n \" --base-branch <branch> Base branch for the worktree\",\n \" --agent <codex|claude> Built-in terminal template\",\n \" --tool-command <command> Custom terminal command\",\n \" --title <title> Terminal tab title\",\n \" --initial-input <text> Text sent after the command is ready\",\n \" --prompt <text> Alias for --initial-input\",\n \" --initial-input-file <path|-> Read initial input from a file or stdin\",\n \" --from-json <path|-> Read a full request payload\",\n \" --timeout-ms <milliseconds> Pane creation timeout\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --dry-run Validate and preview without creating panes\",\n \" --yes Skip confirmation for mutating commands\"\n ],\n \"panels list\": [\n \"Usage:\",\n \" runpane panels list --pane <pane-id> [--json]\",\n \"\",\n \"Lists tool panels in a Pane session.\",\n \"\",\n \"Options:\",\n \" --pane <pane-id> Pane/session id\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panels output\": [\n \"Usage:\",\n \" runpane panels output --panel <panel-id> [--limit <count>] [--json]\",\n \"\",\n \"Reads bounded recent terminal output from a panel.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Tool panel id\",\n \" --limit <count> Maximum recent output lines or records to read\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\"\n ],\n \"panels input\": [\n \"Usage:\",\n \" runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\",\n \"\",\n \"Sends exact input bytes to a terminal panel. Include a newline in the input when you mean Enter.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id> Terminal panel id\",\n \" --text <text> Text bytes to send\",\n \" --input-file <path|-> Read input from a file or stdin\",\n \" --pane-dir <path> Connect to a specific Pane data directory\",\n \" --json Print machine-readable output\",\n \" --yes Skip confirmation for mutating commands\"\n ],\n \"agent-context\": [\n \"Usage:\",\n \" runpane agent-context [--json]\",\n \" runpane agent-context --command <command> [--json]\",\n \"\",\n \"Prints Pane command context for coding agents without requiring a running Pane app.\",\n \"\",\n \"Options:\",\n \" --command <command> Print the full definition for one runpane command\",\n \" --json Print machine-readable output\",\n \"\",\n \"Examples:\",\n \" runpane agent-context\",\n \" runpane agent-context --json\",\n \" runpane agent-context --command \\\"panes create\\\"\",\n \" runpane agent-context --command \\\"panes create\\\" --json\"\n ]\n },\n \"pip\": {\n \"default\": [\n \"Usage:\",\n \" runpane\",\n \" runpane setup\",\n \" runpane install [client|daemon] [options]\",\n \" runpane update [options]\",\n \" runpane version\",\n \" runpane doctor\",\n \" runpane agent-context [--json]\",\n \" runpane repos list [--json]\",\n \" runpane repos add --path <path> [--name <name>]\",\n \" runpane panes list [--repo <selector>] [--json]\",\n \" runpane panes create --repo <selector> --name <name> --agent <codex|claude>\",\n \" runpane panels list --pane <pane-id> [--json]\",\n \" runpane panels output --panel <panel-id> [--limit <count>] [--json]\",\n \" runpane panels input --panel <panel-id> --input-file <path|-> --yes\",\n \" runpane help [command]\",\n \"\",\n \"Quick start:\",\n \" pipx run runpane\",\n \" python -m pip install runpane && python -m runpane setup\",\n \"\",\n \"Advanced examples:\",\n \" pipx run runpane install client\",\n \" pipx run runpane install daemon --label \\\"My Server\\\"\",\n \" uvx runpane@latest\",\n \"\",\n \"Run \\\"runpane agent-context\\\" when an agent needs Pane command context.\",\n \"Run \\\"runpane help panes create\\\" for pane orchestration options.\"\n ],\n \"install\": [\n \"Usage:\",\n \" runpane install [client|daemon] [options]\",\n \"\",\n \"Examples:\",\n \" npx --yes runpane@latest install daemon --label \\\"My Server\\\"\",\n \" pnpm dlx runpane@latest install daemon --prefer-tunnel ssh --label \\\"VM\\\"\",\n \" pipx run runpane install daemon --label \\\"My Server\\\"\",\n \"\",\n \"Wrapper options:\",\n \" --version <latest|vX.Y.Z>\",\n \" --format <auto|appimage|deb|dmg|zip|exe>\",\n \" --download-dir <path>\",\n \" --pane-path <path>\",\n \" --dry-run\",\n \" --yes\",\n \" --verbose\",\n \"\",\n \"Daemon passthrough options:\",\n \" --label <name>\",\n \" --prefer-tunnel <tailscale|ssh|manual|auto>\",\n \" --channel <stable|nightly>\",\n \" --base-url <url>\",\n \" --pane-dir <path>\",\n \" --listen-port <port> / --port <port>\",\n \" --auto-listen-port\",\n \" --interactive-tailscale-setup\",\n \" --no-install-service\",\n \" --no-tailscale-serve\",\n \" --print-only\",\n \" --repo-ref <ref>\"\n ],\n \"setup\": [\n \"Usage:\",\n \" runpane setup\",\n \"\",\n \"Opens the guided setup for desktop install, remote host setup, update, and diagnostics.\",\n \"\",\n \"Quick start:\",\n \" pipx run runpane\",\n \" python -m pip install runpane && python -m runpane setup\"\n ],\n \"update\": [\n \"Usage:\",\n \" runpane update [--version <latest|vX.Y.Z>] [--dry-run] [--yes]\"\n ],\n \"version\": [\n \"Usage:\",\n \" runpane version\",\n \" runpane --version\"\n ],\n \"doctor\": [\n \"Usage:\",\n \" runpane doctor [--pane-path <path>] [--format <format>] [--verbose]\"\n ],\n \"repos list\": [\n \"Usage:\",\n \" runpane repos list [--json] [--pane-dir <path>]\",\n \"\",\n \"Lists repositories saved in the running Pane app.\",\n \"\",\n \"Options:\",\n \" --json\",\n \" --pane-dir <path>\"\n ],\n \"repos add\": [\n \"Usage:\",\n \" runpane repos add --path <path> [--name <name>] [--json] [--yes]\",\n \"\",\n \"Registers an existing git repository with the running Pane app.\",\n \"\",\n \"Options:\",\n \" --path <path>\",\n \" --name <name>\",\n \" --pane-dir <path>\",\n \" --json\",\n \" --dry-run\",\n \" --yes\"\n ],\n \"panes list\": [\n \"Usage:\",\n \" runpane panes list [--repo <selector>] [--json]\",\n \"\",\n \"Lists Pane sessions. Pass --repo to limit results to one saved repository.\",\n \"\",\n \"Options:\",\n \" --repo <selector>\",\n \" --pane-dir <path>\",\n \" --json\"\n ],\n \"panes create\": [\n \"Usage:\",\n \" runpane panes create --repo <selector> --name <name> --agent <codex|claude> [options]\",\n \" runpane panes create --from-json <path|-> [--yes] [--json]\",\n \"\",\n \"Creates Pane sessions in a saved repository and opens a terminal-backed tool tab.\",\n \"\",\n \"Options:\",\n \" --repo <selector>\",\n \" --name <name>\",\n \" --worktree-name <name>\",\n \" --base-branch <branch>\",\n \" --agent <codex|claude>\",\n \" --tool-command <command>\",\n \" --title <title>\",\n \" --initial-input <text>\",\n \" --prompt <text>\",\n \" --initial-input-file <path|->\",\n \" --from-json <path|->\",\n \" --timeout-ms <milliseconds>\",\n \" --pane-dir <path>\",\n \" --json\",\n \" --dry-run\",\n \" --yes\"\n ],\n \"panels list\": [\n \"Usage:\",\n \" runpane panels list --pane <pane-id> [--json]\",\n \"\",\n \"Lists tool panels in a Pane session.\",\n \"\",\n \"Options:\",\n \" --pane <pane-id>\",\n \" --pane-dir <path>\",\n \" --json\"\n ],\n \"panels output\": [\n \"Usage:\",\n \" runpane panels output --panel <panel-id> [--limit <count>] [--json]\",\n \"\",\n \"Reads recent terminal output records from a panel.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id>\",\n \" --limit <count>\",\n \" --pane-dir <path>\",\n \" --json\"\n ],\n \"panels input\": [\n \"Usage:\",\n \" runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]\",\n \"\",\n \"Sends exact input bytes to a terminal panel. Include a newline in the input when you mean Enter.\",\n \"\",\n \"Options:\",\n \" --panel <panel-id>\",\n \" --text <text>\",\n \" --input-file <path|->\",\n \" --pane-dir <path>\",\n \" --json\",\n \" --yes\"\n ],\n \"agent-context\": [\n \"Usage:\",\n \" runpane agent-context [--json]\",\n \" runpane agent-context --command <command> [--json]\",\n \"\",\n \"Prints Pane command context for coding agents without requiring a running Pane app.\",\n \"\",\n \"Options:\",\n \" --command <command>\",\n \" --json\",\n \"\",\n \"Examples:\",\n \" runpane agent-context\",\n \" runpane agent-context --json\",\n \" runpane agent-context --command \\\"panes create\\\"\",\n \" runpane agent-context --command \\\"panes create\\\" --json\"\n ]\n }\n },\n \"docs\": {\n \"maintainerRules\": [\n \"Treat `contracts/runpane/contract.json` as the source of truth for both wrapper packages and generated docs.\",\n \"Every command, flag, platform default, artifact-selection rule, and attribution rule change must be reflected in the contract.\",\n \"The npm and PyPI wrappers must expose the same command behavior unless the contract explicitly documents a package-manager-specific difference.\",\n \"Root `README.md` and package READMEs should lead with one guided quick-start command. Explicit commands, package-manager variants, and flags belong in an Advanced section.\",\n \"Release version bumps must keep root `package.json`, `packages/runpane`, and `packages/runpane-py` versions in sync. Run `pnpm run check:runpane-package-versions` before release.\",\n \"`pnpm run test:runpane-contract` must pass before changing wrapper command parsing, help output, platform defaults, release asset selection, or generated contract artifacts.\",\n \"Token-based npm or PyPI publishing is a temporary fallback. Prefer trusted publishing once the package names are reserved and trusted publishers are configured.\"\n ],\n \"recommendedQuickStarts\": [\n \"npx --yes runpane@latest\",\n \"npm i -g runpane && runpane setup\",\n \"pipx run runpane\",\n \"python -m pip install runpane && python -m runpane setup\"\n ],\n \"npmCommands\": [\n \"npx --yes runpane@latest\",\n \"npx --yes runpane@latest setup\",\n \"npx --yes runpane@latest install client\",\n \"npx --yes runpane@latest install daemon --label \\\"My Server\\\"\",\n \"pnpm dlx runpane@latest\",\n \"pnpm dlx runpane@latest install daemon --label \\\"My Server\\\"\",\n \"npm i -g runpane && runpane\",\n \"npm i -g runpane && runpane setup\",\n \"npm i -g runpane && runpane install daemon --label \\\"My Server\\\"\",\n \"pnpm add -g runpane && runpane\",\n \"pnpm add -g runpane && runpane setup\",\n \"pnpm add -g runpane && runpane install daemon --label \\\"My Server\\\"\",\n \"yarn dlx runpane@latest install daemon --label \\\"My Server\\\"\",\n \"bunx runpane@latest install daemon --label \\\"My Server\\\"\"\n ],\n \"pythonCommands\": [\n \"pipx run runpane\",\n \"pipx run runpane setup\",\n \"python -m pip install runpane\",\n \"runpane\",\n \"runpane setup\",\n \"python -m runpane setup\",\n \"runpane install daemon --label \\\"My Server\\\"\",\n \"pipx install runpane\",\n \"runpane\",\n \"runpane setup\",\n \"pipx run runpane install daemon --label \\\"My Server\\\"\",\n \"uvx runpane@latest\",\n \"uvx runpane@latest setup\",\n \"uvx runpane@latest install daemon --label \\\"My Server\\\"\",\n \"python -m runpane install daemon --label \\\"My Server\\\"\"\n ],\n \"packageManagerNotes\": [\n \"Use `pnpm dlx` for one-shot pnpm execution and `pnpm add -g` for persistent CLI installation.\",\n \"Do not document `pnpm install runpane` as the public CLI install path.\"\n ],\n \"commandUsages\": [\n \"runpane\",\n \"runpane setup\",\n \"runpane install\",\n \"runpane install client\",\n \"runpane install daemon\",\n \"runpane update\",\n \"runpane version\",\n \"runpane doctor\",\n \"runpane agent-context\",\n \"runpane agent-context --command \\\"panes create\\\" --json\",\n \"runpane repos list --json\",\n \"runpane repos add --path /path/to/repo --name Pane --yes --json\",\n \"runpane panes list --repo active --json\",\n \"runpane panes create --repo active --name issue-252 --agent codex --prompt \\\"Kick off the discussion skill for issue 252\\\" --yes\",\n \"runpane panes create --from-json panes.json --yes --json\",\n \"runpane panels list --pane <pane-id> --json\",\n \"runpane panels output --panel <panel-id> --limit 200 --json\",\n \"printf 'Continue\\\\n' | runpane panels input --panel <panel-id> --input-file - --yes --json\",\n \"runpane help\",\n \"runpane <command> --help\"\n ],\n \"commandDescriptions\": [\n \"`runpane` with no arguments and `runpane setup` open an interactive wizard when stdin and stdout are TTYs. In non-interactive shells or CI, both forms must print help and exit successfully instead of waiting for input.\",\n \"`runpane install` is an alias for `runpane install client`.\",\n \"`runpane install client` downloads the selected Pane desktop artifact and installs, opens, or launches it for the current platform.\",\n \"`runpane install daemon` downloads or installs Pane, resolves a stable Pane executable path, and spawns `<pane executable> --remote-setup <forwarded remote setup args>`.\",\n \"The wrapper must stream Pane stdout/stderr without reformatting because `pane --remote-setup` prints the one-time `pane-remote://...` connection code.\",\n \"`runpane update` uses the same release resolution and installer path as `install client`.\",\n \"`runpane version` prints the wrapper package version, the installed Pane version when detectable, and the latest GitHub release version when reachable.\",\n \"`runpane doctor` checks platform support, release metadata reachability, download URL selection, installed Pane detection, and remote-daemon hints.\",\n \"`runpane agent-context` prints a brief, token-efficient command schema for coding agents without connecting to the Pane daemon.\",\n \"`runpane agent-context --command \\\"panes create\\\"` prints the detailed definition for one command. Add `--json` for machine-readable output.\",\n \"`runpane repos list` connects to the running local Pane daemon and prints saved repository records.\",\n \"`runpane repos add` registers an existing git repository with the running local Pane daemon. It does not create directories or initialize git repositories by default.\",\n \"`runpane panes list` lists Pane sessions, optionally scoped to one saved repository.\",\n \"`runpane panes create` connects to the running local Pane daemon, resolves the requested repository, creates Pane sessions, opens terminal-backed tool tabs, and optionally sends initial input to the started tool.\",\n \"`runpane panels list` lists tool panels inside one Pane session.\",\n \"`runpane panels output` reads bounded recent terminal output from one panel and strips common terminal control noise for agent use.\",\n \"`runpane panels input` sends exact input bytes to one terminal panel. Prefer `--input-file` for newlines, Ctrl-C, quotes, or shell-sensitive text.\",\n \"`runpane panes create --prompt` is an alias for `--initial-input`; request JSON and daemon payloads should use the canonical `initialInput` field.\",\n \"When running from WSL while Pane is installed on Windows, the Linux wrapper may look for a missing `/tmp/pane-daemon.../daemon.sock` or resolve to a Windows shim such as Volta. In that case invoke the Windows wrapper through PowerShell from a Windows cwd, for example `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane repos list --json'`.\"\n ],\n \"wrapperFlagNote\": \"The top-level `runpane --version` form prints the wrapper version. The install subcommand form `runpane install --version vX.Y.Z` selects a Pane release.\",\n \"localControlFlagNote\": \"`runpane repos list`, `runpane panes list`, `runpane panes create`, and `runpane panels ...` commands use the local framed daemon socket/pipe for a running Pane app. `--pane-dir` points the wrapper at a non-default Pane data directory, such as `PANE_DIR=~/.pane_test` in development. `runpane agent-context` is local/offline and can be used before Pane is running. From WSL, if the user runs Windows Pane, call the Windows wrapper through `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane ...'` so the command can reach the Windows named-pipe daemon and avoid UNC cwd issues.\",\n \"daemonFlagNote\": \"Unknown daemon flags should be forwarded rather than dropped so newer Pane versions can extend `--remote-setup` without requiring an immediate wrapper release. Unknown flags for non-daemon commands should fail clearly.\",\n \"downloadAttribution\": [\n \"The npm package uses `source=npm` for all npm-registry consumers, including `npx`, `pnpm dlx`, `yarn dlx`, `bunx`, and global npm/pnpm installs.\",\n \"The PyPI package uses `source=pip` for all Python consumers, including pip, pipx, uvx, and `python -m runpane`.\",\n \"Wrappers should prefer `https://runpane.com/api/download?platform=<platform>&arch=<arch>&format=<format>&version=<version>&channel=<channel>&source=<npm|pip>`.\",\n \"If the website route cannot satisfy the download, wrappers may fall back to the matching GitHub release asset and print a warning that website attribution may be incomplete for that run.\",\n \"Wrappers also emit best-effort lifecycle telemetry to `https://runpane.com/api/runpane/telemetry` for command start/success/failure, download request/success/failure, and GitHub fallback usage.\",\n \"Wrapper telemetry uses a persisted anonymous `install_id` in the form `install_<uuid>` and PostHog `distinct_id = install:<install_id>` so distinct wrapper users can be counted with `count(DISTINCT properties.install_id)`.\",\n \"Wrapper telemetry must be disabled in CI and when `RUNPANE_TELEMETRY_DISABLED` is set, and must not include raw paths, labels, prompts, raw error text, or environment values.\"\n ],\n \"publishingCredentials\": [\n \"Local implementation, build, and dry-run validation do not need npm or PyPI API tokens.\",\n \"Release publishing should prefer npm Trusted Publishing and PyPI Trusted Publishing from GitHub Actions.\",\n \"Fallback `NPM_TOKEN` or `PYPI_API_TOKEN` credentials may be used for first package reservation or manual publication only. They must be supplied through local environment variables or GitHub Actions secrets, never committed, and revoked or rotated after use.\"\n ]\n },\n \"testFixtures\": {\n \"parserSamples\": [\n [\n \"setup\"\n ],\n [\n \"install\"\n ],\n [\n \"install\",\n \"client\",\n \"--version\",\n \"v2.2.8\",\n \"--format\",\n \"dmg\",\n \"--download-dir\",\n \"/tmp/pane-downloads\",\n \"--dry-run\",\n \"--yes\"\n ],\n [\n \"install\",\n \"daemon\",\n \"--label\",\n \"VM\",\n \"--prefer-tunnel\",\n \"ssh\",\n \"--channel\",\n \"nightly\",\n \"--base-url\",\n \"https://example.test\",\n \"--pane-dir\",\n \"/tmp/pane\",\n \"--listen-port\",\n \"4555\",\n \"--auto-listen-port\",\n \"--print-only\",\n \"--repo-ref\",\n \"main\",\n \"--unknown-future-flag\",\n \"future-value\",\n \"--dry-run\",\n \"--verbose\"\n ],\n [\n \"update\",\n \"--version\",\n \"latest\",\n \"--format\",\n \"appimage\",\n \"--pane-path\",\n \"/usr/bin/pane\",\n \"--dry-run\"\n ],\n [\n \"doctor\",\n \"--pane-path\",\n \"/usr/bin/pane\",\n \"--format\",\n \"zip\",\n \"--verbose\"\n ],\n [\n \"agent-context\"\n ],\n [\n \"agent-context\",\n \"--command\",\n \"panes create\",\n \"--json\"\n ],\n [\n \"repos\",\n \"list\",\n \"--json\",\n \"--pane-dir\",\n \"/tmp/pane\"\n ],\n [\n \"repos\",\n \"add\",\n \"--path\",\n \"/tmp/repo\",\n \"--name\",\n \"Repo\",\n \"--dry-run\",\n \"--yes\",\n \"--json\",\n \"--pane-dir\",\n \"/tmp/pane\"\n ],\n [\n \"panes\",\n \"list\",\n \"--repo\",\n \"active\",\n \"--json\"\n ],\n [\n \"panes\",\n \"create\",\n \"--repo\",\n \"active\",\n \"--name\",\n \"issue-252\",\n \"--agent\",\n \"codex\",\n \"--prompt\",\n \"Kick off discussion\",\n \"--dry-run\",\n \"--yes\",\n \"--json\"\n ],\n [\n \"panes\",\n \"create\",\n \"--from-json\",\n \"-\",\n \"--yes\",\n \"--json\"\n ],\n [\n \"panels\",\n \"list\",\n \"--pane\",\n \"session-1\",\n \"--json\"\n ],\n [\n \"panels\",\n \"output\",\n \"--panel\",\n \"panel-1\",\n \"--limit\",\n \"200\",\n \"--json\"\n ],\n [\n \"panels\",\n \"input\",\n \"--panel\",\n \"panel-1\",\n \"--text\",\n \"Continue\\\\n\",\n \"--yes\",\n \"--json\"\n ],\n [\n \"--version\"\n ]\n ],\n \"topLevelHelpIncludes\": [\n \"runpane setup\",\n \"runpane install\",\n \"runpane update\",\n \"runpane version\",\n \"runpane doctor\",\n \"runpane agent-context\",\n \"runpane repos list\",\n \"runpane repos add\",\n \"runpane panes list\",\n \"runpane panes create\",\n \"runpane panels list\",\n \"runpane panels output\",\n \"runpane panels input\"\n ],\n \"npmHelpIncludes\": [\n \"pnpm dlx runpane@latest\",\n \"npx --yes runpane@latest\"\n ],\n \"pipHelpIncludes\": [\n \"pipx run runpane\",\n \"python -m pip install runpane && python -m runpane setup\"\n ],\n \"installHelpIncludes\": [\n \"--version <latest|vX.Y.Z>\",\n \"--format <auto|appimage|deb|dmg|zip|exe>\",\n \"--download-dir <path>\",\n \"--pane-path <path>\",\n \"--label <name>\",\n \"--prefer-tunnel <tailscale|ssh|manual|auto>\",\n \"--repo-ref <ref>\"\n ]\n },\n \"jsonSchemas\": {\n \"error\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"error\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": false\n },\n \"error\": {\n \"type\": \"object\",\n \"required\": [\n \"message\"\n ],\n \"properties\": {\n \"message\": {\n \"type\": \"string\"\n },\n \"code\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n },\n \"repoListResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"repos\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"repos\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"id\",\n \"name\",\n \"path\",\n \"active\",\n \"sessionCount\"\n ],\n \"properties\": {\n \"id\": {\n \"type\": \"number\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"active\": {\n \"type\": \"boolean\"\n },\n \"environment\": {\n \"type\": \"string\"\n },\n \"sessionCount\": {\n \"type\": \"number\"\n }\n },\n \"additionalProperties\": false\n }\n }\n },\n \"additionalProperties\": false\n },\n \"repoAddRequest\": {\n \"type\": \"object\",\n \"required\": [\n \"path\"\n ],\n \"properties\": {\n \"path\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"dryRun\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n },\n \"repoAddResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"created\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"created\": {\n \"type\": \"boolean\"\n },\n \"dryRun\": {\n \"type\": \"boolean\"\n },\n \"repo\": {\n \"$ref\": \"#/jsonSchemas/repoListResult/properties/repos/items\"\n },\n \"preview\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"path\",\n \"alreadyExists\",\n \"wouldCreate\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"alreadyExists\": {\n \"type\": \"boolean\"\n },\n \"wouldCreate\": {\n \"type\": \"boolean\"\n },\n \"environment\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n },\n \"paneCreateRequest\": {\n \"type\": \"object\",\n \"required\": [\n \"repo\",\n \"panes\"\n ],\n \"properties\": {\n \"repo\": {\n \"oneOf\": [\n {\n \"type\": \"string\"\n },\n {\n \"type\": \"object\",\n \"properties\": {\n \"id\": {\n \"type\": \"number\"\n },\n \"path\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"active\": {\n \"const\": true\n }\n },\n \"additionalProperties\": false\n }\n ]\n },\n \"panes\": {\n \"type\": \"array\",\n \"minItems\": 1,\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"tool\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"worktreeName\": {\n \"type\": \"string\"\n },\n \"baseBranch\": {\n \"type\": \"string\"\n },\n \"sessionPrompt\": {\n \"type\": \"string\"\n },\n \"tool\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"required\": [\n \"agent\"\n ],\n \"properties\": {\n \"agent\": {\n \"enum\": [\n \"codex\",\n \"claude\"\n ]\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"initialInput\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"required\": [\n \"command\"\n ],\n \"properties\": {\n \"command\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"initialInput\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n ]\n }\n },\n \"additionalProperties\": false\n }\n },\n \"dryRun\": {\n \"type\": \"boolean\"\n },\n \"timeoutMs\": {\n \"type\": \"number\"\n }\n },\n \"additionalProperties\": false\n },\n \"paneCreateResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"repo\",\n \"items\"\n ],\n \"properties\": {\n \"ok\": {\n \"type\": \"boolean\"\n },\n \"repo\": {\n \"$ref\": \"#/jsonSchemas/repoListResult/properties/repos/items\"\n },\n \"items\": {\n \"type\": \"array\",\n \"items\": {\n \"oneOf\": [\n {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"index\",\n \"name\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"index\": {\n \"type\": \"number\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"sessionId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"worktreePath\": {\n \"type\": \"string\"\n },\n \"nextCommand\": {\n \"type\": \"string\"\n },\n \"tool\": {\n \"type\": \"object\",\n \"required\": [\n \"title\",\n \"command\"\n ],\n \"properties\": {\n \"title\": {\n \"type\": \"string\"\n },\n \"command\": {\n \"type\": \"string\"\n },\n \"agent\": {\n \"enum\": [\n \"codex\",\n \"claude\"\n ]\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n },\n {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"index\",\n \"error\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": false\n },\n \"index\": {\n \"type\": \"number\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"error\": {\n \"type\": \"object\",\n \"required\": [\n \"message\"\n ],\n \"properties\": {\n \"message\": {\n \"type\": \"string\"\n },\n \"code\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n }\n ]\n }\n }\n },\n \"additionalProperties\": false\n },\n \"paneListResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panes\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"repo\": {\n \"$ref\": \"#/jsonSchemas/repoListResult/properties/repos/items\"\n },\n \"panes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"id\",\n \"paneId\",\n \"name\",\n \"status\",\n \"worktreePath\",\n \"repoId\",\n \"panelCount\"\n ],\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"status\": {\n \"type\": \"string\"\n },\n \"worktreePath\": {\n \"type\": \"string\"\n },\n \"repoId\": {\n \"type\": \"number\"\n },\n \"repoName\": {\n \"type\": \"string\"\n },\n \"panelCount\": {\n \"type\": \"number\"\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"lastActivity\": {\n \"type\": \"string\"\n },\n \"archived\": {\n \"type\": \"boolean\"\n }\n },\n \"additionalProperties\": false\n }\n }\n },\n \"additionalProperties\": false\n },\n \"panelListResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"paneId\",\n \"panels\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"panels\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"id\",\n \"panelId\",\n \"paneId\",\n \"type\",\n \"title\",\n \"active\"\n ],\n \"properties\": {\n \"id\": {\n \"type\": \"string\"\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"type\": {\n \"type\": \"string\"\n },\n \"title\": {\n \"type\": \"string\"\n },\n \"active\": {\n \"type\": \"boolean\"\n },\n \"initialized\": {\n \"type\": \"boolean\"\n },\n \"agentType\": {\n \"type\": \"string\"\n },\n \"isCliPanel\": {\n \"type\": \"boolean\"\n },\n \"position\": {\n \"type\": \"number\"\n },\n \"createdAt\": {\n \"type\": \"string\"\n },\n \"lastActiveAt\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n }\n },\n \"additionalProperties\": false\n },\n \"panelOutputResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panelId\",\n \"limit\",\n \"returnedCount\",\n \"hasMore\",\n \"outputs\",\n \"text\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"limit\": {\n \"type\": \"number\"\n },\n \"returnedCount\": {\n \"type\": \"number\"\n },\n \"hasMore\": {\n \"type\": \"boolean\"\n },\n \"outputs\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"type\",\n \"data\",\n \"timestamp\"\n ],\n \"properties\": {\n \"type\": {\n \"type\": \"string\"\n },\n \"data\": {},\n \"timestamp\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n }\n },\n \"text\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"panelInputRequest\": {\n \"type\": \"object\",\n \"required\": [\n \"panelId\",\n \"input\"\n ],\n \"properties\": {\n \"panelId\": {\n \"type\": \"string\"\n },\n \"input\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"panelInputResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"panelId\",\n \"inputBytes\",\n \"sentAt\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"panelId\": {\n \"type\": \"string\"\n },\n \"paneId\": {\n \"type\": \"string\"\n },\n \"inputBytes\": {\n \"type\": \"number\"\n },\n \"sentAt\": {\n \"type\": \"string\"\n },\n \"nextCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"agentContextBriefResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"mode\",\n \"source\",\n \"summary\",\n \"rules\",\n \"tools\",\n \"detailCommand\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"mode\": {\n \"const\": \"brief\"\n },\n \"source\": {\n \"const\": \"runpane-contract\"\n },\n \"summary\": {\n \"type\": \"string\"\n },\n \"rules\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"tools\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"summary\",\n \"arguments\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"summary\": {\n \"type\": \"string\"\n },\n \"arguments\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"additionalProperties\": false\n }\n },\n \"detailCommand\": {\n \"type\": \"string\"\n }\n },\n \"additionalProperties\": false\n },\n \"agentContextCommandResult\": {\n \"type\": \"object\",\n \"required\": [\n \"ok\",\n \"mode\",\n \"source\",\n \"command\"\n ],\n \"properties\": {\n \"ok\": {\n \"const\": true\n },\n \"mode\": {\n \"const\": \"command\"\n },\n \"source\": {\n \"const\": \"runpane-contract\"\n },\n \"command\": {\n \"type\": \"object\",\n \"required\": [\n \"name\",\n \"summary\",\n \"details\",\n \"arguments\",\n \"examples\"\n ],\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"summary\": {\n \"type\": \"string\"\n },\n \"details\": {\n \"type\": \"string\"\n },\n \"requiresPaneDaemon\": {\n \"type\": \"boolean\"\n },\n \"mutates\": {\n \"type\": \"boolean\"\n },\n \"arguments\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\"\n }\n },\n \"examples\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"jsonSchemas\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"notes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"additionalProperties\": false\n }\n },\n \"additionalProperties\": false\n }\n },\n \"agentContext\": {\n \"brief\": {\n \"title\": \"Pane agent context\",\n \"summary\": \"Pane lets a developer manage repositories and user-visible panes. Agents can use runpane to list/add Pane repositories and create panes with terminal-backed tools.\",\n \"rules\": [\n \"Start with `runpane repos list --json` to find the saved repository when unsure.\",\n \"If WSL cannot reach Pane or `runpane` resolves to a broken Windows shim, the user may be running Windows Pane; try `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane repos list --json'`.\",\n \"If the repository exists on disk but is not saved in Pane, use `runpane repos add --path <repo> --yes --json` before creating panes.\",\n \"Use `runpane panes create` to create a Pane session and open a built-in agent or custom terminal command.\",\n \"Use `runpane panels list`, `runpane panels output`, and `runpane panels input` when you need to inspect or drive an existing Pane terminal.\",\n \"After creating panes or sending terminal input, validate with bounded panel output before reporting success.\",\n \"Prefer `--input-file` for terminal input that includes Enter, Ctrl-C, quotes, or multiple lines.\",\n \"Use `runpane agent-context --command <command>` for detailed command definitions only when needed.\"\n ],\n \"detailCommand\": \"runpane agent-context --command <command> [--json]\",\n \"tools\": [\n {\n \"name\": \"agent-context\",\n \"summary\": \"Print token-efficient Pane command context for coding agents.\",\n \"arguments\": [\n \"--command <command>\",\n \"--json\"\n ]\n },\n {\n \"name\": \"repos list\",\n \"summary\": \"List repositories saved in the running Pane app.\",\n \"arguments\": [\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"repos add\",\n \"summary\": \"Register an existing git repository with the running Pane app.\",\n \"arguments\": [\n \"--path <path>\",\n \"--name <name>\",\n \"--yes\",\n \"--json\",\n \"--dry-run\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panes list\",\n \"summary\": \"List Pane sessions, optionally scoped to a saved repository.\",\n \"arguments\": [\n \"--repo <selector>\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panes create\",\n \"summary\": \"Create one or more Pane sessions in a saved repository and open a terminal-backed tool tab.\",\n \"arguments\": [\n \"--repo <selector>\",\n \"--name <name>\",\n \"--agent <codex|claude>\",\n \"--tool-command <command>\",\n \"--prompt <text>\",\n \"--initial-input-file <path|->\",\n \"--from-json <path|->\",\n \"--yes\",\n \"--json\"\n ]\n },\n {\n \"name\": \"panels list\",\n \"summary\": \"List tool panels inside a Pane session.\",\n \"arguments\": [\n \"--pane <pane-id>\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panels output\",\n \"summary\": \"Read recent terminal output from a panel.\",\n \"arguments\": [\n \"--panel <panel-id>\",\n \"--limit <count>\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n },\n {\n \"name\": \"panels input\",\n \"summary\": \"Send input bytes to a terminal panel.\",\n \"arguments\": [\n \"--panel <panel-id>\",\n \"--text <text>\",\n \"--input-file <path|->\",\n \"--yes\",\n \"--json\",\n \"--pane-dir <path>\"\n ]\n }\n ]\n },\n \"commands\": {\n \"help\": {\n \"name\": \"help\",\n \"summary\": \"Show help for runpane or a specific command.\",\n \"details\": \"Use this when you need human-readable usage text for a command.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"command\",\n \"value\": \"<command>\",\n \"required\": false,\n \"description\": \"Optional command topic such as \\\"panes create\\\".\"\n }\n ],\n \"examples\": [\n \"runpane help\",\n \"runpane help panes create\"\n ],\n \"notes\": [\n \"Help text is generated from the runpane contract.\"\n ]\n },\n \"setup\": {\n \"name\": \"setup\",\n \"summary\": \"Open the guided setup wizard for install, remote host setup, update, and diagnostics.\",\n \"details\": \"Use this for a human-driven Pane setup flow, not for unattended agent orchestration.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [],\n \"examples\": [\n \"runpane setup\"\n ],\n \"notes\": [\n \"In non-interactive shells, setup prints help and exits successfully.\"\n ]\n },\n \"install\": {\n \"name\": \"install\",\n \"summary\": \"Install Pane on this machine or configure this machine as a remote daemon host.\",\n \"details\": \"Installs or launches Pane release artifacts at command runtime. `install daemon` forwards remote setup flags to Pane.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"target\",\n \"value\": \"<client|daemon>\",\n \"required\": false,\n \"description\": \"Install the desktop client or configure a remote daemon host.\"\n },\n {\n \"name\": \"--version\",\n \"value\": \"<latest|vX.Y.Z>\",\n \"required\": false,\n \"description\": \"Pane release to install.\"\n },\n {\n \"name\": \"--format\",\n \"value\": \"<auto|appimage|deb|dmg|zip|exe>\",\n \"required\": false,\n \"description\": \"Release artifact format.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip interactive prompts where possible.\"\n }\n ],\n \"examples\": [\n \"runpane install client\",\n \"runpane install daemon --label \\\"My Server\\\"\"\n ],\n \"notes\": [\n \"Package install itself is inert; work begins only when runpane is executed.\"\n ]\n },\n \"update\": {\n \"name\": \"update\",\n \"summary\": \"Update the Pane desktop app using the same artifact path as install client.\",\n \"details\": \"Resolves and installs the selected Pane client release.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--version\",\n \"value\": \"<latest|vX.Y.Z>\",\n \"required\": false,\n \"description\": \"Pane release to update to.\"\n },\n {\n \"name\": \"--format\",\n \"value\": \"<auto|appimage|deb|dmg|zip|exe>\",\n \"required\": false,\n \"description\": \"Release artifact format.\"\n },\n {\n \"name\": \"--dry-run\",\n \"required\": false,\n \"description\": \"Print the update plan without downloading.\"\n }\n ],\n \"examples\": [\n \"runpane update\",\n \"runpane update --version latest\"\n ],\n \"notes\": [\n \"Equivalent artifact selection to `runpane install client`.\"\n ]\n },\n \"version\": {\n \"name\": \"version\",\n \"summary\": \"Print the runpane wrapper version and installed Pane version when detectable.\",\n \"details\": \"Use this for diagnostics or to confirm which wrapper is available.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--pane-path\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Inspect a specific Pane executable.\"\n }\n ],\n \"examples\": [\n \"runpane version\",\n \"runpane --version\"\n ],\n \"notes\": []\n },\n \"doctor\": {\n \"name\": \"doctor\",\n \"summary\": \"Run platform, release, installed Pane, and remote setup diagnostics.\",\n \"details\": \"Use this when runpane install/update behavior needs environment diagnostics.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--pane-path\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Use an existing Pane executable for diagnostics.\"\n },\n {\n \"name\": \"--verbose\",\n \"required\": false,\n \"description\": \"Print extra diagnostics.\"\n }\n ],\n \"examples\": [\n \"runpane doctor\",\n \"runpane doctor --verbose\"\n ],\n \"notes\": []\n },\n \"agent-context\": {\n \"name\": \"agent-context\",\n \"summary\": \"Print token-efficient Pane command context for coding agents.\",\n \"details\": \"Use this first when an agent needs to discover Pane primitives. It is local/offline and does not require a running Pane app.\",\n \"requiresPaneDaemon\": false,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--command\",\n \"value\": \"<command>\",\n \"required\": false,\n \"description\": \"Print the detailed definition for one command, for example \\\"panes create\\\".\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n }\n ],\n \"examples\": [\n \"runpane agent-context\",\n \"runpane agent-context --command \\\"panes create\\\" --json\"\n ],\n \"jsonSchemas\": [\n \"agentContextBriefResult\",\n \"agentContextCommandResult\"\n ],\n \"notes\": [\n \"Default output is brief so AGENTS.md can point here without bloating context.\"\n ]\n },\n \"repos list\": {\n \"name\": \"repos list\",\n \"summary\": \"List repositories saved in the running Pane app.\",\n \"details\": \"Use this to find the right Pane-managed repository before creating panes. If the repo is missing, use `repos add` first.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable repository records.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane repos list --json\"\n ],\n \"jsonSchemas\": [\n \"repoListResult\"\n ],\n \"notes\": [\n \"Requires a running Pane app or daemon for the selected Pane data directory.\",\n \"If this fails from WSL with a missing `/tmp/pane-daemon.../daemon.sock`, `volta: command not found`, or a Windows shim error, the user may be running Windows Pane. Retry via `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane repos list --json'`.\",\n \"When using PowerShell from WSL, set a Windows cwd such as `$env:TEMP` or `$env:USERPROFILE` before running runpane to avoid UNC cwd issues.\"\n ]\n },\n \"repos add\": {\n \"name\": \"repos add\",\n \"summary\": \"Register an existing git repository with the running Pane app.\",\n \"details\": \"Use this when the repository exists on disk but is not saved in Pane yet. It validates the path as a git repository.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--path\",\n \"value\": \"<path>\",\n \"required\": true,\n \"description\": \"Existing git repository path to register with Pane.\"\n },\n {\n \"name\": \"--name\",\n \"value\": \"<name>\",\n \"required\": false,\n \"description\": \"Saved repository name; defaults to the directory name.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip confirmation for mutating commands.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--dry-run\",\n \"required\": false,\n \"description\": \"Validate and preview without adding the repo.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane repos add --path /path/to/repo --yes --json\"\n ],\n \"jsonSchemas\": [\n \"repoAddRequest\",\n \"repoAddResult\"\n ],\n \"notes\": [\n \"It does not create directories or initialize git repositories by default.\",\n \"For a Windows Pane app managing WSL repositories, prefer a saved WSL repo from `repos list` when possible. Adding a brand-new WSL repo from Windows may require WSL-aware path handling.\"\n ]\n },\n \"panes list\": {\n \"name\": \"panes list\",\n \"summary\": \"List Pane sessions, optionally scoped to a saved repository.\",\n \"details\": \"Use this after selecting a repository to find existing Pane sessions and their ids before inspecting panels.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--repo\",\n \"value\": \"<selector>\",\n \"required\": false,\n \"description\": \"Optional repository selector: active, id, exact path, or saved repository name.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panes list --repo active --json\"\n ],\n \"jsonSchemas\": [\n \"paneListResult\"\n ],\n \"notes\": [\n \"Without --repo, this lists sessions across saved Pane repositories.\"\n ]\n },\n \"panes create\": {\n \"name\": \"panes create\",\n \"summary\": \"Create one or more Pane sessions in a saved repository and open a terminal-backed tool tab.\",\n \"details\": \"Use this to set up user-visible panes for work. Select a saved repository, choose a built-in agent or custom terminal command, and optionally send initial input after the tool starts. For multi-step shell setup, pass a shell command through --tool-command rather than adding a new runpane primitive.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--repo\",\n \"value\": \"<selector>\",\n \"required\": true,\n \"description\": \"Repository selector: active, id, exact path, or saved repository name.\"\n },\n {\n \"name\": \"--name\",\n \"value\": \"<name>\",\n \"required\": true,\n \"description\": \"Pane/session name.\"\n },\n {\n \"name\": \"--agent\",\n \"value\": \"<codex|claude>\",\n \"required\": false,\n \"description\": \"Built-in agent terminal template to open.\"\n },\n {\n \"name\": \"--tool-command\",\n \"value\": \"<command>\",\n \"required\": false,\n \"description\": \"Custom terminal command to run instead of a built-in agent.\"\n },\n {\n \"name\": \"--prompt\",\n \"value\": \"<text>\",\n \"required\": false,\n \"description\": \"Alias for --initial-input; sends text after the command is ready.\"\n },\n {\n \"name\": \"--initial-input-file\",\n \"value\": \"<path|->\",\n \"required\": false,\n \"description\": \"Read initial input from a file or stdin.\"\n },\n {\n \"name\": \"--from-json\",\n \"value\": \"<path|->\",\n \"required\": false,\n \"description\": \"Read a full panes.create request JSON payload.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip confirmation for mutating commands.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n }\n ],\n \"examples\": [\n \"runpane panes create --repo active --name issue-257 --agent codex --prompt \\\"Plan this issue\\\" --yes\",\n \"runpane panes create --from-json panes.json --yes --json\"\n ],\n \"jsonSchemas\": [\n \"paneCreateRequest\",\n \"paneCreateResult\"\n ],\n \"notes\": [\n \"At least one of --agent or --tool-command is required unless --from-json is used.\",\n \"The built-in agent templates come from the runpane contract; custom terminal commands can pass agent-specific flags when requested by the user.\",\n \"Use --initial-input-file for multi-line prompts or shell-sensitive initial input.\",\n \"When the JSON result includes nextCommand, run it to validate that the terminal produced output before reporting success.\",\n \"For POSIX or WSL command chaining, use a custom terminal command like `bash -lc 'cmd1 && cmd2 && cmd3'`.\",\n \"For Windows PowerShell command chaining, use a custom terminal command like `powershell -NoProfile -Command \\\"cmd1; if ($LASTEXITCODE) { exit $LASTEXITCODE }; cmd2\\\"`.\",\n \"From WSL with Windows Pane, invoke through PowerShell and select the saved WSL repo by name or id, for example `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane panes create --repo \\\"WSL Pane\\\" --name issue-123 --agent codex --prompt \\\"Plan this issue\\\" --yes --json'`.\"\n ]\n },\n \"panels list\": {\n \"name\": \"panels list\",\n \"summary\": \"List tool panels inside a Pane session.\",\n \"details\": \"Use this to find the terminal panel id to inspect or control after creating or selecting a Pane session.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--pane\",\n \"value\": \"<pane-id>\",\n \"required\": true,\n \"description\": \"Pane/session id.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panels list --pane <pane-id> --json\"\n ],\n \"jsonSchemas\": [\n \"panelListResult\"\n ],\n \"notes\": [\n \"The ids returned here are stable inputs for `panels output` and `panels input`.\"\n ]\n },\n \"panels output\": {\n \"name\": \"panels output\",\n \"summary\": \"Read recent terminal output from a panel.\",\n \"details\": \"Use this to inspect recent terminal output from a terminal-backed panel without loading the full history by default. Live terminal scrollback is returned as bounded recent lines; persisted output fallback is returned as bounded records. Terminal control noise is stripped before returning text.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": false,\n \"arguments\": [\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"required\": true,\n \"description\": \"Tool panel id.\"\n },\n {\n \"name\": \"--limit\",\n \"value\": \"<count>\",\n \"required\": false,\n \"description\": \"Maximum recent output lines or records to read. Defaults to 200.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"runpane panels output --panel <panel-id> --limit 200 --json\"\n ],\n \"jsonSchemas\": [\n \"panelOutputResult\"\n ],\n \"notes\": [\n \"Default output is bounded to the latest 200 lines or records. Use a larger --limit only when hasMore is true and more history is needed.\",\n \"Use --json when an agent needs timestamps, record types, returnedCount, or hasMore.\",\n \"The output is intended to be agent-readable, but terminal prompts and shell echoes may still appear; use the newest relevant lines before concluding success.\"\n ]\n },\n \"panels input\": {\n \"name\": \"panels input\",\n \"summary\": \"Send input bytes to a terminal panel.\",\n \"details\": \"Use this to answer prompts or continue an agent inside an existing Pane terminal panel. Input is byte-oriented; choose --input-file for exact control over newlines and control characters.\",\n \"requiresPaneDaemon\": true,\n \"mutates\": true,\n \"arguments\": [\n {\n \"name\": \"--panel\",\n \"value\": \"<panel-id>\",\n \"required\": true,\n \"description\": \"Terminal panel id.\"\n },\n {\n \"name\": \"--text\",\n \"value\": \"<text>\",\n \"required\": false,\n \"description\": \"Text bytes to send.\"\n },\n {\n \"name\": \"--input-file\",\n \"value\": \"<path|->\",\n \"required\": false,\n \"description\": \"Read input from a file or stdin.\"\n },\n {\n \"name\": \"--yes\",\n \"required\": false,\n \"description\": \"Skip confirmation for this mutating command.\"\n },\n {\n \"name\": \"--json\",\n \"required\": false,\n \"description\": \"Print machine-readable output.\"\n },\n {\n \"name\": \"--pane-dir\",\n \"value\": \"<path>\",\n \"required\": false,\n \"description\": \"Connect to a specific Pane data directory.\"\n }\n ],\n \"examples\": [\n \"printf 'Continue\\\\n' | runpane panels input --panel <panel-id> --input-file - --yes\",\n \"printf '\\\\003' | runpane panels input --panel <panel-id> --input-file - --yes\",\n \"runpane panels input --panel <panel-id> --text \\\"simple text\\\" --yes --json\"\n ],\n \"jsonSchemas\": [\n \"panelInputRequest\",\n \"panelInputResult\"\n ],\n \"notes\": [\n \"Input is sent exactly as provided. Include a real newline byte when the terminal should receive Enter; across shells, `--input-file` is safer than `--text \\\"...\\\\n\\\"`.\",\n \"Use `--input-file -` or a temp file for multi-line input, quotes, Ctrl-C, or shell-sensitive text.\",\n \"If interrupting a running process, send Ctrl-C first, validate/read output, then send the next command in a separate `panels input` call so bytes are not dropped.\",\n \"After sending input, validate with `runpane panels output --panel <panel-id> --json` before reporting success.\",\n \"Runpane records action metadata and errors for observability, but should not log full input text by default.\"\n ]\n }\n },\n \"managedBlock\": [\n \"## Pane\",\n \"\",\n \"The developer is using Pane for this repository. Pane can manage saved repositories and create user-visible panes with terminal-backed tools for planning, discussion, and implementation work.\",\n \"\",\n \"Use `runpane agent-context` for a brief Pane command schema. Use `runpane agent-context --command \\\"panes create\\\"` or another command name for the detailed schema only when needed.\",\n \"\",\n \"After creating panes or sending terminal input, validate with bounded panel output before reporting success. Prefer `--input-file` for exact terminal bytes, newlines, Ctrl-C, quotes, or multi-line input.\",\n \"\",\n \"Common commands:\",\n \"- `runpane repos list --json`\",\n \"- `runpane repos add --path <repo> --yes --json`\",\n \"- `runpane panes create --repo active --name <name> --agent codex --prompt \\\"<task>\\\" --yes`\",\n \"- `runpane panels list --pane <pane-id> --json`\",\n \"- `runpane panels output --panel <panel-id> --limit 200 --json`\",\n \"- `runpane panels input --panel <panel-id> --input-file <path|-> --yes`\",\n \"\",\n \"WSL note: if `runpane repos list` cannot find `/tmp/pane-daemon.../daemon.sock` or `runpane` resolves to a broken Windows shim, Pane may be running on Windows. Try `powershell.exe -NoProfile -Command 'Set-Location $env:TEMP; runpane repos list --json'`, then create panes through the same PowerShell form using the saved WSL repo name or id.\"\n ]\n }\n}")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|