runpane 2.4.136 → 2.4.138

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.
@@ -135,7 +135,7 @@ exports.RUNPANE_CONTRACT = {
135
135
  "name": "version",
136
136
  "summary": "Print the runpane wrapper version without contacting, launching, or focusing Pane.",
137
137
  "usage": [
138
- "runpane version",
138
+ "runpane version [--pane-dir <path>]",
139
139
  "runpane --version"
140
140
  ]
141
141
  },
@@ -173,7 +173,7 @@ exports.RUNPANE_CONTRACT = {
173
173
  "name": "agents doctor",
174
174
  "summary": "Diagnose whether a built-in agent command is available in a Pane repository environment.",
175
175
  "usage": [
176
- "runpane agents doctor --agent <codex|claude|cursor> [--repo <selector>] [--json]"
176
+ "runpane agents doctor --agent <codex|claude|cursor> [--repo <selector>] [--json] [--pane-dir <path>]"
177
177
  ],
178
178
  "toolsets": [
179
179
  "admin"
@@ -226,7 +226,7 @@ exports.RUNPANE_CONTRACT = {
226
226
  "name": "repos add",
227
227
  "summary": "Register an existing git repository with the running Pane app.",
228
228
  "usage": [
229
- "runpane repos add --path <path> [--name <name>] [--json] [--yes]"
229
+ "runpane repos add --path <path> [--name <name>] [--json] [--yes] [--pane-dir <path>]"
230
230
  ],
231
231
  "mutates": true,
232
232
  "additive": true,
@@ -244,7 +244,7 @@ exports.RUNPANE_CONTRACT = {
244
244
  "name": "panes list",
245
245
  "summary": "List Pane sessions in a saved repository.",
246
246
  "usage": [
247
- "runpane panes list [--repo <selector>] [--json]"
247
+ "runpane panes list [--repo <selector>] [--json] [--pane-dir <path>]"
248
248
  ],
249
249
  "toolsets": [
250
250
  "core",
@@ -258,7 +258,7 @@ exports.RUNPANE_CONTRACT = {
258
258
  "name": "panes cost",
259
259
  "summary": "Report estimated token cost per Pane, with per-model breakdown and cache efficiency.",
260
260
  "usage": [
261
- "runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]"
261
+ "runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json] [--pane-dir <path>]"
262
262
  ],
263
263
  "toolsets": [
264
264
  "panes"
@@ -272,7 +272,7 @@ exports.RUNPANE_CONTRACT = {
272
272
  "name": "workspace state",
273
273
  "summary": "Read one workspace snapshot of every Pane and CLI panel.",
274
274
  "usage": [
275
- "runpane workspace state [--repo <selector>] [--json]"
275
+ "runpane workspace state [--repo <selector>] [--json] [--pane-dir <path>]"
276
276
  ],
277
277
  "toolsets": [
278
278
  "core",
@@ -286,7 +286,7 @@ exports.RUNPANE_CONTRACT = {
286
286
  "name": "watch",
287
287
  "summary": "Wait for workspace agent and Pane transitions using a daemon-held cursor.",
288
288
  "usage": [
289
- "runpane watch [--as <name>|--since <generation>] [--follow] [--format <lines|json>] [--heartbeat <seconds>] [--idle-after <ms>] [--settle <ms>] [--blocked-settle <ms>] [--min-interval <ms>] [--idle-backoff] [--all-managed|--pane <id>] [--include-shells] [--self-test] [--kinds <kind,...>] [--repo <selector>] [--name-contains <text>] [--timeout-ms <ms>] [--from <now|earliest>] [--json]"
289
+ "runpane watch [--as <name>|--since <generation>] [--follow] [--format <lines|json>] [--heartbeat <seconds>] [--idle-after <ms>] [--settle <ms>] [--blocked-settle <ms>] [--min-interval <ms>] [--idle-backoff] [--all-managed|--pane <id>|--session <id|name>] [--include-shells] [--self-test] [--quiet] [--kinds <kind,...>] [--repo <selector>] [--name-contains <text>] [--timeout-ms <ms>] [--from <now|earliest>] [--json] [--pane-dir <path>]"
290
290
  ],
291
291
  "toolsets": [
292
292
  "agents"
@@ -300,8 +300,9 @@ exports.RUNPANE_CONTRACT = {
300
300
  "name": "panes create",
301
301
  "summary": "Create user-visible Panes (Pane sessions) backed by Pane-managed worktrees for feature/PR work and open terminal-backed tool tabs.",
302
302
  "usage": [
303
- "runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] [options]",
304
- "runpane panes create --from-json <path|-> [--yes] [--json]"
303
+ "runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options] [--pane-dir <path>]",
304
+ "runpane panes create --repo <selector> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [--source user|agent] [--focus|--no-focus] [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options] [--pane-dir <path>]",
305
+ "runpane panes create --from-json <path|-> [--yes] [--json] [--pane-dir <path>]"
305
306
  ],
306
307
  "mutates": true,
307
308
  "additive": true,
@@ -317,7 +318,8 @@ exports.RUNPANE_CONTRACT = {
317
318
  "name": "panes adopt",
318
319
  "summary": "Adopt an existing externally managed git worktree as a Pane without changing the worktree.",
319
320
  "usage": [
320
- "runpane panes adopt --repo <selector> --path <dir> --name <name> --agent <codex|claude|cursor> [--resume <id>] [--folder <name>] [--launch] [--no-pinned] [--no-associate] [--dry-run] [--yes] [--json]"
321
+ "runpane panes adopt --repo <selector> --path <dir> --name <name> --agent <codex|claude|cursor> [--resume <id>] [--folder <name>] [--launch [--prompt <text>|--prompt-file <path|->] [--wait-ready] [--ready-timeout-ms <ms>]] [--no-pinned] [--no-associate] [--dry-run] [--yes] [--json] [--pane-dir <path>]",
322
+ "runpane panes adopt --repo <selector> --path <dir> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [--folder <name>] [--launch [--prompt <text>|--prompt-file <path|->] [--wait-ready] [--ready-timeout-ms <ms>]] [--no-pinned] [--no-associate] [--dry-run] [--yes] [--json] [--pane-dir <path>]"
321
323
  ],
322
324
  "mutates": true,
323
325
  "additive": true,
@@ -330,9 +332,10 @@ exports.RUNPANE_CONTRACT = {
330
332
  },
331
333
  {
332
334
  "name": "panes archive",
333
- "summary": "Archive a Pane (session) exactly like the UI Archive action, including safe removal of its Pane-managed git worktree.",
335
+ "summary": "Archive a Pane (session) exactly like the UI Archive action, including safe removal of its Pane-managed git worktree, or archive every merged Pane in a Session.",
334
336
  "usage": [
335
- "runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--dry-run] --yes [--json]"
337
+ "runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes [--json] [--pane-dir <path>]",
338
+ "runpane panes archive --session <id|name> --merged [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json] [--pane-dir <path>]"
336
339
  ],
337
340
  "mutates": true,
338
341
  "toolsets": [
@@ -341,14 +344,16 @@ exports.RUNPANE_CONTRACT = {
341
344
  ],
342
345
  "jsonSchemas": [
343
346
  "paneArchiveRequest",
344
- "paneArchiveResult"
347
+ "paneArchiveBulkRequest",
348
+ "paneArchiveResult",
349
+ "paneArchiveBulkResult"
345
350
  ]
346
351
  },
347
352
  {
348
353
  "name": "panes pin",
349
354
  "summary": "Declaratively pin a Pane; pinned is the Pane UI's favorite/pin star and repeated requests are idempotent.",
350
355
  "usage": [
351
- "runpane panes pin --pane <pane-id> --yes [--dry-run] [--json]"
356
+ "runpane panes pin --pane <pane-id> --yes [--dry-run] [--json] [--pane-dir <path>]"
352
357
  ],
353
358
  "mutates": true,
354
359
  "idempotent": true,
@@ -364,7 +369,7 @@ exports.RUNPANE_CONTRACT = {
364
369
  "name": "panes unpin",
365
370
  "summary": "Declaratively unpin a Pane; pinned is the Pane UI's favorite/pin star and repeated requests are idempotent.",
366
371
  "usage": [
367
- "runpane panes unpin --pane <pane-id> --yes [--dry-run] [--json]"
372
+ "runpane panes unpin --pane <pane-id> --yes [--dry-run] [--json] [--pane-dir <path>]"
368
373
  ],
369
374
  "mutates": true,
370
375
  "idempotent": true,
@@ -380,7 +385,7 @@ exports.RUNPANE_CONTRACT = {
380
385
  "name": "panes rename",
381
386
  "summary": "Rename a Pane without changing its worktree, branch, panels, or focus.",
382
387
  "usage": [
383
- "runpane panes rename --pane <pane-id> --name <new-name> --yes [--dry-run] [--json]"
388
+ "runpane panes rename --pane <pane-id> --name <new-name> --yes [--dry-run] [--json] [--pane-dir <path>]"
384
389
  ],
385
390
  "mutates": true,
386
391
  "idempotent": true,
@@ -396,7 +401,7 @@ exports.RUNPANE_CONTRACT = {
396
401
  "name": "panes focus",
397
402
  "summary": "Raise the Pane window and select a Pane (and optionally one of its panels) on explicit user request.",
398
403
  "usage": [
399
- "runpane panes focus --pane <pane-id> [--panel <panel-id>] --source user|agent --yes [--json]"
404
+ "runpane panes focus --pane <pane-id> [--panel <panel-id>] --source user|agent --yes [--json] [--pane-dir <path>]"
400
405
  ],
401
406
  "mutates": true,
402
407
  "additive": true,
@@ -413,8 +418,8 @@ exports.RUNPANE_CONTRACT = {
413
418
  "name": "panels create",
414
419
  "summary": "Create a terminal-backed tool panel inside an existing Pane session.",
415
420
  "usage": [
416
- "runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] [--wait-ready] --yes [--json]",
417
- "runpane panels create --pane <pane-id> --tool-command <command> [--title <title>] [--focus|--no-focus] --yes [--json]"
421
+ "runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] [--wait-ready] --yes [--json] [--pane-dir <path>]",
422
+ "runpane panels create --pane <pane-id> --tool-command <command> [--agent <codex|claude|cursor>] [--title <title>] [--focus|--no-focus] [--wait-ready] --yes [--json] [--pane-dir <path>]"
418
423
  ],
419
424
  "mutates": true,
420
425
  "additive": true,
@@ -426,11 +431,23 @@ exports.RUNPANE_CONTRACT = {
426
431
  "panelCreateResult"
427
432
  ]
428
433
  },
434
+ {
435
+ "name": "panels open",
436
+ "summary": "Open a URL or file as a browser/editor tab in a Pane, in split view beside the agent by default.",
437
+ "usage": [
438
+ "runpane panels open [--pane <pane-id>] (--url <url>|--file <path>) [--title <title>] [--split|--tab] [--focus|--no-focus] [--source user|agent] --yes [--json]"
439
+ ],
440
+ "mutates": true,
441
+ "jsonSchemas": [
442
+ "panelOpenRequest",
443
+ "panelOpenResult"
444
+ ]
445
+ },
429
446
  {
430
447
  "name": "panels list",
431
448
  "summary": "List tool panels inside a Pane session.",
432
449
  "usage": [
433
- "runpane panels list --pane <pane-id> [--json]"
450
+ "runpane panels list --pane <pane-id> [--json] [--pane-dir <path>]"
434
451
  ],
435
452
  "toolsets": [
436
453
  "panels"
@@ -443,7 +460,7 @@ exports.RUNPANE_CONTRACT = {
443
460
  "name": "panels output",
444
461
  "summary": "Read recent terminal output from a panel.",
445
462
  "usage": [
446
- "runpane panels output --panel <panel-id> [--limit <count>] [--json]"
463
+ "runpane panels output --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]"
447
464
  ],
448
465
  "toolsets": [
449
466
  "panels"
@@ -456,7 +473,7 @@ exports.RUNPANE_CONTRACT = {
456
473
  "name": "panels screen",
457
474
  "summary": "Read a compact current-screen view from a terminal panel.",
458
475
  "usage": [
459
- "runpane panels screen --panel <panel-id> [--limit <count>] [--json]"
476
+ "runpane panels screen --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]"
460
477
  ],
461
478
  "toolsets": [
462
479
  "panels"
@@ -469,7 +486,7 @@ exports.RUNPANE_CONTRACT = {
469
486
  "name": "panels input",
470
487
  "summary": "Send input bytes to a terminal panel.",
471
488
  "usage": [
472
- "runpane panels input --panel <panel-id> (--text <text>|--keys <name,...>|--input-file <path|->) --yes [--json]"
489
+ "runpane panels input --panel <panel-id> (--text <text>|--keys <name,...>|--input-file <path|->) --yes [--json] [--pane-dir <path>]"
473
490
  ],
474
491
  "mutates": true,
475
492
  "toolsets": [
@@ -485,7 +502,7 @@ exports.RUNPANE_CONTRACT = {
485
502
  "name": "panels submit",
486
503
  "summary": "Send and submit text to a terminal panel, including idle agent composers.",
487
504
  "usage": [
488
- "runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]"
505
+ "runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) [--as-file-pointer] --yes [--json] [--pane-dir <path>]"
489
506
  ],
490
507
  "mutates": true,
491
508
  "toolsets": [
@@ -500,7 +517,7 @@ exports.RUNPANE_CONTRACT = {
500
517
  "name": "panels submit-composer",
501
518
  "summary": "Submit an agent composer using the panel-appropriate key sequence.",
502
519
  "usage": [
503
- "runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]"
520
+ "runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json] [--pane-dir <path>]"
504
521
  ],
505
522
  "mutates": true,
506
523
  "toolsets": [
@@ -515,7 +532,7 @@ exports.RUNPANE_CONTRACT = {
515
532
  "name": "panels wait",
516
533
  "summary": "Wait for a terminal panel to initialize, become ready/idle, or contain text.",
517
534
  "usage": [
518
- "runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--contains <text>] [--timeout-ms <ms>] [--interval-ms <ms>] [--json]"
535
+ "runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--contains <text>] [--timeout-ms <ms>] [--interval-ms <ms>] [--json] [--pane-dir <path>]"
519
536
  ],
520
537
  "toolsets": [
521
538
  "panels"
@@ -524,6 +541,20 @@ exports.RUNPANE_CONTRACT = {
524
541
  "panelWaitResult"
525
542
  ]
526
543
  },
544
+ {
545
+ "name": "panels last-message",
546
+ "summary": "Read an agent's last reply from its transcript, without scraping the screen.",
547
+ "usage": [
548
+ "runpane panels last-message --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]"
549
+ ],
550
+ "toolsets": [
551
+ "panels",
552
+ "agents"
553
+ ],
554
+ "jsonSchemas": [
555
+ "panelLastMessageResult"
556
+ ]
557
+ },
527
558
  {
528
559
  "name": "panes git-status",
529
560
  "summary": "Read the git status of a Pane worktree: uncommitted, unpushed, and behind-main counts.",
@@ -974,7 +1005,7 @@ exports.RUNPANE_CONTRACT = {
974
1005
  "name": "agents send",
975
1006
  "summary": "Send a follow-up message to an agent and confirm it was submitted.",
976
1007
  "usage": [
977
- "runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]"
1008
+ "runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> [--as-file-pointer] --yes [--json] [--pane-dir <path>]"
978
1009
  ],
979
1010
  "mutates": true,
980
1011
  "wrappers": [
@@ -988,6 +1019,22 @@ exports.RUNPANE_CONTRACT = {
988
1019
  "agentSendResult"
989
1020
  ]
990
1021
  },
1022
+ {
1023
+ "name": "report",
1024
+ "summary": "Hand back a worker's structured report: state, PR, head commit, summary, and the question when blocked.",
1025
+ "usage": [
1026
+ "runpane report --state <ready|blocked|failed|done> [--pr <number>] [--head <sha>] [--summary <text>|--summary-file <path|->] [--question <text>] [--pane <pane-id> --panel <panel-id>] [--json] [--pane-dir <path>]"
1027
+ ],
1028
+ "mutates": true,
1029
+ "additive": true,
1030
+ "idempotent": true,
1031
+ "toolsets": [
1032
+ "agents"
1033
+ ],
1034
+ "jsonSchemas": [
1035
+ "reportResult"
1036
+ ]
1037
+ },
991
1038
  {
992
1039
  "name": "sessions list",
993
1040
  "summary": "List durable named orchestration Sessions.",
@@ -1102,6 +1149,51 @@ exports.RUNPANE_CONTRACT = {
1102
1149
  "jsonSchemas": [
1103
1150
  "sessionOverviewResult"
1104
1151
  ]
1152
+ },
1153
+ {
1154
+ "name": "lock acquire",
1155
+ "summary": "Acquire a named lock on a resource shared between agents, such as one test account, optionally waiting for it.",
1156
+ "usage": [
1157
+ "runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]"
1158
+ ],
1159
+ "mutates": true,
1160
+ "additive": true,
1161
+ "idempotent": true,
1162
+ "toolsets": [
1163
+ "sessions"
1164
+ ],
1165
+ "jsonSchemas": [
1166
+ "lockAcquireRequest",
1167
+ "lockAcquireResult"
1168
+ ]
1169
+ },
1170
+ {
1171
+ "name": "lock release",
1172
+ "summary": "Release a named lock you hold, or force-release another owner's lock.",
1173
+ "usage": [
1174
+ "runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]"
1175
+ ],
1176
+ "mutates": true,
1177
+ "idempotent": true,
1178
+ "toolsets": [
1179
+ "sessions"
1180
+ ],
1181
+ "jsonSchemas": [
1182
+ "lockReleaseResult"
1183
+ ]
1184
+ },
1185
+ {
1186
+ "name": "lock list",
1187
+ "summary": "List held named locks, optionally only one Session's.",
1188
+ "usage": [
1189
+ "runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]"
1190
+ ],
1191
+ "toolsets": [
1192
+ "sessions"
1193
+ ],
1194
+ "jsonSchemas": [
1195
+ "lockListResult"
1196
+ ]
1105
1197
  }
1106
1198
  ],
1107
1199
  "flags": {
@@ -1222,17 +1314,25 @@ exports.RUNPANE_CONTRACT = {
1222
1314
  {
1223
1315
  "name": "--name",
1224
1316
  "value": "<name>",
1225
- "description": "Name for the registered repository or created/renamed pane session."
1317
+ "description": "Name for the registered repository, created/renamed pane session, or named lock."
1226
1318
  },
1227
1319
  {
1228
1320
  "name": "--worktree-name",
1229
1321
  "value": "<name>",
1230
1322
  "description": "Worktree name to request. Defaults to --name."
1231
1323
  },
1324
+ {
1325
+ "name": "--branch",
1326
+ "value": "<name>",
1327
+ "description": "Exact new branch name for the created worktree, slashes included. Must not exist yet; defaults to the worktree name."
1328
+ },
1232
1329
  {
1233
1330
  "name": "--base-branch",
1234
- "value": "<branch>",
1235
- "description": "Base branch for the created worktree."
1331
+ "value": "<ref>",
1332
+ "aliases": [
1333
+ "--base"
1334
+ ],
1335
+ "description": "Ref the created worktree branches from. --base is an alias."
1236
1336
  },
1237
1337
  {
1238
1338
  "name": "--folder",
@@ -1247,7 +1347,7 @@ exports.RUNPANE_CONTRACT = {
1247
1347
  {
1248
1348
  "name": "--agent",
1249
1349
  "value": "<codex|claude|cursor>",
1250
- "description": "Built-in agent terminal template to open."
1350
+ "description": "Built-in agent terminal template to open. With --tool-command, the agent that command runs."
1251
1351
  },
1252
1352
  {
1253
1353
  "name": "--tool-command",
@@ -1259,6 +1359,16 @@ exports.RUNPANE_CONTRACT = {
1259
1359
  "value": "<title>",
1260
1360
  "description": "Terminal tab title. Defaults to the selected agent title or Terminal."
1261
1361
  },
1362
+ {
1363
+ "name": "--url",
1364
+ "value": "<url>",
1365
+ "description": "http(s) or file URL for panels open; pane:// link for links open."
1366
+ },
1367
+ {
1368
+ "name": "--file",
1369
+ "value": "<path>",
1370
+ "description": "File inside the Pane worktree to open; HTML renders in a browser tab."
1371
+ },
1262
1372
  {
1263
1373
  "name": "--initial-input",
1264
1374
  "value": "<text>",
@@ -1270,7 +1380,10 @@ exports.RUNPANE_CONTRACT = {
1270
1380
  {
1271
1381
  "name": "--initial-input-file",
1272
1382
  "value": "<path|->",
1273
- "description": "Read initial input from a file or stdin."
1383
+ "aliases": [
1384
+ "--prompt-file"
1385
+ ],
1386
+ "description": "Read initial input from a file or stdin. --prompt-file is an alias."
1274
1387
  },
1275
1388
  {
1276
1389
  "name": "--from-json",
@@ -1285,7 +1398,7 @@ exports.RUNPANE_CONTRACT = {
1285
1398
  {
1286
1399
  "name": "--ready-timeout-ms",
1287
1400
  "value": "<milliseconds>",
1288
- "description": "Readiness wait timeout for panes create --wait-ready."
1401
+ "description": "Readiness wait timeout for panes create/adopt --wait-ready."
1289
1402
  },
1290
1403
  {
1291
1404
  "name": "--concurrency",
@@ -1390,7 +1503,7 @@ exports.RUNPANE_CONTRACT = {
1390
1503
  {
1391
1504
  "name": "--min-interval",
1392
1505
  "value": "<milliseconds>",
1393
- "description": "Follow-only opt-in: hold non-urgent lines and flush them together at most once per interval; BLOCKED bypasses it."
1506
+ "description": "Follow-only opt-in: hold non-urgent lines and flush them together at most once per interval; BLOCKED, REPORT, PR CONFLICTED, and PR CHECKS FAILED bypass it."
1394
1507
  },
1395
1508
  {
1396
1509
  "name": "--body-file",
@@ -1402,6 +1515,21 @@ exports.RUNPANE_CONTRACT = {
1402
1515
  "value": "<id|name>",
1403
1516
  "description": "Named orchestration Session id or exact name."
1404
1517
  },
1518
+ {
1519
+ "name": "--ttl",
1520
+ "value": "<duration>",
1521
+ "description": "How long a named lock is held before it expires: a number with ms, s, m, or h (such as 30m); a bare number is milliseconds. At least 1s, at most 24h."
1522
+ },
1523
+ {
1524
+ "name": "--wait",
1525
+ "value": "<milliseconds>",
1526
+ "description": "How long lock acquire waits for a held lock to come free; 0 (the default) returns at once."
1527
+ },
1528
+ {
1529
+ "name": "--note",
1530
+ "value": "<text>",
1531
+ "description": "What a named lock is for. Outside a Pane terminal it also names the owner, so pass the same note to release it."
1532
+ },
1405
1533
  {
1406
1534
  "name": "--message",
1407
1535
  "value": "<message>",
@@ -1417,11 +1545,6 @@ exports.RUNPANE_CONTRACT = {
1417
1545
  "value": "<path>",
1418
1546
  "description": "Doc path for docs read."
1419
1547
  },
1420
- {
1421
- "name": "--url",
1422
- "value": "<pane-url>",
1423
- "description": "pane:// link for links open."
1424
- },
1425
1548
  {
1426
1549
  "name": "--toolsets",
1427
1550
  "value": "<name,...>",
@@ -1431,6 +1554,36 @@ exports.RUNPANE_CONTRACT = {
1431
1554
  "name": "--keys",
1432
1555
  "value": "<name,...>",
1433
1556
  "description": "Named keys for panels input, such as down,enter."
1557
+ },
1558
+ {
1559
+ "name": "--state",
1560
+ "value": "<ready|blocked|failed|done>",
1561
+ "description": "Report state for runpane report."
1562
+ },
1563
+ {
1564
+ "name": "--pr",
1565
+ "value": "<number>",
1566
+ "description": "Pull request number for runpane report."
1567
+ },
1568
+ {
1569
+ "name": "--head",
1570
+ "value": "<sha>",
1571
+ "description": "Head commit (7-40 hex characters) for runpane report."
1572
+ },
1573
+ {
1574
+ "name": "--summary",
1575
+ "value": "<text>",
1576
+ "description": "Report summary text; up to 16,000 characters are kept."
1577
+ },
1578
+ {
1579
+ "name": "--summary-file",
1580
+ "value": "<path|->",
1581
+ "description": "Read the report summary from a file or stdin."
1582
+ },
1583
+ {
1584
+ "name": "--question",
1585
+ "value": "<text>",
1586
+ "description": "What a blocked worker needs answered; required with --state blocked."
1434
1587
  }
1435
1588
  ],
1436
1589
  "localBoolean": [
@@ -1450,6 +1603,14 @@ exports.RUNPANE_CONTRACT = {
1450
1603
  "name": "--focus",
1451
1604
  "description": "Explicitly focus the created pane or panel."
1452
1605
  },
1606
+ {
1607
+ "name": "--split",
1608
+ "description": "Open the tab in split view beside the primary tab group (default for panels open)."
1609
+ },
1610
+ {
1611
+ "name": "--tab",
1612
+ "description": "Open the tab in the current tab group instead of split view."
1613
+ },
1453
1614
  {
1454
1615
  "name": "--pinned",
1455
1616
  "description": "Accepted for backward compatibility; `panes create` already pins by default."
@@ -1464,12 +1625,24 @@ exports.RUNPANE_CONTRACT = {
1464
1625
  },
1465
1626
  {
1466
1627
  "name": "--force",
1467
- "description": "Archive even if the pane's branch has uncommitted, untracked, or unpushed changes."
1628
+ "description": "Archive even if the pane's branch has uncommitted, untracked, or unpushed changes; for lock release, release another owner's lock."
1629
+ },
1630
+ {
1631
+ "name": "--remove-worktree",
1632
+ "description": "Also check and remove an adopted Pane's worktree when archiving it. The local branch is kept."
1633
+ },
1634
+ {
1635
+ "name": "--merged",
1636
+ "description": "With panes archive --session, archive only Panes that are clean and pushed, or merged via a pull request."
1468
1637
  },
1469
1638
  {
1470
1639
  "name": "--launch",
1471
1640
  "description": "Run an adopted pane's agent resume command immediately instead of staging it."
1472
1641
  },
1642
+ {
1643
+ "name": "--as-file-pointer",
1644
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
1645
+ },
1473
1646
  {
1474
1647
  "name": "--follow",
1475
1648
  "description": "Continue waiting for workspace events until interrupted."
@@ -1488,7 +1661,7 @@ exports.RUNPANE_CONTRACT = {
1488
1661
  },
1489
1662
  {
1490
1663
  "name": "--all-managed",
1491
- "description": "Watch all non-archived, non-hidden managed panes."
1664
+ "description": "Watch every non-archived, non-hidden managed pane. This is the default scope; the flag states it explicitly and cannot be combined with --pane."
1492
1665
  },
1493
1666
  {
1494
1667
  "name": "--include-shells",
@@ -1496,12 +1669,19 @@ exports.RUNPANE_CONTRACT = {
1496
1669
  },
1497
1670
  {
1498
1671
  "name": "--no-held-input",
1499
- "description": "Disable redacted STUCK detection in lines follow mode."
1672
+ "description": "Disable redacted held-input detection under --follow (STUCK lines, and heldInputPresent in JSON)."
1500
1673
  },
1501
1674
  {
1502
1675
  "name": "--self-test",
1503
1676
  "description": "Probe the current daemon watch path without advancing a named cursor."
1504
1677
  },
1678
+ {
1679
+ "name": "--quiet",
1680
+ "aliases": [
1681
+ "--no-control-lines"
1682
+ ],
1683
+ "description": "Watch only: drop the WATCH OK, HEARTBEAT, and WATCH RECONNECTED control lines (_ok, _heartbeat, _reconnected in JSON). Errors, resets, and dropped counts always print."
1684
+ },
1505
1685
  {
1506
1686
  "name": "--idle-backoff",
1507
1687
  "description": "Follow-only opt-in: IDLE fires at --idle-after, then 30m, 1h, 3h, then daily per panel; any activity resets it."
@@ -1541,12 +1721,16 @@ exports.RUNPANE_CONTRACT = {
1541
1721
  " runpane sessions associate --session <id|name> --pane <pane-id> [--json] [--pane-dir <path>]",
1542
1722
  " runpane sessions detach --session <id|name> [--pane <pane-id>] [--json] [--pane-dir <path>]",
1543
1723
  " runpane sessions overview --session <id|name> [--json] [--pane-dir <path>]",
1724
+ " runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
1725
+ " runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
1726
+ " runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]",
1544
1727
  " runpane panes list [--repo <selector>] [--json]",
1545
1728
  " runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]",
1546
1729
  " runpane workspace state [--repo <selector>] [--json]",
1547
1730
  " runpane watch --follow",
1548
- " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] [--wait-ready]",
1549
- " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--dry-run] --yes",
1731
+ " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--base-branch <branch>] [--source user|agent] [--focus|--no-focus] [--wait-ready]",
1732
+ " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes",
1733
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--dry-run] --yes",
1550
1734
  " runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] --yes",
1551
1735
  " runpane panels list --pane <pane-id> [--json]",
1552
1736
  " runpane panels output --panel <panel-id> [--limit <count>] [--json]",
@@ -1555,6 +1739,7 @@ exports.RUNPANE_CONTRACT = {
1555
1739
  " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
1556
1740
  " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
1557
1741
  " runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--json]",
1742
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json]",
1558
1743
  " runpane panes git-status --pane <pane-id> [--json] [--pane-dir <path>]",
1559
1744
  " runpane panes commit --pane <pane-id> --message <message> --yes [--json] [--pane-dir <path>]",
1560
1745
  " runpane panes push --pane <pane-id> --yes [--json] [--pane-dir <path>]",
@@ -1568,6 +1753,7 @@ exports.RUNPANE_CONTRACT = {
1568
1753
  " runpane agents start --repo <selector> --name <name> (--agent <codex|claude|cursor>|--tool-command <command>) --prompt <task> [--base-branch <branch>] --yes [--json] [--pane-dir <path>]",
1569
1754
  " runpane agents status (--pane <pane-id>|--panel <panel-id>) [--limit <count>] [--json] [--pane-dir <path>]",
1570
1755
  " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]",
1756
+ " runpane report --state <ready|blocked|failed|done> [--pr <number>] [--head <sha>] [--summary-file <path|->] [--question <text>] [--json]",
1571
1757
  " runpane panes squash-rebase --pane <pane-id> --message <message> --yes [--json] [--pane-dir <path>]",
1572
1758
  " runpane panes stash --pane <pane-id> --yes [--json] [--pane-dir <path>]",
1573
1759
  " runpane panes stash-pop --pane <pane-id> --yes [--json] [--pane-dir <path>]",
@@ -1661,7 +1847,7 @@ exports.RUNPANE_CONTRACT = {
1661
1847
  ],
1662
1848
  "version": [
1663
1849
  "Usage:",
1664
- " runpane version",
1850
+ " runpane version [--pane-dir <path>]",
1665
1851
  " runpane --version"
1666
1852
  ],
1667
1853
  "doctor": [
@@ -1732,7 +1918,8 @@ exports.RUNPANE_CONTRACT = {
1732
1918
  " runpane panes list [--repo <selector>] [--json]",
1733
1919
  " runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]",
1734
1920
  " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [options]",
1735
- " runpane panes archive --pane <pane-id> [--force] [--source user|agent] [--dry-run] --yes [--json]",
1921
+ " runpane panes archive --pane <pane-id> [--force] [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json]",
1922
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--dry-run] --yes [--json]",
1736
1923
  " runpane panes pin --pane <pane-id> --yes [--dry-run] [--json]",
1737
1924
  " runpane panes unpin --pane <pane-id> --yes [--dry-run] [--json]",
1738
1925
  " runpane panes rename --pane <pane-id> --name <new-name> --yes [--dry-run] [--json]",
@@ -1745,6 +1932,8 @@ exports.RUNPANE_CONTRACT = {
1745
1932
  "",
1746
1933
  "Lists Pane sessions. Pass --repo to limit results to one saved repository.",
1747
1934
  "",
1935
+ "status is running while any terminal panel is live. agentState is the most urgent state of the live agent panels: blocked, working, ready, or none.",
1936
+ "",
1748
1937
  "Options:",
1749
1938
  " --repo <selector> active, id, exact path, or saved repository name",
1750
1939
  " --pane-dir <path> Connect to a specific Pane data directory",
@@ -1791,15 +1980,18 @@ exports.RUNPANE_CONTRACT = {
1791
1980
  " --idle-after <ms> Re-firing READY idle interval; defaults to 600000 under --follow",
1792
1981
  " --settle <ms> Opt-in: emit READY only after this quiet window (--follow only)",
1793
1982
  " --blocked-settle <ms> Opt-in: emit BLOCKED only after this window (--follow only)",
1794
- " --min-interval <ms> Opt-in: batch non-urgent lines per interval; BLOCKED bypasses (--follow only)",
1983
+ " --min-interval <ms> Opt-in: batch non-urgent lines per interval; BLOCKED, REPORT, and PR failures bypass (--follow only)",
1795
1984
  " --idle-backoff Opt-in: IDLE at --idle-after, 30m, 1h, 3h, then daily (--follow only)",
1796
1985
  " --all-managed Explicitly watch all managed panes",
1797
1986
  " --include-shells Include ordinary shell panels",
1798
1987
  " --agents-only Limit to CLI agent panels",
1799
1988
  " --exclude-pane <id> Exclude a Pane; repeatable",
1800
1989
  " --self-test Anonymous, read-only daemon path probe",
1990
+ " --quiet Drop WATCH OK, HEARTBEAT, and WATCH RECONNECTED lines",
1991
+ " --no-control-lines Alias for --quiet",
1801
1992
  " --kinds <kind,...> Limit event kinds",
1802
1993
  " --pane <id> Limit to a Pane; repeatable",
1994
+ " --session <id|name> Follow every Pane in a named Session; associate/detach apply live",
1803
1995
  " --repo <selector> Limit to a saved repository",
1804
1996
  " --name-contains <text> Limit by Pane name substring",
1805
1997
  " --timeout-ms <ms> Wait timeout; 0 polls once",
@@ -1807,32 +1999,42 @@ exports.RUNPANE_CONTRACT = {
1807
1999
  " --ack-now Use at-most-once named-cursor delivery",
1808
2000
  " --include-held-input Include unsubmitted composer text in JSON",
1809
2001
  " --no-held-input Disable redacted STUCK detection",
2002
+ " --pane-dir <path> Connect to a specific Pane data directory",
1810
2003
  " --json Alias for --format json",
1811
2004
  "",
1812
2005
  "Defaults are responsive: no settle, no batching, all kinds, IDLE every --idle-after. BUSY carries no action; drop it with --kinds.",
1813
- "Expensive consumers opt in: --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
2006
+ "agent.report (a worker ran `runpane report`) is opt-in: list it in --kinds. REPORT lines skip the --min-interval batch.",
2007
+ "Unattended (Pane Chat default): --quiet --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
2008
+ "User present: the same kinds with --settle 60000 --blocked-settle 15000 --min-interval 120000 and no --idle-backoff",
2009
+ "Session orchestrator: runpane watch --session <id|name> --follow --quiet --json --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone,pane.associated,pane.detached,pr.conflicted,pr.checks,pr.merged --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
1814
2010
  "Pane Chat arms those flags itself through its skill; pass them only for your own scripts.",
1815
2011
  "STUCK means real unsubmitted composer text; an agent prompt suggestion never counts.",
1816
- "Dead watch: HEARTBEAT is proof of life only. Judge death by a non-zero exit or a WATCH ERROR line, not by silence."
2012
+ "Dead watch: HEARTBEAT is proof of life only (--quiet drops it). Judge death by a non-zero exit or a WATCH ERROR line, not by silence."
1817
2013
  ],
1818
2014
  "panes create": [
1819
2015
  "Usage:",
1820
- " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [options]",
2016
+ " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options]",
2017
+ " runpane panes create --repo <selector> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options]",
1821
2018
  " runpane panes create --from-json <path|-> [--yes] [--json]",
1822
2019
  "",
1823
2020
  "Creates user-visible Panes (Pane sessions) for feature/PR work in a saved repository and opens a terminal-backed tool tab. Pane creates and owns the worktree/branch for each new Pane.",
1824
2021
  "",
2022
+ "A long or multi-line prompt is never typed into the shell: on bash, zsh or sh the agent launches with `\"$(cat '<prompt file>')\"` reading a private copy under `<pane-dir>/prompts/<pane-id>/`; on PowerShell, cmd, fish or WSL the prompt is pasted into the agent's composer once it is ready.",
2023
+ "",
1825
2024
  "Options:",
1826
2025
  " --repo <selector> active, id, exact path, or saved repository name",
1827
2026
  " --name <name> Pane/session name",
1828
- " --worktree-name <name> Worktree name; defaults to --name",
1829
- " --base-branch <branch> Base branch for the worktree",
1830
- " --agent <codex|claude|cursor> Built-in terminal template",
2027
+ " --worktree-name <name> Worktree directory name; defaults to --name",
2028
+ " --branch <name> Exact new branch name (slashes kept); must not exist; defaults to the worktree name",
2029
+ " --base-branch <ref> Ref to branch from; --base is an alias",
2030
+ " --agent <codex|claude|cursor> Built-in terminal template; with --tool-command, the agent it runs",
1831
2031
  " --tool-command <command> Custom terminal command",
1832
2032
  " --title <title> Terminal tab title",
1833
2033
  " --initial-input <text> Text sent after the command is ready",
1834
2034
  " --prompt <text> Alias for --initial-input",
1835
2035
  " --initial-input-file <path|-> Read initial input from a file or stdin",
2036
+ " --as-file-pointer Send `Read and follow <prompt file>` instead of the prompt",
2037
+ " --prompt-file <path|-> Alias for --initial-input-file",
1836
2038
  " --from-json <path|-> Read a full request payload",
1837
2039
  " --timeout-ms <milliseconds> Pane creation timeout",
1838
2040
  " --wait-ready Wait for terminal readiness before returning",
@@ -1852,21 +2054,28 @@ exports.RUNPANE_CONTRACT = {
1852
2054
  "panes adopt": [
1853
2055
  "Usage:",
1854
2056
  " runpane panes adopt --repo <selector> --path <dir> --name <name> --agent <codex|claude|cursor> [options]",
2057
+ " runpane panes adopt --repo <selector> --path <dir> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [options]",
2058
+ "",
2059
+ "Adopts an existing externally managed git worktree without creating, syncing, or deleting it. Archiving only removes its worktree with `panes archive --remove-worktree`. To start new work on a named branch, use `panes create --base <ref> --branch <name>` instead of `git worktree add` plus adopt.",
1855
2060
  "",
1856
- "Adopts an existing externally managed git worktree without creating, syncing, or deleting it.",
2061
+ "Options: --resume <id> stages the agent resume command (built-in agents only); --launch runs the command immediately; --prompt <text> or --prompt-file <path|-> and --wait-ready require --launch; --folder <name> groups the pane; --no-pinned opts out of pinning; --no-associate skips automatic Session association; --dry-run previews.",
1857
2062
  "",
1858
- "Options: --resume <id> stages the agent resume command; --launch runs it immediately; --folder <name> groups the pane; --no-pinned opts out of pinning; --no-associate skips automatic Session association; --dry-run previews."
2063
+ "With --tool-command, --agent names the agent the command runs (a wrapper such as `agent-farm run`): Pane launches the command unchanged and treats the panel as that agent. Without --agent, Pane detects Claude Code, Codex and Cursor from the foreground process or the agent's screen."
1859
2064
  ],
1860
2065
  "panes archive": [
1861
2066
  "Usage:",
1862
- " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--dry-run] --yes [--json]",
2067
+ " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes [--json]",
2068
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json]",
1863
2069
  "",
1864
- "Archives a Pane (session) exactly like the UI Archive action, including removal of its Pane-managed git worktree. Refreshes the configured upstream before checking for unpushed commits and reports exact commit evidence. Refuses unsafe archives unless --force is passed. Use --dry-run to print the evidence without mutating Pane state.",
2070
+ "Archives a Pane (session) exactly like the UI Archive action, including removal of its Pane-managed git worktree. Refreshes the configured upstream before checking for unpushed commits and reports exact commit evidence. When the branch has no upstream or its upstream is gone, a merged GitHub pull request whose head is HEAD (found with `gh`) counts as pushed. Refuses unsafe archives unless --force is passed. An adopted worktree is kept unless --remove-worktree is passed, which applies the same safety check and removal. The local branch is always kept. With --session and --merged, archives every Pane associated with the Session whose work is clean and pushed or merged, and reports a reason for each Pane it skips. Use --dry-run to print the evidence without mutating Pane state.",
1865
2071
  "",
1866
2072
  "Options:",
1867
2073
  " --pane <pane-id> Pane/session id to archive",
1868
2074
  " --source <user|agent> Mark mutation source",
1869
2075
  " --force Archive even if the pane has uncommitted, untracked, or unpushed changes",
2076
+ " --remove-worktree Also check and remove an adopted Pane's worktree (the branch is kept)",
2077
+ " --session <id|name> Archive the Panes associated with this Session (requires --merged)",
2078
+ " --merged Only archive Panes that are clean and pushed, or merged via a PR",
1870
2079
  " --pane-dir <path> Connect to a specific Pane data directory",
1871
2080
  " --json Print machine-readable output",
1872
2081
  " --dry-run Refresh and print archive safety evidence without archiving",
@@ -1934,6 +2143,7 @@ exports.RUNPANE_CONTRACT = {
1934
2143
  "",
1935
2144
  "Commands:",
1936
2145
  " runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [options]",
2146
+ " runpane panels open (--url <url>|--file <path>) [--split|--tab] --yes [--json]",
1937
2147
  " runpane panels list --pane <pane-id> [--json]",
1938
2148
  " runpane panels screen --panel <panel-id> [--limit <count>] [--json]",
1939
2149
  " runpane panels output --panel <panel-id> [--limit <count>] [--json]",
@@ -1941,6 +2151,7 @@ exports.RUNPANE_CONTRACT = {
1941
2151
  " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
1942
2152
  " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
1943
2153
  " runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--json]",
2154
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json]",
1944
2155
  "",
1945
2156
  "Run \"runpane help panels create\" or another command-specific topic for options."
1946
2157
  ],
@@ -1950,6 +2161,8 @@ exports.RUNPANE_CONTRACT = {
1950
2161
  "",
1951
2162
  "Lists tool panels in a Pane session.",
1952
2163
  "",
2164
+ "agentDetection says how Pane knows agentType: declared, command, process, or screen. launchCommand is the command the panel was launched with.",
2165
+ "",
1953
2166
  "Options:",
1954
2167
  " --pane <pane-id> Pane/session id",
1955
2168
  " --pane-dir <path> Connect to a specific Pane data directory",
@@ -1992,6 +2205,7 @@ exports.RUNPANE_CONTRACT = {
1992
2205
  "Options:",
1993
2206
  " --command <command> Print the full definition for one runpane command",
1994
2207
  " --json Print machine-readable output",
2208
+ " --pane-dir <path> Accepted and ignored; agent-context never contacts Pane",
1995
2209
  "",
1996
2210
  "Examples:",
1997
2211
  " runpane agent-context",
@@ -2040,14 +2254,21 @@ exports.RUNPANE_CONTRACT = {
2040
2254
  ],
2041
2255
  "panels submit": [
2042
2256
  "Usage:",
2043
- " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
2257
+ " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) [--as-file-pointer] --yes [--json]",
2044
2258
  "",
2045
2259
  "Sends text to a terminal panel and normalizes the final terminal Enter to CR. Use this for ordinary prompt answers and shell commands.",
2046
2260
  "",
2261
+ "For a Claude or Codex panel with no composer on screen, nothing is sent: the result is ok: false with blocked.kind composer-unknown.",
2262
+ "",
2263
+ "Multi-line or long (over 512 characters) text reaches a Claude or Codex composer as one bracketed paste: CRLF becomes LF, and the submit key goes as its own write once the paste has settled, even while the agent is working.",
2264
+ "",
2265
+ "For Claude, text starting with `!`, `#`, `/` or `@` is sent unchanged and the result carries a `warnings` entry (for example `leading-bang-runs-shell`), because Claude Code gives those characters a meaning of its own.",
2266
+ "",
2047
2267
  "Options:",
2048
2268
  " --panel <panel-id> Terminal panel id",
2049
2269
  " --text <text> Text to submit before Enter",
2050
2270
  " --input-file <path|-> Read text from a file or stdin before Enter",
2271
+ " --as-file-pointer Write the text to a prompt file and submit `Read and follow <path>`",
2051
2272
  " --pane-dir <path> Connect to a specific Pane data directory",
2052
2273
  " --json Print machine-readable output",
2053
2274
  " --yes Skip confirmation for this mutating command"
@@ -2072,15 +2293,16 @@ exports.RUNPANE_CONTRACT = {
2072
2293
  "",
2073
2294
  "Usage:",
2074
2295
  " runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--title <title>] [--initial-input <text>] [--no-focus] [--wait-ready] --yes [--json]",
2075
- " runpane panels create --pane <pane-id> --tool-command <command> [--title <title>] [--no-focus] --yes [--json]",
2296
+ " runpane panels create --pane <pane-id> --tool-command <command> [--agent <codex|claude|cursor>] [--title <title>] [--no-focus] [--wait-ready] --yes [--json]",
2076
2297
  "",
2077
2298
  "Options:",
2078
2299
  " --pane <pane-id> Existing Pane session to add the panel to.",
2079
- " --agent <codex|claude|cursor> Built-in agent command template to launch.",
2300
+ " --agent <codex|claude|cursor> Built-in agent command template, or with --tool-command the agent it runs.",
2080
2301
  " --tool-command <command> Custom terminal command to launch.",
2081
2302
  " --title <title> Panel title override.",
2082
2303
  " --initial-input, --prompt Initial input to send after the tool starts.",
2083
2304
  " --initial-input-file <path|-> Read initial input from a file or stdin.",
2305
+ " --as-file-pointer Send `Read and follow <prompt file>` instead of the prompt.",
2084
2306
  " --no-focus Create the panel in the background.",
2085
2307
  " --focus Explicitly focus the created panel.",
2086
2308
  " --source <user|agent> Mark the mutation source; agent implies background creation.",
@@ -2089,6 +2311,28 @@ exports.RUNPANE_CONTRACT = {
2089
2311
  " --yes Skip confirmation prompts.",
2090
2312
  " --json Print JSON output."
2091
2313
  ],
2314
+ "panels open": [
2315
+ "Open a URL or file as a browser/editor tab in a Pane, in split view beside the agent by default.",
2316
+ "",
2317
+ "Usage:",
2318
+ " runpane panels open [--pane <pane-id>] (--url <url>|--file <path>) [--title <title>] [--split|--tab] [--focus|--no-focus] [--source user|agent] --yes [--json]",
2319
+ "",
2320
+ "Opens a tab inside a Pane (default: the Pane of the calling panel, from PANE_SESSION_ID). Use it to show the user an HTML page, plan, report, local dev server, or file beside the conversation. --url opens a browser tab (http, https, or file). --file opens a file inside the Pane worktree: .html/.htm files render in a browser tab, other files open in an editor tab. Tabs open in split view beside the agent by default; --tab keeps them in the current group. An existing tab showing the same URL or file is reused. Never raises or focuses the Pane window.",
2321
+ "",
2322
+ "Options:",
2323
+ " --pane <pane-id> Pane to open the tab in; defaults to PANE_SESSION_ID.",
2324
+ " --url <url> http(s) or file URL to open in a browser tab.",
2325
+ " --file <path> File inside the Pane worktree (relative or absolute).",
2326
+ " --title <title> Tab title override.",
2327
+ " --split Open in split view beside the agent (default).",
2328
+ " --tab Open in the current tab group instead.",
2329
+ " --no-focus Open without selecting the tab.",
2330
+ " --focus Select the tab (default); never raises the window.",
2331
+ " --source <user|agent> Mutation source.",
2332
+ " --pane-dir <path> Connect to a specific Pane data directory.",
2333
+ " --yes Skip confirmation prompts.",
2334
+ " --json Print JSON output."
2335
+ ],
2092
2336
  "panels submit-composer": [
2093
2337
  "Submit an agent composer using the panel-appropriate key sequence.",
2094
2338
  "",
@@ -2097,7 +2341,7 @@ exports.RUNPANE_CONTRACT = {
2097
2341
  "",
2098
2342
  "Options:",
2099
2343
  " --panel <panel-id> Terminal panel id.",
2100
- " --strategy <strategy> Defaults to auto; Codex queues with Tab while working and submits with Enter when ready.",
2344
+ " --strategy <strategy> Defaults to auto; Codex queues with Tab while working and submits with Enter when ready. auto retries once if the text is still in the composer.",
2101
2345
  " --yes Skip confirmation prompts.",
2102
2346
  " --json Print JSON output."
2103
2347
  ],
@@ -2463,7 +2707,7 @@ exports.RUNPANE_CONTRACT = {
2463
2707
  ],
2464
2708
  "agents send": [
2465
2709
  "Usage:",
2466
- " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]",
2710
+ " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> [--as-file-pointer] --yes [--json] [--pane-dir <path>]",
2467
2711
  "",
2468
2712
  "Send a follow-up message to an agent and confirm it was submitted.",
2469
2713
  "",
@@ -2471,6 +2715,7 @@ exports.RUNPANE_CONTRACT = {
2471
2715
  " --pane <pane-id> Pane id; its agent panel is used.",
2472
2716
  " --panel <panel-id> Panel id.",
2473
2717
  " --text <message> The message to submit.",
2718
+ " --as-file-pointer Write the message to a prompt file and send `Read and follow <path>`.",
2474
2719
  " --yes Confirm this change; required in non-interactive shells.",
2475
2720
  " --json Print machine-readable output.",
2476
2721
  " --pane-dir <path> Connect to a specific Pane data directory."
@@ -2480,6 +2725,96 @@ exports.RUNPANE_CONTRACT = {
2480
2725
  " runpane sessions <list|create|get|update|set-agent|associate|detach|overview> [options]",
2481
2726
  "",
2482
2727
  "Use a named Session to keep context, activity, and evidence attached to one orchestration thread."
2728
+ ],
2729
+ "report": [
2730
+ "Usage:",
2731
+ " runpane report --state <ready|blocked|failed|done> [--pr <number>] [--head <sha>] [--summary <text>|--summary-file <path|->] [--question <text>] [--pane <pane-id> --panel <panel-id>] [--json] [--pane-dir <path>]",
2732
+ "",
2733
+ "Hands back a worker's structured report for its panel: the orchestrator receives it as an",
2734
+ "agent.report watch event and reads it in `agents status` and `sessions overview`.",
2735
+ "Inside a Pane terminal the panel comes from PANE_SESSION_ID and PANE_PANEL_ID.",
2736
+ "",
2737
+ "Options:",
2738
+ " --state <state> ready, blocked, failed, or done",
2739
+ " --pr <number> Pull request number",
2740
+ " --head <sha> Head commit, 7-40 hex characters",
2741
+ " --summary <text> Summary text; up to 16,000 characters are kept",
2742
+ " --summary-file <path|-> Read the summary from a file or stdin",
2743
+ " --question <text> What you need answered; required with --state blocked",
2744
+ " --pane <pane-id> Pane id when not running inside a Pane terminal",
2745
+ " --panel <panel-id> Panel id when not running inside a Pane terminal",
2746
+ " --pane-dir <path> Connect to a specific Pane data directory",
2747
+ " --json Print machine-readable output",
2748
+ "",
2749
+ "Example:",
2750
+ " runpane report --state ready --pr 747 --head fc5dce9 --summary-file /tmp/report.md"
2751
+ ],
2752
+ "panels last-message": [
2753
+ "Usage:",
2754
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]",
2755
+ "",
2756
+ "Reads a Claude or Codex agent's last reply from its transcript. It never scrapes the screen:",
2757
+ "without a transcript it reports transcript-unavailable and exits non-zero.",
2758
+ "",
2759
+ "Options:",
2760
+ " --panel <panel-id> Agent panel id",
2761
+ " --limit <count> Maximum characters to return; defaults to 20000 (the end is kept)",
2762
+ " --pane-dir <path> Connect to a specific Pane data directory",
2763
+ " --json Print machine-readable output"
2764
+ ],
2765
+ "lock": [
2766
+ "Usage:",
2767
+ " runpane lock <acquire|release|list> [options]",
2768
+ "",
2769
+ "Named locks coordinate a resource shared between agents, such as one test account.",
2770
+ "The caller is the owner: the Pane and panel from $PANE_SESSION_ID and $PANE_PANEL_ID.",
2771
+ "A lock is scoped to the owner's Session when its Pane belongs to one; otherwise it is global.",
2772
+ "It is released on --ttl expiry, when the owner panel exits, or when the owner Pane is archived."
2773
+ ],
2774
+ "lock acquire": [
2775
+ "Usage:",
2776
+ "runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
2777
+ "",
2778
+ "Options:",
2779
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
2780
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
2781
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
2782
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
2783
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
2784
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
2785
+ " --force Release a lock another owner holds (release).",
2786
+ " --session <id|name> Named Session whose locks to list or release.",
2787
+ " --json Print JSON output."
2788
+ ],
2789
+ "lock release": [
2790
+ "Usage:",
2791
+ "runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
2792
+ "",
2793
+ "Options:",
2794
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
2795
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
2796
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
2797
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
2798
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
2799
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
2800
+ " --force Release a lock another owner holds (release).",
2801
+ " --session <id|name> Named Session whose locks to list or release.",
2802
+ " --json Print JSON output."
2803
+ ],
2804
+ "lock list": [
2805
+ "Usage:",
2806
+ "runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]",
2807
+ "",
2808
+ "Options:",
2809
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
2810
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
2811
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
2812
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
2813
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
2814
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
2815
+ " --force Release a lock another owner holds (release).",
2816
+ " --session <id|name> Named Session whose locks to list or release.",
2817
+ " --json Print JSON output."
2483
2818
  ]
2484
2819
  },
2485
2820
  "pip": {
@@ -2502,8 +2837,9 @@ exports.RUNPANE_CONTRACT = {
2502
2837
  " runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]",
2503
2838
  " runpane workspace state [--repo <selector>] [--json]",
2504
2839
  " runpane watch --follow",
2505
- " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] [--wait-ready]",
2506
- " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--dry-run] --yes",
2840
+ " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--base-branch <branch>] [--source user|agent] [--focus|--no-focus] [--wait-ready]",
2841
+ " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes",
2842
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--dry-run] --yes",
2507
2843
  " python -m runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] --yes",
2508
2844
  " runpane panels list --pane <pane-id> [--json]",
2509
2845
  " runpane panels output --panel <panel-id> [--limit <count>] [--json]",
@@ -2512,6 +2848,7 @@ exports.RUNPANE_CONTRACT = {
2512
2848
  " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
2513
2849
  " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
2514
2850
  " runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--json]",
2851
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json]",
2515
2852
  " runpane panes git-status --pane <pane-id> [--json] [--pane-dir <path>]",
2516
2853
  " runpane panes commit --pane <pane-id> --message <message> --yes [--json] [--pane-dir <path>]",
2517
2854
  " runpane panes push --pane <pane-id> --yes [--json] [--pane-dir <path>]",
@@ -2525,6 +2862,7 @@ exports.RUNPANE_CONTRACT = {
2525
2862
  " runpane agents start --repo <selector> --name <name> (--agent <codex|claude|cursor>|--tool-command <command>) --prompt <task> [--base-branch <branch>] --yes [--json] [--pane-dir <path>]",
2526
2863
  " runpane agents status (--pane <pane-id>|--panel <panel-id>) [--limit <count>] [--json] [--pane-dir <path>]",
2527
2864
  " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]",
2865
+ " runpane report --state <ready|blocked|failed|done> [--pr <number>] [--head <sha>] [--summary-file <path|->] [--question <text>] [--json]",
2528
2866
  " runpane panes squash-rebase --pane <pane-id> --message <message> --yes [--json] [--pane-dir <path>]",
2529
2867
  " runpane panes stash --pane <pane-id> --yes [--json] [--pane-dir <path>]",
2530
2868
  " runpane panes stash-pop --pane <pane-id> --yes [--json] [--pane-dir <path>]",
@@ -2535,6 +2873,9 @@ exports.RUNPANE_CONTRACT = {
2535
2873
  " runpane panes move --pane <pane-id> --folder <folder-id> --yes [--json] [--pane-dir <path>]",
2536
2874
  " runpane folders list --repo <repo-id> [--json] [--pane-dir <path>]",
2537
2875
  " runpane folders create --repo <repo-id> --name <name> --yes [--json] [--pane-dir <path>]",
2876
+ " runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
2877
+ " runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
2878
+ " runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]",
2538
2879
  " runpane help [command]",
2539
2880
  "",
2540
2881
  "Quick start:",
@@ -2607,7 +2948,7 @@ exports.RUNPANE_CONTRACT = {
2607
2948
  ],
2608
2949
  "version": [
2609
2950
  "Usage:",
2610
- " runpane version",
2951
+ " runpane version [--pane-dir <path>]",
2611
2952
  " runpane --version"
2612
2953
  ],
2613
2954
  "doctor": [
@@ -2678,7 +3019,8 @@ exports.RUNPANE_CONTRACT = {
2678
3019
  " runpane panes list [--repo <selector>] [--json]",
2679
3020
  " runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]",
2680
3021
  " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [options]",
2681
- " runpane panes archive --pane <pane-id> [--force] [--source user|agent] [--dry-run] --yes [--json]",
3022
+ " runpane panes archive --pane <pane-id> [--force] [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json]",
3023
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--dry-run] --yes [--json]",
2682
3024
  " runpane panes pin --pane <pane-id> --yes [--dry-run] [--json]",
2683
3025
  " runpane panes unpin --pane <pane-id> --yes [--dry-run] [--json]",
2684
3026
  " runpane panes rename --pane <pane-id> --name <new-name> --yes [--dry-run] [--json]",
@@ -2691,6 +3033,8 @@ exports.RUNPANE_CONTRACT = {
2691
3033
  "",
2692
3034
  "Lists Pane sessions. Pass --repo to limit results to one saved repository.",
2693
3035
  "",
3036
+ "status is running while any terminal panel is live. agentState is the most urgent state of the live agent panels: blocked, working, ready, or none.",
3037
+ "",
2694
3038
  "Options:",
2695
3039
  " --repo <selector>",
2696
3040
  " --pane-dir <path>",
@@ -2737,15 +3081,18 @@ exports.RUNPANE_CONTRACT = {
2737
3081
  " --idle-after <ms>",
2738
3082
  " --settle <ms> Opt-in READY quiet window (--follow only)",
2739
3083
  " --blocked-settle <ms> Opt-in BLOCKED window (--follow only)",
2740
- " --min-interval <ms> Opt-in batching; BLOCKED bypasses (--follow only)",
3084
+ " --min-interval <ms> Opt-in batching; BLOCKED, REPORT, and PR failures bypass (--follow only)",
2741
3085
  " --idle-backoff Opt-in IDLE backoff (--follow only)",
2742
3086
  " --all-managed",
2743
3087
  " --include-shells",
2744
3088
  " --agents-only",
2745
3089
  " --exclude-pane <id> Repeatable",
2746
3090
  " --self-test",
3091
+ " --quiet Drop OK, HEARTBEAT, and RECONNECTED lines",
3092
+ " --no-control-lines Alias for --quiet",
2747
3093
  " --kinds <kind,...>",
2748
3094
  " --pane <id> Repeatable",
3095
+ " --session <id|name> Follow a named Session's Panes; no re-arm",
2749
3096
  " --repo <selector>",
2750
3097
  " --name-contains <text>",
2751
3098
  " --timeout-ms <ms> 0 polls once",
@@ -2753,32 +3100,42 @@ exports.RUNPANE_CONTRACT = {
2753
3100
  " --ack-now",
2754
3101
  " --include-held-input",
2755
3102
  " --no-held-input",
3103
+ " --pane-dir <path> Connect to a specific Pane data directory",
2756
3104
  " --json Alias for --format json",
2757
3105
  "",
2758
3106
  "Defaults are responsive: no settle, no batching, all kinds, IDLE every --idle-after. BUSY carries no action; drop it with --kinds.",
2759
- "Expensive consumers opt in: --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
3107
+ "agent.report (a worker ran `runpane report`) is opt-in: list it in --kinds. REPORT lines skip the --min-interval batch.",
3108
+ "Unattended (Pane Chat default): --quiet --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
3109
+ "User present: the same kinds with --settle 60000 --blocked-settle 15000 --min-interval 120000 and no --idle-backoff",
3110
+ "Session orchestrator: runpane watch --session <id|name> --follow --quiet --json --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone,pane.associated,pane.detached,pr.conflicted,pr.checks,pr.merged --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
2760
3111
  "Pane Chat arms those flags itself through its skill; pass them only for your own scripts.",
2761
3112
  "STUCK means real unsubmitted composer text; an agent prompt suggestion never counts.",
2762
- "Dead watch: HEARTBEAT is proof of life only. Judge death by a non-zero exit or a WATCH ERROR line, not by silence."
3113
+ "Dead watch: HEARTBEAT is proof of life only (--quiet drops it). Judge death by a non-zero exit or a WATCH ERROR line, not by silence."
2763
3114
  ],
2764
3115
  "panes create": [
2765
3116
  "Usage:",
2766
- " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [options]",
3117
+ " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options]",
3118
+ " python -m runpane panes create --repo <selector> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options]",
2767
3119
  " runpane panes create --from-json <path|-> [--yes] [--json]",
2768
3120
  "",
2769
3121
  "Creates user-visible Panes (Pane sessions) for feature/PR work in a saved repository and opens a terminal-backed tool tab. Pane creates and owns the worktree/branch for each new Pane.",
2770
3122
  "",
3123
+ "A long or multi-line prompt is never typed into the shell: on bash, zsh or sh the agent launches with `\"$(cat '<prompt file>')\"` reading a private copy under `<pane-dir>/prompts/<pane-id>/`; on PowerShell, cmd, fish or WSL the prompt is pasted into the agent's composer once it is ready.",
3124
+ "",
2771
3125
  "Options:",
2772
3126
  " --repo <selector> active, id, exact path, or saved repository name",
2773
3127
  " --name <name> Pane/session name",
2774
- " --worktree-name <name> Worktree name; defaults to --name",
2775
- " --base-branch <branch> Base branch for the worktree",
2776
- " --agent <codex|claude|cursor> Built-in terminal template",
3128
+ " --worktree-name <name> Worktree directory name; defaults to --name",
3129
+ " --branch <name> Exact new branch name (slashes kept); must not exist; defaults to the worktree name",
3130
+ " --base-branch <ref> Ref to branch from; --base is an alias",
3131
+ " --agent <codex|claude|cursor> Built-in terminal template; with --tool-command, the agent it runs",
2777
3132
  " --tool-command <command> Custom terminal command",
2778
3133
  " --title <title> Terminal tab title",
2779
3134
  " --initial-input <text> Text sent after the command is ready",
2780
3135
  " --prompt <text> Alias for --initial-input",
2781
3136
  " --initial-input-file <path|-> Read initial input from a file or stdin",
3137
+ " --as-file-pointer Send `Read and follow <prompt file>` instead of the prompt",
3138
+ " --prompt-file <path|-> Alias for --initial-input-file",
2782
3139
  " --from-json <path|-> Read a full request payload",
2783
3140
  " --timeout-ms <milliseconds> Pane creation timeout",
2784
3141
  " --wait-ready Wait for terminal readiness before returning",
@@ -2798,21 +3155,28 @@ exports.RUNPANE_CONTRACT = {
2798
3155
  "panes adopt": [
2799
3156
  "Usage:",
2800
3157
  " runpane panes adopt --repo <selector> --path <dir> --name <name> --agent <codex|claude|cursor> [options]",
3158
+ " runpane panes adopt --repo <selector> --path <dir> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [options]",
2801
3159
  "",
2802
- "Adopts an existing externally managed git worktree without creating, syncing, or deleting it.",
3160
+ "Adopts an existing externally managed git worktree without creating, syncing, or deleting it. Archiving only removes its worktree with `panes archive --remove-worktree`. To start new work on a named branch, use `panes create --base <ref> --branch <name>` instead of `git worktree add` plus adopt.",
2803
3161
  "",
2804
- "Options: --resume <id> stages the agent resume command; --launch runs it immediately; --folder <name> groups the pane; --no-pinned opts out of pinning; --no-associate skips automatic Session association; --dry-run previews."
3162
+ "Options: --resume <id> stages the agent resume command (built-in agents only); --launch runs the command immediately; --prompt <text> or --prompt-file <path|-> and --wait-ready require --launch; --folder <name> groups the pane; --no-pinned opts out of pinning; --no-associate skips automatic Session association; --dry-run previews.",
3163
+ "",
3164
+ "With --tool-command, --agent names the agent the command runs (a wrapper such as `agent-farm run`): Pane launches the command unchanged and treats the panel as that agent. Without --agent, Pane detects Claude Code, Codex and Cursor from the foreground process or the agent's screen."
2805
3165
  ],
2806
3166
  "panes archive": [
2807
3167
  "Usage:",
2808
- " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--dry-run] --yes [--json]",
3168
+ " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes [--json]",
3169
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json]",
2809
3170
  "",
2810
- "Archives a Pane (session) exactly like the UI Archive action, including removal of its Pane-managed git worktree. Refreshes the configured upstream before checking for unpushed commits and reports exact commit evidence. Refuses unsafe archives unless --force is passed. Use --dry-run to print the evidence without mutating Pane state.",
3171
+ "Archives a Pane (session) exactly like the UI Archive action, including removal of its Pane-managed git worktree. Refreshes the configured upstream before checking for unpushed commits and reports exact commit evidence. When the branch has no upstream or its upstream is gone, a merged GitHub pull request whose head is HEAD (found with `gh`) counts as pushed. Refuses unsafe archives unless --force is passed. An adopted worktree is kept unless --remove-worktree is passed, which applies the same safety check and removal. The local branch is always kept. With --session and --merged, archives every Pane associated with the Session whose work is clean and pushed or merged, and reports a reason for each Pane it skips. Use --dry-run to print the evidence without mutating Pane state.",
2811
3172
  "",
2812
3173
  "Options:",
2813
3174
  " --pane <pane-id>",
2814
3175
  " --source <user|agent>",
2815
3176
  " --force",
3177
+ " --remove-worktree",
3178
+ " --session <id|name>",
3179
+ " --merged",
2816
3180
  " --pane-dir <path>",
2817
3181
  " --json",
2818
3182
  " --dry-run",
@@ -2880,6 +3244,7 @@ exports.RUNPANE_CONTRACT = {
2880
3244
  "",
2881
3245
  "Commands:",
2882
3246
  " runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [options]",
3247
+ " runpane panels open (--url <url>|--file <path>) [--split|--tab] --yes [--json]",
2883
3248
  " runpane panels list --pane <pane-id> [--json]",
2884
3249
  " runpane panels screen --panel <panel-id> [--limit <count>] [--json]",
2885
3250
  " runpane panels output --panel <panel-id> [--limit <count>] [--json]",
@@ -2887,6 +3252,7 @@ exports.RUNPANE_CONTRACT = {
2887
3252
  " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
2888
3253
  " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
2889
3254
  " runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--json]",
3255
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json]",
2890
3256
  "",
2891
3257
  "Run \"runpane help panels create\" or another command-specific topic for options."
2892
3258
  ],
@@ -2896,6 +3262,8 @@ exports.RUNPANE_CONTRACT = {
2896
3262
  "",
2897
3263
  "Lists tool panels in a Pane session.",
2898
3264
  "",
3265
+ "agentDetection says how Pane knows agentType: declared, command, process, or screen. launchCommand is the command the panel was launched with.",
3266
+ "",
2899
3267
  "Options:",
2900
3268
  " --pane <pane-id>",
2901
3269
  " --pane-dir <path>",
@@ -2938,6 +3306,7 @@ exports.RUNPANE_CONTRACT = {
2938
3306
  "Options:",
2939
3307
  " --command <command>",
2940
3308
  " --json",
3309
+ " --pane-dir <path> Accepted and ignored",
2941
3310
  "",
2942
3311
  "Examples:",
2943
3312
  " runpane agent-context",
@@ -2978,14 +3347,21 @@ exports.RUNPANE_CONTRACT = {
2978
3347
  ],
2979
3348
  "panels submit": [
2980
3349
  "Usage:",
2981
- " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
3350
+ " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) [--as-file-pointer] --yes [--json]",
2982
3351
  "",
2983
3352
  "Sends text to a terminal panel and normalizes the final terminal Enter to CR. Use this for ordinary prompt answers and shell commands.",
2984
3353
  "",
3354
+ "For a Claude or Codex panel with no composer on screen, nothing is sent: the result is ok: false with blocked.kind composer-unknown.",
3355
+ "",
3356
+ "Multi-line or long (over 512 characters) text reaches a Claude or Codex composer as one bracketed paste: CRLF becomes LF, and the submit key goes as its own write once the paste has settled, even while the agent is working.",
3357
+ "",
3358
+ "For Claude, text starting with `!`, `#`, `/` or `@` is sent unchanged and the result carries a `warnings` entry (for example `leading-bang-runs-shell`), because Claude Code gives those characters a meaning of its own.",
3359
+ "",
2985
3360
  "Options:",
2986
3361
  " --panel <panel-id> Terminal panel id",
2987
3362
  " --text <text> Text to submit before Enter",
2988
3363
  " --input-file <path|-> Read text from a file or stdin before Enter",
3364
+ " --as-file-pointer Write the text to a prompt file and submit `Read and follow <path>`",
2989
3365
  " --pane-dir <path> Connect to a specific Pane data directory",
2990
3366
  " --json Print machine-readable output",
2991
3367
  " --yes Skip confirmation for this mutating command"
@@ -3010,15 +3386,16 @@ exports.RUNPANE_CONTRACT = {
3010
3386
  "",
3011
3387
  "Usage:",
3012
3388
  " python -m runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--title <title>] [--initial-input <text>] [--no-focus] [--wait-ready] --yes [--json]",
3013
- " python -m runpane panels create --pane <pane-id> --tool-command <command> [--title <title>] [--no-focus] --yes [--json]",
3389
+ " python -m runpane panels create --pane <pane-id> --tool-command <command> [--agent <codex|claude|cursor>] [--title <title>] [--no-focus] [--wait-ready] --yes [--json]",
3014
3390
  "",
3015
3391
  "Options:",
3016
3392
  " --pane <pane-id> Existing Pane session to add the panel to.",
3017
- " --agent <codex|claude|cursor> Built-in agent command template to launch.",
3393
+ " --agent <codex|claude|cursor> Built-in agent command template, or with --tool-command the agent it runs.",
3018
3394
  " --tool-command <command> Custom terminal command to launch.",
3019
3395
  " --title <title> Panel title override.",
3020
3396
  " --initial-input, --prompt Initial input to send after the tool starts.",
3021
3397
  " --initial-input-file <path|-> Read initial input from a file or stdin.",
3398
+ " --as-file-pointer Send `Read and follow <prompt file>` instead of the prompt.",
3022
3399
  " --no-focus Create the panel in the background.",
3023
3400
  " --focus Explicitly focus the created panel.",
3024
3401
  " --source <user|agent> Mark the mutation source; agent implies background creation.",
@@ -3027,6 +3404,28 @@ exports.RUNPANE_CONTRACT = {
3027
3404
  " --yes Skip confirmation prompts.",
3028
3405
  " --json Print JSON output."
3029
3406
  ],
3407
+ "panels open": [
3408
+ "Open a URL or file as a browser/editor tab in a Pane, in split view beside the agent by default.",
3409
+ "",
3410
+ "Usage:",
3411
+ " python -m runpane panels open [--pane <pane-id>] (--url <url>|--file <path>) [--title <title>] [--split|--tab] [--focus|--no-focus] [--source user|agent] --yes [--json]",
3412
+ "",
3413
+ "Opens a tab inside a Pane (default: the Pane of the calling panel, from PANE_SESSION_ID). Use it to show the user an HTML page, plan, report, local dev server, or file beside the conversation. --url opens a browser tab (http, https, or file). --file opens a file inside the Pane worktree: .html/.htm files render in a browser tab, other files open in an editor tab. Tabs open in split view beside the agent by default; --tab keeps them in the current group. An existing tab showing the same URL or file is reused. Never raises or focuses the Pane window.",
3414
+ "",
3415
+ "Options:",
3416
+ " --pane <pane-id> Pane to open the tab in; defaults to PANE_SESSION_ID.",
3417
+ " --url <url> http(s) or file URL to open in a browser tab.",
3418
+ " --file <path> File inside the Pane worktree (relative or absolute).",
3419
+ " --title <title> Tab title override.",
3420
+ " --split Open in split view beside the agent (default).",
3421
+ " --tab Open in the current tab group instead.",
3422
+ " --no-focus Open without selecting the tab.",
3423
+ " --focus Select the tab (default); never raises the window.",
3424
+ " --source <user|agent> Mutation source.",
3425
+ " --pane-dir <path> Connect to a specific Pane data directory.",
3426
+ " --yes Skip confirmation prompts.",
3427
+ " --json Print JSON output."
3428
+ ],
3030
3429
  "panels submit-composer": [
3031
3430
  "Submit an agent composer using the panel-appropriate key sequence.",
3032
3431
  "",
@@ -3035,7 +3434,7 @@ exports.RUNPANE_CONTRACT = {
3035
3434
  "",
3036
3435
  "Options:",
3037
3436
  " --panel <panel-id> Terminal panel id.",
3038
- " --strategy <strategy> Defaults to auto; Codex queues with Tab while working and submits with Enter when ready.",
3437
+ " --strategy <strategy> Defaults to auto; Codex queues with Tab while working and submits with Enter when ready. auto retries once if the text is still in the composer.",
3039
3438
  " --yes Skip confirmation prompts.",
3040
3439
  " --json Print JSON output."
3041
3440
  ],
@@ -3378,7 +3777,7 @@ exports.RUNPANE_CONTRACT = {
3378
3777
  ],
3379
3778
  "agents send": [
3380
3779
  "Usage:",
3381
- " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]",
3780
+ " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> [--as-file-pointer] --yes [--json] [--pane-dir <path>]",
3382
3781
  "",
3383
3782
  "`runpane agents send` ships in the npm package and the Pane app, not in the Python package.",
3384
3783
  "Run it with Node instead: npx --yes runpane@latest agents send"
@@ -3388,6 +3787,96 @@ exports.RUNPANE_CONTRACT = {
3388
3787
  " runpane sessions <list|create|get|update|set-agent|associate|detach|overview> [options]",
3389
3788
  "",
3390
3789
  "Use a named Session to keep context, activity, and evidence attached to one orchestration thread."
3790
+ ],
3791
+ "report": [
3792
+ "Usage:",
3793
+ " runpane report --state <ready|blocked|failed|done> [--pr <number>] [--head <sha>] [--summary <text>|--summary-file <path|->] [--question <text>] [--pane <pane-id> --panel <panel-id>] [--json] [--pane-dir <path>]",
3794
+ "",
3795
+ "Hands back a worker's structured report for its panel: the orchestrator receives it as an",
3796
+ "agent.report watch event and reads it in `agents status` and `sessions overview`.",
3797
+ "Inside a Pane terminal the panel comes from PANE_SESSION_ID and PANE_PANEL_ID.",
3798
+ "",
3799
+ "Options:",
3800
+ " --state <state> ready, blocked, failed, or done",
3801
+ " --pr <number> Pull request number",
3802
+ " --head <sha> Head commit, 7-40 hex characters",
3803
+ " --summary <text> Summary text; up to 16,000 characters are kept",
3804
+ " --summary-file <path|-> Read the summary from a file or stdin",
3805
+ " --question <text> What you need answered; required with --state blocked",
3806
+ " --pane <pane-id> Pane id when not running inside a Pane terminal",
3807
+ " --panel <panel-id> Panel id when not running inside a Pane terminal",
3808
+ " --pane-dir <path> Connect to a specific Pane data directory",
3809
+ " --json Print machine-readable output",
3810
+ "",
3811
+ "Example:",
3812
+ " runpane report --state ready --pr 747 --head fc5dce9 --summary-file /tmp/report.md"
3813
+ ],
3814
+ "panels last-message": [
3815
+ "Usage:",
3816
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]",
3817
+ "",
3818
+ "Reads a Claude or Codex agent's last reply from its transcript. It never scrapes the screen:",
3819
+ "without a transcript it reports transcript-unavailable and exits non-zero.",
3820
+ "",
3821
+ "Options:",
3822
+ " --panel <panel-id> Agent panel id",
3823
+ " --limit <count> Maximum characters to return; defaults to 20000 (the end is kept)",
3824
+ " --pane-dir <path> Connect to a specific Pane data directory",
3825
+ " --json Print machine-readable output"
3826
+ ],
3827
+ "lock": [
3828
+ "Usage:",
3829
+ " python -m runpane lock <acquire|release|list> [options]",
3830
+ "",
3831
+ "Named locks coordinate a resource shared between agents, such as one test account.",
3832
+ "The caller is the owner: the Pane and panel from $PANE_SESSION_ID and $PANE_PANEL_ID.",
3833
+ "A lock is scoped to the owner's Session when its Pane belongs to one; otherwise it is global.",
3834
+ "It is released on --ttl expiry, when the owner panel exits, or when the owner Pane is archived."
3835
+ ],
3836
+ "lock acquire": [
3837
+ "Usage:",
3838
+ "python -m runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
3839
+ "",
3840
+ "Options:",
3841
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
3842
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
3843
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
3844
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
3845
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
3846
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
3847
+ " --force Release a lock another owner holds (release).",
3848
+ " --session <id|name> Named Session whose locks to list or release.",
3849
+ " --json Print JSON output."
3850
+ ],
3851
+ "lock release": [
3852
+ "Usage:",
3853
+ "python -m runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
3854
+ "",
3855
+ "Options:",
3856
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
3857
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
3858
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
3859
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
3860
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
3861
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
3862
+ " --force Release a lock another owner holds (release).",
3863
+ " --session <id|name> Named Session whose locks to list or release.",
3864
+ " --json Print JSON output."
3865
+ ],
3866
+ "lock list": [
3867
+ "Usage:",
3868
+ "python -m runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]",
3869
+ "",
3870
+ "Options:",
3871
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
3872
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
3873
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
3874
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
3875
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
3876
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
3877
+ " --force Release a lock another owner holds (release).",
3878
+ " --session <id|name> Named Session whose locks to list or release.",
3879
+ " --json Print JSON output."
3391
3880
  ]
3392
3881
  }
3393
3882
  },
@@ -3472,6 +3961,7 @@ exports.RUNPANE_CONTRACT = {
3472
3961
  "runpane watch --self-test",
3473
3962
  "runpane watch --follow",
3474
3963
  "runpane watch --follow --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
3964
+ "runpane watch --session <id|name> --follow --quiet --json --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone,pane.associated,pane.detached,pr.conflicted,pr.checks,pr.merged --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
3475
3965
  "runpane sessions list [--json] [--pane-dir <path>]",
3476
3966
  "runpane sessions create --from-json <path|-> [--json] [--pane-dir <path>]",
3477
3967
  "runpane sessions get --session <id|name> [--json] [--pane-dir <path>]",
@@ -3480,9 +3970,14 @@ exports.RUNPANE_CONTRACT = {
3480
3970
  "runpane sessions associate --session <id|name> --pane <pane-id> [--json] [--pane-dir <path>]",
3481
3971
  "runpane sessions detach --session <id|name> [--pane <pane-id>] [--json] [--pane-dir <path>]",
3482
3972
  "runpane sessions overview --session <id|name> [--json] [--pane-dir <path>]",
3973
+ "runpane lock acquire --name testing-account --ttl 30m --wait 1800000 --note \"call QA\" --json",
3974
+ "runpane lock release --name testing-account --json",
3975
+ "runpane lock list --json",
3483
3976
  "runpane agents start --repo active --name fix-login --agent claude --prompt \"Fix the login redirect\" --yes --json",
3484
3977
  "runpane agents status --pane <pane-id> --json",
3485
3978
  "runpane agents send --pane <pane-id> --text \"Also add a test\" --yes --json",
3979
+ "runpane report --state ready --pr 747 --head fc5dce9 --summary-file /tmp/report.md --json",
3980
+ "runpane panels last-message --panel <panel-id> --json",
3486
3981
  "runpane docs search --query \"archive a pane\" --json",
3487
3982
  "runpane links create --pane <pane-id> --json",
3488
3983
  "runpane panes git-status --pane <pane-id> --json",
@@ -3500,24 +3995,27 @@ exports.RUNPANE_CONTRACT = {
3500
3995
  "`runpane doctor` checks platform support, release metadata reachability, download URL selection, installed Pane detection, daemon reachability, and remote-daemon hints. Add `--json` for a machine-readable report that agents should run before mutating Pane state. Installed app version detection must be best-effort and must not launch, focus, or configure Pane; macOS wrappers read app bundle metadata instead of executing `Pane --version`.",
3501
3996
  "`runpane daemon repair` rewrites and restarts only the managed remote-daemon launcher/service. It never creates pairing credentials, changes tunnels, or downloads Pane; doctor only recommends it and never runs it automatically.",
3502
3997
  "`runpane agent-context` prints a brief, token-efficient command schema for coding agents without connecting to the Pane daemon.",
3503
- "`runpane agent-context --command \"panes create\"` prints the detailed definition for one command. Add `--json` for machine-readable output.",
3998
+ "`runpane agent-context --command \"panes create\"` prints the detailed definition for one command. Add `--json` for machine-readable output. An unknown command exits 2 and lists the closest command names; with `--json` it prints `{ ok: false, code: \"unknown_command\", message, candidates }` on stdout.",
3504
3999
  "`runpane mcp` runs a stdio MCP server whose tools are generated from this contract: every command with result `jsonSchemas` becomes a tool that runs `runpane <command> --json` and returns its output. Only the npm package and the Pane app include it; the Python wrapper prints how to run it with Node and exits non-zero.",
3505
4000
  "`runpane repos list` connects to the running local Pane daemon and prints saved repository records.",
3506
4001
  "`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.",
3507
4002
  "`runpane panes list` lists Pane sessions, optionally scoped to one saved repository.",
3508
4003
  "`runpane panes cost` reports estimated token costs per Pane for the last 30 days, including per-model breakdowns and cache efficiency; unscoped output includes an Unattributed bucket that reconciles against workspace totals.",
3509
- "`runpane panes create` connects to the running local Pane daemon, resolves the requested saved base repository, creates user-visible Pane sessions backed by Pane-managed worktrees/branches, opens terminal-backed tool tabs, and optionally sends initial input to the started tool. Built-in agent panes and `--source agent` default to background/no-focus unless `--focus` is passed. New Panes are pinned into the UI's favorite/pin set by default; pass `--no-pinned` to opt out. Panes created interactively in the Pane UI are unaffected. Inside a Session orchestrator (`PANE_ORCHESTRATION_SESSION_ID` set), new Panes are associated with that Session automatically; `--no-associate` opts out. A failed association is reported on the item and never undoes the Pane.",
3510
- "For `panes create --wait-ready`, `initialInput.verifiedSubmitted: true` is reported only after argument attachment or composer-clear plus activity evidence. Routing input does not by itself verify submission.",
3511
- "`runpane panes archive` refreshes the configured upstream, reports exact unpushed commit evidence, and refuses unsafe archive operations unless `--force` is used. Add `--dry-run` to inspect the same evidence without archiving. Successful archives wait for worktree removal and report `worktreeCleanup`.",
4004
+ "`runpane panes create` connects to the running local Pane daemon, resolves the requested saved base repository, creates user-visible Pane sessions backed by Pane-managed worktrees/branches, opens terminal-backed tool tabs, and optionally sends initial input to the started tool. Built-in agent panes and `--source agent` default to background/no-focus unless `--focus` is passed. New Panes are pinned into the UI's favorite/pin set by default, except when the CLI runs inside a Session orchestrator (`PANE_ORCHESTRATION_SESSION_ID`), where child worktrees default to unpinned. Explicit `--pinned` / `--no-pinned` override creation defaults. First Session association clears an existing pin; manual pins applied afterward are preserved. Panes created interactively in the Pane UI are unaffected. Inside a Session orchestrator (`PANE_ORCHESTRATION_SESSION_ID` set), new Panes are associated with that Session automatically; `--no-associate` opts out. A failed association is reported on the item and never undoes the Pane.",
4005
+ "For `panes create --wait-ready`, `initialInput.delivery` says where the prompt went: `taken` or `queued` (from the agent's transcript, its screen, or `argv` for a launch-argument prompt), `in-composer`, or `unknown`. `initialInput.verifiedSubmitted` is true exactly when it is `taken` or `queued`. Routing input does not by itself verify submission.",
4006
+ "`runpane panes archive` refreshes the configured upstream, reports exact unpushed commit evidence, and refuses unsafe archive operations unless `--force` is used. A branch whose upstream is gone counts as pushed when a merged GitHub pull request has HEAD as its head (`safetyCheck.mergedViaPr`). Add `--dry-run` to inspect the same evidence without archiving. `--remove-worktree` applies the same check and removal to an adopted worktree; local branches are always kept. Successful archives report `worktreeCleanup: completed` once the worktree is gone from its path and from git; `trashDeletion: pending` means its files are still being deleted in the background. `runpane panes archive --session <id|name> --merged` archives every Session Pane that is clean and pushed or merged, and reports a reason for each skipped Pane.",
3512
4007
  "`runpane panes rename` trims and updates a Pane's display name without changing its worktree, branch, panels, or focus, and returns the updated pane summary.",
3513
4008
  "`runpane panes focus` raises the Pane window and selects a Pane (and optionally one of its panels) exactly like clicking it in the UI. Because it steals the user's window focus, run it only on an explicit user request to open, focus, show, or switch to a Pane; never focus a Pane proactively, the same doctrine that keeps `panes create` background/no-focus for `--source agent`.",
4009
+ "`runpane panels open` opens a URL or a file from the Pane worktree as a tab in an existing Pane (default: the calling panel's Pane from `PANE_SESSION_ID`), in split view beside the agent unless `--tab` is passed. HTML files render in a browser tab and other files open in an editor tab; an existing tab showing the same target is reused. It activates the tab inside the Pane but never raises or focuses the Pane window.",
3514
4010
  "`runpane panels list` lists tool panels inside one Pane session.",
3515
4011
  "`runpane panels output` reads bounded recent terminal output from one panel and strips common terminal control noise for agent use.",
3516
4012
  "`runpane panels input` sends exact input bytes to one terminal panel. Prefer `--input-file` for newlines, Ctrl-C, quotes, or shell-sensitive text.",
3517
4013
  "`runpane panes create --prompt` is an alias for `--initial-input`; request JSON and daemon payloads should use the canonical `initialInput` field.",
4014
+ "`runpane panes create --branch <name>` creates the Pane's worktree on exactly that new branch, slashes included (for example `agents/w5a`). The name is checked with `git check-ref-format --branch`, creation fails if the branch already exists, and Pane never renames it to make it unique. `--worktree-name` still names the directory and defaults to `--name`. `--base` is an alias for `--base-branch`, and `--prompt-file` for `--initial-input-file`. `panes create --base <ref> --branch <name> --prompt-file <file>` replaces `git worktree add` plus `panes adopt`.",
4015
+ "`runpane panes adopt --launch` accepts `--prompt`, `--prompt-file`, `--wait-ready`, and `--ready-timeout-ms`, and reports `readiness`, `initialInput`, and `nextCommand` like `panes create`. A prompt without `--launch` is an error rather than being dropped.",
3518
4016
  "If composer submission cannot be verified without risking a duplicate, the create item is unsuccessful with `initialInput.staged`, `initialInput.attempts`, `initialInput.blocked.kind: submission_unverified`, and an actionable `nextCommand`. The CLI-facing `--prompt` alias maps to this canonical `initialInput` result.",
3519
4017
  "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'`.",
3520
- "`runpane watch` waits for workspace transitions from the daemon journal without polling. `--follow` keeps waiting and prints one line per event: READY, BLOCKED, IDLE, STUCK, NEW, GONE, EXIT, plus HEARTBEAT every 60 seconds as proof of life. Defaults are responsive: no settle, no batching, all kinds, IDLE every `--idle-after`. Expensive consumers opt into `--kinds` (drop `agent.busy`; BUSY carries no action), `--settle <ms>` (READY only after a quiet window; a BUSY inside it cancels the line), `--blocked-settle <ms>`, `--min-interval <ms>` (batch non-urgent lines; BLOCKED bypasses it), and `--idle-backoff` (10m, 30m, 1h, 3h, then daily). The recommended orchestrator invocation is `runpane watch --follow --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff`, which budgets about 6 wake-ups per active pane per hour worst case, usually 1-3. Pane Chat arms it automatically through its skill; only your own scripts need the flags. STUCK means real unsubmitted composer text, never an agent prompt suggestion. Judge a dead watch by a non-zero exit or a WATCH ERROR line, not by silence.",
4018
+ "`runpane watch` waits for workspace transitions from the daemon journal without polling. `--follow` keeps waiting and prints one line per event: READY, BLOCKED, IDLE, STUCK, NEW, GONE, EXIT, plus HEARTBEAT every 60 seconds as proof of life. Defaults are responsive: no settle, no batching, all kinds, IDLE every `--idle-after`. Expensive consumers opt into `--kinds` (drop `agent.busy`; BUSY carries no action), `--settle <ms>` (READY only after a quiet window; a BUSY inside it cancels the line), `--blocked-settle <ms>`, `--min-interval <ms>` (batch non-urgent lines; BLOCKED bypasses it), and `--idle-backoff` (10m, 30m, 1h, 3h, then daily). Two profiles cover orchestrators. Unattended: `runpane watch --follow --quiet --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff`, which budgets about 6 wake-ups per active pane per hour worst case, usually 1-3, and can deliver READY up to about 13 minutes late. User present: the same kinds with `--settle 60000 --blocked-settle 15000 --min-interval 120000` and no `--idle-backoff`, so READY arrives within about 3 minutes. Pane Chat arms it automatically through its skill; only your own scripts need the flags. STUCK means real unsubmitted composer text, never an agent prompt suggestion. `--quiet` (alias `--no-control-lines`) drops the WATCH OK, HEARTBEAT, and WATCH RECONNECTED control lines (`_ok`, `_heartbeat`, `_reconnected` in JSON); WATCH ERROR, RESET, and DROPPED (`_error`, `_reset`, `_dropped`) always print. Judge a dead watch by a non-zero exit or a WATCH ERROR line, not by silence. `--session <id|name>` follows every Pane associated with a named Session and re-reads membership on every read, so associate and detach need no re-arm; JOINED and LEFT (`pane.associated`, `pane.detached`) report membership changes. For Session members with an open PR, the daemon polls GitHub about every 3 minutes and reports `pr.conflicted` (`PR <pane-name> pane <pane-id> #<number> CONFLICTED`), `pr.checks` (`... CHECKS PASSED` or `... CHECKS FAILED <names>`), and `pr.merged` (`... MERGED`) on transitions only; list them in `--kinds`. In JSON, an entry with `replay: true` restates current state after a reset and is never READY.",
3521
4019
  "`sessions list` list durable named orchestration Sessions.",
3522
4020
  "`sessions create` create a durable named orchestration Session and its hidden terminal owner.",
3523
4021
  "`sessions get` read one durable named orchestration Session.",
@@ -3526,13 +4024,16 @@ exports.RUNPANE_CONTRACT = {
3526
4024
  "`sessions associate` associate a user-visible Pane with a named Session.",
3527
4025
  "`sessions detach` detach a Pane from a named Session.",
3528
4026
  "`sessions overview` read a live status, activity, git, and pull request overview for a named Session.",
4027
+ "`runpane lock acquire|release|list` coordinate a resource shared between agents, such as one test account. The caller's Pane and panel own the lock; it is scoped to the owner's Session (or global outside one), renews for the same owner, and is released on TTL expiry, owner panel exit, or owner Pane archive. `--wait` blocks in the daemon until the lock comes free.",
3529
4028
  "`runpane agents start|status|send` finish the three common agent jobs in one call each: start an agent on a task in a repository, check on it, and send it a follow-up.",
4029
+ "`runpane report --state ready|blocked|failed|done` is how a worker hands back its result. It stores the latest report on the worker's panel (state, `--pr`, `--head`, up to 16,000 characters of `--summary` or `--summary-file`, and the `--question` a blocked worker needs answered), journals an opt-in `agent.report` watch event (`REPORT <pane-name> pane <pane-id> panel <panel-id> ready pr#747 fc5dce9`; it skips the `--min-interval` batch), records it as Session activity, and shows it in `agents status`, `panels list`, and `sessions overview` (`panes[].report`). Inside a Pane terminal the panel comes from `PANE_SESSION_ID` and `PANE_PANEL_ID`; elsewhere pass `--pane` and `--panel`.",
4030
+ "`runpane panels last-message --panel <panel-id>` reads a Claude or Codex agent's last reply from its transcript (up to `--limit` characters, default 20,000, keeping the end and reporting `truncated`). It never scrapes the screen: without a transcript it prints `{ ok: false, reason: \"transcript-unavailable\" }` and exits 1.",
3530
4031
  "Commands with a contract `daemonAction` (the `panes` git, script, restore, and move commands, `folders list|create`, and `links open`) call the same Pane daemon channel as the matching button in the app and print `{ ok, data, error }`. Destructive ones add a pane:// `link` to review the Pane.",
3531
4032
  "`runpane links create` builds `pane://open?...` links; opening one in Pane selects what it names and never changes Pane state.",
3532
4033
  "`runpane docs search|read` search and read Pane docs, help, and installed Pane Chat skills offline. They ship in the npm package and the Pane app only."
3533
4034
  ],
3534
4035
  "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.",
3535
- "localControlFlagNote": "`runpane doctor --json`, `runpane repos list`, `runpane panes ...`, and `runpane panels ...` commands use or describe 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. In a Pane repository checkout, if `runpane` is not on PATH, use the built local wrapper with Node 22, for example `PATH=/opt/homebrew/opt/node@22/bin:$PATH node packages/runpane/dist/cli.js doctor --json`. 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.",
4036
+ "localControlFlagNote": "`runpane doctor --json`, `runpane repos list`, `runpane panes ...`, and `runpane panels ...` commands use or describe 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. `agent-context` and `version` accept and ignore `--pane-dir`, so one `--pane-dir` can be passed to every runpane command. In a Pane repository checkout, if `runpane` is not on PATH, use the built local wrapper with Node 22, for example `PATH=/opt/homebrew/opt/node@22/bin:$PATH node packages/runpane/dist/cli.js doctor --json`. 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.",
3536
4037
  "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.",
3537
4038
  "downloadAttribution": [
3538
4039
  "The npm package uses `source=npm` for all npm-registry consumers, including `npx`, `pnpm dlx`, `yarn dlx`, `bunx`, and global npm/pnpm installs.",
@@ -4058,42 +4559,355 @@ exports.RUNPANE_CONTRACT = {
4058
4559
  "folder-9",
4059
4560
  "--yes",
4060
4561
  "--json"
4061
- ]
4062
- ],
4063
- "topLevelHelpIncludes": [
4064
- "runpane setup",
4065
- "runpane install",
4066
- "runpane update",
4067
- "runpane version",
4068
- "runpane doctor",
4069
- "runpane agent-context",
4070
- "runpane repos list",
4071
- "runpane repos add",
4072
- "runpane panes list",
4073
- "runpane panes create",
4074
- "runpane panes archive",
4075
- "runpane panels create",
4076
- "runpane panels list",
4077
- "runpane panels output",
4078
- "runpane panels input",
4079
- "runpane agents doctor",
4080
- "runpane panels screen",
4081
- "runpane panels submit",
4082
- "runpane panels submit-composer",
4083
- "runpane panels wait",
4084
- "runpane doctor --json",
4085
- "runpane agent-context --json",
4086
- "Agent discovery:",
4087
- "Common commands:"
4088
- ],
4089
- "npmHelpIncludes": [
4090
- "pnpm dlx runpane@latest",
4091
- "npx --yes runpane@latest"
4092
- ],
4093
- "pipHelpIncludes": [
4094
- "pipx run runpane",
4095
- "python -m pip install runpane && python -m runpane setup"
4096
- ],
4562
+ ],
4563
+ [
4564
+ "watch",
4565
+ "--follow",
4566
+ "--quiet",
4567
+ "--json",
4568
+ "--pane-dir",
4569
+ "/tmp/pane"
4570
+ ],
4571
+ [
4572
+ "watch",
4573
+ "--follow",
4574
+ "--no-control-lines",
4575
+ "--all-managed"
4576
+ ],
4577
+ [
4578
+ "watch",
4579
+ "--session",
4580
+ "__orchestration_session_1b4e28ba-2fa1-11d2-883f-0016d3cca427__",
4581
+ "--follow",
4582
+ "--quiet",
4583
+ "--json",
4584
+ "--kinds",
4585
+ "agent.ready,agent.blocked,pane.associated,pane.detached,pr.conflicted,pr.checks,pr.merged",
4586
+ "--settle",
4587
+ "180000"
4588
+ ],
4589
+ [
4590
+ "watch",
4591
+ "--session=Release train",
4592
+ "--as",
4593
+ "release-watch",
4594
+ "--exclude-pane",
4595
+ "pane-old"
4596
+ ],
4597
+ [
4598
+ "agent-context",
4599
+ "--command",
4600
+ "panes create",
4601
+ "--json",
4602
+ "--pane-dir",
4603
+ "/tmp/pane"
4604
+ ],
4605
+ [
4606
+ "agent-context",
4607
+ "--pane-dir=/tmp/pane"
4608
+ ],
4609
+ [
4610
+ "version",
4611
+ "--pane-dir",
4612
+ "/tmp/pane"
4613
+ ],
4614
+ [
4615
+ "panes",
4616
+ "create",
4617
+ "--repo",
4618
+ "active",
4619
+ "--name",
4620
+ "w5a",
4621
+ "--agent",
4622
+ "claude",
4623
+ "--base-branch",
4624
+ "origin/release",
4625
+ "--source",
4626
+ "agent",
4627
+ "--no-focus",
4628
+ "--yes",
4629
+ "--json",
4630
+ "--pane-dir",
4631
+ "/tmp/pane"
4632
+ ],
4633
+ [
4634
+ "panels",
4635
+ "create",
4636
+ "--pane",
4637
+ "pane-1",
4638
+ "--agent",
4639
+ "codex",
4640
+ "--tool-command",
4641
+ "wrapper codex-run",
4642
+ "--wait-ready",
4643
+ "--yes",
4644
+ "--json"
4645
+ ],
4646
+ [
4647
+ "panes",
4648
+ "create",
4649
+ "--repo",
4650
+ "active",
4651
+ "--name",
4652
+ "farm",
4653
+ "--tool-command",
4654
+ "agent-farm run free-range",
4655
+ "--agent",
4656
+ "claude",
4657
+ "--prompt",
4658
+ "Plan",
4659
+ "--yes",
4660
+ "--json"
4661
+ ],
4662
+ [
4663
+ "panels",
4664
+ "submit",
4665
+ "--panel",
4666
+ "panel-1",
4667
+ "--input-file",
4668
+ "brief.md",
4669
+ "--as-file-pointer",
4670
+ "--yes",
4671
+ "--json"
4672
+ ],
4673
+ [
4674
+ "panes",
4675
+ "create",
4676
+ "--repo",
4677
+ "active",
4678
+ "--name",
4679
+ "long",
4680
+ "--agent",
4681
+ "claude",
4682
+ "--initial-input-file",
4683
+ "brief.md",
4684
+ "--as-file-pointer",
4685
+ "--dry-run",
4686
+ "--yes",
4687
+ "--json"
4688
+ ],
4689
+ [
4690
+ "report",
4691
+ "--state",
4692
+ "ready",
4693
+ "--pr",
4694
+ "747",
4695
+ "--head",
4696
+ "FC5DCE9",
4697
+ "--summary",
4698
+ "Done: tests pass",
4699
+ "--json"
4700
+ ],
4701
+ [
4702
+ "report",
4703
+ "--state",
4704
+ "blocked",
4705
+ "--question",
4706
+ "Which API version?",
4707
+ "--pane",
4708
+ "session-1",
4709
+ "--panel",
4710
+ "panel-1",
4711
+ "--summary-file",
4712
+ "-"
4713
+ ],
4714
+ [
4715
+ "report",
4716
+ "--state=done",
4717
+ "--summary-file=/tmp/report.md",
4718
+ "--pane-dir",
4719
+ "/tmp/pane"
4720
+ ],
4721
+ [
4722
+ "panels",
4723
+ "last-message",
4724
+ "--panel",
4725
+ "panel-1",
4726
+ "--limit",
4727
+ "5000",
4728
+ "--json"
4729
+ ],
4730
+ [
4731
+ "panes",
4732
+ "create",
4733
+ "--repo",
4734
+ "active",
4735
+ "--name",
4736
+ "w5a",
4737
+ "--base",
4738
+ "release/foo",
4739
+ "--branch",
4740
+ "agents/w5a",
4741
+ "--agent",
4742
+ "claude",
4743
+ "--prompt-file",
4744
+ "prompt.md",
4745
+ "--dry-run",
4746
+ "--yes",
4747
+ "--json"
4748
+ ],
4749
+ [
4750
+ "panes",
4751
+ "create",
4752
+ "--repo",
4753
+ "active",
4754
+ "--name",
4755
+ "w5b",
4756
+ "--base-branch",
4757
+ "origin/main",
4758
+ "--branch",
4759
+ "agents/w5b",
4760
+ "--worktree-name",
4761
+ "w5b-dir",
4762
+ "--tool-command",
4763
+ "bash",
4764
+ "--initial-input-file",
4765
+ "-",
4766
+ "--dry-run",
4767
+ "--yes",
4768
+ "--json"
4769
+ ],
4770
+ [
4771
+ "panes",
4772
+ "archive",
4773
+ "--pane",
4774
+ "session-1",
4775
+ "--remove-worktree",
4776
+ "--yes",
4777
+ "--json"
4778
+ ],
4779
+ [
4780
+ "panes",
4781
+ "archive",
4782
+ "--session",
4783
+ "refactor",
4784
+ "--merged",
4785
+ "--dry-run",
4786
+ "--json"
4787
+ ],
4788
+ [
4789
+ "panes",
4790
+ "archive",
4791
+ "--session",
4792
+ "refactor",
4793
+ "--merged",
4794
+ "--remove-worktree",
4795
+ "--yes"
4796
+ ],
4797
+ [
4798
+ "lock",
4799
+ "acquire",
4800
+ "--name",
4801
+ "testing-account",
4802
+ "--ttl",
4803
+ "30m",
4804
+ "--wait",
4805
+ "1800000",
4806
+ "--note",
4807
+ "call QA",
4808
+ "--json"
4809
+ ],
4810
+ [
4811
+ "lock",
4812
+ "acquire",
4813
+ "--name",
4814
+ "staging-db",
4815
+ "--ttl",
4816
+ "1500",
4817
+ "--pane",
4818
+ "session-1",
4819
+ "--panel",
4820
+ "panel-1",
4821
+ "--pane-dir",
4822
+ "/tmp/pane"
4823
+ ],
4824
+ [
4825
+ "lock",
4826
+ "acquire",
4827
+ "--name=db",
4828
+ "--ttl=2h"
4829
+ ],
4830
+ [
4831
+ "lock",
4832
+ "release",
4833
+ "--name",
4834
+ "testing-account",
4835
+ "--force",
4836
+ "--session",
4837
+ "Release QA",
4838
+ "--json"
4839
+ ],
4840
+ [
4841
+ "lock",
4842
+ "list",
4843
+ "--session",
4844
+ "Release QA",
4845
+ "--json"
4846
+ ],
4847
+ [
4848
+ "lock",
4849
+ "--help"
4850
+ ],
4851
+ [
4852
+ "panels",
4853
+ "open",
4854
+ "--pane",
4855
+ "session-1",
4856
+ "--file",
4857
+ "plan.html",
4858
+ "--title",
4859
+ "Plan",
4860
+ "--split",
4861
+ "--no-focus",
4862
+ "--source",
4863
+ "agent",
4864
+ "--yes",
4865
+ "--json"
4866
+ ],
4867
+ [
4868
+ "panels",
4869
+ "open",
4870
+ "--url",
4871
+ "http://localhost:3000",
4872
+ "--tab",
4873
+ "--yes",
4874
+ "--json"
4875
+ ]
4876
+ ],
4877
+ "topLevelHelpIncludes": [
4878
+ "runpane setup",
4879
+ "runpane install",
4880
+ "runpane update",
4881
+ "runpane version",
4882
+ "runpane doctor",
4883
+ "runpane agent-context",
4884
+ "runpane repos list",
4885
+ "runpane repos add",
4886
+ "runpane panes list",
4887
+ "runpane panes create",
4888
+ "runpane panes archive",
4889
+ "runpane panels create",
4890
+ "runpane panels list",
4891
+ "runpane panels output",
4892
+ "runpane panels input",
4893
+ "runpane agents doctor",
4894
+ "runpane panels screen",
4895
+ "runpane panels submit",
4896
+ "runpane panels submit-composer",
4897
+ "runpane panels wait",
4898
+ "runpane doctor --json",
4899
+ "runpane agent-context --json",
4900
+ "Agent discovery:",
4901
+ "Common commands:"
4902
+ ],
4903
+ "npmHelpIncludes": [
4904
+ "pnpm dlx runpane@latest",
4905
+ "npx --yes runpane@latest"
4906
+ ],
4907
+ "pipHelpIncludes": [
4908
+ "pipx run runpane",
4909
+ "python -m pip install runpane && python -m runpane setup"
4910
+ ],
4097
4911
  "installHelpIncludes": [
4098
4912
  "--version <latest|vX.Y.Z>",
4099
4913
  "--format <auto|appimage|deb|dmg|zip|exe>",
@@ -4727,6 +5541,9 @@ exports.RUNPANE_CONTRACT = {
4727
5541
  "worktreeName": {
4728
5542
  "type": "string"
4729
5543
  },
5544
+ "branch": {
5545
+ "type": "string"
5546
+ },
4730
5547
  "baseBranch": {
4731
5548
  "type": "string"
4732
5549
  },
@@ -4755,6 +5572,9 @@ exports.RUNPANE_CONTRACT = {
4755
5572
  },
4756
5573
  "initialInput": {
4757
5574
  "type": "string"
5575
+ },
5576
+ "initialInputAsFilePointer": {
5577
+ "type": "boolean"
4758
5578
  }
4759
5579
  },
4760
5580
  "additionalProperties": false
@@ -4768,12 +5588,22 @@ exports.RUNPANE_CONTRACT = {
4768
5588
  "command": {
4769
5589
  "type": "string"
4770
5590
  },
5591
+ "agentType": {
5592
+ "enum": [
5593
+ "codex",
5594
+ "claude",
5595
+ "cursor"
5596
+ ]
5597
+ },
4771
5598
  "title": {
4772
5599
  "type": "string"
4773
5600
  },
4774
5601
  "initialInput": {
4775
5602
  "type": "string"
4776
- }
5603
+ },
5604
+ "initialInputAsFilePointer": {
5605
+ "type": "boolean"
5606
+ }
4777
5607
  },
4778
5608
  "additionalProperties": false
4779
5609
  }
@@ -5035,6 +5865,9 @@ exports.RUNPANE_CONTRACT = {
5035
5865
  "verifiedSubmitted": {
5036
5866
  "type": "boolean"
5037
5867
  },
5868
+ "delivery": {
5869
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/delivery"
5870
+ },
5038
5871
  "staged": {
5039
5872
  "type": "boolean"
5040
5873
  },
@@ -5113,6 +5946,12 @@ exports.RUNPANE_CONTRACT = {
5113
5946
  }
5114
5947
  },
5115
5948
  "additionalProperties": false
5949
+ },
5950
+ "promptFile": {
5951
+ "type": "string"
5952
+ },
5953
+ "warnings": {
5954
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/warnings"
5116
5955
  }
5117
5956
  },
5118
5957
  "additionalProperties": false
@@ -5239,6 +6078,14 @@ exports.RUNPANE_CONTRACT = {
5239
6078
  "idle"
5240
6079
  ]
5241
6080
  },
6081
+ "agentState": {
6082
+ "enum": [
6083
+ "ready",
6084
+ "working",
6085
+ "blocked",
6086
+ "none"
6087
+ ]
6088
+ },
5242
6089
  "ownership": {
5243
6090
  "enum": [
5244
6091
  "pane",
@@ -5604,7 +6451,13 @@ exports.RUNPANE_CONTRACT = {
5604
6451
  "agent.idle",
5605
6452
  "pane.created",
5606
6453
  "pane.gone",
5607
- "panel.exited"
6454
+ "panel.exited",
6455
+ "agent.report",
6456
+ "pane.associated",
6457
+ "pane.detached",
6458
+ "pr.conflicted",
6459
+ "pr.checks",
6460
+ "pr.merged"
5608
6461
  ]
5609
6462
  },
5610
6463
  "paneId": {
@@ -5648,7 +6501,8 @@ exports.RUNPANE_CONTRACT = {
5648
6501
  "enum": [
5649
6502
  "agent",
5650
6503
  "exit",
5651
- "session"
6504
+ "session",
6505
+ "github"
5652
6506
  ]
5653
6507
  },
5654
6508
  "reason": {
@@ -5682,8 +6536,98 @@ exports.RUNPANE_CONTRACT = {
5682
6536
  "baseline": {
5683
6537
  "const": true
5684
6538
  },
6539
+ "replay": {
6540
+ "const": true,
6541
+ "description": "Set on baseline entries delivered after a reset. A replayed entry restates current state and is never a new transition: a replayed agent.ready is not READY."
6542
+ },
5685
6543
  "changedWhileAway": {
5686
6544
  "type": "boolean"
6545
+ },
6546
+ "sessionId": {
6547
+ "type": "string",
6548
+ "description": "Named Session of a pane.associated or pane.detached entry."
6549
+ },
6550
+ "sessionName": {
6551
+ "type": "string"
6552
+ },
6553
+ "pr": {
6554
+ "type": "object",
6555
+ "description": "PR of a pr.conflicted, pr.checks, or pr.merged entry.",
6556
+ "required": [
6557
+ "number",
6558
+ "url",
6559
+ "headOid"
6560
+ ],
6561
+ "properties": {
6562
+ "number": {
6563
+ "type": "number"
6564
+ },
6565
+ "url": {
6566
+ "type": "string"
6567
+ },
6568
+ "headOid": {
6569
+ "type": "string"
6570
+ }
6571
+ },
6572
+ "additionalProperties": false
6573
+ },
6574
+ "checks": {
6575
+ "enum": [
6576
+ "passed",
6577
+ "failed"
6578
+ ],
6579
+ "description": "Settled result of a pr.checks entry: every check on pr.headOid finished."
6580
+ },
6581
+ "failingChecks": {
6582
+ "type": "array",
6583
+ "items": {
6584
+ "type": "string"
6585
+ },
6586
+ "description": "Up to five failing check names of a failed pr.checks entry."
6587
+ },
6588
+ "report": {
6589
+ "$ref": "#/jsonSchemas/agentReport",
6590
+ "description": "Report of an agent.report entry; its summary is cut to 2,000 characters (the panel keeps up to 16,000)."
6591
+ }
6592
+ },
6593
+ "additionalProperties": false
6594
+ },
6595
+ "agentReport": {
6596
+ "type": "object",
6597
+ "description": "The latest runpane report from an agent panel.",
6598
+ "required": [
6599
+ "state",
6600
+ "reportedAt"
6601
+ ],
6602
+ "properties": {
6603
+ "state": {
6604
+ "enum": [
6605
+ "ready",
6606
+ "blocked",
6607
+ "failed",
6608
+ "done"
6609
+ ]
6610
+ },
6611
+ "pr": {
6612
+ "type": "number"
6613
+ },
6614
+ "head": {
6615
+ "type": "string"
6616
+ },
6617
+ "summary": {
6618
+ "type": "string"
6619
+ },
6620
+ "summaryTruncated": {
6621
+ "const": true
6622
+ },
6623
+ "summaryPath": {
6624
+ "type": "string"
6625
+ },
6626
+ "question": {
6627
+ "type": "string"
6628
+ },
6629
+ "reportedAt": {
6630
+ "type": "string"
5687
6631
  }
5688
6632
  },
5689
6633
  "additionalProperties": false
@@ -5721,6 +6665,10 @@ exports.RUNPANE_CONTRACT = {
5721
6665
  "type": "string"
5722
6666
  }
5723
6667
  },
6668
+ "session": {
6669
+ "type": "string",
6670
+ "description": "Named Session id or exact name. Limits the wait to the Session's associated Panes, resolved on every read, and implies the opt-in pane.associated, pane.detached, and pr.* entries. Cannot be combined with paneIds."
6671
+ },
5724
6672
  "excludePaneIds": {
5725
6673
  "type": "array",
5726
6674
  "items": {
@@ -5864,6 +6812,23 @@ exports.RUNPANE_CONTRACT = {
5864
6812
  },
5865
6813
  "additionalProperties": false
5866
6814
  },
6815
+ "session": {
6816
+ "type": "object",
6817
+ "description": "The Session a session request resolved to. A client that sent session and gets no session back is talking to a daemon that ignored it.",
6818
+ "required": [
6819
+ "id",
6820
+ "name"
6821
+ ],
6822
+ "properties": {
6823
+ "id": {
6824
+ "type": "string"
6825
+ },
6826
+ "name": {
6827
+ "type": "string"
6828
+ }
6829
+ },
6830
+ "additionalProperties": false
6831
+ },
5867
6832
  "nextCommand": {
5868
6833
  "type": "string"
5869
6834
  }
@@ -5890,6 +6855,9 @@ exports.RUNPANE_CONTRACT = {
5890
6855
  },
5891
6856
  "dryRun": {
5892
6857
  "type": "boolean"
6858
+ },
6859
+ "removeWorktree": {
6860
+ "type": "boolean"
5893
6861
  }
5894
6862
  },
5895
6863
  "additionalProperties": false
@@ -6062,7 +7030,15 @@ exports.RUNPANE_CONTRACT = {
6062
7030
  "failed",
6063
7031
  "timeout",
6064
7032
  "not-applicable"
6065
- ]
7033
+ ],
7034
+ "description": "`completed`: the worktree is gone from its path and from git (see trashDeletion). `failed`: removal failed and the worktree may remain; ok is false. `timeout`: the archive script or git removal is still running in the background; ok stays true. `not-applicable`: nothing was removed (main-repo Pane, or an adopted worktree without --remove-worktree). Released CLIs decode exactly these values."
7035
+ },
7036
+ "trashDeletion": {
7037
+ "enum": [
7038
+ "pending",
7039
+ "done"
7040
+ ],
7041
+ "description": "Present with worktreeCleanup `completed`. `pending`: the removed worktree was moved into the repository's .git/pane-trash and its files are still being deleted in the background. `done`: the files are gone."
6066
7042
  },
6067
7043
  "worktreePath": {
6068
7044
  "type": "string"
@@ -6112,6 +7088,38 @@ exports.RUNPANE_CONTRACT = {
6112
7088
  },
6113
7089
  "additionalProperties": false
6114
7090
  }
7091
+ },
7092
+ "reason": {
7093
+ "enum": [
7094
+ "external-worktree",
7095
+ "main-repo",
7096
+ "missing-project-context",
7097
+ "git-error"
7098
+ ]
7099
+ },
7100
+ "worktreeWillRemain": {
7101
+ "const": true
7102
+ },
7103
+ "upstreamGone": {
7104
+ "type": "boolean",
7105
+ "description": "The branch had an upstream that no longer exists on the remote, so commits were compared with the base branch."
7106
+ },
7107
+ "mergedViaPr": {
7108
+ "type": "object",
7109
+ "description": "A merged pull request whose head commit is HEAD. Its commits are not counted as unpushed.",
7110
+ "required": [
7111
+ "number",
7112
+ "headOid"
7113
+ ],
7114
+ "properties": {
7115
+ "number": {
7116
+ "type": "number"
7117
+ },
7118
+ "headOid": {
7119
+ "type": "string"
7120
+ }
7121
+ },
7122
+ "additionalProperties": false
6115
7123
  }
6116
7124
  },
6117
7125
  "additionalProperties": false
@@ -6239,6 +7247,17 @@ exports.RUNPANE_CONTRACT = {
6239
7247
  },
6240
7248
  "additionalProperties": false
6241
7249
  }
7250
+ },
7251
+ "reason": {
7252
+ "enum": [
7253
+ "external-worktree",
7254
+ "main-repo",
7255
+ "missing-project-context",
7256
+ "git-error"
7257
+ ]
7258
+ },
7259
+ "worktreeWillRemain": {
7260
+ "const": true
6242
7261
  }
6243
7262
  },
6244
7263
  "additionalProperties": false
@@ -6305,6 +7324,17 @@ exports.RUNPANE_CONTRACT = {
6305
7324
  "agentType": {
6306
7325
  "type": "string"
6307
7326
  },
7327
+ "agentDetection": {
7328
+ "enum": [
7329
+ "declared",
7330
+ "command",
7331
+ "process",
7332
+ "screen"
7333
+ ]
7334
+ },
7335
+ "launchCommand": {
7336
+ "type": "string"
7337
+ },
6308
7338
  "isCliPanel": {
6309
7339
  "type": "boolean"
6310
7340
  },
@@ -6316,6 +7346,9 @@ exports.RUNPANE_CONTRACT = {
6316
7346
  },
6317
7347
  "lastActiveAt": {
6318
7348
  "type": "string"
7349
+ },
7350
+ "report": {
7351
+ "$ref": "#/jsonSchemas/agentReport"
6319
7352
  }
6320
7353
  },
6321
7354
  "additionalProperties": false
@@ -6659,6 +7692,9 @@ exports.RUNPANE_CONTRACT = {
6659
7692
  },
6660
7693
  "hasUndeliveredText": {
6661
7694
  "type": "boolean"
7695
+ },
7696
+ "ghostText": {
7697
+ "type": "string"
6662
7698
  }
6663
7699
  },
6664
7700
  "additionalProperties": false
@@ -6684,6 +7720,9 @@ exports.RUNPANE_CONTRACT = {
6684
7720
  },
6685
7721
  "input": {
6686
7722
  "type": "string"
7723
+ },
7724
+ "asFilePointer": {
7725
+ "type": "boolean"
6687
7726
  }
6688
7727
  },
6689
7728
  "additionalProperties": false
@@ -6731,12 +7770,64 @@ exports.RUNPANE_CONTRACT = {
6731
7770
  "verifiedSubmitted": {
6732
7771
  "type": "boolean"
6733
7772
  },
7773
+ "delivery": {
7774
+ "type": "object",
7775
+ "required": [
7776
+ "state",
7777
+ "evidence"
7778
+ ],
7779
+ "properties": {
7780
+ "state": {
7781
+ "enum": [
7782
+ "taken",
7783
+ "queued",
7784
+ "in-composer",
7785
+ "unknown"
7786
+ ]
7787
+ },
7788
+ "evidence": {
7789
+ "enum": [
7790
+ "transcript",
7791
+ "screen",
7792
+ "argv"
7793
+ ]
7794
+ }
7795
+ },
7796
+ "additionalProperties": false
7797
+ },
6734
7798
  "sentAt": {
6735
7799
  "type": "string"
6736
7800
  },
6737
7801
  "blocked": {
6738
7802
  "$ref": "#/jsonSchemas/panelSubmitComposerResult/properties/blocked"
6739
7803
  },
7804
+ "promptFile": {
7805
+ "type": "string"
7806
+ },
7807
+ "warnings": {
7808
+ "type": "array",
7809
+ "items": {
7810
+ "type": "object",
7811
+ "required": [
7812
+ "code",
7813
+ "message"
7814
+ ],
7815
+ "properties": {
7816
+ "code": {
7817
+ "enum": [
7818
+ "leading-bang-runs-shell",
7819
+ "leading-hash-memory",
7820
+ "leading-slash-command",
7821
+ "leading-at-mention"
7822
+ ]
7823
+ },
7824
+ "message": {
7825
+ "type": "string"
7826
+ }
7827
+ },
7828
+ "additionalProperties": false
7829
+ }
7830
+ },
6740
7831
  "nextCommand": {
6741
7832
  "type": "string"
6742
7833
  },
@@ -6879,6 +7970,81 @@ exports.RUNPANE_CONTRACT = {
6879
7970
  },
6880
7971
  "additionalProperties": false
6881
7972
  },
7973
+ "panelLastMessageResult": {
7974
+ "oneOf": [
7975
+ {
7976
+ "type": "object",
7977
+ "required": [
7978
+ "ok",
7979
+ "panelId",
7980
+ "paneId",
7981
+ "agentType",
7982
+ "text",
7983
+ "length",
7984
+ "limit",
7985
+ "truncated"
7986
+ ],
7987
+ "properties": {
7988
+ "ok": {
7989
+ "const": true
7990
+ },
7991
+ "panelId": {
7992
+ "type": "string"
7993
+ },
7994
+ "paneId": {
7995
+ "type": "string"
7996
+ },
7997
+ "agentType": {
7998
+ "enum": [
7999
+ "claude",
8000
+ "codex"
8001
+ ]
8002
+ },
8003
+ "text": {
8004
+ "type": "string"
8005
+ },
8006
+ "length": {
8007
+ "type": "number"
8008
+ },
8009
+ "limit": {
8010
+ "type": "number"
8011
+ },
8012
+ "truncated": {
8013
+ "type": "boolean"
8014
+ }
8015
+ },
8016
+ "additionalProperties": false
8017
+ },
8018
+ {
8019
+ "type": "object",
8020
+ "required": [
8021
+ "ok",
8022
+ "panelId",
8023
+ "paneId",
8024
+ "reason",
8025
+ "message"
8026
+ ],
8027
+ "properties": {
8028
+ "ok": {
8029
+ "const": false
8030
+ },
8031
+ "panelId": {
8032
+ "type": "string"
8033
+ },
8034
+ "paneId": {
8035
+ "type": "string"
8036
+ },
8037
+ "reason": {
8038
+ "const": "transcript-unavailable"
8039
+ },
8040
+ "message": {
8041
+ "type": "string"
8042
+ }
8043
+ },
8044
+ "additionalProperties": false
8045
+ }
8046
+ ]
8047
+ },
6882
8048
  "agentDoctorResult": {
6883
8049
  "type": "object",
6884
8050
  "required": [
@@ -7143,38 +8309,135 @@ exports.RUNPANE_CONTRACT = {
7143
8309
  },
7144
8310
  "additionalProperties": false
7145
8311
  },
8312
+ "promptFile": {
8313
+ "type": "string"
8314
+ },
8315
+ "warnings": {
8316
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/warnings"
8317
+ },
7146
8318
  "nextCommand": {
7147
8319
  "type": "string"
7148
8320
  }
7149
8321
  },
7150
8322
  "additionalProperties": false
7151
8323
  },
7152
- "panelSubmitComposerRequest": {
8324
+ "panelOpenRequest": {
7153
8325
  "type": "object",
7154
8326
  "required": [
7155
- "panelId"
8327
+ "paneId"
7156
8328
  ],
7157
8329
  "properties": {
7158
- "panelId": {
8330
+ "paneId": {
7159
8331
  "type": "string"
7160
8332
  },
7161
- "strategy": {
8333
+ "url": {
8334
+ "type": "string"
8335
+ },
8336
+ "filePath": {
8337
+ "type": "string"
8338
+ },
8339
+ "title": {
8340
+ "type": "string"
8341
+ },
8342
+ "placement": {
7162
8343
  "enum": [
7163
- "auto",
7164
- "codex-ctrl-enter",
7165
- "enter",
8344
+ "split",
7166
8345
  "tab"
7167
8346
  ]
8347
+ },
8348
+ "noFocus": {
8349
+ "type": "boolean"
8350
+ },
8351
+ "focus": {
8352
+ "type": "boolean"
8353
+ },
8354
+ "source": {
8355
+ "enum": [
8356
+ "user",
8357
+ "agent"
8358
+ ]
7168
8359
  }
7169
8360
  },
7170
8361
  "additionalProperties": false
7171
8362
  },
7172
- "panelSubmitComposerResult": {
8363
+ "panelOpenResult": {
7173
8364
  "type": "object",
7174
8365
  "required": [
7175
8366
  "ok",
8367
+ "paneId",
7176
8368
  "panelId",
7177
- "inputBytes",
8369
+ "type",
8370
+ "title",
8371
+ "placement",
8372
+ "active",
8373
+ "reused"
8374
+ ],
8375
+ "properties": {
8376
+ "ok": {
8377
+ "const": true
8378
+ },
8379
+ "paneId": {
8380
+ "type": "string"
8381
+ },
8382
+ "panelId": {
8383
+ "type": "string"
8384
+ },
8385
+ "type": {
8386
+ "enum": [
8387
+ "browser",
8388
+ "editor"
8389
+ ]
8390
+ },
8391
+ "title": {
8392
+ "type": "string"
8393
+ },
8394
+ "url": {
8395
+ "type": "string"
8396
+ },
8397
+ "filePath": {
8398
+ "type": "string"
8399
+ },
8400
+ "placement": {
8401
+ "enum": [
8402
+ "split",
8403
+ "tab"
8404
+ ]
8405
+ },
8406
+ "active": {
8407
+ "type": "boolean"
8408
+ },
8409
+ "reused": {
8410
+ "type": "boolean"
8411
+ }
8412
+ },
8413
+ "additionalProperties": false
8414
+ },
8415
+ "panelSubmitComposerRequest": {
8416
+ "type": "object",
8417
+ "required": [
8418
+ "panelId"
8419
+ ],
8420
+ "properties": {
8421
+ "panelId": {
8422
+ "type": "string"
8423
+ },
8424
+ "strategy": {
8425
+ "enum": [
8426
+ "auto",
8427
+ "codex-ctrl-enter",
8428
+ "enter",
8429
+ "tab"
8430
+ ]
8431
+ }
8432
+ },
8433
+ "additionalProperties": false
8434
+ },
8435
+ "panelSubmitComposerResult": {
8436
+ "type": "object",
8437
+ "required": [
8438
+ "ok",
8439
+ "panelId",
8440
+ "inputBytes",
7178
8441
  "strategy",
7179
8442
  "sequenceName",
7180
8443
  "verifiedSubmitted",
@@ -7213,6 +8476,9 @@ exports.RUNPANE_CONTRACT = {
7213
8476
  "verifiedSubmitted": {
7214
8477
  "type": "boolean"
7215
8478
  },
8479
+ "delivery": {
8480
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/delivery"
8481
+ },
7216
8482
  "sentAt": {
7217
8483
  "type": "string"
7218
8484
  },
@@ -7228,6 +8494,7 @@ exports.RUNPANE_CONTRACT = {
7228
8494
  "codex-update",
7229
8495
  "agent-prompt",
7230
8496
  "submission_unverified",
8497
+ "composer-unknown",
7231
8498
  "unknown"
7232
8499
  ]
7233
8500
  },
@@ -7324,10 +8591,261 @@ exports.RUNPANE_CONTRACT = {
7324
8591
  },
7325
8592
  "refreshedAt": {
7326
8593
  "type": "string"
8594
+ },
8595
+ "locks": {
8596
+ "type": "array",
8597
+ "items": {
8598
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8599
+ }
8600
+ }
8601
+ },
8602
+ "additionalProperties": false
8603
+ },
8604
+ "lockListResult": {
8605
+ "type": "object",
8606
+ "required": [
8607
+ "ok",
8608
+ "locks"
8609
+ ],
8610
+ "properties": {
8611
+ "ok": {
8612
+ "const": true
8613
+ },
8614
+ "locks": {
8615
+ "type": "array",
8616
+ "items": {
8617
+ "type": "object",
8618
+ "required": [
8619
+ "name",
8620
+ "scope",
8621
+ "owner",
8622
+ "acquiredAt",
8623
+ "expiresAt",
8624
+ "ttlMs"
8625
+ ],
8626
+ "properties": {
8627
+ "name": {
8628
+ "type": "string",
8629
+ "minLength": 1
8630
+ },
8631
+ "scope": {
8632
+ "enum": [
8633
+ "session",
8634
+ "global"
8635
+ ]
8636
+ },
8637
+ "sessionId": {
8638
+ "type": "string"
8639
+ },
8640
+ "owner": {
8641
+ "type": "object",
8642
+ "required": [
8643
+ "kind"
8644
+ ],
8645
+ "properties": {
8646
+ "kind": {
8647
+ "enum": [
8648
+ "pane",
8649
+ "external"
8650
+ ]
8651
+ },
8652
+ "paneId": {
8653
+ "type": "string"
8654
+ },
8655
+ "panelId": {
8656
+ "type": "string"
8657
+ },
8658
+ "label": {
8659
+ "type": "string"
8660
+ }
8661
+ },
8662
+ "additionalProperties": false
8663
+ },
8664
+ "note": {
8665
+ "type": "string"
8666
+ },
8667
+ "acquiredAt": {
8668
+ "type": "string"
8669
+ },
8670
+ "expiresAt": {
8671
+ "type": "string"
8672
+ },
8673
+ "ttlMs": {
8674
+ "type": "number"
8675
+ }
8676
+ },
8677
+ "additionalProperties": false
8678
+ }
8679
+ }
8680
+ },
8681
+ "additionalProperties": false
8682
+ },
8683
+ "lockAcquireRequest": {
8684
+ "type": "object",
8685
+ "required": [
8686
+ "name",
8687
+ "ttlMs",
8688
+ "owner"
8689
+ ],
8690
+ "properties": {
8691
+ "name": {
8692
+ "type": "string",
8693
+ "minLength": 1
8694
+ },
8695
+ "ttlMs": {
8696
+ "type": "number"
8697
+ },
8698
+ "waitMs": {
8699
+ "type": "number"
8700
+ },
8701
+ "note": {
8702
+ "type": "string"
8703
+ },
8704
+ "owner": {
8705
+ "type": "object",
8706
+ "properties": {
8707
+ "paneId": {
8708
+ "type": "string"
8709
+ },
8710
+ "panelId": {
8711
+ "type": "string"
8712
+ },
8713
+ "label": {
8714
+ "type": "string"
8715
+ }
8716
+ },
8717
+ "additionalProperties": false
7327
8718
  }
7328
8719
  },
7329
8720
  "additionalProperties": false
7330
8721
  },
8722
+ "lockAcquireResult": {
8723
+ "oneOf": [
8724
+ {
8725
+ "type": "object",
8726
+ "required": [
8727
+ "ok",
8728
+ "acquired",
8729
+ "renewed",
8730
+ "waitedMs",
8731
+ "lock"
8732
+ ],
8733
+ "properties": {
8734
+ "ok": {
8735
+ "const": true
8736
+ },
8737
+ "acquired": {
8738
+ "const": true
8739
+ },
8740
+ "renewed": {
8741
+ "type": "boolean"
8742
+ },
8743
+ "waitedMs": {
8744
+ "type": "number"
8745
+ },
8746
+ "lock": {
8747
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8748
+ }
8749
+ },
8750
+ "additionalProperties": false
8751
+ },
8752
+ {
8753
+ "type": "object",
8754
+ "required": [
8755
+ "ok",
8756
+ "acquired",
8757
+ "timedOut",
8758
+ "waitedMs",
8759
+ "heldBy",
8760
+ "expiresAt",
8761
+ "lock"
8762
+ ],
8763
+ "properties": {
8764
+ "ok": {
8765
+ "const": false
8766
+ },
8767
+ "acquired": {
8768
+ "const": false
8769
+ },
8770
+ "timedOut": {
8771
+ "type": "boolean"
8772
+ },
8773
+ "waitedMs": {
8774
+ "type": "number"
8775
+ },
8776
+ "heldBy": {
8777
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items/properties/owner"
8778
+ },
8779
+ "expiresAt": {
8780
+ "type": "string"
8781
+ },
8782
+ "lock": {
8783
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8784
+ }
8785
+ },
8786
+ "additionalProperties": false
8787
+ }
8788
+ ]
8789
+ },
8790
+ "lockReleaseResult": {
8791
+ "oneOf": [
8792
+ {
8793
+ "type": "object",
8794
+ "required": [
8795
+ "ok",
8796
+ "released",
8797
+ "forced"
8798
+ ],
8799
+ "properties": {
8800
+ "ok": {
8801
+ "const": true
8802
+ },
8803
+ "released": {
8804
+ "type": "boolean"
8805
+ },
8806
+ "forced": {
8807
+ "type": "boolean"
8808
+ },
8809
+ "lock": {
8810
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8811
+ }
8812
+ },
8813
+ "additionalProperties": false
8814
+ },
8815
+ {
8816
+ "type": "object",
8817
+ "required": [
8818
+ "ok",
8819
+ "released",
8820
+ "reason",
8821
+ "heldBy",
8822
+ "expiresAt",
8823
+ "lock"
8824
+ ],
8825
+ "properties": {
8826
+ "ok": {
8827
+ "const": false
8828
+ },
8829
+ "released": {
8830
+ "const": false
8831
+ },
8832
+ "reason": {
8833
+ "const": "not-owner"
8834
+ },
8835
+ "heldBy": {
8836
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items/properties/owner"
8837
+ },
8838
+ "expiresAt": {
8839
+ "type": "string"
8840
+ },
8841
+ "lock": {
8842
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8843
+ }
8844
+ },
8845
+ "additionalProperties": false
8846
+ }
8847
+ ]
8848
+ },
7331
8849
  "daemonActionResult": {
7332
8850
  "type": "object",
7333
8851
  "required": [
@@ -7558,6 +9076,9 @@ exports.RUNPANE_CONTRACT = {
7558
9076
  },
7559
9077
  "link": {
7560
9078
  "type": "string"
9079
+ },
9080
+ "report": {
9081
+ "$ref": "#/jsonSchemas/agentReport"
7561
9082
  }
7562
9083
  },
7563
9084
  "additionalProperties": false
@@ -7583,25 +9104,230 @@ exports.RUNPANE_CONTRACT = {
7583
9104
  "delivered": {
7584
9105
  "type": "boolean"
7585
9106
  },
9107
+ "delivery": {
9108
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/delivery"
9109
+ },
7586
9110
  "blocked": {
7587
9111
  "type": "string"
7588
9112
  },
9113
+ "promptFile": {
9114
+ "type": "string"
9115
+ },
9116
+ "warnings": {
9117
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/warnings"
9118
+ },
7589
9119
  "next": {
7590
9120
  "type": "string"
7591
9121
  }
7592
9122
  },
7593
9123
  "additionalProperties": false
7594
- }
7595
- },
7596
- "agentContext": {
7597
- "brief": {
7598
- "title": "Pane agent context",
7599
- "summary": "Pane lets a developer manage saved base repositories, user-visible Panes (Pane sessions) for feature/PR work, and terminal-backed panel tabs. A Pane is a visible workspace that normally maps to one Pane-managed git worktree and branch; a panel is a terminal tab inside one Pane and shares that Pane's worktree; an agent is a CLI process running inside a panel.",
7600
- "rules": [
7601
- "Start with `runpane doctor --json` to understand wrapper, platform, daemon reachability, and the next safe commands before mutating Pane state.",
7602
- "In a Pane repository checkout, if `runpane` is not on PATH, use the built local wrapper with Node 22, for example `PATH=/opt/homebrew/opt/node@22/bin:$PATH node packages/runpane/dist/cli.js doctor --json`.",
7603
- "Happy path for any user request to use Pane/RunPane: run `runpane doctor --json`, read `runpane agent-context --json`, resolve or add the saved base repo, create the requested visible Pane with a complete command such as `runpane panes create --repo <repo> --name <name> --agent <agent> --prompt \"<task>\" --source agent --no-focus --wait-ready --yes --json` (the new Pane is pinned by default; add `--no-pinned` for a throwaway Pane, or use `--tool-command <command>` instead of `--agent <agent>`), then validate with `panels wait` or `panels screen`. For long-lived supervision, use `runpane watch --follow` instead of polling wait or screen.",
7604
- "Treat Pane as the user's visible cockpit for watching/co-driving work. Do not create Panes or panels for private delegation unless the user asked for visible Pane orchestration or the result should appear in the Pane app.",
9124
+ },
9125
+ "agentContextUnknownCommandError": {
9126
+ "type": "object",
9127
+ "required": [
9128
+ "ok",
9129
+ "code",
9130
+ "message",
9131
+ "candidates"
9132
+ ],
9133
+ "properties": {
9134
+ "ok": {
9135
+ "const": false
9136
+ },
9137
+ "code": {
9138
+ "const": "unknown_command"
9139
+ },
9140
+ "message": {
9141
+ "type": "string"
9142
+ },
9143
+ "candidates": {
9144
+ "type": "array",
9145
+ "items": {
9146
+ "type": "string"
9147
+ }
9148
+ }
9149
+ },
9150
+ "additionalProperties": false
9151
+ },
9152
+ "reportResult": {
9153
+ "type": "object",
9154
+ "required": [
9155
+ "ok",
9156
+ "paneId",
9157
+ "panelId",
9158
+ "report",
9159
+ "sessionIds"
9160
+ ],
9161
+ "properties": {
9162
+ "ok": {
9163
+ "const": true
9164
+ },
9165
+ "generation": {
9166
+ "type": "number"
9167
+ },
9168
+ "paneId": {
9169
+ "type": "string"
9170
+ },
9171
+ "panelId": {
9172
+ "type": "string"
9173
+ },
9174
+ "report": {
9175
+ "$ref": "#/jsonSchemas/agentReport"
9176
+ },
9177
+ "sessionIds": {
9178
+ "type": "array",
9179
+ "items": {
9180
+ "type": "string"
9181
+ }
9182
+ }
9183
+ },
9184
+ "additionalProperties": false
9185
+ },
9186
+ "paneArchiveBulkRequest": {
9187
+ "type": "object",
9188
+ "required": [
9189
+ "sessionId",
9190
+ "merged"
9191
+ ],
9192
+ "properties": {
9193
+ "sessionId": {
9194
+ "type": "string"
9195
+ },
9196
+ "merged": {
9197
+ "const": true
9198
+ },
9199
+ "source": {
9200
+ "enum": [
9201
+ "user",
9202
+ "agent"
9203
+ ]
9204
+ },
9205
+ "dryRun": {
9206
+ "type": "boolean"
9207
+ },
9208
+ "removeWorktree": {
9209
+ "type": "boolean"
9210
+ }
9211
+ },
9212
+ "additionalProperties": false
9213
+ },
9214
+ "paneArchiveBulkResult": {
9215
+ "type": "object",
9216
+ "required": [
9217
+ "ok",
9218
+ "sessionId",
9219
+ "merged",
9220
+ "removeWorktree",
9221
+ "archived",
9222
+ "skipped",
9223
+ "failed",
9224
+ "items"
9225
+ ],
9226
+ "properties": {
9227
+ "ok": {
9228
+ "type": "boolean"
9229
+ },
9230
+ "sessionId": {
9231
+ "type": "string"
9232
+ },
9233
+ "merged": {
9234
+ "const": true
9235
+ },
9236
+ "dryRun": {
9237
+ "const": true
9238
+ },
9239
+ "removeWorktree": {
9240
+ "type": "boolean"
9241
+ },
9242
+ "archived": {
9243
+ "type": "number",
9244
+ "description": "Panes archived, or that would be archived with --dry-run."
9245
+ },
9246
+ "skipped": {
9247
+ "type": "number"
9248
+ },
9249
+ "failed": {
9250
+ "type": "number"
9251
+ },
9252
+ "items": {
9253
+ "type": "array",
9254
+ "items": {
9255
+ "type": "object",
9256
+ "required": [
9257
+ "paneId",
9258
+ "outcome"
9259
+ ],
9260
+ "properties": {
9261
+ "paneId": {
9262
+ "type": "string"
9263
+ },
9264
+ "name": {
9265
+ "type": "string"
9266
+ },
9267
+ "outcome": {
9268
+ "enum": [
9269
+ "archived",
9270
+ "would-archive",
9271
+ "skipped",
9272
+ "failed"
9273
+ ]
9274
+ },
9275
+ "skipped": {
9276
+ "type": "object",
9277
+ "required": [
9278
+ "code",
9279
+ "message"
9280
+ ],
9281
+ "properties": {
9282
+ "code": {
9283
+ "enum": [
9284
+ "uncommitted-changes",
9285
+ "unpushed-commits",
9286
+ "uncommitted-and-unpushed",
9287
+ "status-unknown",
9288
+ "missing-pane",
9289
+ "already-archived",
9290
+ "main-repo"
9291
+ ]
9292
+ },
9293
+ "message": {
9294
+ "type": "string"
9295
+ }
9296
+ },
9297
+ "additionalProperties": false
9298
+ },
9299
+ "error": {
9300
+ "type": "string"
9301
+ },
9302
+ "safetyCheck": {
9303
+ "$ref": "#/jsonSchemas/paneArchiveResult/oneOf/0/properties/safetyCheck"
9304
+ },
9305
+ "worktreeCleanup": {
9306
+ "$ref": "#/jsonSchemas/paneArchiveResult/oneOf/0/properties/worktreeCleanup"
9307
+ },
9308
+ "trashDeletion": {
9309
+ "$ref": "#/jsonSchemas/paneArchiveResult/oneOf/0/properties/trashDeletion"
9310
+ },
9311
+ "worktreePath": {
9312
+ "type": "string"
9313
+ }
9314
+ },
9315
+ "additionalProperties": false
9316
+ }
9317
+ }
9318
+ },
9319
+ "additionalProperties": false
9320
+ }
9321
+ },
9322
+ "agentContext": {
9323
+ "brief": {
9324
+ "title": "Pane agent context",
9325
+ "summary": "Pane lets a developer manage saved base repositories, user-visible Panes (Pane sessions) for feature/PR work, and terminal-backed panel tabs. A Pane is a visible workspace that normally maps to one Pane-managed git worktree and branch; a panel is a terminal tab inside one Pane and shares that Pane's worktree; an agent is a CLI process running inside a panel.",
9326
+ "rules": [
9327
+ "Start with `runpane doctor --json` to understand wrapper, platform, daemon reachability, and the next safe commands before mutating Pane state.",
9328
+ "In a Pane repository checkout, if `runpane` is not on PATH, use the built local wrapper with Node 22, for example `PATH=/opt/homebrew/opt/node@22/bin:$PATH node packages/runpane/dist/cli.js doctor --json`.",
9329
+ "Happy path for any user request to use Pane/RunPane: run `runpane doctor --json`, read `runpane agent-context --json`, resolve or add the saved base repo, create the requested visible Pane with a complete command such as `runpane panes create --repo <repo> --name <name> --agent <agent> --prompt \"<task>\" --source agent --no-focus --wait-ready --yes --json` (the new Pane is pinned by default; add `--no-pinned` for a throwaway Pane, add `--base-branch <ref>` to branch from something other than the repository default, or use `--tool-command <command>` instead of `--agent <agent>`), then validate with `panels wait` or `panels screen`. For long-lived supervision, use `runpane watch --follow` instead of polling wait or screen.",
9330
+ "Treat Pane as the user's visible cockpit for watching/co-driving work. Do not create Panes or panels for private delegation unless the user asked for visible Pane orchestration or the result should appear in the Pane app.",
7605
9331
  "Register the saved base repository once with `repos add`; do not register a pre-created worktree as a separate repo unless the user explicitly asks.",
7606
9332
  "Use `panes create` for separate visible Panes (Pane sessions) for feature/PR work. Pane creates and owns the worktree/branch for each new Pane.",
7607
9333
  "Use `panels create` for reviewer/helper/clean-context tabs that should stay inside an existing Pane and share that Pane's worktree.",
@@ -7618,7 +9344,8 @@ exports.RUNPANE_CONTRACT = {
7618
9344
  "Use `runpane panels screen` for compact current state, including Claude and Codex composer state. Use `panels wait` for create-time readiness or text checks. Use `runpane watch --follow` to block on workspace transitions (READY, BLOCKED, IDLE, STUCK, EXIT) without polling. Use `panels submit` to send and submit a new turn. Use `panels submit-composer --strategy auto` only for a composer that was filled separately.",
7619
9345
  "Use `runpane panels input` only when exact bytes are required, such as Ctrl-C or handcrafted terminal input.",
7620
9346
  "Pane terminals draw inline images: sixel, iTerm2 inline images, and the kitty graphics protocol. Tools that need kitty graphics, such as terminal-browser and terminal-doom, run inside a Pane panel; `runpane doctor --json` reports the exact list under `terminal.graphicsProtocols`.",
7621
- "After creating Panes or sending terminal input, validate with `panels wait` or bounded `panels screen` before reporting success. For ongoing supervision, `runpane watch --follow` is the canonical monitor."
9347
+ "After creating Panes or sending terminal input, validate with `panels wait` or bounded `panels screen` before reporting success. For ongoing supervision, `runpane watch --follow` is the canonical monitor.",
9348
+ "When several agents share one resource, such as a test account, name a lock in their prompts: each worker runs `runpane lock acquire --name <name> --ttl 30m --wait 1800000 --json` before using it and `runpane lock release --name <name>` after."
7622
9349
  ],
7623
9350
  "detailCommand": "runpane agent-context --command <command> [--json]",
7624
9351
  "tools": [
@@ -7713,11 +9440,14 @@ exports.RUNPANE_CONTRACT = {
7713
9440
  },
7714
9441
  {
7715
9442
  "name": "panes archive",
7716
- "summary": "Archive a Pane exactly like the UI Archive action, including safe removal of its Pane-managed git worktree.",
9443
+ "summary": "Archive a Pane exactly like the UI Archive action, including safe removal of its Pane-managed git worktree, or archive every merged Pane in a Session.",
7717
9444
  "arguments": [
7718
9445
  "--pane <pane-id>",
9446
+ "--session <id|name>",
9447
+ "--merged",
7719
9448
  "--source <user|agent>",
7720
9449
  "--force",
9450
+ "--remove-worktree",
7721
9451
  "--dry-run",
7722
9452
  "--yes",
7723
9453
  "--json"
@@ -7780,6 +9510,22 @@ exports.RUNPANE_CONTRACT = {
7780
9510
  "--json"
7781
9511
  ]
7782
9512
  },
9513
+ {
9514
+ "name": "panels open",
9515
+ "summary": "Show the user an HTML page, plan, report, dev server URL, or file as a tab in split view beside the agent.",
9516
+ "arguments": [
9517
+ "--pane <pane-id>",
9518
+ "--url <url>",
9519
+ "--file <path>",
9520
+ "--title <title>",
9521
+ "--split",
9522
+ "--tab",
9523
+ "--no-focus",
9524
+ "--source <user|agent>",
9525
+ "--yes",
9526
+ "--json"
9527
+ ]
9528
+ },
7783
9529
  {
7784
9530
  "name": "panels list",
7785
9531
  "summary": "List tool panels inside a Pane session.",
@@ -7858,9 +9604,10 @@ exports.RUNPANE_CONTRACT = {
7858
9604
  },
7859
9605
  {
7860
9606
  "name": "watch",
7861
- "summary": "Wait for workspace transitions (READY, BLOCKED, IDLE, STUCK, NEW, GONE, EXIT) from the daemon journal without polling; responsive by default, with opt-in cadence flags for expensive consumers.",
9607
+ "summary": "Wait for workspace transitions (READY, BLOCKED, IDLE, STUCK, NEW, GONE, EXIT, JOINED, LEFT, PR) from the daemon journal without polling; responsive by default, with opt-in cadence flags for expensive consumers.",
7862
9608
  "arguments": [
7863
9609
  "--follow",
9610
+ "--session <id|name>",
7864
9611
  "--self-test",
7865
9612
  "--kinds <kind,...>",
7866
9613
  "--settle <ms>",
@@ -7993,6 +9740,12 @@ exports.RUNPANE_CONTRACT = {
7993
9740
  "value": "<path>",
7994
9741
  "required": false,
7995
9742
  "description": "Ignored for version; retained only for parser compatibility."
9743
+ },
9744
+ {
9745
+ "name": "--pane-dir",
9746
+ "value": "<path>",
9747
+ "required": false,
9748
+ "description": "Accepted and ignored, so one --pane-dir can be passed to every runpane command."
7996
9749
  }
7997
9750
  ],
7998
9751
  "examples": [
@@ -8138,11 +9891,14 @@ exports.RUNPANE_CONTRACT = {
8138
9891
  ],
8139
9892
  "jsonSchemas": [
8140
9893
  "agentContextBriefResult",
8141
- "agentContextCommandResult"
9894
+ "agentContextCommandResult",
9895
+ "agentContextUnknownCommandError"
8142
9896
  ],
8143
9897
  "notes": [
8144
9898
  "Default output is brief so AGENTS.md can point here without bloating context.",
8145
- "`--command` accepts canonical spaced names and common copied forms, including `panes.create` and `runpane panes create`."
9899
+ "`--command` accepts canonical spaced names and common copied forms, including `panes.create` and `runpane panes create`.",
9900
+ "An unknown `--command` exits 2. With `--json` it prints `{ ok: false, code: \"unknown_command\", message, candidates }` on stdout, where `candidates` lists the closest command names first; without `--json` the same candidates go to stderr.",
9901
+ "`--pane-dir <path>` is accepted and ignored, so one `--pane-dir` can be passed to every runpane command."
8146
9902
  ]
8147
9903
  },
8148
9904
  "mcp": {
@@ -8289,7 +10045,8 @@ exports.RUNPANE_CONTRACT = {
8289
10045
  "paneListResult"
8290
10046
  ],
8291
10047
  "notes": [
8292
- "Without --repo, this lists sessions across saved Pane repositories."
10048
+ "Without --repo, this lists sessions across saved Pane repositories.",
10049
+ "`status` is `running` while any terminal panel is live, otherwise the stored lifecycle value. `agentState` is the most urgent state of the live agent panels: `blocked`, `working`, `ready`, or `none`. `agentStatus` (`active`/`idle`) is kept for older clients."
8293
10050
  ]
8294
10051
  },
8295
10052
  "panes cost": {
@@ -8355,11 +10112,23 @@ exports.RUNPANE_CONTRACT = {
8355
10112
  "required": true,
8356
10113
  "description": "Pane/session name."
8357
10114
  },
10115
+ {
10116
+ "name": "--base-branch",
10117
+ "value": "<branch>",
10118
+ "required": false,
10119
+ "description": "Branch the new worktree from this ref (for example origin/main or release/2.4) instead of the repository default."
10120
+ },
10121
+ {
10122
+ "name": "--worktree-name",
10123
+ "value": "<name>",
10124
+ "required": false,
10125
+ "description": "Worktree and branch name; defaults to --name. Characters outside [a-z0-9-] are removed."
10126
+ },
8358
10127
  {
8359
10128
  "name": "--agent",
8360
10129
  "value": "<codex|claude|cursor>",
8361
10130
  "required": false,
8362
- "description": "Built-in agent terminal template to open."
10131
+ "description": "Built-in agent terminal template to open. With --tool-command, the agent that command runs."
8363
10132
  },
8364
10133
  {
8365
10134
  "name": "--tool-command",
@@ -8367,6 +10136,24 @@ exports.RUNPANE_CONTRACT = {
8367
10136
  "required": false,
8368
10137
  "description": "Custom terminal command to run instead of a built-in agent."
8369
10138
  },
10139
+ {
10140
+ "name": "--base-branch",
10141
+ "value": "<ref>",
10142
+ "required": false,
10143
+ "description": "Ref to branch from, such as origin/main or release/foo. --base is an alias."
10144
+ },
10145
+ {
10146
+ "name": "--branch",
10147
+ "value": "<name>",
10148
+ "required": false,
10149
+ "description": "Exact new branch name, slashes included (for example agents/w5a). Fails if the branch exists; never renamed to be unique. Defaults to the worktree name."
10150
+ },
10151
+ {
10152
+ "name": "--worktree-name",
10153
+ "value": "<name>",
10154
+ "required": false,
10155
+ "description": "Worktree directory name; defaults to --name."
10156
+ },
8370
10157
  {
8371
10158
  "name": "--prompt",
8372
10159
  "value": "<text>",
@@ -8377,7 +10164,12 @@ exports.RUNPANE_CONTRACT = {
8377
10164
  "name": "--initial-input-file",
8378
10165
  "value": "<path|->",
8379
10166
  "required": false,
8380
- "description": "Read initial input from a file or stdin."
10167
+ "description": "Read initial input from a file or stdin. --prompt-file is an alias."
10168
+ },
10169
+ {
10170
+ "name": "--as-file-pointer",
10171
+ "required": false,
10172
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
8381
10173
  },
8382
10174
  {
8383
10175
  "name": "--from-json",
@@ -8447,12 +10239,20 @@ exports.RUNPANE_CONTRACT = {
8447
10239
  "value": "<count>",
8448
10240
  "required": false,
8449
10241
  "description": "Accepted for compatibility. Pane currently serializes multi-pane session creation so queued jobs do not time out before starting."
10242
+ },
10243
+ {
10244
+ "name": "--pane-dir",
10245
+ "value": "<path>",
10246
+ "required": false,
10247
+ "description": "Connect to a specific Pane data directory."
8450
10248
  }
8451
10249
  ],
8452
10250
  "examples": [
8453
10251
  "runpane panes create --repo active --name issue-257 --agent <agent> --prompt \"Plan this issue\" --source agent --no-focus --wait-ready --yes --json",
10252
+ "runpane panes create --repo active --name w5a --base origin/main --branch agents/w5a --agent <agent> --prompt-file prompt.md --source agent --no-focus --wait-ready --yes --json",
8454
10253
  "runpane panes create --from-json panes.json --yes --json",
8455
- "runpane panes create --repo active --name issue-123 --agent <agent> --prompt \"Plan this issue\" --source agent --no-focus --wait-ready --yes --json"
10254
+ "runpane panes create --repo active --name issue-123 --agent <agent> --prompt \"Plan this issue\" --source agent --no-focus --wait-ready --yes --json",
10255
+ "runpane panes create --repo active --name issue-123 --agent claude --initial-input-file brief.md --as-file-pointer --source agent --no-focus --wait-ready --yes --json"
8456
10256
  ],
8457
10257
  "jsonSchemas": [
8458
10258
  "paneCreateRequest",
@@ -8462,11 +10262,14 @@ exports.RUNPANE_CONTRACT = {
8462
10262
  "At least one of --agent or --tool-command is required unless --from-json is used.",
8463
10263
  "`panes create` is for user-visible Pane orchestration, not the agent's default private delegation mechanism.",
8464
10264
  "Register the saved base repository once. Pane creates and owns the worktree/branch for each new Pane.",
10265
+ "`panes create --base <ref> --branch <name> --prompt-file <file>` replaces `git worktree add` plus `panes adopt`: Pane creates the worktree on exactly that branch name. `--branch` is checked with `git check-ref-format --branch` and fails if the branch already exists; `--worktree-name` still names the directory.",
8465
10266
  "Use `panels create` instead when a reviewer/helper should share an existing Pane's worktree.",
8466
10267
  "Agent-created Panes should pass `--source agent --no-focus --wait-ready --yes --json` unless the user explicitly wants focus moved. `panes create` pins the new Pane by default, so a follow-up `panes pin` call is unnecessary; pass `--no-pinned` for throwaway shells or bulk imports. `--pinned` is still accepted and is now a no-op. Inside a Session orchestrator (`PANE_ORCHESTRATION_SESSION_ID` set), new Panes are associated with that Session automatically; `--no-associate` opts out. A failed association is reported on the item and never undoes the Pane.",
8467
10268
  "The built-in agent templates come from the runpane contract; custom terminal commands can pass agent-specific flags when requested by the user.",
8468
- "Use --initial-input-file for multi-line prompts or shell-sensitive initial input.",
8469
- "With --wait-ready, verifiedSubmitted is earned from delivery evidence; routing initial input alone does not imply verified submission.",
10269
+ "Use --initial-input-file for multi-line prompts or shell-sensitive initial input. A long or multi-line prompt is never typed into the shell: on bash, zsh or sh the agent launches with `\"$(cat '<prompt file>')\"` reading a private copy under `<pane-dir>/prompts/<pane-id>/`; on PowerShell, cmd, fish or WSL the prompt is pasted into the agent's composer once it is ready.",
10270
+ "`--as-file-pointer` writes the text to `<pane-dir>/prompts/<pane-id>/<timestamp>.md` (readable only by you) and sends the one line `Read and follow <path>`; the result includes `promptFile`. Prefer it for long prompts.",
10271
+ "For Claude, text starting with `!`, `#`, `/` or `@` is sent unchanged and the result carries a `warnings` entry (for example `leading-bang-runs-shell`), because Claude Code gives those characters a meaning of its own.",
10272
+ "With --wait-ready, `initialInput.delivery` reports `taken`, `queued`, `in-composer` or `unknown` with its evidence (`transcript`, `screen`, or `argv` for a prompt passed at launch); verifiedSubmitted is true for `taken` or `queued`. Routing initial input alone does not imply verified submission.",
8470
10273
  "If initialInput.blocked.kind is submission_unverified, do not submit again automatically. Inspect initialInput.staged and attempts, then run nextCommand to resolve the ambiguous composer state.",
8471
10274
  "When the JSON result includes nextCommand, run it to validate that the terminal produced output before reporting success.",
8472
10275
  "Multi-pane requests are created sequentially today. The --concurrency flag is accepted for compatibility, but agents should not rely on parallel creation.",
@@ -8474,7 +10277,8 @@ exports.RUNPANE_CONTRACT = {
8474
10277
  "For Windows PowerShell command chaining, use a custom terminal command like `powershell -NoProfile -Command \"cmd1; if ($LASTEXITCODE) { exit $LASTEXITCODE }; cmd2\"`.",
8475
10278
  "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 <agent> --prompt \"Plan this issue\" --source agent --no-focus --wait-ready --yes --json'`.",
8476
10279
  "Use --wait-ready when an agent needs to verify that an agent terminal started instead of only creating a pane.",
8477
- "If readiness returns blocked, inspect blocked.suggestedCommand rather than guessing which prompt to answer."
10280
+ "If readiness returns blocked, inspect blocked.suggestedCommand rather than guessing which prompt to answer.",
10281
+ "With --tool-command, --agent names the agent the command runs (a wrapper such as `agent-farm run`): Pane launches the command unchanged and treats the panel as that agent. Without --agent, Pane detects Claude Code, Codex and Cursor from the foreground process or the agent's screen."
8478
10282
  ]
8479
10283
  },
8480
10284
  "panes adopt": {
@@ -8505,8 +10309,14 @@ exports.RUNPANE_CONTRACT = {
8505
10309
  {
8506
10310
  "name": "--agent",
8507
10311
  "value": "<codex|claude|cursor>",
8508
- "required": true,
8509
- "description": "Agent whose terminal to create."
10312
+ "required": false,
10313
+ "description": "Agent whose terminal to create; with --tool-command, the agent that command runs."
10314
+ },
10315
+ {
10316
+ "name": "--tool-command",
10317
+ "value": "<command>",
10318
+ "required": false,
10319
+ "description": "Custom command to stage or launch instead of a built-in agent, such as a wrapper that runs one."
8510
10320
  },
8511
10321
  {
8512
10322
  "name": "--resume",
@@ -8523,7 +10333,30 @@ exports.RUNPANE_CONTRACT = {
8523
10333
  {
8524
10334
  "name": "--launch",
8525
10335
  "required": false,
8526
- "description": "Run the resume command immediately."
10336
+ "description": "Run the agent (or its resume command) immediately."
10337
+ },
10338
+ {
10339
+ "name": "--prompt",
10340
+ "value": "<text>",
10341
+ "required": false,
10342
+ "description": "Alias for --initial-input; sent once the launched agent is ready. Requires --launch."
10343
+ },
10344
+ {
10345
+ "name": "--prompt-file",
10346
+ "value": "<path|->",
10347
+ "required": false,
10348
+ "description": "Alias for --initial-input-file; read the prompt from a file or stdin. Requires --launch."
10349
+ },
10350
+ {
10351
+ "name": "--wait-ready",
10352
+ "required": false,
10353
+ "description": "Wait for the launched agent to be ready and the prompt submitted before returning. Requires --launch."
10354
+ },
10355
+ {
10356
+ "name": "--ready-timeout-ms",
10357
+ "value": "<ms>",
10358
+ "required": false,
10359
+ "description": "Readiness timeout; defaults to 30000."
8527
10360
  },
8528
10361
  {
8529
10362
  "name": "--no-pinned",
@@ -8549,31 +10382,46 @@ exports.RUNPANE_CONTRACT = {
8549
10382
  "name": "--json",
8550
10383
  "required": false,
8551
10384
  "description": "Print machine-readable output."
10385
+ },
10386
+ {
10387
+ "name": "--pane-dir",
10388
+ "value": "<path>",
10389
+ "required": false,
10390
+ "description": "Connect to a specific Pane data directory."
8552
10391
  }
8553
10392
  ],
8554
10393
  "examples": [
8555
- "runpane panes adopt --repo active --path /path/to/worktree --name imported --agent codex --resume <id> --yes --json"
10394
+ "runpane panes adopt --repo active --path /path/to/worktree --name imported --agent codex --resume <id> --yes --json",
10395
+ "runpane panes adopt --repo active --path /path/to/worktree --name imported --tool-command \"agent-farm run free-range\" --agent claude --launch --yes --json",
10396
+ "runpane panes adopt --repo active --path /path/to/worktree --name imported --agent claude --launch --prompt-file prompt.md --wait-ready --yes --json"
8556
10397
  ],
8557
10398
  "jsonSchemas": [
8558
10399
  "paneCreateResult"
8559
10400
  ],
8560
10401
  "notes": [
8561
10402
  "The resume command is staged without Enter unless --launch is passed.",
8562
- "Pane never removes an externally owned worktree."
10403
+ "Archiving never deletes an adopted worktree unless `runpane panes archive --remove-worktree` is used.",
10404
+ "One of --agent or --tool-command is required.",
10405
+ "With --tool-command, --agent names the agent the command runs (a wrapper such as `agent-farm run`): Pane launches the command unchanged and treats the panel as that agent. Without --agent, Pane detects Claude Code, Codex and Cursor from the foreground process or the agent's screen.",
10406
+ "--resume needs a built-in agent command; a wrapper command resumes its own way.",
10407
+ "The adopted Pane reports `status: running` in `panes list` while its terminal is live.",
10408
+ "A prompt (--prompt, --initial-input, --prompt-file, --initial-input-file) or --wait-ready needs --launch; without it adopt fails instead of dropping the prompt.",
10409
+ "With --launch the result carries the same readiness, initialInput, and nextCommand fields as panes create. With --resume the prompt goes to the resumed conversation's composer once the agent is ready.",
10410
+ "To start new work on a named branch, prefer `panes create --base <ref> --branch <name>` over `git worktree add` plus adopt."
8563
10411
  ]
8564
10412
  },
8565
10413
  "panes archive": {
8566
10414
  "name": "panes archive",
8567
- "summary": "Archive a Pane (session) exactly like the UI Archive action, including safe removal of its Pane-managed git worktree.",
8568
- "details": "Use this to close out a Pane once its PR has merged. The safety check refreshes the configured upstream before comparing it to HEAD and includes exact unpushed commit IDs and subjects. Refuses unsafe archive operations unless --force is used. Use --dry-run to inspect the same evidence without mutating Pane state.",
10415
+ "summary": "Archive a Pane (session) exactly like the UI Archive action, including safe removal of its Pane-managed git worktree, or archive every merged Pane in a Session.",
10416
+ "details": "Use this to close out a Pane once its PR has merged. The safety check refreshes the configured upstream before comparing it to HEAD and includes exact unpushed commit IDs and subjects. When the branch has no upstream or its upstream is gone (GitHub deletes merged branches), a merged pull request whose head is HEAD counts as pushed, so squash-merged branches archive without --force. Refuses unsafe archive operations unless --force is used. Use --dry-run to inspect the same evidence without mutating Pane state. Use --session <id|name> --merged to close out every finished Pane of a Session at once.",
8569
10417
  "requiresPaneDaemon": true,
8570
10418
  "mutates": true,
8571
10419
  "arguments": [
8572
10420
  {
8573
10421
  "name": "--pane",
8574
10422
  "value": "<pane-id>",
8575
- "required": true,
8576
- "description": "Pane/session id to archive."
10423
+ "required": false,
10424
+ "description": "Pane/session id to archive. Required unless --session is used."
8577
10425
  },
8578
10426
  {
8579
10427
  "name": "--source",
@@ -8586,6 +10434,22 @@ exports.RUNPANE_CONTRACT = {
8586
10434
  "required": false,
8587
10435
  "description": "Archive even if the pane's branch has uncommitted, untracked, or unpushed changes."
8588
10436
  },
10437
+ {
10438
+ "name": "--remove-worktree",
10439
+ "required": false,
10440
+ "description": "Also check and remove an adopted Pane's worktree. Pane-managed worktrees are always removed; the local branch is always kept."
10441
+ },
10442
+ {
10443
+ "name": "--session",
10444
+ "value": "<id|name>",
10445
+ "required": false,
10446
+ "description": "Archive the Panes associated with this named Session instead of one Pane. Requires --merged."
10447
+ },
10448
+ {
10449
+ "name": "--merged",
10450
+ "required": false,
10451
+ "description": "With --session, archive only Panes that are clean and pushed, or merged via a pull request; skip the rest with a reason."
10452
+ },
8589
10453
  {
8590
10454
  "name": "--yes",
8591
10455
  "required": false,
@@ -8600,24 +10464,39 @@ exports.RUNPANE_CONTRACT = {
8600
10464
  "name": "--json",
8601
10465
  "required": false,
8602
10466
  "description": "Print machine-readable output."
10467
+ },
10468
+ {
10469
+ "name": "--pane-dir",
10470
+ "value": "<path>",
10471
+ "required": false,
10472
+ "description": "Connect to a specific Pane data directory."
8603
10473
  }
8604
10474
  ],
8605
10475
  "examples": [
8606
10476
  "runpane panes archive --pane <pane-id> --source agent --yes --json",
8607
10477
  "runpane panes archive --pane <pane-id> --dry-run --json",
10478
+ "runpane panes archive --pane <pane-id> --remove-worktree --yes --json",
10479
+ "runpane panes archive --session <id|name> --merged --dry-run --json",
10480
+ "runpane panes archive --session <id|name> --merged --remove-worktree --yes --json",
8608
10481
  "runpane panes archive --pane <pane-id> --force --yes --json"
8609
10482
  ],
8610
10483
  "jsonSchemas": [
8611
10484
  "paneArchiveRequest",
8612
- "paneArchiveResult"
10485
+ "paneArchiveBulkRequest",
10486
+ "paneArchiveResult",
10487
+ "paneArchiveBulkResult"
8613
10488
  ],
8614
10489
  "notes": [
8615
10490
  "If the result has ok:false with a blocked field, the pane was NOT archived; inspect blocked.code and rerun with --force if discarding the flagged work is intentional.",
8616
10491
  "Inspect safetyCheck.unpushedCommitDetails for exact commit IDs and subjects; upstreamRefreshed confirms the tracking ref was refreshed first.",
8617
10492
  "A --dry-run result sets dryRun:true and wouldArchive without deleting the Pane or its worktree.",
8618
- "A successful archive waits for the Pane-managed worktree to be removed before returning; check worktreeCleanup in the result for the final outcome.",
10493
+ "A successful archive reports worktreeCleanup `completed` once the worktree is gone from its path and from git. trashDeletion `pending` means a large worktree (for example one with node_modules) is still being deleted from .git/pane-trash in the background; that is still ok:true. `timeout` (also ok:true) means removal is still running; only `failed` sets ok:false.",
10494
+ "safetyCheck.mergedViaPr names the merged PR whose head is HEAD; it needs an authenticated `gh`. Without it, a squash-merged branch whose remote branch was deleted reports unpushed-commits.",
10495
+ "An adopted Pane (panes adopt) keeps its worktree unless --remove-worktree is passed. `panes restore` does not recreate a removed adopted worktree; the local branch is kept, so `git worktree add <path> <branch>` brings it back.",
10496
+ "With --session --merged, each item has outcome archived, would-archive (dry run), skipped (with skipped.code and skipped.message), or failed.",
8619
10497
  "Archiving a main-repo Pane (no Pane-managed worktree) always succeeds immediately since nothing is deleted from disk.",
8620
- "Undo an archive with `runpane panes restore --pane <pane-id> --yes`, which recreates the worktree. `runpane links create --pane <pane-id>` gives the user a link to review the Pane first."
10498
+ "Undo an archive with `runpane panes restore --pane <pane-id> --yes`, which recreates the worktree. `runpane links create --pane <pane-id>` gives the user a link to review the Pane first.",
10499
+ "When the safety check is skipped, `safetyCheck.reason` says why: `external-worktree` (an adopted Pane whose worktree Pane does not own), `main-repo`, `missing-project-context`, or `git-error`. `worktreeWillRemain: true` means archiving leaves the worktree on disk."
8621
10500
  ]
8622
10501
  },
8623
10502
  "panes pin": {
@@ -8647,6 +10526,12 @@ exports.RUNPANE_CONTRACT = {
8647
10526
  "name": "--json",
8648
10527
  "required": false,
8649
10528
  "description": "Print machine-readable output."
10529
+ },
10530
+ {
10531
+ "name": "--pane-dir",
10532
+ "value": "<path>",
10533
+ "required": false,
10534
+ "description": "Connect to a specific Pane data directory."
8650
10535
  }
8651
10536
  ],
8652
10537
  "examples": [
@@ -8689,11 +10574,17 @@ exports.RUNPANE_CONTRACT = {
8689
10574
  "name": "--json",
8690
10575
  "required": false,
8691
10576
  "description": "Print machine-readable output."
8692
- }
8693
- ],
8694
- "examples": [
8695
- "runpane panes unpin --pane <pane-id> --yes --json",
8696
- "runpane panes unpin --pane <pane-id> --dry-run --json"
10577
+ },
10578
+ {
10579
+ "name": "--pane-dir",
10580
+ "value": "<path>",
10581
+ "required": false,
10582
+ "description": "Connect to a specific Pane data directory."
10583
+ }
10584
+ ],
10585
+ "examples": [
10586
+ "runpane panes unpin --pane <pane-id> --yes --json",
10587
+ "runpane panes unpin --pane <pane-id> --dry-run --json"
8697
10588
  ],
8698
10589
  "jsonSchemas": [
8699
10590
  "panePinRequest",
@@ -8737,6 +10628,12 @@ exports.RUNPANE_CONTRACT = {
8737
10628
  "name": "--json",
8738
10629
  "required": false,
8739
10630
  "description": "Print machine-readable output including the updated pane."
10631
+ },
10632
+ {
10633
+ "name": "--pane-dir",
10634
+ "value": "<path>",
10635
+ "required": false,
10636
+ "description": "Connect to a specific Pane data directory."
8740
10637
  }
8741
10638
  ],
8742
10639
  "examples": [
@@ -8786,6 +10683,12 @@ exports.RUNPANE_CONTRACT = {
8786
10683
  "name": "--json",
8787
10684
  "required": false,
8788
10685
  "description": "Print machine-readable output."
10686
+ },
10687
+ {
10688
+ "name": "--pane-dir",
10689
+ "value": "<path>",
10690
+ "required": false,
10691
+ "description": "Connect to a specific Pane data directory."
8789
10692
  }
8790
10693
  ],
8791
10694
  "examples": [
@@ -8834,7 +10737,8 @@ exports.RUNPANE_CONTRACT = {
8834
10737
  "panelListResult"
8835
10738
  ],
8836
10739
  "notes": [
8837
- "The ids returned here are stable inputs for `panels output` and `panels input`."
10740
+ "The ids returned here are stable inputs for `panels output` and `panels input`.",
10741
+ "`agentType` is the agent Pane treats the panel as; `agentDetection` says how it knows (`declared`, `command`, `process`, or `screen`), and `launchCommand` is the command the panel was launched with."
8838
10742
  ]
8839
10743
  },
8840
10744
  "panels output": {
@@ -9030,14 +10934,14 @@ exports.RUNPANE_CONTRACT = {
9030
10934
  ],
9031
10935
  "notes": [
9032
10936
  "Use this before `panels output` when an agent only needs the latest visible/current state.",
9033
- "The composer object reports whether a Claude or Codex composer is present and whether it holds undelivered text. Claude's dim placeholder suggestion does not count as undelivered text.",
10937
+ "The composer object reports whether a Claude or Codex composer is present and whether it holds undelivered text. Placeholder and suggestion text (drawn dim or grey, such as Claude's suggested next prompt) does not count as undelivered text; `composer.ghostText` carries it, and text output marks its line with `⟨suggestion⟩`.",
9034
10938
  "If hasMore is true and context is missing, rerun with a larger --limit or use `panels output`."
9035
10939
  ]
9036
10940
  },
9037
10941
  "panels submit": {
9038
10942
  "name": "panels submit",
9039
10943
  "summary": "Send and submit text to a terminal panel, including idle agent composers.",
9040
- "details": "Use this for ordinary interactive submissions. For Claude, Pane waits for the composer to appear and show the staged text, then sends Enter on its own and verifies that the composer cleared; Claude keeps an Enter that arrives together with the text as a newline. For an idle Codex composer, Pane stages the text, waits for Codex paste handling, sends the Codex submit sequence, and verifies that the turn started when visible evidence is available. Other terminals receive a normalized CR Enter. Exact byte workflows remain on `panels input`.",
10944
+ "details": "Use this for ordinary interactive submissions. For Claude, Pane waits for the composer to appear and show the staged text, then sends Enter on its own and verifies that the composer cleared; Claude keeps an Enter that arrives together with the text as a newline. For a Codex composer, Pane stages the text, waits for paste handling, then queues with Tab while working or submits with Enter when ready, and verifies delivery when visible evidence is available. Wrapper-launched agents are handled the same way once Pane knows the agent (declared, from the foreground process, or from the screen). A Claude or Codex panel with no composer on screen gets nothing: the result is `ok: false` with `blocked.kind: composer-unknown`. Multi-line or long (over 512 characters) text reaches a Claude or Codex composer as one bracketed paste: CRLF becomes LF, and the submit key goes as its own write once the paste has settled, even while the agent is working. Other terminals receive a normalized CR Enter. Exact byte workflows remain on `panels input`.",
9041
10945
  "requiresPaneDaemon": true,
9042
10946
  "mutates": true,
9043
10947
  "arguments": [
@@ -9059,6 +10963,11 @@ exports.RUNPANE_CONTRACT = {
9059
10963
  "required": false,
9060
10964
  "description": "Read text from a file or stdin before Enter."
9061
10965
  },
10966
+ {
10967
+ "name": "--as-file-pointer",
10968
+ "required": false,
10969
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
10970
+ },
9062
10971
  {
9063
10972
  "name": "--yes",
9064
10973
  "required": false,
@@ -9078,16 +10987,20 @@ exports.RUNPANE_CONTRACT = {
9078
10987
  ],
9079
10988
  "examples": [
9080
10989
  "runpane panels submit --panel <panel-id> --text \"2\" --yes --json",
9081
- "printf \"echo hello\" | runpane panels submit --panel <panel-id> --input-file - --yes --json"
10990
+ "printf \"echo hello\" | runpane panels submit --panel <panel-id> --input-file - --yes --json",
10991
+ "runpane panels submit --panel <panel-id> --input-file brief.md --as-file-pointer --yes --json"
9082
10992
  ],
9083
10993
  "jsonSchemas": [
9084
10994
  "panelSubmitRequest",
9085
10995
  "panelSubmitResult"
9086
10996
  ],
9087
10997
  "notes": [
9088
- "The response includes sequenceName, verifiedSubmitted, and nextCommand. If ok is false, inspect blocked and do not assume the turn started.",
9089
- "Do not follow `panels submit` with `panels submit-composer`; Claude and idle Codex composer submission is handled atomically.",
9090
- "Use `panels input` for Ctrl-C, escape sequences, or any workflow requiring exact bytes."
10998
+ "The response includes sequenceName, verifiedSubmitted, delivery and nextCommand. For Claude and Codex, `delivery.state` is `taken` (the agent started a turn with the text), `queued` (it holds the text until its current turn ends), `in-composer` (the text is still in the composer) or `unknown`, and `delivery.evidence` is `transcript` (the agent's own transcript) or `screen`. verifiedSubmitted is true for `taken` or `queued`; never resend those. If ok is false, inspect blocked and do not assume the turn started.",
10999
+ "Do not follow `panels submit` with `panels submit-composer`; Claude and Codex composer submission is handled atomically.",
11000
+ "Use `panels input` for Ctrl-C, escape sequences, or any workflow requiring exact bytes.",
11001
+ "On `blocked.kind: composer-unknown`, nothing was typed. Check `panels screen`; if the agent is at a prompt Pane does not recognise, use `panels input`.",
11002
+ "For Claude, text starting with `!`, `#`, `/` or `@` is sent unchanged and the result carries a `warnings` entry (for example `leading-bang-runs-shell`), because Claude Code gives those characters a meaning of its own.",
11003
+ "`--as-file-pointer` writes the text to `<pane-dir>/prompts/<pane-id>/<timestamp>.md` (readable only by you) and sends the one line `Read and follow <path>`; the result includes `promptFile`. Prefer it for long prompts."
9091
11004
  ]
9092
11005
  },
9093
11006
  "panels wait": {
@@ -9151,6 +11064,48 @@ exports.RUNPANE_CONTRACT = {
9151
11064
  "The default timeout and screen are intentionally small for agent context safety."
9152
11065
  ]
9153
11066
  },
11067
+ "panels last-message": {
11068
+ "name": "panels last-message",
11069
+ "summary": "Read an agent's last reply from its transcript, without scraping the screen.",
11070
+ "details": "Use this when a worker is READY and you need what it said, such as its PR number or result. It reads the Claude or Codex transcript Pane found for the panel and never falls back to the screen.",
11071
+ "requiresPaneDaemon": true,
11072
+ "mutates": false,
11073
+ "arguments": [
11074
+ {
11075
+ "name": "--panel",
11076
+ "value": "<panel-id>",
11077
+ "required": true,
11078
+ "description": "Agent panel id."
11079
+ },
11080
+ {
11081
+ "name": "--limit",
11082
+ "value": "<count>",
11083
+ "required": false,
11084
+ "description": "Maximum characters to return; defaults to 20000. The end of the reply is kept."
11085
+ },
11086
+ {
11087
+ "name": "--json",
11088
+ "required": false,
11089
+ "description": "Print machine-readable output."
11090
+ },
11091
+ {
11092
+ "name": "--pane-dir",
11093
+ "value": "<path>",
11094
+ "required": false,
11095
+ "description": "Connect to a specific Pane data directory."
11096
+ }
11097
+ ],
11098
+ "examples": [
11099
+ "runpane panels last-message --panel <panel-id> --json"
11100
+ ],
11101
+ "jsonSchemas": [
11102
+ "panelLastMessageResult"
11103
+ ],
11104
+ "notes": [
11105
+ "Without a transcript (a shell panel, another agent, or no reply yet) the result is `{ ok: false, reason: \"transcript-unavailable\" }` and the command exits 1. Use `panels screen` then.",
11106
+ "A worker that ran `runpane report` already handed back its state, PR, head, and summary; read those with `agents status` before reading the whole reply."
11107
+ ]
11108
+ },
9154
11109
  "panels create": {
9155
11110
  "name": "panels create",
9156
11111
  "summary": "Create a reviewer/helper terminal tab inside an existing Pane.",
@@ -9168,7 +11123,7 @@ exports.RUNPANE_CONTRACT = {
9168
11123
  "name": "--agent",
9169
11124
  "value": "<codex|claude|cursor>",
9170
11125
  "required": false,
9171
- "description": "Built-in agent command template to launch."
11126
+ "description": "Built-in agent command template to launch. With --tool-command, the agent that command runs."
9172
11127
  },
9173
11128
  {
9174
11129
  "name": "--tool-command",
@@ -9194,6 +11149,11 @@ exports.RUNPANE_CONTRACT = {
9194
11149
  "required": false,
9195
11150
  "description": "Read initial input from a file or stdin."
9196
11151
  },
11152
+ {
11153
+ "name": "--as-file-pointer",
11154
+ "required": false,
11155
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
11156
+ },
9197
11157
  {
9198
11158
  "name": "--source",
9199
11159
  "value": "<user|agent>",
@@ -9230,11 +11190,18 @@ exports.RUNPANE_CONTRACT = {
9230
11190
  "name": "--json",
9231
11191
  "required": false,
9232
11192
  "description": "Print machine-readable output."
11193
+ },
11194
+ {
11195
+ "name": "--pane-dir",
11196
+ "value": "<path>",
11197
+ "required": false,
11198
+ "description": "Connect to a specific Pane data directory."
9233
11199
  }
9234
11200
  ],
9235
11201
  "examples": [
9236
11202
  "runpane panels create --pane <pane-id> --agent <agent> --source agent --no-focus --wait-ready --yes --json",
9237
- "runpane panels create --pane <pane-id> --tool-command <command> --title <title> --source agent --no-focus --wait-ready --yes --json"
11203
+ "runpane panels create --pane <pane-id> --tool-command <command> --title <title> --source agent --no-focus --wait-ready --yes --json",
11204
+ "runpane panels create --pane <pane-id> --tool-command \"agent-farm run free-range\" --agent claude --source agent --no-focus --wait-ready --yes --json"
9238
11205
  ],
9239
11206
  "jsonSchemas": [
9240
11207
  "panelCreateRequest",
@@ -9244,7 +11211,91 @@ exports.RUNPANE_CONTRACT = {
9244
11211
  "Use this for same-pane reviewer loops after PR creation/testing.",
9245
11212
  "Panels share the existing Pane's worktree and branch.",
9246
11213
  "`panels create` is for visible helper/reviewer tabs, not the agent's default private delegation mechanism.",
9247
- "For agent-created panels, prefer --source agent or --no-focus to avoid stealing focus from the user or implementation tab."
11214
+ "For agent-created panels, prefer --source agent or --no-focus to avoid stealing focus from the user or implementation tab.",
11215
+ "With --tool-command, --agent names the agent the command runs (a wrapper such as `agent-farm run`): Pane launches the command unchanged and treats the panel as that agent. Without --agent, Pane detects Claude Code, Codex and Cursor from the foreground process or the agent's screen."
11216
+ ]
11217
+ },
11218
+ "panels open": {
11219
+ "name": "panels open",
11220
+ "summary": "Open a URL or file as a browser/editor tab in a Pane, in split view beside the agent by default.",
11221
+ "details": "Opens a tab inside a Pane (default: the Pane of the calling panel, from PANE_SESSION_ID). Use it to show the user an HTML page, plan, report, local dev server, or file beside the conversation. --url opens a browser tab (http, https, or file). --file opens a file inside the Pane worktree: .html/.htm files render in a browser tab, other files open in an editor tab. Tabs open in split view beside the agent by default; --tab keeps them in the current group. An existing tab showing the same URL or file is reused. Never raises or focuses the Pane window.",
11222
+ "requiresPaneDaemon": true,
11223
+ "mutates": true,
11224
+ "arguments": [
11225
+ {
11226
+ "name": "--pane",
11227
+ "value": "<pane-id>",
11228
+ "required": false,
11229
+ "description": "Pane to open the tab in; defaults to PANE_SESSION_ID (the calling panel's Pane, including a Session orchestrator's)."
11230
+ },
11231
+ {
11232
+ "name": "--url",
11233
+ "value": "<url>",
11234
+ "required": false,
11235
+ "description": "http(s) or file URL to open in a browser tab. Pass exactly one of --url or --file."
11236
+ },
11237
+ {
11238
+ "name": "--file",
11239
+ "value": "<path>",
11240
+ "required": false,
11241
+ "description": "File inside the Pane worktree, relative or absolute. .html/.htm renders in a browser tab; other files open in an editor tab."
11242
+ },
11243
+ {
11244
+ "name": "--title",
11245
+ "value": "<title>",
11246
+ "required": false,
11247
+ "description": "Tab title override."
11248
+ },
11249
+ {
11250
+ "name": "--split",
11251
+ "required": false,
11252
+ "description": "Open in split view beside the primary tab group (default)."
11253
+ },
11254
+ {
11255
+ "name": "--tab",
11256
+ "required": false,
11257
+ "description": "Open in the current tab group instead of split view."
11258
+ },
11259
+ {
11260
+ "name": "--no-focus",
11261
+ "required": false,
11262
+ "description": "Open the tab without selecting it."
11263
+ },
11264
+ {
11265
+ "name": "--focus",
11266
+ "required": false,
11267
+ "description": "Select the tab (default). Never raises or focuses the Pane window."
11268
+ },
11269
+ {
11270
+ "name": "--source",
11271
+ "value": "<user|agent>",
11272
+ "required": false,
11273
+ "description": "Mutation source."
11274
+ },
11275
+ {
11276
+ "name": "--yes",
11277
+ "required": false,
11278
+ "description": "Skip confirmation for this mutating command."
11279
+ },
11280
+ {
11281
+ "name": "--json",
11282
+ "required": false,
11283
+ "description": "Print machine-readable output."
11284
+ }
11285
+ ],
11286
+ "examples": [
11287
+ "runpane panels open --file plan.html --source agent --yes --json",
11288
+ "runpane panels open --url http://localhost:3000 --source agent --yes --json",
11289
+ "runpane panels open --pane <pane-id> --file src/app.ts --tab --source agent --yes --json"
11290
+ ],
11291
+ "jsonSchemas": [
11292
+ "panelOpenRequest",
11293
+ "panelOpenResult"
11294
+ ],
11295
+ "notes": [
11296
+ "Prefer this over opening the system browser when showing the user a page, plan, report, or dev server.",
11297
+ "Write plans and reports as self-contained HTML files, then open them with --file; rerunning the command on the same file reuses its tab.",
11298
+ "Opening a tab does not steal window focus; use `panes focus` only on explicit user request."
9248
11299
  ]
9249
11300
  },
9250
11301
  "panels submit-composer": {
@@ -9275,6 +11326,12 @@ exports.RUNPANE_CONTRACT = {
9275
11326
  "name": "--json",
9276
11327
  "required": false,
9277
11328
  "description": "Print machine-readable output."
11329
+ },
11330
+ {
11331
+ "name": "--pane-dir",
11332
+ "value": "<path>",
11333
+ "required": false,
11334
+ "description": "Connect to a specific Pane data directory."
9278
11335
  }
9279
11336
  ],
9280
11337
  "examples": [
@@ -9288,7 +11345,8 @@ exports.RUNPANE_CONTRACT = {
9288
11345
  "notes": [
9289
11346
  "Use `panels input` or `panels submit` to write prompt text first; this command only submits the current composer.",
9290
11347
  "Use --strategy auto for agent workflows; explicit strategies are diagnostic escape hatches.",
9291
- "The JSON result includes sequenceName and verifiedSubmitted. If ok is false, follow blocked.suggestedCommand instead of assuming submission happened."
11348
+ "The JSON result includes sequenceName, verifiedSubmitted and, for Claude and Codex, delivery (`taken`, `queued`, `in-composer` or `unknown`, with `transcript` or `screen` evidence). If ok is false, follow blocked.suggestedCommand instead of assuming submission happened.",
11349
+ "With `--strategy auto`, if the staged text is still visible in the composer after the first attempt, Pane retries once and checks again: Tab for working Codex, Enter otherwise. It never retries an empty composer."
9292
11350
  ]
9293
11351
  },
9294
11352
  "workspace state": {
@@ -9308,6 +11366,12 @@ exports.RUNPANE_CONTRACT = {
9308
11366
  "name": "--json",
9309
11367
  "required": false,
9310
11368
  "description": "Print machine-readable output."
11369
+ },
11370
+ {
11371
+ "name": "--pane-dir",
11372
+ "value": "<path>",
11373
+ "required": false,
11374
+ "description": "Connect to a specific Pane data directory."
9311
11375
  }
9312
11376
  ],
9313
11377
  "examples": [
@@ -9328,7 +11392,7 @@ exports.RUNPANE_CONTRACT = {
9328
11392
  "name": "--as",
9329
11393
  "value": "<consumer-name>",
9330
11394
  "required": false,
9331
- "description": "Use a persisted named cursor (at-least-once delivery). Default: PANE_PANEL_ID under --follow when set, otherwise anonymous."
11395
+ "description": "Use a persisted named cursor (at-least-once delivery): 1-128 letters, numbers, dots, underscores, or hyphens (daemons before this release accept 64). Default under --follow: session-<uuid> with --session (session-<name> for a name; shortened to session-<sha256 prefix> when longer than 64 characters), else PANE_PANEL_ID when set, shortened to panel-<sha256 prefix> when it is longer than 64 characters; otherwise anonymous."
9332
11396
  },
9333
11397
  {
9334
11398
  "name": "--since",
@@ -9357,7 +11421,7 @@ exports.RUNPANE_CONTRACT = {
9357
11421
  "name": "--heartbeat",
9358
11422
  "value": "<seconds>",
9359
11423
  "required": false,
9360
- "description": "Healthy-silence bound; a HEARTBEAT line proves the watcher is alive. Default 60 under --follow, 0 otherwise. Filter it out of any monitor that wakes an agent."
11424
+ "description": "Healthy-silence bound; a HEARTBEAT line proves the watcher is alive. Default 60 under --follow, 0 otherwise. Any monitor that wakes an agent should pass --quiet, which drops it."
9361
11425
  },
9362
11426
  {
9363
11427
  "name": "--idle-after",
@@ -9369,19 +11433,19 @@ exports.RUNPANE_CONTRACT = {
9369
11433
  "name": "--settle",
9370
11434
  "value": "<milliseconds>",
9371
11435
  "required": false,
9372
- "description": "Opt-in (follow only): emit READY only after the panel stays idle this long; a BUSY, BLOCKED, UNKNOWN, EXIT, or GONE inside the window cancels it silently. Default 0. Use when a pane flips idle/working while it waits on subagents; the orchestrator value is 180000."
11436
+ "description": "Opt-in (follow only): emit READY only after the panel stays idle this long; a BUSY, BLOCKED, UNKNOWN, EXIT, or GONE inside the window cancels it silently. Default 0. Use when a pane flips idle/working while it waits on subagents; the unattended orchestrator value is 180000, the user-present value 60000."
9373
11437
  },
9374
11438
  {
9375
11439
  "name": "--blocked-settle",
9376
11440
  "value": "<milliseconds>",
9377
11441
  "required": false,
9378
- "description": "Opt-in (follow only): emit BLOCKED only after this window; an in-pane answer inside it cancels the line. Default 0. The orchestrator value is 30000."
11442
+ "description": "Opt-in (follow only): emit BLOCKED only after this window; an in-pane answer inside it cancels the line. Default 0. The unattended orchestrator value is 30000, the user-present value 15000."
9379
11443
  },
9380
11444
  {
9381
11445
  "name": "--min-interval",
9382
11446
  "value": "<milliseconds>",
9383
11447
  "required": false,
9384
- "description": "Opt-in (follow only): hold READY, IDLE, NEW, GONE, EXIT, and UNKNOWN lines and flush them together at most once per interval; BLOCKED bypasses it and carries the held lines with it. Default 0. The orchestrator value is 600000."
11448
+ "description": "Opt-in (follow only): hold READY, IDLE, NEW, GONE, EXIT, and UNKNOWN lines and flush them together at most once per interval; BLOCKED, REPORT, pr.conflicted, and failed pr.checks bypass it and carry the held lines with them. Default 0. The unattended orchestrator value is 600000, the user-present value 120000."
9385
11449
  },
9386
11450
  {
9387
11451
  "name": "--idle-backoff",
@@ -9392,13 +11456,19 @@ exports.RUNPANE_CONTRACT = {
9392
11456
  "name": "--kinds",
9393
11457
  "required": false,
9394
11458
  "value": "<kind,...>",
9395
- "description": "Limit event kinds: agent.ready, agent.busy, agent.blocked, agent.unknown, agent.idle, pane.created, pane.gone, panel.exited. Default all. Drop agent.busy for any consumer that acts on lines; BUSY carries no action."
11459
+ "description": "Limit event kinds: agent.ready, agent.busy, agent.blocked, agent.unknown, agent.idle, pane.created, pane.gone, panel.exited, agent.report, pane.associated, pane.detached, pr.conflicted, pr.checks, pr.merged. agent.report arrives only when listed explicitly. Default all, except that pane.associated, pane.detached, and the pr.* kinds arrive only when listed here or implied by --session. Drop agent.busy for any consumer that acts on lines; BUSY carries no action."
9396
11460
  },
9397
11461
  {
9398
11462
  "name": "--pane",
9399
11463
  "required": false,
9400
11464
  "value": "<pane-id>",
9401
- "description": "Limit to a Pane; repeatable. Default all managed panes."
11465
+ "description": "Limit to a Pane; repeatable. Default all managed panes. Cannot be combined with --session."
11466
+ },
11467
+ {
11468
+ "name": "--session",
11469
+ "required": false,
11470
+ "value": "<id|name>",
11471
+ "description": "Follow every Pane associated with a named Session (id or exact name). The daemon re-reads membership on every read, so a Pane associated after arming is included and a detached or archived Pane drops out without a re-arm. The Session's own orchestrator panels are never reported. Cannot be combined with --pane or --all-managed; an unknown Session fails."
9402
11472
  },
9403
11473
  {
9404
11474
  "name": "--exclude-pane",
@@ -9426,7 +11496,7 @@ exports.RUNPANE_CONTRACT = {
9426
11496
  {
9427
11497
  "name": "--all-managed",
9428
11498
  "required": false,
9429
- "description": "Explicit spelling for the all-managed default scope."
11499
+ "description": "Explicit spelling of the default scope: every non-archived, non-hidden managed Pane. Cannot be combined with --pane."
9430
11500
  },
9431
11501
  {
9432
11502
  "name": "--include-shells",
@@ -9453,39 +11523,68 @@ exports.RUNPANE_CONTRACT = {
9453
11523
  {
9454
11524
  "name": "--include-held-input",
9455
11525
  "required": false,
9456
- "description": "Include up to 120 characters of unsubmitted composer text in JSON entries. Default off (presence only)."
11526
+ "description": "Include up to 120 characters of unsubmitted composer text in JSON entries. Default off: under --follow, JSON entries carry only heldInputPresent: true."
9457
11527
  },
9458
11528
  {
9459
11529
  "name": "--no-held-input",
9460
11530
  "required": false,
9461
- "description": "Disable redacted STUCK detection in lines follow mode."
11531
+ "description": "Disable redacted held-input detection under --follow: no STUCK lines, and no heldInputPresent in JSON."
9462
11532
  },
9463
11533
  {
9464
11534
  "name": "--self-test",
9465
11535
  "required": false,
9466
11536
  "description": "Probe the watch path anonymously without advancing a named cursor; run it before arming --follow."
9467
11537
  },
11538
+ {
11539
+ "name": "--quiet",
11540
+ "required": false,
11541
+ "description": "Drop the control lines that only prove liveness: WATCH OK, HEARTBEAT, and WATCH RECONNECTED (_ok, _heartbeat, _reconnected in JSON). WATCH ERROR/_error, RESET/_reset, and DROPPED/_dropped always print, and --self-test still prints its WATCH OK result. Alias: --no-control-lines."
11542
+ },
9468
11543
  {
9469
11544
  "name": "--json",
9470
11545
  "required": false,
9471
11546
  "description": "Emit structured NDJSON; held-input content remains opt-in."
11547
+ },
11548
+ {
11549
+ "name": "--pane-dir",
11550
+ "value": "<path>",
11551
+ "required": false,
11552
+ "description": "Connect to a specific Pane data directory."
11553
+ },
11554
+ {
11555
+ "name": "--pane-dir",
11556
+ "value": "<path>",
11557
+ "required": false,
11558
+ "description": "Connect to a specific Pane data directory."
9472
11559
  }
9473
11560
  ],
9474
11561
  "examples": [
9475
11562
  "runpane watch --self-test",
9476
11563
  "runpane watch --follow",
9477
- "runpane watch --as monitor --follow --json",
9478
- "runpane watch --follow --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff"
11564
+ "runpane watch --as monitor --follow --quiet --json",
11565
+ "runpane watch --follow --quiet --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
11566
+ "runpane watch --follow --quiet --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 60000 --blocked-settle 15000 --min-interval 120000",
11567
+ "runpane watch --session <id|name> --follow --quiet --json --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone,pane.associated,pane.detached,pr.conflicted,pr.checks,pr.merged --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
11568
+ "runpane watch --session <id|name> --follow --quiet --json --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone,pane.associated,pane.detached,pr.conflicted,pr.checks,pr.merged --settle 60000 --blocked-settle 15000 --min-interval 120000"
9479
11569
  ],
9480
11570
  "notes": [
9481
11571
  "Defaults stay responsive: no settle, no batching, all kinds, IDLE every --idle-after. Cadence flags are opt-in for expensive consumers and require --follow.",
9482
- "Recommended orchestrator invocation (what Pane Chat arms automatically): runpane watch --self-test, then runpane watch --follow --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff. Budget: about 6 wake-ups per active pane per hour worst case, usually 1-3.",
9483
- "BUSY carries no action; drop it with --kinds. HEARTBEAT is client-side proof of life, is never shaped by cadence flags, and should be filtered out of any monitor that wakes an agent.",
11572
+ "Unattended profile (what Pane Chat arms automatically, for overnight or background runs): runpane watch --self-test, then runpane watch --follow --quiet --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff. Budget: about 6 wake-ups per active pane per hour worst case, usually 1-3; READY can arrive up to about 13 minutes after the turn ended.",
11573
+ "User-present profile (a person is waiting on the result): the same command with --settle 60000 --blocked-settle 15000 --min-interval 120000 and no --idle-backoff. READY arrives within about 3 minutes of the turn ending.",
11574
+ "BUSY carries no action; drop it with --kinds. HEARTBEAT is client-side proof of life and is never shaped by cadence flags; pass --quiet for any monitor that wakes an agent.",
9484
11575
  "STUCK means real unsubmitted composer text. An agent prompt suggestion (for example a grey Try \"...\" hint) never counts.",
9485
11576
  "Dead watch: judge death by a non-zero exit or a WATCH ERROR line, not by silence. Re-arm once; if it dies again, file runpane doctor --report.",
9486
11577
  "Cadence state is held per named consumer; an anonymous --follow with a cadence flag names itself follow-<pid>. Held lines survive a reconnect of the same consumer; a changed filter re-delivers them under the new filter.",
9487
11578
  "Journal loss is surfaced through reset and dropped metadata.",
9488
- "The daemon treats omitted idleAfterMs as disabled so older clients never receive agent.idle unexpectedly."
11579
+ "The daemon treats omitted idleAfterMs as disabled so older clients never receive agent.idle unexpectedly.",
11580
+ "Control lines are not journal entries. JSON kinds and their lines-format text: _ok (WATCH OK, once when armed), _heartbeat (HEARTBEAT, every --heartbeat seconds), _reconnected (WATCH RECONNECTED, after a retried daemon error), _error (WATCH ERROR, a daemon error; the process exits 2 unless --follow retries it), _reset (RESET, the journal restarted or the cursor fell behind; a fresh baseline follows), and _dropped (DROPPED, entries lost to journal truncation). --quiet drops _ok, _heartbeat, and _reconnected; _error, _reset, and _dropped always print.",
11581
+ "Under --follow, JSON entries for panels holding unsubmitted composer text carry heldInputPresent: true, the JSON equivalent of the STUCK line. --no-held-input turns this off.",
11582
+ "--session <id|name> scopes the watch to a named Session. The daemon resolves the Session once per request and its associated Panes on every read, so sessions associate and sessions detach take effect without a re-arm; archived and detached Panes drop out, and the Session's own orchestrator panels are excluded. Cadence state is keyed by the Session, not its current Panes, so membership changes keep held lines. A detached Pane's held lines are dropped.",
11583
+ "Under --session, pane.associated (JOINED <pane-name> pane <pane-id> session <session-id>) and pane.detached (LEFT ...) report membership changes; list them in --kinds next to the agent kinds. Other consumers receive them only when --kinds lists them, so older clients never see an unknown kind.",
11584
+ "PR events (decision D7): about every 3 minutes (jittered) the daemon visits each Pane associated with a live Session (none: no gh at all), finds its PR by branch when no open PR is known yet (gh pr list --head, so unwatched workers' new and reopened PRs are found), runs gh pr view on an open PR, and appends pr.conflicted (PR <pane-name> pane <pane-id> #<number> CONFLICTED: the PR now conflicts with its base), pr.checks (... CHECKS PASSED, or CHECKS FAILED <up to five names>: every check on the head commit finished), and pr.merged (... MERGED). Entries carry pr: {number, url, headOid}, plus checks and failingChecks for pr.checks. They fire on transitions only: the first poll of a PR after the daemon starts only records its state, so re-check conflicts after a restart with gh pr view. pr.conflicted and failed pr.checks bypass --min-interval like BLOCKED. Like JOINED/LEFT, they reach a consumer only under --session or when --kinds lists them. Without gh, or while it is signed out or rate limited, polling backs off (up to an hour) and no PR entries arrive.",
11585
+ "A daemon that predates --session returns no session field; runpane then fails with WATCH ERROR instead of watching every Pane.",
11586
+ "Replay: after a reset (RESET/_reset), the baseline restates current state. In JSON, those entries carry replay: true (and changedWhileAway: true after an epoch change). A replayed agent.ready is never READY: re-read runpane sessions overview instead of acting on it. Lines mode prints only CHANGED for them.",
11587
+ "agent.report (REPORT <pane-name> pane <pane-id> panel <panel-id> <state> [pr#<n>] [<head>][: <question>]) is a worker's `runpane report`. It is opt-in: only a consumer that lists it in --kinds receives it. It bypasses --min-interval, and orchestrators treat it as the completion signal; a READY without a report means look, and maybe nudge."
9489
11588
  ]
9490
11589
  },
9491
11590
  "panes git-status": {
@@ -10458,6 +12557,11 @@ exports.RUNPANE_CONTRACT = {
10458
12557
  "required": true,
10459
12558
  "description": "The message to submit."
10460
12559
  },
12560
+ {
12561
+ "name": "--as-file-pointer",
12562
+ "required": false,
12563
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
12564
+ },
10461
12565
  {
10462
12566
  "name": "--yes",
10463
12567
  "required": false,
@@ -10476,14 +12580,96 @@ exports.RUNPANE_CONTRACT = {
10476
12580
  }
10477
12581
  ],
10478
12582
  "examples": [
10479
- "runpane agents send --pane <pane-id> --text \"Also add a test\" --yes --json"
12583
+ "runpane agents send --pane <pane-id> --text \"Also add a test\" --yes --json",
12584
+ "runpane agents send --pane <pane-id> --text \"$(cat review-notes.md)\" --as-file-pointer --yes --json"
10480
12585
  ],
10481
12586
  "jsonSchemas": [
10482
12587
  "agentSendResult"
10483
12588
  ],
10484
12589
  "notes": [
10485
- "`delivered` is true only when Pane saw the message leave the composer.",
10486
- "It types the text, then queues with Tab when Codex is working or submits with Enter when ready. It is for messages, not keys. To answer a menu, use `runpane panels input --panel <panel-id> --keys down,enter --yes`, then check the screen with `runpane agents status`."
12590
+ "`delivered` is true when the agent took the message or queued it for after its current turn; `delivery` says which (`taken` or `queued`) and how Pane knows (`transcript` or `screen`). Never resend a delivered message.",
12591
+ "It types the text, then queues with Tab when Codex is working or submits with Enter when ready. It is for messages, not keys. To answer a menu, use `runpane panels input --panel <panel-id> --keys down,enter --yes`, then check the screen with `runpane agents status`.",
12592
+ "`--as-file-pointer` writes the text to `<pane-dir>/prompts/<pane-id>/<timestamp>.md` (readable only by you) and sends the one line `Read and follow <path>`; the result includes `promptFile`. Prefer it for long prompts."
12593
+ ]
12594
+ },
12595
+ "report": {
12596
+ "name": "report",
12597
+ "summary": "Hand back a worker's structured report: state, PR, head commit, summary, and the question when blocked.",
12598
+ "details": "Run this as a delegated worker when you finish, fail, or get blocked, as the last step of your task. The orchestrator receives it as an agent.report watch event and treats it as the completion signal.",
12599
+ "requiresPaneDaemon": true,
12600
+ "mutates": true,
12601
+ "arguments": [
12602
+ {
12603
+ "name": "--state",
12604
+ "value": "<ready|blocked|failed|done>",
12605
+ "required": true,
12606
+ "description": "ready: work is ready for review; done: finished with nothing to review; blocked: needs an answer; failed: could not finish."
12607
+ },
12608
+ {
12609
+ "name": "--pr",
12610
+ "value": "<number>",
12611
+ "required": false,
12612
+ "description": "Pull request number."
12613
+ },
12614
+ {
12615
+ "name": "--head",
12616
+ "value": "<sha>",
12617
+ "required": false,
12618
+ "description": "Head commit the report is about, 7-40 hex characters."
12619
+ },
12620
+ {
12621
+ "name": "--summary",
12622
+ "value": "<text>",
12623
+ "required": false,
12624
+ "description": "Summary text; up to 16,000 characters are kept."
12625
+ },
12626
+ {
12627
+ "name": "--summary-file",
12628
+ "value": "<path|->",
12629
+ "required": false,
12630
+ "description": "Read the summary from a file or stdin; the absolute path is kept as summaryPath."
12631
+ },
12632
+ {
12633
+ "name": "--question",
12634
+ "value": "<text>",
12635
+ "required": false,
12636
+ "description": "What you need answered; required with --state blocked."
12637
+ },
12638
+ {
12639
+ "name": "--pane",
12640
+ "value": "<pane-id>",
12641
+ "required": false,
12642
+ "description": "Pane id when not running inside a Pane terminal (PANE_SESSION_ID)."
12643
+ },
12644
+ {
12645
+ "name": "--panel",
12646
+ "value": "<panel-id>",
12647
+ "required": false,
12648
+ "description": "Panel id when not running inside a Pane terminal (PANE_PANEL_ID)."
12649
+ },
12650
+ {
12651
+ "name": "--json",
12652
+ "required": false,
12653
+ "description": "Print machine-readable output."
12654
+ },
12655
+ {
12656
+ "name": "--pane-dir",
12657
+ "value": "<path>",
12658
+ "required": false,
12659
+ "description": "Connect to a specific Pane data directory."
12660
+ }
12661
+ ],
12662
+ "examples": [
12663
+ "runpane report --state ready --pr 747 --head fc5dce9 --summary-file /tmp/report.md --json",
12664
+ "runpane report --state blocked --question \"Should the migration drop the old column?\""
12665
+ ],
12666
+ "jsonSchemas": [
12667
+ "reportResult"
12668
+ ],
12669
+ "notes": [
12670
+ "Inside a Pane terminal the report is for the current panel (PANE_SESSION_ID and PANE_PANEL_ID). Explicit --panel (with an optional --pane) wins; with neither, the command fails with a clear error.",
12671
+ "Each report replaces the panel's previous one and survives a Pane restart.",
12672
+ "Watchers receive agent.report only when they list it in --kinds. REPORT lines skip the --min-interval batch."
10487
12673
  ]
10488
12674
  },
10489
12675
  "sessions list": {
@@ -10492,7 +12678,14 @@ exports.RUNPANE_CONTRACT = {
10492
12678
  "details": "List durable named orchestration Sessions.",
10493
12679
  "requiresPaneDaemon": true,
10494
12680
  "mutates": false,
10495
- "arguments": [],
12681
+ "arguments": [
12682
+ {
12683
+ "name": "--pane-dir",
12684
+ "value": "<path>",
12685
+ "required": false,
12686
+ "description": "Connect to a specific Pane data directory."
12687
+ }
12688
+ ],
10496
12689
  "examples": [
10497
12690
  "runpane sessions list [--json] [--pane-dir <path>]"
10498
12691
  ],
@@ -10507,14 +12700,23 @@ exports.RUNPANE_CONTRACT = {
10507
12700
  "details": "Create a durable named orchestration Session and its hidden terminal owner.",
10508
12701
  "requiresPaneDaemon": true,
10509
12702
  "mutates": true,
10510
- "arguments": [],
12703
+ "arguments": [
12704
+ {
12705
+ "name": "--pane-dir",
12706
+ "value": "<path>",
12707
+ "required": false,
12708
+ "description": "Connect to a specific Pane data directory."
12709
+ }
12710
+ ],
10511
12711
  "examples": [
10512
12712
  "runpane sessions create --from-json <path|-> [--json] [--pane-dir <path>]"
10513
12713
  ],
10514
12714
  "jsonSchemas": [
10515
12715
  "sessionResult"
10516
12716
  ],
10517
- "notes": []
12717
+ "notes": [
12718
+ "Structured input accepts launchCommand (full command including arguments; empty uses the selected agent default) and profile (Session behavior instructions). Creating/opening a Session submits no automatic prompt. Changes apply on next terminal launch."
12719
+ ]
10518
12720
  },
10519
12721
  "sessions get": {
10520
12722
  "name": "sessions get",
@@ -10522,7 +12724,14 @@ exports.RUNPANE_CONTRACT = {
10522
12724
  "details": "Read one durable named orchestration Session.",
10523
12725
  "requiresPaneDaemon": true,
10524
12726
  "mutates": false,
10525
- "arguments": [],
12727
+ "arguments": [
12728
+ {
12729
+ "name": "--pane-dir",
12730
+ "value": "<path>",
12731
+ "required": false,
12732
+ "description": "Connect to a specific Pane data directory."
12733
+ }
12734
+ ],
10526
12735
  "examples": [
10527
12736
  "runpane sessions get --session <id|name> [--json] [--pane-dir <path>]"
10528
12737
  ],
@@ -10537,14 +12746,23 @@ exports.RUNPANE_CONTRACT = {
10537
12746
  "details": "Update a Session overview from structured JSON.",
10538
12747
  "requiresPaneDaemon": true,
10539
12748
  "mutates": true,
10540
- "arguments": [],
12749
+ "arguments": [
12750
+ {
12751
+ "name": "--pane-dir",
12752
+ "value": "<path>",
12753
+ "required": false,
12754
+ "description": "Connect to a specific Pane data directory."
12755
+ }
12756
+ ],
10541
12757
  "examples": [
10542
12758
  "runpane sessions update --session <id|name> --from-json <path|-> [--json] [--pane-dir <path>]"
10543
12759
  ],
10544
12760
  "jsonSchemas": [
10545
12761
  "sessionResult"
10546
12762
  ],
10547
- "notes": []
12763
+ "notes": [
12764
+ "Structured input accepts launchCommand (full command including arguments; empty uses the selected agent default) and profile (Session behavior instructions). Creating/opening a Session submits no automatic prompt. Changes apply on next terminal launch."
12765
+ ]
10548
12766
  },
10549
12767
  "sessions set-agent": {
10550
12768
  "name": "sessions set-agent",
@@ -10552,7 +12770,14 @@ exports.RUNPANE_CONTRACT = {
10552
12770
  "details": "Switch the durable terminal agent for a named Session.",
10553
12771
  "requiresPaneDaemon": true,
10554
12772
  "mutates": true,
10555
- "arguments": [],
12773
+ "arguments": [
12774
+ {
12775
+ "name": "--pane-dir",
12776
+ "value": "<path>",
12777
+ "required": false,
12778
+ "description": "Connect to a specific Pane data directory."
12779
+ }
12780
+ ],
10556
12781
  "examples": [
10557
12782
  "runpane sessions set-agent --session <id|name> --agent <codex|claude|cursor> [--json] [--pane-dir <path>]"
10558
12783
  ],
@@ -10567,7 +12792,14 @@ exports.RUNPANE_CONTRACT = {
10567
12792
  "details": "Associate a user-visible Pane with a named Session. `panes create` and `panes adopt` already do this automatically when run inside a Session orchestrator; use this for existing Panes or after `--no-associate`.",
10568
12793
  "requiresPaneDaemon": true,
10569
12794
  "mutates": true,
10570
- "arguments": [],
12795
+ "arguments": [
12796
+ {
12797
+ "name": "--pane-dir",
12798
+ "value": "<path>",
12799
+ "required": false,
12800
+ "description": "Connect to a specific Pane data directory."
12801
+ }
12802
+ ],
10571
12803
  "examples": [
10572
12804
  "runpane sessions associate --session <id|name> --pane <pane-id> [--json] [--pane-dir <path>]"
10573
12805
  ],
@@ -10582,7 +12814,14 @@ exports.RUNPANE_CONTRACT = {
10582
12814
  "details": "Detach a Pane from a named Session.",
10583
12815
  "requiresPaneDaemon": true,
10584
12816
  "mutates": true,
10585
- "arguments": [],
12817
+ "arguments": [
12818
+ {
12819
+ "name": "--pane-dir",
12820
+ "value": "<path>",
12821
+ "required": false,
12822
+ "description": "Connect to a specific Pane data directory."
12823
+ }
12824
+ ],
10586
12825
  "examples": [
10587
12826
  "runpane sessions detach --session <id|name> [--pane <pane-id>] [--json] [--pane-dir <path>]"
10588
12827
  ],
@@ -10597,13 +12836,190 @@ exports.RUNPANE_CONTRACT = {
10597
12836
  "details": "Read a live status, activity, git, and pull request overview for a named Session.",
10598
12837
  "requiresPaneDaemon": true,
10599
12838
  "mutates": false,
10600
- "arguments": [],
12839
+ "arguments": [
12840
+ {
12841
+ "name": "--pane-dir",
12842
+ "value": "<path>",
12843
+ "required": false,
12844
+ "description": "Connect to a specific Pane data directory."
12845
+ }
12846
+ ],
10601
12847
  "examples": [
10602
12848
  "runpane sessions overview --session <id|name> [--json] [--pane-dir <path>]"
10603
12849
  ],
10604
12850
  "jsonSchemas": [
10605
12851
  "sessionOverviewResult"
10606
12852
  ],
12853
+ "notes": [
12854
+ "The result includes `locks`: named locks scoped to the Session or held by its Panes (see `runpane lock`)."
12855
+ ]
12856
+ },
12857
+ "lock acquire": {
12858
+ "name": "lock acquire",
12859
+ "summary": "Acquire a named lock on a resource shared between agents, such as one test account, optionally waiting for it.",
12860
+ "details": "Run this before using a resource that only one agent may use at a time, such as a shared test account, and release it when done. The owner is the calling Pane and panel ($PANE_SESSION_ID and $PANE_PANEL_ID, or --pane/--panel). The lock is scoped to the owner's Session when its Pane belongs to one, so two Sessions can each hold `testing-account`; otherwise it is global. It succeeds when the lock is free, expired, or already yours (which renews the TTL). Otherwise it returns ok:false with heldBy and expiresAt at once, or with --wait blocks in the daemon until the lock is released, expires, or its owner's panel exits or Pane is archived.",
12861
+ "requiresPaneDaemon": true,
12862
+ "mutates": true,
12863
+ "arguments": [
12864
+ {
12865
+ "name": "--name",
12866
+ "value": "<name>",
12867
+ "required": true,
12868
+ "description": "Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\"."
12869
+ },
12870
+ {
12871
+ "name": "--ttl",
12872
+ "value": "<duration>",
12873
+ "required": true,
12874
+ "description": "How long the lock is held before it expires, such as 90s, 30m, or 2h; at most 24h. Acquire again before it runs out to renew."
12875
+ },
12876
+ {
12877
+ "name": "--wait",
12878
+ "value": "<milliseconds>",
12879
+ "required": false,
12880
+ "description": "Wait this long for the lock to come free. The CLI waits in daemon calls of up to 120 seconds each."
12881
+ },
12882
+ {
12883
+ "name": "--note",
12884
+ "value": "<text>",
12885
+ "required": false,
12886
+ "description": "What the lock is for, shown to other agents. Required outside a Pane terminal, where it also names the owner."
12887
+ },
12888
+ {
12889
+ "name": "--pane",
12890
+ "value": "<pane-id>",
12891
+ "required": false,
12892
+ "description": "Act for this Pane instead of $PANE_SESSION_ID."
12893
+ },
12894
+ {
12895
+ "name": "--panel",
12896
+ "value": "<panel-id>",
12897
+ "required": false,
12898
+ "description": "Act for this panel instead of $PANE_PANEL_ID."
12899
+ },
12900
+ {
12901
+ "name": "--json",
12902
+ "required": false,
12903
+ "description": "Print machine-readable output."
12904
+ },
12905
+ {
12906
+ "name": "--pane-dir",
12907
+ "value": "<path>",
12908
+ "required": false,
12909
+ "description": "Connect to a specific Pane data directory."
12910
+ }
12911
+ ],
12912
+ "examples": [
12913
+ "runpane lock acquire --name testing-account --ttl 30m --wait 1800000 --note \"call QA\" --json",
12914
+ "runpane lock acquire --name staging-db --ttl 10m --json"
12915
+ ],
12916
+ "jsonSchemas": [
12917
+ "lockAcquireRequest",
12918
+ "lockAcquireResult"
12919
+ ],
12920
+ "notes": [
12921
+ "Exit status is 0 only when the lock is yours; ok:false (exit 1) means another owner holds it, named by heldBy until expiresAt.",
12922
+ "Release the lock as soon as you are done with the resource: `runpane lock release --name <name>`. If you interrupt a waiting acquire, the lock can still be granted to you for up to two minutes; release it or let the TTL expire.",
12923
+ "Pane releases the lock when its TTL runs out, when the owner panel exits, or when the owner Pane is archived. Quitting Pane does not release it; locks survive a restart."
12924
+ ]
12925
+ },
12926
+ "lock release": {
12927
+ "name": "lock release",
12928
+ "summary": "Release a named lock you hold, or force-release another owner's lock.",
12929
+ "details": "Only the owner can release a lock. --force releases another owner's lock, for example a stuck worker's; use --session to name a Session-scoped lock from outside that Session.",
12930
+ "requiresPaneDaemon": true,
12931
+ "mutates": true,
12932
+ "arguments": [
12933
+ {
12934
+ "name": "--name",
12935
+ "value": "<name>",
12936
+ "required": true,
12937
+ "description": "Lock name."
12938
+ },
12939
+ {
12940
+ "name": "--force",
12941
+ "required": false,
12942
+ "description": "Release the lock even though another owner holds it."
12943
+ },
12944
+ {
12945
+ "name": "--session",
12946
+ "value": "<id|name>",
12947
+ "required": false,
12948
+ "description": "Session whose lock to release; defaults to the caller's Session, or global."
12949
+ },
12950
+ {
12951
+ "name": "--note",
12952
+ "value": "<text>",
12953
+ "required": false,
12954
+ "description": "Outside a Pane terminal, the note the lock was acquired with."
12955
+ },
12956
+ {
12957
+ "name": "--pane",
12958
+ "value": "<pane-id>",
12959
+ "required": false,
12960
+ "description": "Act for this Pane instead of $PANE_SESSION_ID."
12961
+ },
12962
+ {
12963
+ "name": "--panel",
12964
+ "value": "<panel-id>",
12965
+ "required": false,
12966
+ "description": "Act for this panel instead of $PANE_PANEL_ID."
12967
+ },
12968
+ {
12969
+ "name": "--json",
12970
+ "required": false,
12971
+ "description": "Print machine-readable output."
12972
+ },
12973
+ {
12974
+ "name": "--pane-dir",
12975
+ "value": "<path>",
12976
+ "required": false,
12977
+ "description": "Connect to a specific Pane data directory."
12978
+ }
12979
+ ],
12980
+ "examples": [
12981
+ "runpane lock release --name testing-account --json",
12982
+ "runpane lock release --name testing-account --session \"<session-id-or-name>\" --force --json"
12983
+ ],
12984
+ "jsonSchemas": [
12985
+ "lockReleaseResult"
12986
+ ],
12987
+ "notes": [
12988
+ "released:false with ok:true means no such lock was held. ok:false with reason not-owner (exit 1) means another owner holds it."
12989
+ ]
12990
+ },
12991
+ "lock list": {
12992
+ "name": "lock list",
12993
+ "summary": "List held named locks, optionally only one Session's.",
12994
+ "details": "List every held lock, or with --session the locks scoped to that Session plus those its Panes hold. `runpane sessions overview` includes the same Session locks.",
12995
+ "requiresPaneDaemon": true,
12996
+ "mutates": false,
12997
+ "arguments": [
12998
+ {
12999
+ "name": "--session",
13000
+ "value": "<id|name>",
13001
+ "required": false,
13002
+ "description": "Named Session id or exact name."
13003
+ },
13004
+ {
13005
+ "name": "--json",
13006
+ "required": false,
13007
+ "description": "Print machine-readable output."
13008
+ },
13009
+ {
13010
+ "name": "--pane-dir",
13011
+ "value": "<path>",
13012
+ "required": false,
13013
+ "description": "Connect to a specific Pane data directory."
13014
+ }
13015
+ ],
13016
+ "examples": [
13017
+ "runpane lock list --json",
13018
+ "runpane lock list --session \"<session-id-or-name>\" --json"
13019
+ ],
13020
+ "jsonSchemas": [
13021
+ "lockListResult"
13022
+ ],
10607
13023
  "notes": []
10608
13024
  }
10609
13025
  },