runpane 2.4.135 → 2.4.137

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,
@@ -430,7 +435,7 @@ exports.RUNPANE_CONTRACT = {
430
435
  "name": "panels list",
431
436
  "summary": "List tool panels inside a Pane session.",
432
437
  "usage": [
433
- "runpane panels list --pane <pane-id> [--json]"
438
+ "runpane panels list --pane <pane-id> [--json] [--pane-dir <path>]"
434
439
  ],
435
440
  "toolsets": [
436
441
  "panels"
@@ -443,7 +448,7 @@ exports.RUNPANE_CONTRACT = {
443
448
  "name": "panels output",
444
449
  "summary": "Read recent terminal output from a panel.",
445
450
  "usage": [
446
- "runpane panels output --panel <panel-id> [--limit <count>] [--json]"
451
+ "runpane panels output --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]"
447
452
  ],
448
453
  "toolsets": [
449
454
  "panels"
@@ -456,7 +461,7 @@ exports.RUNPANE_CONTRACT = {
456
461
  "name": "panels screen",
457
462
  "summary": "Read a compact current-screen view from a terminal panel.",
458
463
  "usage": [
459
- "runpane panels screen --panel <panel-id> [--limit <count>] [--json]"
464
+ "runpane panels screen --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]"
460
465
  ],
461
466
  "toolsets": [
462
467
  "panels"
@@ -469,7 +474,7 @@ exports.RUNPANE_CONTRACT = {
469
474
  "name": "panels input",
470
475
  "summary": "Send input bytes to a terminal panel.",
471
476
  "usage": [
472
- "runpane panels input --panel <panel-id> (--text <text>|--keys <name,...>|--input-file <path|->) --yes [--json]"
477
+ "runpane panels input --panel <panel-id> (--text <text>|--keys <name,...>|--input-file <path|->) --yes [--json] [--pane-dir <path>]"
473
478
  ],
474
479
  "mutates": true,
475
480
  "toolsets": [
@@ -485,7 +490,7 @@ exports.RUNPANE_CONTRACT = {
485
490
  "name": "panels submit",
486
491
  "summary": "Send and submit text to a terminal panel, including idle agent composers.",
487
492
  "usage": [
488
- "runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]"
493
+ "runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) [--as-file-pointer] --yes [--json] [--pane-dir <path>]"
489
494
  ],
490
495
  "mutates": true,
491
496
  "toolsets": [
@@ -500,7 +505,7 @@ exports.RUNPANE_CONTRACT = {
500
505
  "name": "panels submit-composer",
501
506
  "summary": "Submit an agent composer using the panel-appropriate key sequence.",
502
507
  "usage": [
503
- "runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter] --yes [--json]"
508
+ "runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json] [--pane-dir <path>]"
504
509
  ],
505
510
  "mutates": true,
506
511
  "toolsets": [
@@ -515,7 +520,7 @@ exports.RUNPANE_CONTRACT = {
515
520
  "name": "panels wait",
516
521
  "summary": "Wait for a terminal panel to initialize, become ready/idle, or contain text.",
517
522
  "usage": [
518
- "runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--contains <text>] [--timeout-ms <ms>] [--interval-ms <ms>] [--json]"
523
+ "runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--contains <text>] [--timeout-ms <ms>] [--interval-ms <ms>] [--json] [--pane-dir <path>]"
519
524
  ],
520
525
  "toolsets": [
521
526
  "panels"
@@ -524,6 +529,20 @@ exports.RUNPANE_CONTRACT = {
524
529
  "panelWaitResult"
525
530
  ]
526
531
  },
532
+ {
533
+ "name": "panels last-message",
534
+ "summary": "Read an agent's last reply from its transcript, without scraping the screen.",
535
+ "usage": [
536
+ "runpane panels last-message --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]"
537
+ ],
538
+ "toolsets": [
539
+ "panels",
540
+ "agents"
541
+ ],
542
+ "jsonSchemas": [
543
+ "panelLastMessageResult"
544
+ ]
545
+ },
527
546
  {
528
547
  "name": "panes git-status",
529
548
  "summary": "Read the git status of a Pane worktree: uncommitted, unpushed, and behind-main counts.",
@@ -974,7 +993,7 @@ exports.RUNPANE_CONTRACT = {
974
993
  "name": "agents send",
975
994
  "summary": "Send a follow-up message to an agent and confirm it was submitted.",
976
995
  "usage": [
977
- "runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]"
996
+ "runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> [--as-file-pointer] --yes [--json] [--pane-dir <path>]"
978
997
  ],
979
998
  "mutates": true,
980
999
  "wrappers": [
@@ -988,6 +1007,22 @@ exports.RUNPANE_CONTRACT = {
988
1007
  "agentSendResult"
989
1008
  ]
990
1009
  },
1010
+ {
1011
+ "name": "report",
1012
+ "summary": "Hand back a worker's structured report: state, PR, head commit, summary, and the question when blocked.",
1013
+ "usage": [
1014
+ "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>]"
1015
+ ],
1016
+ "mutates": true,
1017
+ "additive": true,
1018
+ "idempotent": true,
1019
+ "toolsets": [
1020
+ "agents"
1021
+ ],
1022
+ "jsonSchemas": [
1023
+ "reportResult"
1024
+ ]
1025
+ },
991
1026
  {
992
1027
  "name": "sessions list",
993
1028
  "summary": "List durable named orchestration Sessions.",
@@ -1102,6 +1137,51 @@ exports.RUNPANE_CONTRACT = {
1102
1137
  "jsonSchemas": [
1103
1138
  "sessionOverviewResult"
1104
1139
  ]
1140
+ },
1141
+ {
1142
+ "name": "lock acquire",
1143
+ "summary": "Acquire a named lock on a resource shared between agents, such as one test account, optionally waiting for it.",
1144
+ "usage": [
1145
+ "runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]"
1146
+ ],
1147
+ "mutates": true,
1148
+ "additive": true,
1149
+ "idempotent": true,
1150
+ "toolsets": [
1151
+ "sessions"
1152
+ ],
1153
+ "jsonSchemas": [
1154
+ "lockAcquireRequest",
1155
+ "lockAcquireResult"
1156
+ ]
1157
+ },
1158
+ {
1159
+ "name": "lock release",
1160
+ "summary": "Release a named lock you hold, or force-release another owner's lock.",
1161
+ "usage": [
1162
+ "runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]"
1163
+ ],
1164
+ "mutates": true,
1165
+ "idempotent": true,
1166
+ "toolsets": [
1167
+ "sessions"
1168
+ ],
1169
+ "jsonSchemas": [
1170
+ "lockReleaseResult"
1171
+ ]
1172
+ },
1173
+ {
1174
+ "name": "lock list",
1175
+ "summary": "List held named locks, optionally only one Session's.",
1176
+ "usage": [
1177
+ "runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]"
1178
+ ],
1179
+ "toolsets": [
1180
+ "sessions"
1181
+ ],
1182
+ "jsonSchemas": [
1183
+ "lockListResult"
1184
+ ]
1105
1185
  }
1106
1186
  ],
1107
1187
  "flags": {
@@ -1222,17 +1302,25 @@ exports.RUNPANE_CONTRACT = {
1222
1302
  {
1223
1303
  "name": "--name",
1224
1304
  "value": "<name>",
1225
- "description": "Name for the registered repository or created/renamed pane session."
1305
+ "description": "Name for the registered repository, created/renamed pane session, or named lock."
1226
1306
  },
1227
1307
  {
1228
1308
  "name": "--worktree-name",
1229
1309
  "value": "<name>",
1230
1310
  "description": "Worktree name to request. Defaults to --name."
1231
1311
  },
1312
+ {
1313
+ "name": "--branch",
1314
+ "value": "<name>",
1315
+ "description": "Exact new branch name for the created worktree, slashes included. Must not exist yet; defaults to the worktree name."
1316
+ },
1232
1317
  {
1233
1318
  "name": "--base-branch",
1234
- "value": "<branch>",
1235
- "description": "Base branch for the created worktree."
1319
+ "value": "<ref>",
1320
+ "aliases": [
1321
+ "--base"
1322
+ ],
1323
+ "description": "Ref the created worktree branches from. --base is an alias."
1236
1324
  },
1237
1325
  {
1238
1326
  "name": "--folder",
@@ -1247,7 +1335,7 @@ exports.RUNPANE_CONTRACT = {
1247
1335
  {
1248
1336
  "name": "--agent",
1249
1337
  "value": "<codex|claude|cursor>",
1250
- "description": "Built-in agent terminal template to open."
1338
+ "description": "Built-in agent terminal template to open. With --tool-command, the agent that command runs."
1251
1339
  },
1252
1340
  {
1253
1341
  "name": "--tool-command",
@@ -1270,7 +1358,10 @@ exports.RUNPANE_CONTRACT = {
1270
1358
  {
1271
1359
  "name": "--initial-input-file",
1272
1360
  "value": "<path|->",
1273
- "description": "Read initial input from a file or stdin."
1361
+ "aliases": [
1362
+ "--prompt-file"
1363
+ ],
1364
+ "description": "Read initial input from a file or stdin. --prompt-file is an alias."
1274
1365
  },
1275
1366
  {
1276
1367
  "name": "--from-json",
@@ -1285,7 +1376,7 @@ exports.RUNPANE_CONTRACT = {
1285
1376
  {
1286
1377
  "name": "--ready-timeout-ms",
1287
1378
  "value": "<milliseconds>",
1288
- "description": "Readiness wait timeout for panes create --wait-ready."
1379
+ "description": "Readiness wait timeout for panes create/adopt --wait-ready."
1289
1380
  },
1290
1381
  {
1291
1382
  "name": "--concurrency",
@@ -1329,7 +1420,7 @@ exports.RUNPANE_CONTRACT = {
1329
1420
  },
1330
1421
  {
1331
1422
  "name": "--strategy",
1332
- "value": "<auto|codex-ctrl-enter|enter>",
1423
+ "value": "<auto|codex-ctrl-enter|enter|tab>",
1333
1424
  "description": "Composer submit key sequence strategy for panels submit-composer."
1334
1425
  },
1335
1426
  {
@@ -1390,7 +1481,7 @@ exports.RUNPANE_CONTRACT = {
1390
1481
  {
1391
1482
  "name": "--min-interval",
1392
1483
  "value": "<milliseconds>",
1393
- "description": "Follow-only opt-in: hold non-urgent lines and flush them together at most once per interval; BLOCKED bypasses it."
1484
+ "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
1485
  },
1395
1486
  {
1396
1487
  "name": "--body-file",
@@ -1402,6 +1493,21 @@ exports.RUNPANE_CONTRACT = {
1402
1493
  "value": "<id|name>",
1403
1494
  "description": "Named orchestration Session id or exact name."
1404
1495
  },
1496
+ {
1497
+ "name": "--ttl",
1498
+ "value": "<duration>",
1499
+ "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."
1500
+ },
1501
+ {
1502
+ "name": "--wait",
1503
+ "value": "<milliseconds>",
1504
+ "description": "How long lock acquire waits for a held lock to come free; 0 (the default) returns at once."
1505
+ },
1506
+ {
1507
+ "name": "--note",
1508
+ "value": "<text>",
1509
+ "description": "What a named lock is for. Outside a Pane terminal it also names the owner, so pass the same note to release it."
1510
+ },
1405
1511
  {
1406
1512
  "name": "--message",
1407
1513
  "value": "<message>",
@@ -1431,6 +1537,36 @@ exports.RUNPANE_CONTRACT = {
1431
1537
  "name": "--keys",
1432
1538
  "value": "<name,...>",
1433
1539
  "description": "Named keys for panels input, such as down,enter."
1540
+ },
1541
+ {
1542
+ "name": "--state",
1543
+ "value": "<ready|blocked|failed|done>",
1544
+ "description": "Report state for runpane report."
1545
+ },
1546
+ {
1547
+ "name": "--pr",
1548
+ "value": "<number>",
1549
+ "description": "Pull request number for runpane report."
1550
+ },
1551
+ {
1552
+ "name": "--head",
1553
+ "value": "<sha>",
1554
+ "description": "Head commit (7-40 hex characters) for runpane report."
1555
+ },
1556
+ {
1557
+ "name": "--summary",
1558
+ "value": "<text>",
1559
+ "description": "Report summary text; up to 16,000 characters are kept."
1560
+ },
1561
+ {
1562
+ "name": "--summary-file",
1563
+ "value": "<path|->",
1564
+ "description": "Read the report summary from a file or stdin."
1565
+ },
1566
+ {
1567
+ "name": "--question",
1568
+ "value": "<text>",
1569
+ "description": "What a blocked worker needs answered; required with --state blocked."
1434
1570
  }
1435
1571
  ],
1436
1572
  "localBoolean": [
@@ -1464,12 +1600,24 @@ exports.RUNPANE_CONTRACT = {
1464
1600
  },
1465
1601
  {
1466
1602
  "name": "--force",
1467
- "description": "Archive even if the pane's branch has uncommitted, untracked, or unpushed changes."
1603
+ "description": "Archive even if the pane's branch has uncommitted, untracked, or unpushed changes; for lock release, release another owner's lock."
1604
+ },
1605
+ {
1606
+ "name": "--remove-worktree",
1607
+ "description": "Also check and remove an adopted Pane's worktree when archiving it. The local branch is kept."
1608
+ },
1609
+ {
1610
+ "name": "--merged",
1611
+ "description": "With panes archive --session, archive only Panes that are clean and pushed, or merged via a pull request."
1468
1612
  },
1469
1613
  {
1470
1614
  "name": "--launch",
1471
1615
  "description": "Run an adopted pane's agent resume command immediately instead of staging it."
1472
1616
  },
1617
+ {
1618
+ "name": "--as-file-pointer",
1619
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
1620
+ },
1473
1621
  {
1474
1622
  "name": "--follow",
1475
1623
  "description": "Continue waiting for workspace events until interrupted."
@@ -1488,7 +1636,7 @@ exports.RUNPANE_CONTRACT = {
1488
1636
  },
1489
1637
  {
1490
1638
  "name": "--all-managed",
1491
- "description": "Watch all non-archived, non-hidden managed panes."
1639
+ "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
1640
  },
1493
1641
  {
1494
1642
  "name": "--include-shells",
@@ -1496,12 +1644,19 @@ exports.RUNPANE_CONTRACT = {
1496
1644
  },
1497
1645
  {
1498
1646
  "name": "--no-held-input",
1499
- "description": "Disable redacted STUCK detection in lines follow mode."
1647
+ "description": "Disable redacted held-input detection under --follow (STUCK lines, and heldInputPresent in JSON)."
1500
1648
  },
1501
1649
  {
1502
1650
  "name": "--self-test",
1503
1651
  "description": "Probe the current daemon watch path without advancing a named cursor."
1504
1652
  },
1653
+ {
1654
+ "name": "--quiet",
1655
+ "aliases": [
1656
+ "--no-control-lines"
1657
+ ],
1658
+ "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."
1659
+ },
1505
1660
  {
1506
1661
  "name": "--idle-backoff",
1507
1662
  "description": "Follow-only opt-in: IDLE fires at --idle-after, then 30m, 1h, 3h, then daily per panel; any activity resets it."
@@ -1541,20 +1696,25 @@ exports.RUNPANE_CONTRACT = {
1541
1696
  " runpane sessions associate --session <id|name> --pane <pane-id> [--json] [--pane-dir <path>]",
1542
1697
  " runpane sessions detach --session <id|name> [--pane <pane-id>] [--json] [--pane-dir <path>]",
1543
1698
  " runpane sessions overview --session <id|name> [--json] [--pane-dir <path>]",
1699
+ " runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
1700
+ " runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
1701
+ " runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]",
1544
1702
  " runpane panes list [--repo <selector>] [--json]",
1545
1703
  " runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]",
1546
1704
  " runpane workspace state [--repo <selector>] [--json]",
1547
1705
  " 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",
1706
+ " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--base-branch <branch>] [--source user|agent] [--focus|--no-focus] [--wait-ready]",
1707
+ " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes",
1708
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--dry-run] --yes",
1550
1709
  " runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] --yes",
1551
1710
  " runpane panels list --pane <pane-id> [--json]",
1552
1711
  " runpane panels output --panel <panel-id> [--limit <count>] [--json]",
1553
1712
  " runpane panels screen --panel <panel-id> [--limit <count>] [--json]",
1554
1713
  " runpane panels input --panel <panel-id> (--text <text>|--keys <name,...>|--input-file <path|->) --yes [--json]",
1555
1714
  " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
1556
- " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter] --yes [--json]",
1715
+ " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
1557
1716
  " runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--json]",
1717
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json]",
1558
1718
  " runpane panes git-status --pane <pane-id> [--json] [--pane-dir <path>]",
1559
1719
  " runpane panes commit --pane <pane-id> --message <message> --yes [--json] [--pane-dir <path>]",
1560
1720
  " runpane panes push --pane <pane-id> --yes [--json] [--pane-dir <path>]",
@@ -1568,6 +1728,7 @@ exports.RUNPANE_CONTRACT = {
1568
1728
  " 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
1729
  " runpane agents status (--pane <pane-id>|--panel <panel-id>) [--limit <count>] [--json] [--pane-dir <path>]",
1570
1730
  " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]",
1731
+ " runpane report --state <ready|blocked|failed|done> [--pr <number>] [--head <sha>] [--summary-file <path|->] [--question <text>] [--json]",
1571
1732
  " runpane panes squash-rebase --pane <pane-id> --message <message> --yes [--json] [--pane-dir <path>]",
1572
1733
  " runpane panes stash --pane <pane-id> --yes [--json] [--pane-dir <path>]",
1573
1734
  " runpane panes stash-pop --pane <pane-id> --yes [--json] [--pane-dir <path>]",
@@ -1661,7 +1822,7 @@ exports.RUNPANE_CONTRACT = {
1661
1822
  ],
1662
1823
  "version": [
1663
1824
  "Usage:",
1664
- " runpane version",
1825
+ " runpane version [--pane-dir <path>]",
1665
1826
  " runpane --version"
1666
1827
  ],
1667
1828
  "doctor": [
@@ -1732,7 +1893,8 @@ exports.RUNPANE_CONTRACT = {
1732
1893
  " runpane panes list [--repo <selector>] [--json]",
1733
1894
  " runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]",
1734
1895
  " 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]",
1896
+ " runpane panes archive --pane <pane-id> [--force] [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json]",
1897
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--dry-run] --yes [--json]",
1736
1898
  " runpane panes pin --pane <pane-id> --yes [--dry-run] [--json]",
1737
1899
  " runpane panes unpin --pane <pane-id> --yes [--dry-run] [--json]",
1738
1900
  " runpane panes rename --pane <pane-id> --name <new-name> --yes [--dry-run] [--json]",
@@ -1745,6 +1907,8 @@ exports.RUNPANE_CONTRACT = {
1745
1907
  "",
1746
1908
  "Lists Pane sessions. Pass --repo to limit results to one saved repository.",
1747
1909
  "",
1910
+ "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.",
1911
+ "",
1748
1912
  "Options:",
1749
1913
  " --repo <selector> active, id, exact path, or saved repository name",
1750
1914
  " --pane-dir <path> Connect to a specific Pane data directory",
@@ -1791,15 +1955,18 @@ exports.RUNPANE_CONTRACT = {
1791
1955
  " --idle-after <ms> Re-firing READY idle interval; defaults to 600000 under --follow",
1792
1956
  " --settle <ms> Opt-in: emit READY only after this quiet window (--follow only)",
1793
1957
  " --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)",
1958
+ " --min-interval <ms> Opt-in: batch non-urgent lines per interval; BLOCKED, REPORT, and PR failures bypass (--follow only)",
1795
1959
  " --idle-backoff Opt-in: IDLE at --idle-after, 30m, 1h, 3h, then daily (--follow only)",
1796
1960
  " --all-managed Explicitly watch all managed panes",
1797
1961
  " --include-shells Include ordinary shell panels",
1798
1962
  " --agents-only Limit to CLI agent panels",
1799
1963
  " --exclude-pane <id> Exclude a Pane; repeatable",
1800
1964
  " --self-test Anonymous, read-only daemon path probe",
1965
+ " --quiet Drop WATCH OK, HEARTBEAT, and WATCH RECONNECTED lines",
1966
+ " --no-control-lines Alias for --quiet",
1801
1967
  " --kinds <kind,...> Limit event kinds",
1802
1968
  " --pane <id> Limit to a Pane; repeatable",
1969
+ " --session <id|name> Follow every Pane in a named Session; associate/detach apply live",
1803
1970
  " --repo <selector> Limit to a saved repository",
1804
1971
  " --name-contains <text> Limit by Pane name substring",
1805
1972
  " --timeout-ms <ms> Wait timeout; 0 polls once",
@@ -1807,32 +1974,42 @@ exports.RUNPANE_CONTRACT = {
1807
1974
  " --ack-now Use at-most-once named-cursor delivery",
1808
1975
  " --include-held-input Include unsubmitted composer text in JSON",
1809
1976
  " --no-held-input Disable redacted STUCK detection",
1977
+ " --pane-dir <path> Connect to a specific Pane data directory",
1810
1978
  " --json Alias for --format json",
1811
1979
  "",
1812
1980
  "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",
1981
+ "agent.report (a worker ran `runpane report`) is opt-in: list it in --kinds. REPORT lines skip the --min-interval batch.",
1982
+ "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",
1983
+ "User present: the same kinds with --settle 60000 --blocked-settle 15000 --min-interval 120000 and no --idle-backoff",
1984
+ "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
1985
  "Pane Chat arms those flags itself through its skill; pass them only for your own scripts.",
1815
1986
  "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."
1987
+ "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
1988
  ],
1818
1989
  "panes create": [
1819
1990
  "Usage:",
1820
- " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [options]",
1991
+ " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options]",
1992
+ " runpane panes create --repo <selector> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options]",
1821
1993
  " runpane panes create --from-json <path|-> [--yes] [--json]",
1822
1994
  "",
1823
1995
  "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
1996
  "",
1997
+ "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.",
1998
+ "",
1825
1999
  "Options:",
1826
2000
  " --repo <selector> active, id, exact path, or saved repository name",
1827
2001
  " --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",
2002
+ " --worktree-name <name> Worktree directory name; defaults to --name",
2003
+ " --branch <name> Exact new branch name (slashes kept); must not exist; defaults to the worktree name",
2004
+ " --base-branch <ref> Ref to branch from; --base is an alias",
2005
+ " --agent <codex|claude|cursor> Built-in terminal template; with --tool-command, the agent it runs",
1831
2006
  " --tool-command <command> Custom terminal command",
1832
2007
  " --title <title> Terminal tab title",
1833
2008
  " --initial-input <text> Text sent after the command is ready",
1834
2009
  " --prompt <text> Alias for --initial-input",
1835
2010
  " --initial-input-file <path|-> Read initial input from a file or stdin",
2011
+ " --as-file-pointer Send `Read and follow <prompt file>` instead of the prompt",
2012
+ " --prompt-file <path|-> Alias for --initial-input-file",
1836
2013
  " --from-json <path|-> Read a full request payload",
1837
2014
  " --timeout-ms <milliseconds> Pane creation timeout",
1838
2015
  " --wait-ready Wait for terminal readiness before returning",
@@ -1852,21 +2029,28 @@ exports.RUNPANE_CONTRACT = {
1852
2029
  "panes adopt": [
1853
2030
  "Usage:",
1854
2031
  " runpane panes adopt --repo <selector> --path <dir> --name <name> --agent <codex|claude|cursor> [options]",
2032
+ " runpane panes adopt --repo <selector> --path <dir> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [options]",
2033
+ "",
2034
+ "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
2035
  "",
1856
- "Adopts an existing externally managed git worktree without creating, syncing, or deleting it.",
2036
+ "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
2037
  "",
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."
2038
+ "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
2039
  ],
1860
2040
  "panes archive": [
1861
2041
  "Usage:",
1862
- " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--dry-run] --yes [--json]",
2042
+ " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes [--json]",
2043
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json]",
1863
2044
  "",
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.",
2045
+ "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
2046
  "",
1866
2047
  "Options:",
1867
2048
  " --pane <pane-id> Pane/session id to archive",
1868
2049
  " --source <user|agent> Mark mutation source",
1869
2050
  " --force Archive even if the pane has uncommitted, untracked, or unpushed changes",
2051
+ " --remove-worktree Also check and remove an adopted Pane's worktree (the branch is kept)",
2052
+ " --session <id|name> Archive the Panes associated with this Session (requires --merged)",
2053
+ " --merged Only archive Panes that are clean and pushed, or merged via a PR",
1870
2054
  " --pane-dir <path> Connect to a specific Pane data directory",
1871
2055
  " --json Print machine-readable output",
1872
2056
  " --dry-run Refresh and print archive safety evidence without archiving",
@@ -1939,8 +2123,9 @@ exports.RUNPANE_CONTRACT = {
1939
2123
  " runpane panels output --panel <panel-id> [--limit <count>] [--json]",
1940
2124
  " runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
1941
2125
  " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
1942
- " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter] --yes [--json]",
2126
+ " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
1943
2127
  " runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--json]",
2128
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json]",
1944
2129
  "",
1945
2130
  "Run \"runpane help panels create\" or another command-specific topic for options."
1946
2131
  ],
@@ -1950,6 +2135,8 @@ exports.RUNPANE_CONTRACT = {
1950
2135
  "",
1951
2136
  "Lists tool panels in a Pane session.",
1952
2137
  "",
2138
+ "agentDetection says how Pane knows agentType: declared, command, process, or screen. launchCommand is the command the panel was launched with.",
2139
+ "",
1953
2140
  "Options:",
1954
2141
  " --pane <pane-id> Pane/session id",
1955
2142
  " --pane-dir <path> Connect to a specific Pane data directory",
@@ -1992,6 +2179,7 @@ exports.RUNPANE_CONTRACT = {
1992
2179
  "Options:",
1993
2180
  " --command <command> Print the full definition for one runpane command",
1994
2181
  " --json Print machine-readable output",
2182
+ " --pane-dir <path> Accepted and ignored; agent-context never contacts Pane",
1995
2183
  "",
1996
2184
  "Examples:",
1997
2185
  " runpane agent-context",
@@ -2040,14 +2228,21 @@ exports.RUNPANE_CONTRACT = {
2040
2228
  ],
2041
2229
  "panels submit": [
2042
2230
  "Usage:",
2043
- " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
2231
+ " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) [--as-file-pointer] --yes [--json]",
2044
2232
  "",
2045
2233
  "Sends text to a terminal panel and normalizes the final terminal Enter to CR. Use this for ordinary prompt answers and shell commands.",
2046
2234
  "",
2235
+ "For a Claude or Codex panel with no composer on screen, nothing is sent: the result is ok: false with blocked.kind composer-unknown.",
2236
+ "",
2237
+ "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.",
2238
+ "",
2239
+ "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.",
2240
+ "",
2047
2241
  "Options:",
2048
2242
  " --panel <panel-id> Terminal panel id",
2049
2243
  " --text <text> Text to submit before Enter",
2050
2244
  " --input-file <path|-> Read text from a file or stdin before Enter",
2245
+ " --as-file-pointer Write the text to a prompt file and submit `Read and follow <path>`",
2051
2246
  " --pane-dir <path> Connect to a specific Pane data directory",
2052
2247
  " --json Print machine-readable output",
2053
2248
  " --yes Skip confirmation for this mutating command"
@@ -2072,15 +2267,16 @@ exports.RUNPANE_CONTRACT = {
2072
2267
  "",
2073
2268
  "Usage:",
2074
2269
  " 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]",
2270
+ " runpane panels create --pane <pane-id> --tool-command <command> [--agent <codex|claude|cursor>] [--title <title>] [--no-focus] [--wait-ready] --yes [--json]",
2076
2271
  "",
2077
2272
  "Options:",
2078
2273
  " --pane <pane-id> Existing Pane session to add the panel to.",
2079
- " --agent <codex|claude|cursor> Built-in agent command template to launch.",
2274
+ " --agent <codex|claude|cursor> Built-in agent command template, or with --tool-command the agent it runs.",
2080
2275
  " --tool-command <command> Custom terminal command to launch.",
2081
2276
  " --title <title> Panel title override.",
2082
2277
  " --initial-input, --prompt Initial input to send after the tool starts.",
2083
2278
  " --initial-input-file <path|-> Read initial input from a file or stdin.",
2279
+ " --as-file-pointer Send `Read and follow <prompt file>` instead of the prompt.",
2084
2280
  " --no-focus Create the panel in the background.",
2085
2281
  " --focus Explicitly focus the created panel.",
2086
2282
  " --source <user|agent> Mark the mutation source; agent implies background creation.",
@@ -2093,11 +2289,11 @@ exports.RUNPANE_CONTRACT = {
2093
2289
  "Submit an agent composer using the panel-appropriate key sequence.",
2094
2290
  "",
2095
2291
  "Usage:",
2096
- " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter] --yes [--json]",
2292
+ " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
2097
2293
  "",
2098
2294
  "Options:",
2099
2295
  " --panel <panel-id> Terminal panel id.",
2100
- " --strategy <strategy> Defaults to auto; Codex sends Ctrl+Enter and other panels send Enter.",
2296
+ " --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
2297
  " --yes Skip confirmation prompts.",
2102
2298
  " --json Print JSON output."
2103
2299
  ],
@@ -2463,7 +2659,7 @@ exports.RUNPANE_CONTRACT = {
2463
2659
  ],
2464
2660
  "agents send": [
2465
2661
  "Usage:",
2466
- " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]",
2662
+ " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> [--as-file-pointer] --yes [--json] [--pane-dir <path>]",
2467
2663
  "",
2468
2664
  "Send a follow-up message to an agent and confirm it was submitted.",
2469
2665
  "",
@@ -2471,6 +2667,7 @@ exports.RUNPANE_CONTRACT = {
2471
2667
  " --pane <pane-id> Pane id; its agent panel is used.",
2472
2668
  " --panel <panel-id> Panel id.",
2473
2669
  " --text <message> The message to submit.",
2670
+ " --as-file-pointer Write the message to a prompt file and send `Read and follow <path>`.",
2474
2671
  " --yes Confirm this change; required in non-interactive shells.",
2475
2672
  " --json Print machine-readable output.",
2476
2673
  " --pane-dir <path> Connect to a specific Pane data directory."
@@ -2480,6 +2677,96 @@ exports.RUNPANE_CONTRACT = {
2480
2677
  " runpane sessions <list|create|get|update|set-agent|associate|detach|overview> [options]",
2481
2678
  "",
2482
2679
  "Use a named Session to keep context, activity, and evidence attached to one orchestration thread."
2680
+ ],
2681
+ "report": [
2682
+ "Usage:",
2683
+ " 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>]",
2684
+ "",
2685
+ "Hands back a worker's structured report for its panel: the orchestrator receives it as an",
2686
+ "agent.report watch event and reads it in `agents status` and `sessions overview`.",
2687
+ "Inside a Pane terminal the panel comes from PANE_SESSION_ID and PANE_PANEL_ID.",
2688
+ "",
2689
+ "Options:",
2690
+ " --state <state> ready, blocked, failed, or done",
2691
+ " --pr <number> Pull request number",
2692
+ " --head <sha> Head commit, 7-40 hex characters",
2693
+ " --summary <text> Summary text; up to 16,000 characters are kept",
2694
+ " --summary-file <path|-> Read the summary from a file or stdin",
2695
+ " --question <text> What you need answered; required with --state blocked",
2696
+ " --pane <pane-id> Pane id when not running inside a Pane terminal",
2697
+ " --panel <panel-id> Panel id when not running inside a Pane terminal",
2698
+ " --pane-dir <path> Connect to a specific Pane data directory",
2699
+ " --json Print machine-readable output",
2700
+ "",
2701
+ "Example:",
2702
+ " runpane report --state ready --pr 747 --head fc5dce9 --summary-file /tmp/report.md"
2703
+ ],
2704
+ "panels last-message": [
2705
+ "Usage:",
2706
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]",
2707
+ "",
2708
+ "Reads a Claude or Codex agent's last reply from its transcript. It never scrapes the screen:",
2709
+ "without a transcript it reports transcript-unavailable and exits non-zero.",
2710
+ "",
2711
+ "Options:",
2712
+ " --panel <panel-id> Agent panel id",
2713
+ " --limit <count> Maximum characters to return; defaults to 20000 (the end is kept)",
2714
+ " --pane-dir <path> Connect to a specific Pane data directory",
2715
+ " --json Print machine-readable output"
2716
+ ],
2717
+ "lock": [
2718
+ "Usage:",
2719
+ " runpane lock <acquire|release|list> [options]",
2720
+ "",
2721
+ "Named locks coordinate a resource shared between agents, such as one test account.",
2722
+ "The caller is the owner: the Pane and panel from $PANE_SESSION_ID and $PANE_PANEL_ID.",
2723
+ "A lock is scoped to the owner's Session when its Pane belongs to one; otherwise it is global.",
2724
+ "It is released on --ttl expiry, when the owner panel exits, or when the owner Pane is archived."
2725
+ ],
2726
+ "lock acquire": [
2727
+ "Usage:",
2728
+ "runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
2729
+ "",
2730
+ "Options:",
2731
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
2732
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
2733
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
2734
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
2735
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
2736
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
2737
+ " --force Release a lock another owner holds (release).",
2738
+ " --session <id|name> Named Session whose locks to list or release.",
2739
+ " --json Print JSON output."
2740
+ ],
2741
+ "lock release": [
2742
+ "Usage:",
2743
+ "runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
2744
+ "",
2745
+ "Options:",
2746
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
2747
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
2748
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
2749
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
2750
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
2751
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
2752
+ " --force Release a lock another owner holds (release).",
2753
+ " --session <id|name> Named Session whose locks to list or release.",
2754
+ " --json Print JSON output."
2755
+ ],
2756
+ "lock list": [
2757
+ "Usage:",
2758
+ "runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]",
2759
+ "",
2760
+ "Options:",
2761
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
2762
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
2763
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
2764
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
2765
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
2766
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
2767
+ " --force Release a lock another owner holds (release).",
2768
+ " --session <id|name> Named Session whose locks to list or release.",
2769
+ " --json Print JSON output."
2483
2770
  ]
2484
2771
  },
2485
2772
  "pip": {
@@ -2502,16 +2789,18 @@ exports.RUNPANE_CONTRACT = {
2502
2789
  " runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]",
2503
2790
  " runpane workspace state [--repo <selector>] [--json]",
2504
2791
  " 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",
2792
+ " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--base-branch <branch>] [--source user|agent] [--focus|--no-focus] [--wait-ready]",
2793
+ " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes",
2794
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--dry-run] --yes",
2507
2795
  " python -m runpane panels create --pane <pane-id> --agent <codex|claude|cursor> [--source user|agent] [--focus|--no-focus] --yes",
2508
2796
  " runpane panels list --pane <pane-id> [--json]",
2509
2797
  " runpane panels output --panel <panel-id> [--limit <count>] [--json]",
2510
2798
  " runpane panels screen --panel <panel-id> [--limit <count>] [--json]",
2511
2799
  " runpane panels input --panel <panel-id> (--text <text>|--keys <name,...>|--input-file <path|->) --yes [--json]",
2512
2800
  " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
2513
- " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter] --yes [--json]",
2801
+ " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
2514
2802
  " runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--json]",
2803
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json]",
2515
2804
  " runpane panes git-status --pane <pane-id> [--json] [--pane-dir <path>]",
2516
2805
  " runpane panes commit --pane <pane-id> --message <message> --yes [--json] [--pane-dir <path>]",
2517
2806
  " runpane panes push --pane <pane-id> --yes [--json] [--pane-dir <path>]",
@@ -2525,6 +2814,7 @@ exports.RUNPANE_CONTRACT = {
2525
2814
  " 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
2815
  " runpane agents status (--pane <pane-id>|--panel <panel-id>) [--limit <count>] [--json] [--pane-dir <path>]",
2527
2816
  " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]",
2817
+ " runpane report --state <ready|blocked|failed|done> [--pr <number>] [--head <sha>] [--summary-file <path|->] [--question <text>] [--json]",
2528
2818
  " runpane panes squash-rebase --pane <pane-id> --message <message> --yes [--json] [--pane-dir <path>]",
2529
2819
  " runpane panes stash --pane <pane-id> --yes [--json] [--pane-dir <path>]",
2530
2820
  " runpane panes stash-pop --pane <pane-id> --yes [--json] [--pane-dir <path>]",
@@ -2535,6 +2825,9 @@ exports.RUNPANE_CONTRACT = {
2535
2825
  " runpane panes move --pane <pane-id> --folder <folder-id> --yes [--json] [--pane-dir <path>]",
2536
2826
  " runpane folders list --repo <repo-id> [--json] [--pane-dir <path>]",
2537
2827
  " runpane folders create --repo <repo-id> --name <name> --yes [--json] [--pane-dir <path>]",
2828
+ " runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
2829
+ " runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
2830
+ " runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]",
2538
2831
  " runpane help [command]",
2539
2832
  "",
2540
2833
  "Quick start:",
@@ -2607,7 +2900,7 @@ exports.RUNPANE_CONTRACT = {
2607
2900
  ],
2608
2901
  "version": [
2609
2902
  "Usage:",
2610
- " runpane version",
2903
+ " runpane version [--pane-dir <path>]",
2611
2904
  " runpane --version"
2612
2905
  ],
2613
2906
  "doctor": [
@@ -2678,7 +2971,8 @@ exports.RUNPANE_CONTRACT = {
2678
2971
  " runpane panes list [--repo <selector>] [--json]",
2679
2972
  " runpane panes cost [--repo <selector>] [--pane <pane-id>] [--json]",
2680
2973
  " 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]",
2974
+ " runpane panes archive --pane <pane-id> [--force] [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json]",
2975
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--dry-run] --yes [--json]",
2682
2976
  " runpane panes pin --pane <pane-id> --yes [--dry-run] [--json]",
2683
2977
  " runpane panes unpin --pane <pane-id> --yes [--dry-run] [--json]",
2684
2978
  " runpane panes rename --pane <pane-id> --name <new-name> --yes [--dry-run] [--json]",
@@ -2691,6 +2985,8 @@ exports.RUNPANE_CONTRACT = {
2691
2985
  "",
2692
2986
  "Lists Pane sessions. Pass --repo to limit results to one saved repository.",
2693
2987
  "",
2988
+ "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.",
2989
+ "",
2694
2990
  "Options:",
2695
2991
  " --repo <selector>",
2696
2992
  " --pane-dir <path>",
@@ -2737,15 +3033,18 @@ exports.RUNPANE_CONTRACT = {
2737
3033
  " --idle-after <ms>",
2738
3034
  " --settle <ms> Opt-in READY quiet window (--follow only)",
2739
3035
  " --blocked-settle <ms> Opt-in BLOCKED window (--follow only)",
2740
- " --min-interval <ms> Opt-in batching; BLOCKED bypasses (--follow only)",
3036
+ " --min-interval <ms> Opt-in batching; BLOCKED, REPORT, and PR failures bypass (--follow only)",
2741
3037
  " --idle-backoff Opt-in IDLE backoff (--follow only)",
2742
3038
  " --all-managed",
2743
3039
  " --include-shells",
2744
3040
  " --agents-only",
2745
3041
  " --exclude-pane <id> Repeatable",
2746
3042
  " --self-test",
3043
+ " --quiet Drop OK, HEARTBEAT, and RECONNECTED lines",
3044
+ " --no-control-lines Alias for --quiet",
2747
3045
  " --kinds <kind,...>",
2748
3046
  " --pane <id> Repeatable",
3047
+ " --session <id|name> Follow a named Session's Panes; no re-arm",
2749
3048
  " --repo <selector>",
2750
3049
  " --name-contains <text>",
2751
3050
  " --timeout-ms <ms> 0 polls once",
@@ -2753,32 +3052,42 @@ exports.RUNPANE_CONTRACT = {
2753
3052
  " --ack-now",
2754
3053
  " --include-held-input",
2755
3054
  " --no-held-input",
3055
+ " --pane-dir <path> Connect to a specific Pane data directory",
2756
3056
  " --json Alias for --format json",
2757
3057
  "",
2758
3058
  "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",
3059
+ "agent.report (a worker ran `runpane report`) is opt-in: list it in --kinds. REPORT lines skip the --min-interval batch.",
3060
+ "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",
3061
+ "User present: the same kinds with --settle 60000 --blocked-settle 15000 --min-interval 120000 and no --idle-backoff",
3062
+ "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
3063
  "Pane Chat arms those flags itself through its skill; pass them only for your own scripts.",
2761
3064
  "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."
3065
+ "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
3066
  ],
2764
3067
  "panes create": [
2765
3068
  "Usage:",
2766
- " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [options]",
3069
+ " runpane panes create --repo <selector> --name <name> --agent <codex|claude|cursor> [--base <ref>] [--branch <name>] [--prompt-file <path|->] [options]",
3070
+ " 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
3071
  " runpane panes create --from-json <path|-> [--yes] [--json]",
2768
3072
  "",
2769
3073
  "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
3074
  "",
3075
+ "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.",
3076
+ "",
2771
3077
  "Options:",
2772
3078
  " --repo <selector> active, id, exact path, or saved repository name",
2773
3079
  " --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",
3080
+ " --worktree-name <name> Worktree directory name; defaults to --name",
3081
+ " --branch <name> Exact new branch name (slashes kept); must not exist; defaults to the worktree name",
3082
+ " --base-branch <ref> Ref to branch from; --base is an alias",
3083
+ " --agent <codex|claude|cursor> Built-in terminal template; with --tool-command, the agent it runs",
2777
3084
  " --tool-command <command> Custom terminal command",
2778
3085
  " --title <title> Terminal tab title",
2779
3086
  " --initial-input <text> Text sent after the command is ready",
2780
3087
  " --prompt <text> Alias for --initial-input",
2781
3088
  " --initial-input-file <path|-> Read initial input from a file or stdin",
3089
+ " --as-file-pointer Send `Read and follow <prompt file>` instead of the prompt",
3090
+ " --prompt-file <path|-> Alias for --initial-input-file",
2782
3091
  " --from-json <path|-> Read a full request payload",
2783
3092
  " --timeout-ms <milliseconds> Pane creation timeout",
2784
3093
  " --wait-ready Wait for terminal readiness before returning",
@@ -2798,21 +3107,28 @@ exports.RUNPANE_CONTRACT = {
2798
3107
  "panes adopt": [
2799
3108
  "Usage:",
2800
3109
  " runpane panes adopt --repo <selector> --path <dir> --name <name> --agent <codex|claude|cursor> [options]",
3110
+ " runpane panes adopt --repo <selector> --path <dir> --name <name> --tool-command <command> [--agent <codex|claude|cursor>] [options]",
2801
3111
  "",
2802
- "Adopts an existing externally managed git worktree without creating, syncing, or deleting it.",
3112
+ "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
3113
  "",
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."
3114
+ "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.",
3115
+ "",
3116
+ "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
3117
  ],
2806
3118
  "panes archive": [
2807
3119
  "Usage:",
2808
- " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--dry-run] --yes [--json]",
3120
+ " runpane panes archive --pane <pane-id> [--source user|agent] [--force] [--remove-worktree] [--dry-run] --yes [--json]",
3121
+ " runpane panes archive --session <id|name> --merged [--remove-worktree] [--source user|agent] [--dry-run] --yes [--json]",
2809
3122
  "",
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.",
3123
+ "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
3124
  "",
2812
3125
  "Options:",
2813
3126
  " --pane <pane-id>",
2814
3127
  " --source <user|agent>",
2815
3128
  " --force",
3129
+ " --remove-worktree",
3130
+ " --session <id|name>",
3131
+ " --merged",
2816
3132
  " --pane-dir <path>",
2817
3133
  " --json",
2818
3134
  " --dry-run",
@@ -2885,8 +3201,9 @@ exports.RUNPANE_CONTRACT = {
2885
3201
  " runpane panels output --panel <panel-id> [--limit <count>] [--json]",
2886
3202
  " runpane panels input --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
2887
3203
  " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
2888
- " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter] --yes [--json]",
3204
+ " runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
2889
3205
  " runpane panels wait --panel <panel-id> [--for initialized|ready|idle|text] [--json]",
3206
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json]",
2890
3207
  "",
2891
3208
  "Run \"runpane help panels create\" or another command-specific topic for options."
2892
3209
  ],
@@ -2896,6 +3213,8 @@ exports.RUNPANE_CONTRACT = {
2896
3213
  "",
2897
3214
  "Lists tool panels in a Pane session.",
2898
3215
  "",
3216
+ "agentDetection says how Pane knows agentType: declared, command, process, or screen. launchCommand is the command the panel was launched with.",
3217
+ "",
2899
3218
  "Options:",
2900
3219
  " --pane <pane-id>",
2901
3220
  " --pane-dir <path>",
@@ -2938,6 +3257,7 @@ exports.RUNPANE_CONTRACT = {
2938
3257
  "Options:",
2939
3258
  " --command <command>",
2940
3259
  " --json",
3260
+ " --pane-dir <path> Accepted and ignored",
2941
3261
  "",
2942
3262
  "Examples:",
2943
3263
  " runpane agent-context",
@@ -2978,14 +3298,21 @@ exports.RUNPANE_CONTRACT = {
2978
3298
  ],
2979
3299
  "panels submit": [
2980
3300
  "Usage:",
2981
- " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) --yes [--json]",
3301
+ " runpane panels submit --panel <panel-id> (--text <text>|--input-file <path|->) [--as-file-pointer] --yes [--json]",
2982
3302
  "",
2983
3303
  "Sends text to a terminal panel and normalizes the final terminal Enter to CR. Use this for ordinary prompt answers and shell commands.",
2984
3304
  "",
3305
+ "For a Claude or Codex panel with no composer on screen, nothing is sent: the result is ok: false with blocked.kind composer-unknown.",
3306
+ "",
3307
+ "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.",
3308
+ "",
3309
+ "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.",
3310
+ "",
2985
3311
  "Options:",
2986
3312
  " --panel <panel-id> Terminal panel id",
2987
3313
  " --text <text> Text to submit before Enter",
2988
3314
  " --input-file <path|-> Read text from a file or stdin before Enter",
3315
+ " --as-file-pointer Write the text to a prompt file and submit `Read and follow <path>`",
2989
3316
  " --pane-dir <path> Connect to a specific Pane data directory",
2990
3317
  " --json Print machine-readable output",
2991
3318
  " --yes Skip confirmation for this mutating command"
@@ -3010,15 +3337,16 @@ exports.RUNPANE_CONTRACT = {
3010
3337
  "",
3011
3338
  "Usage:",
3012
3339
  " 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]",
3340
+ " python -m runpane panels create --pane <pane-id> --tool-command <command> [--agent <codex|claude|cursor>] [--title <title>] [--no-focus] [--wait-ready] --yes [--json]",
3014
3341
  "",
3015
3342
  "Options:",
3016
3343
  " --pane <pane-id> Existing Pane session to add the panel to.",
3017
- " --agent <codex|claude|cursor> Built-in agent command template to launch.",
3344
+ " --agent <codex|claude|cursor> Built-in agent command template, or with --tool-command the agent it runs.",
3018
3345
  " --tool-command <command> Custom terminal command to launch.",
3019
3346
  " --title <title> Panel title override.",
3020
3347
  " --initial-input, --prompt Initial input to send after the tool starts.",
3021
3348
  " --initial-input-file <path|-> Read initial input from a file or stdin.",
3349
+ " --as-file-pointer Send `Read and follow <prompt file>` instead of the prompt.",
3022
3350
  " --no-focus Create the panel in the background.",
3023
3351
  " --focus Explicitly focus the created panel.",
3024
3352
  " --source <user|agent> Mark the mutation source; agent implies background creation.",
@@ -3031,11 +3359,11 @@ exports.RUNPANE_CONTRACT = {
3031
3359
  "Submit an agent composer using the panel-appropriate key sequence.",
3032
3360
  "",
3033
3361
  "Usage:",
3034
- " python -m runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter] --yes [--json]",
3362
+ " python -m runpane panels submit-composer --panel <panel-id> [--strategy auto|codex-ctrl-enter|enter|tab] --yes [--json]",
3035
3363
  "",
3036
3364
  "Options:",
3037
3365
  " --panel <panel-id> Terminal panel id.",
3038
- " --strategy <strategy> Defaults to auto; Codex sends Ctrl+Enter and other panels send Enter.",
3366
+ " --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
3367
  " --yes Skip confirmation prompts.",
3040
3368
  " --json Print JSON output."
3041
3369
  ],
@@ -3378,7 +3706,7 @@ exports.RUNPANE_CONTRACT = {
3378
3706
  ],
3379
3707
  "agents send": [
3380
3708
  "Usage:",
3381
- " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> --yes [--json] [--pane-dir <path>]",
3709
+ " runpane agents send (--pane <pane-id>|--panel <panel-id>) --text <message> [--as-file-pointer] --yes [--json] [--pane-dir <path>]",
3382
3710
  "",
3383
3711
  "`runpane agents send` ships in the npm package and the Pane app, not in the Python package.",
3384
3712
  "Run it with Node instead: npx --yes runpane@latest agents send"
@@ -3388,6 +3716,96 @@ exports.RUNPANE_CONTRACT = {
3388
3716
  " runpane sessions <list|create|get|update|set-agent|associate|detach|overview> [options]",
3389
3717
  "",
3390
3718
  "Use a named Session to keep context, activity, and evidence attached to one orchestration thread."
3719
+ ],
3720
+ "report": [
3721
+ "Usage:",
3722
+ " 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>]",
3723
+ "",
3724
+ "Hands back a worker's structured report for its panel: the orchestrator receives it as an",
3725
+ "agent.report watch event and reads it in `agents status` and `sessions overview`.",
3726
+ "Inside a Pane terminal the panel comes from PANE_SESSION_ID and PANE_PANEL_ID.",
3727
+ "",
3728
+ "Options:",
3729
+ " --state <state> ready, blocked, failed, or done",
3730
+ " --pr <number> Pull request number",
3731
+ " --head <sha> Head commit, 7-40 hex characters",
3732
+ " --summary <text> Summary text; up to 16,000 characters are kept",
3733
+ " --summary-file <path|-> Read the summary from a file or stdin",
3734
+ " --question <text> What you need answered; required with --state blocked",
3735
+ " --pane <pane-id> Pane id when not running inside a Pane terminal",
3736
+ " --panel <panel-id> Panel id when not running inside a Pane terminal",
3737
+ " --pane-dir <path> Connect to a specific Pane data directory",
3738
+ " --json Print machine-readable output",
3739
+ "",
3740
+ "Example:",
3741
+ " runpane report --state ready --pr 747 --head fc5dce9 --summary-file /tmp/report.md"
3742
+ ],
3743
+ "panels last-message": [
3744
+ "Usage:",
3745
+ " runpane panels last-message --panel <panel-id> [--limit <count>] [--json] [--pane-dir <path>]",
3746
+ "",
3747
+ "Reads a Claude or Codex agent's last reply from its transcript. It never scrapes the screen:",
3748
+ "without a transcript it reports transcript-unavailable and exits non-zero.",
3749
+ "",
3750
+ "Options:",
3751
+ " --panel <panel-id> Agent panel id",
3752
+ " --limit <count> Maximum characters to return; defaults to 20000 (the end is kept)",
3753
+ " --pane-dir <path> Connect to a specific Pane data directory",
3754
+ " --json Print machine-readable output"
3755
+ ],
3756
+ "lock": [
3757
+ "Usage:",
3758
+ " python -m runpane lock <acquire|release|list> [options]",
3759
+ "",
3760
+ "Named locks coordinate a resource shared between agents, such as one test account.",
3761
+ "The caller is the owner: the Pane and panel from $PANE_SESSION_ID and $PANE_PANEL_ID.",
3762
+ "A lock is scoped to the owner's Session when its Pane belongs to one; otherwise it is global.",
3763
+ "It is released on --ttl expiry, when the owner panel exits, or when the owner Pane is archived."
3764
+ ],
3765
+ "lock acquire": [
3766
+ "Usage:",
3767
+ "python -m runpane lock acquire --name <name> --ttl <duration> [--wait <milliseconds>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
3768
+ "",
3769
+ "Options:",
3770
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
3771
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
3772
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
3773
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
3774
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
3775
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
3776
+ " --force Release a lock another owner holds (release).",
3777
+ " --session <id|name> Named Session whose locks to list or release.",
3778
+ " --json Print JSON output."
3779
+ ],
3780
+ "lock release": [
3781
+ "Usage:",
3782
+ "python -m runpane lock release --name <name> [--force] [--session <id|name>] [--note <text>] [--pane <pane-id>] [--panel <panel-id>] [--json] [--pane-dir <path>]",
3783
+ "",
3784
+ "Options:",
3785
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
3786
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
3787
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
3788
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
3789
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
3790
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
3791
+ " --force Release a lock another owner holds (release).",
3792
+ " --session <id|name> Named Session whose locks to list or release.",
3793
+ " --json Print JSON output."
3794
+ ],
3795
+ "lock list": [
3796
+ "Usage:",
3797
+ "python -m runpane lock list [--session <id|name>] [--json] [--pane-dir <path>]",
3798
+ "",
3799
+ "Options:",
3800
+ " --name <name> Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\".",
3801
+ " --ttl <duration> Time to live, such as 90s, 30m, or 2h; a bare number is milliseconds.",
3802
+ " --wait <milliseconds> Wait this long for a held lock to come free (acquire).",
3803
+ " --note <text> What the lock is for; outside a Pane it also names the owner.",
3804
+ " --pane <pane-id> Act for this Pane instead of $PANE_SESSION_ID.",
3805
+ " --panel <panel-id> Act for this panel instead of $PANE_PANEL_ID.",
3806
+ " --force Release a lock another owner holds (release).",
3807
+ " --session <id|name> Named Session whose locks to list or release.",
3808
+ " --json Print JSON output."
3391
3809
  ]
3392
3810
  }
3393
3811
  },
@@ -3472,6 +3890,7 @@ exports.RUNPANE_CONTRACT = {
3472
3890
  "runpane watch --self-test",
3473
3891
  "runpane watch --follow",
3474
3892
  "runpane watch --follow --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff",
3893
+ "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
3894
  "runpane sessions list [--json] [--pane-dir <path>]",
3476
3895
  "runpane sessions create --from-json <path|-> [--json] [--pane-dir <path>]",
3477
3896
  "runpane sessions get --session <id|name> [--json] [--pane-dir <path>]",
@@ -3480,9 +3899,14 @@ exports.RUNPANE_CONTRACT = {
3480
3899
  "runpane sessions associate --session <id|name> --pane <pane-id> [--json] [--pane-dir <path>]",
3481
3900
  "runpane sessions detach --session <id|name> [--pane <pane-id>] [--json] [--pane-dir <path>]",
3482
3901
  "runpane sessions overview --session <id|name> [--json] [--pane-dir <path>]",
3902
+ "runpane lock acquire --name testing-account --ttl 30m --wait 1800000 --note \"call QA\" --json",
3903
+ "runpane lock release --name testing-account --json",
3904
+ "runpane lock list --json",
3483
3905
  "runpane agents start --repo active --name fix-login --agent claude --prompt \"Fix the login redirect\" --yes --json",
3484
3906
  "runpane agents status --pane <pane-id> --json",
3485
3907
  "runpane agents send --pane <pane-id> --text \"Also add a test\" --yes --json",
3908
+ "runpane report --state ready --pr 747 --head fc5dce9 --summary-file /tmp/report.md --json",
3909
+ "runpane panels last-message --panel <panel-id> --json",
3486
3910
  "runpane docs search --query \"archive a pane\" --json",
3487
3911
  "runpane links create --pane <pane-id> --json",
3488
3912
  "runpane panes git-status --pane <pane-id> --json",
@@ -3500,24 +3924,26 @@ exports.RUNPANE_CONTRACT = {
3500
3924
  "`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
3925
  "`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
3926
  "`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.",
3927
+ "`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
3928
  "`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
3929
  "`runpane repos list` connects to the running local Pane daemon and prints saved repository records.",
3506
3930
  "`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
3931
  "`runpane panes list` lists Pane sessions, optionally scoped to one saved repository.",
3508
3932
  "`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
3933
  "`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`.",
3934
+ "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.",
3935
+ "`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
3936
  "`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
3937
  "`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`.",
3514
3938
  "`runpane panels list` lists tool panels inside one Pane session.",
3515
3939
  "`runpane panels output` reads bounded recent terminal output from one panel and strips common terminal control noise for agent use.",
3516
3940
  "`runpane panels input` sends exact input bytes to one terminal panel. Prefer `--input-file` for newlines, Ctrl-C, quotes, or shell-sensitive text.",
3517
3941
  "`runpane panes create --prompt` is an alias for `--initial-input`; request JSON and daemon payloads should use the canonical `initialInput` field.",
3942
+ "`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`.",
3943
+ "`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
3944
  "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
3945
  "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.",
3946
+ "`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
3947
  "`sessions list` list durable named orchestration Sessions.",
3522
3948
  "`sessions create` create a durable named orchestration Session and its hidden terminal owner.",
3523
3949
  "`sessions get` read one durable named orchestration Session.",
@@ -3526,13 +3952,16 @@ exports.RUNPANE_CONTRACT = {
3526
3952
  "`sessions associate` associate a user-visible Pane with a named Session.",
3527
3953
  "`sessions detach` detach a Pane from a named Session.",
3528
3954
  "`sessions overview` read a live status, activity, git, and pull request overview for a named Session.",
3955
+ "`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
3956
  "`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.",
3957
+ "`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`.",
3958
+ "`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
3959
  "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
3960
  "`runpane links create` builds `pane://open?...` links; opening one in Pane selects what it names and never changes Pane state.",
3532
3961
  "`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
3962
  ],
3534
3963
  "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.",
3964
+ "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
3965
  "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
3966
  "downloadAttribution": [
3538
3967
  "The npm package uses `source=npm` for all npm-registry consumers, including `npx`, `pnpm dlx`, `yarn dlx`, `bunx`, and global npm/pnpm installs.",
@@ -4058,79 +4487,367 @@ exports.RUNPANE_CONTRACT = {
4058
4487
  "folder-9",
4059
4488
  "--yes",
4060
4489
  "--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
- ],
4097
- "installHelpIncludes": [
4098
- "--version <latest|vX.Y.Z>",
4099
- "--format <auto|appimage|deb|dmg|zip|exe>",
4100
- "--download-dir <path>",
4101
- "--pane-path <path>",
4102
- "--label <name>",
4103
- "--prefer-tunnel <tailscale|ssh|manual|auto>",
4104
- "--repo-ref <ref>"
4105
- ]
4106
- },
4107
- "jsonSchemas": {
4108
- "error": {
4109
- "type": "object",
4110
- "required": [
4111
- "ok",
4112
- "error"
4113
4490
  ],
4114
- "properties": {
4115
- "ok": {
4116
- "const": false
4117
- },
4118
- "error": {
4119
- "type": "object",
4120
- "required": [
4121
- "message"
4122
- ],
4123
- "properties": {
4124
- "message": {
4125
- "type": "string"
4126
- },
4127
- "code": {
4128
- "type": "string"
4129
- }
4130
- },
4131
- "additionalProperties": false
4132
- }
4133
- },
4491
+ [
4492
+ "watch",
4493
+ "--follow",
4494
+ "--quiet",
4495
+ "--json",
4496
+ "--pane-dir",
4497
+ "/tmp/pane"
4498
+ ],
4499
+ [
4500
+ "watch",
4501
+ "--follow",
4502
+ "--no-control-lines",
4503
+ "--all-managed"
4504
+ ],
4505
+ [
4506
+ "watch",
4507
+ "--session",
4508
+ "__orchestration_session_1b4e28ba-2fa1-11d2-883f-0016d3cca427__",
4509
+ "--follow",
4510
+ "--quiet",
4511
+ "--json",
4512
+ "--kinds",
4513
+ "agent.ready,agent.blocked,pane.associated,pane.detached,pr.conflicted,pr.checks,pr.merged",
4514
+ "--settle",
4515
+ "180000"
4516
+ ],
4517
+ [
4518
+ "watch",
4519
+ "--session=Release train",
4520
+ "--as",
4521
+ "release-watch",
4522
+ "--exclude-pane",
4523
+ "pane-old"
4524
+ ],
4525
+ [
4526
+ "agent-context",
4527
+ "--command",
4528
+ "panes create",
4529
+ "--json",
4530
+ "--pane-dir",
4531
+ "/tmp/pane"
4532
+ ],
4533
+ [
4534
+ "agent-context",
4535
+ "--pane-dir=/tmp/pane"
4536
+ ],
4537
+ [
4538
+ "version",
4539
+ "--pane-dir",
4540
+ "/tmp/pane"
4541
+ ],
4542
+ [
4543
+ "panes",
4544
+ "create",
4545
+ "--repo",
4546
+ "active",
4547
+ "--name",
4548
+ "w5a",
4549
+ "--agent",
4550
+ "claude",
4551
+ "--base-branch",
4552
+ "origin/release",
4553
+ "--source",
4554
+ "agent",
4555
+ "--no-focus",
4556
+ "--yes",
4557
+ "--json",
4558
+ "--pane-dir",
4559
+ "/tmp/pane"
4560
+ ],
4561
+ [
4562
+ "panels",
4563
+ "create",
4564
+ "--pane",
4565
+ "pane-1",
4566
+ "--agent",
4567
+ "codex",
4568
+ "--tool-command",
4569
+ "wrapper codex-run",
4570
+ "--wait-ready",
4571
+ "--yes",
4572
+ "--json"
4573
+ ],
4574
+ [
4575
+ "panes",
4576
+ "create",
4577
+ "--repo",
4578
+ "active",
4579
+ "--name",
4580
+ "farm",
4581
+ "--tool-command",
4582
+ "agent-farm run free-range",
4583
+ "--agent",
4584
+ "claude",
4585
+ "--prompt",
4586
+ "Plan",
4587
+ "--yes",
4588
+ "--json"
4589
+ ],
4590
+ [
4591
+ "panels",
4592
+ "submit",
4593
+ "--panel",
4594
+ "panel-1",
4595
+ "--input-file",
4596
+ "brief.md",
4597
+ "--as-file-pointer",
4598
+ "--yes",
4599
+ "--json"
4600
+ ],
4601
+ [
4602
+ "panes",
4603
+ "create",
4604
+ "--repo",
4605
+ "active",
4606
+ "--name",
4607
+ "long",
4608
+ "--agent",
4609
+ "claude",
4610
+ "--initial-input-file",
4611
+ "brief.md",
4612
+ "--as-file-pointer",
4613
+ "--dry-run",
4614
+ "--yes",
4615
+ "--json"
4616
+ ],
4617
+ [
4618
+ "report",
4619
+ "--state",
4620
+ "ready",
4621
+ "--pr",
4622
+ "747",
4623
+ "--head",
4624
+ "FC5DCE9",
4625
+ "--summary",
4626
+ "Done: tests pass",
4627
+ "--json"
4628
+ ],
4629
+ [
4630
+ "report",
4631
+ "--state",
4632
+ "blocked",
4633
+ "--question",
4634
+ "Which API version?",
4635
+ "--pane",
4636
+ "session-1",
4637
+ "--panel",
4638
+ "panel-1",
4639
+ "--summary-file",
4640
+ "-"
4641
+ ],
4642
+ [
4643
+ "report",
4644
+ "--state=done",
4645
+ "--summary-file=/tmp/report.md",
4646
+ "--pane-dir",
4647
+ "/tmp/pane"
4648
+ ],
4649
+ [
4650
+ "panels",
4651
+ "last-message",
4652
+ "--panel",
4653
+ "panel-1",
4654
+ "--limit",
4655
+ "5000",
4656
+ "--json"
4657
+ ],
4658
+ [
4659
+ "panes",
4660
+ "create",
4661
+ "--repo",
4662
+ "active",
4663
+ "--name",
4664
+ "w5a",
4665
+ "--base",
4666
+ "release/foo",
4667
+ "--branch",
4668
+ "agents/w5a",
4669
+ "--agent",
4670
+ "claude",
4671
+ "--prompt-file",
4672
+ "prompt.md",
4673
+ "--dry-run",
4674
+ "--yes",
4675
+ "--json"
4676
+ ],
4677
+ [
4678
+ "panes",
4679
+ "create",
4680
+ "--repo",
4681
+ "active",
4682
+ "--name",
4683
+ "w5b",
4684
+ "--base-branch",
4685
+ "origin/main",
4686
+ "--branch",
4687
+ "agents/w5b",
4688
+ "--worktree-name",
4689
+ "w5b-dir",
4690
+ "--tool-command",
4691
+ "bash",
4692
+ "--initial-input-file",
4693
+ "-",
4694
+ "--dry-run",
4695
+ "--yes",
4696
+ "--json"
4697
+ ],
4698
+ [
4699
+ "panes",
4700
+ "archive",
4701
+ "--pane",
4702
+ "session-1",
4703
+ "--remove-worktree",
4704
+ "--yes",
4705
+ "--json"
4706
+ ],
4707
+ [
4708
+ "panes",
4709
+ "archive",
4710
+ "--session",
4711
+ "refactor",
4712
+ "--merged",
4713
+ "--dry-run",
4714
+ "--json"
4715
+ ],
4716
+ [
4717
+ "panes",
4718
+ "archive",
4719
+ "--session",
4720
+ "refactor",
4721
+ "--merged",
4722
+ "--remove-worktree",
4723
+ "--yes"
4724
+ ],
4725
+ [
4726
+ "lock",
4727
+ "acquire",
4728
+ "--name",
4729
+ "testing-account",
4730
+ "--ttl",
4731
+ "30m",
4732
+ "--wait",
4733
+ "1800000",
4734
+ "--note",
4735
+ "call QA",
4736
+ "--json"
4737
+ ],
4738
+ [
4739
+ "lock",
4740
+ "acquire",
4741
+ "--name",
4742
+ "staging-db",
4743
+ "--ttl",
4744
+ "1500",
4745
+ "--pane",
4746
+ "session-1",
4747
+ "--panel",
4748
+ "panel-1",
4749
+ "--pane-dir",
4750
+ "/tmp/pane"
4751
+ ],
4752
+ [
4753
+ "lock",
4754
+ "acquire",
4755
+ "--name=db",
4756
+ "--ttl=2h"
4757
+ ],
4758
+ [
4759
+ "lock",
4760
+ "release",
4761
+ "--name",
4762
+ "testing-account",
4763
+ "--force",
4764
+ "--session",
4765
+ "Release QA",
4766
+ "--json"
4767
+ ],
4768
+ [
4769
+ "lock",
4770
+ "list",
4771
+ "--session",
4772
+ "Release QA",
4773
+ "--json"
4774
+ ],
4775
+ [
4776
+ "lock",
4777
+ "--help"
4778
+ ]
4779
+ ],
4780
+ "topLevelHelpIncludes": [
4781
+ "runpane setup",
4782
+ "runpane install",
4783
+ "runpane update",
4784
+ "runpane version",
4785
+ "runpane doctor",
4786
+ "runpane agent-context",
4787
+ "runpane repos list",
4788
+ "runpane repos add",
4789
+ "runpane panes list",
4790
+ "runpane panes create",
4791
+ "runpane panes archive",
4792
+ "runpane panels create",
4793
+ "runpane panels list",
4794
+ "runpane panels output",
4795
+ "runpane panels input",
4796
+ "runpane agents doctor",
4797
+ "runpane panels screen",
4798
+ "runpane panels submit",
4799
+ "runpane panels submit-composer",
4800
+ "runpane panels wait",
4801
+ "runpane doctor --json",
4802
+ "runpane agent-context --json",
4803
+ "Agent discovery:",
4804
+ "Common commands:"
4805
+ ],
4806
+ "npmHelpIncludes": [
4807
+ "pnpm dlx runpane@latest",
4808
+ "npx --yes runpane@latest"
4809
+ ],
4810
+ "pipHelpIncludes": [
4811
+ "pipx run runpane",
4812
+ "python -m pip install runpane && python -m runpane setup"
4813
+ ],
4814
+ "installHelpIncludes": [
4815
+ "--version <latest|vX.Y.Z>",
4816
+ "--format <auto|appimage|deb|dmg|zip|exe>",
4817
+ "--download-dir <path>",
4818
+ "--pane-path <path>",
4819
+ "--label <name>",
4820
+ "--prefer-tunnel <tailscale|ssh|manual|auto>",
4821
+ "--repo-ref <ref>"
4822
+ ]
4823
+ },
4824
+ "jsonSchemas": {
4825
+ "error": {
4826
+ "type": "object",
4827
+ "required": [
4828
+ "ok",
4829
+ "error"
4830
+ ],
4831
+ "properties": {
4832
+ "ok": {
4833
+ "const": false
4834
+ },
4835
+ "error": {
4836
+ "type": "object",
4837
+ "required": [
4838
+ "message"
4839
+ ],
4840
+ "properties": {
4841
+ "message": {
4842
+ "type": "string"
4843
+ },
4844
+ "code": {
4845
+ "type": "string"
4846
+ }
4847
+ },
4848
+ "additionalProperties": false
4849
+ }
4850
+ },
4134
4851
  "additionalProperties": false
4135
4852
  },
4136
4853
  "doctorResult": {
@@ -4144,6 +4861,7 @@ exports.RUNPANE_CONTRACT = {
4144
4861
  "daemon",
4145
4862
  "remoteDaemonService",
4146
4863
  "remoteSetup",
4864
+ "watchDefaults",
4147
4865
  "nextCommands"
4148
4866
  ],
4149
4867
  "properties": {
@@ -4471,6 +5189,42 @@ exports.RUNPANE_CONTRACT = {
4471
5189
  },
4472
5190
  "additionalProperties": false
4473
5191
  },
5192
+ "watchDefaults": {
5193
+ "type": "object",
5194
+ "required": [
5195
+ "heartbeatSeconds",
5196
+ "idleAfterMs",
5197
+ "settleMs",
5198
+ "blockedSettleMs",
5199
+ "minIntervalMs",
5200
+ "idleBackoff",
5201
+ "kinds"
5202
+ ],
5203
+ "properties": {
5204
+ "heartbeatSeconds": {
5205
+ "type": "number"
5206
+ },
5207
+ "idleAfterMs": {
5208
+ "type": "number"
5209
+ },
5210
+ "settleMs": {
5211
+ "type": "number"
5212
+ },
5213
+ "blockedSettleMs": {
5214
+ "type": "number"
5215
+ },
5216
+ "minIntervalMs": {
5217
+ "type": "number"
5218
+ },
5219
+ "idleBackoff": {
5220
+ "type": "boolean"
5221
+ },
5222
+ "kinds": {
5223
+ "const": "all"
5224
+ }
5225
+ },
5226
+ "additionalProperties": false
5227
+ },
4474
5228
  "nextCommands": {
4475
5229
  "type": "array",
4476
5230
  "items": {
@@ -4690,6 +5444,9 @@ exports.RUNPANE_CONTRACT = {
4690
5444
  "worktreeName": {
4691
5445
  "type": "string"
4692
5446
  },
5447
+ "branch": {
5448
+ "type": "string"
5449
+ },
4693
5450
  "baseBranch": {
4694
5451
  "type": "string"
4695
5452
  },
@@ -4718,6 +5475,9 @@ exports.RUNPANE_CONTRACT = {
4718
5475
  },
4719
5476
  "initialInput": {
4720
5477
  "type": "string"
5478
+ },
5479
+ "initialInputAsFilePointer": {
5480
+ "type": "boolean"
4721
5481
  }
4722
5482
  },
4723
5483
  "additionalProperties": false
@@ -4731,11 +5491,21 @@ exports.RUNPANE_CONTRACT = {
4731
5491
  "command": {
4732
5492
  "type": "string"
4733
5493
  },
5494
+ "agentType": {
5495
+ "enum": [
5496
+ "codex",
5497
+ "claude",
5498
+ "cursor"
5499
+ ]
5500
+ },
4734
5501
  "title": {
4735
5502
  "type": "string"
4736
5503
  },
4737
5504
  "initialInput": {
4738
5505
  "type": "string"
5506
+ },
5507
+ "initialInputAsFilePointer": {
5508
+ "type": "boolean"
4739
5509
  }
4740
5510
  },
4741
5511
  "additionalProperties": false
@@ -4983,6 +5753,7 @@ exports.RUNPANE_CONTRACT = {
4983
5753
  "enum": [
4984
5754
  "codex-ctrl-enter",
4985
5755
  "enter",
5756
+ "tab",
4986
5757
  "argument"
4987
5758
  ]
4988
5759
  },
@@ -4990,12 +5761,16 @@ exports.RUNPANE_CONTRACT = {
4990
5761
  "enum": [
4991
5762
  "codex-ctrl-enter-cr",
4992
5763
  "enter-cr",
5764
+ "tab",
4993
5765
  "argument"
4994
5766
  ]
4995
5767
  },
4996
5768
  "verifiedSubmitted": {
4997
5769
  "type": "boolean"
4998
5770
  },
5771
+ "delivery": {
5772
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/delivery"
5773
+ },
4999
5774
  "staged": {
5000
5775
  "type": "boolean"
5001
5776
  },
@@ -5074,6 +5849,12 @@ exports.RUNPANE_CONTRACT = {
5074
5849
  }
5075
5850
  },
5076
5851
  "additionalProperties": false
5852
+ },
5853
+ "promptFile": {
5854
+ "type": "string"
5855
+ },
5856
+ "warnings": {
5857
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/warnings"
5077
5858
  }
5078
5859
  },
5079
5860
  "additionalProperties": false
@@ -5200,6 +5981,14 @@ exports.RUNPANE_CONTRACT = {
5200
5981
  "idle"
5201
5982
  ]
5202
5983
  },
5984
+ "agentState": {
5985
+ "enum": [
5986
+ "ready",
5987
+ "working",
5988
+ "blocked",
5989
+ "none"
5990
+ ]
5991
+ },
5203
5992
  "ownership": {
5204
5993
  "enum": [
5205
5994
  "pane",
@@ -5565,7 +6354,13 @@ exports.RUNPANE_CONTRACT = {
5565
6354
  "agent.idle",
5566
6355
  "pane.created",
5567
6356
  "pane.gone",
5568
- "panel.exited"
6357
+ "panel.exited",
6358
+ "agent.report",
6359
+ "pane.associated",
6360
+ "pane.detached",
6361
+ "pr.conflicted",
6362
+ "pr.checks",
6363
+ "pr.merged"
5569
6364
  ]
5570
6365
  },
5571
6366
  "paneId": {
@@ -5609,7 +6404,8 @@ exports.RUNPANE_CONTRACT = {
5609
6404
  "enum": [
5610
6405
  "agent",
5611
6406
  "exit",
5612
- "session"
6407
+ "session",
6408
+ "github"
5613
6409
  ]
5614
6410
  },
5615
6411
  "reason": {
@@ -5643,8 +6439,98 @@ exports.RUNPANE_CONTRACT = {
5643
6439
  "baseline": {
5644
6440
  "const": true
5645
6441
  },
6442
+ "replay": {
6443
+ "const": true,
6444
+ "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."
6445
+ },
5646
6446
  "changedWhileAway": {
5647
6447
  "type": "boolean"
6448
+ },
6449
+ "sessionId": {
6450
+ "type": "string",
6451
+ "description": "Named Session of a pane.associated or pane.detached entry."
6452
+ },
6453
+ "sessionName": {
6454
+ "type": "string"
6455
+ },
6456
+ "pr": {
6457
+ "type": "object",
6458
+ "description": "PR of a pr.conflicted, pr.checks, or pr.merged entry.",
6459
+ "required": [
6460
+ "number",
6461
+ "url",
6462
+ "headOid"
6463
+ ],
6464
+ "properties": {
6465
+ "number": {
6466
+ "type": "number"
6467
+ },
6468
+ "url": {
6469
+ "type": "string"
6470
+ },
6471
+ "headOid": {
6472
+ "type": "string"
6473
+ }
6474
+ },
6475
+ "additionalProperties": false
6476
+ },
6477
+ "checks": {
6478
+ "enum": [
6479
+ "passed",
6480
+ "failed"
6481
+ ],
6482
+ "description": "Settled result of a pr.checks entry: every check on pr.headOid finished."
6483
+ },
6484
+ "failingChecks": {
6485
+ "type": "array",
6486
+ "items": {
6487
+ "type": "string"
6488
+ },
6489
+ "description": "Up to five failing check names of a failed pr.checks entry."
6490
+ },
6491
+ "report": {
6492
+ "$ref": "#/jsonSchemas/agentReport",
6493
+ "description": "Report of an agent.report entry; its summary is cut to 2,000 characters (the panel keeps up to 16,000)."
6494
+ }
6495
+ },
6496
+ "additionalProperties": false
6497
+ },
6498
+ "agentReport": {
6499
+ "type": "object",
6500
+ "description": "The latest runpane report from an agent panel.",
6501
+ "required": [
6502
+ "state",
6503
+ "reportedAt"
6504
+ ],
6505
+ "properties": {
6506
+ "state": {
6507
+ "enum": [
6508
+ "ready",
6509
+ "blocked",
6510
+ "failed",
6511
+ "done"
6512
+ ]
6513
+ },
6514
+ "pr": {
6515
+ "type": "number"
6516
+ },
6517
+ "head": {
6518
+ "type": "string"
6519
+ },
6520
+ "summary": {
6521
+ "type": "string"
6522
+ },
6523
+ "summaryTruncated": {
6524
+ "const": true
6525
+ },
6526
+ "summaryPath": {
6527
+ "type": "string"
6528
+ },
6529
+ "question": {
6530
+ "type": "string"
6531
+ },
6532
+ "reportedAt": {
6533
+ "type": "string"
5648
6534
  }
5649
6535
  },
5650
6536
  "additionalProperties": false
@@ -5682,6 +6568,10 @@ exports.RUNPANE_CONTRACT = {
5682
6568
  "type": "string"
5683
6569
  }
5684
6570
  },
6571
+ "session": {
6572
+ "type": "string",
6573
+ "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."
6574
+ },
5685
6575
  "excludePaneIds": {
5686
6576
  "type": "array",
5687
6577
  "items": {
@@ -5825,6 +6715,23 @@ exports.RUNPANE_CONTRACT = {
5825
6715
  },
5826
6716
  "additionalProperties": false
5827
6717
  },
6718
+ "session": {
6719
+ "type": "object",
6720
+ "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.",
6721
+ "required": [
6722
+ "id",
6723
+ "name"
6724
+ ],
6725
+ "properties": {
6726
+ "id": {
6727
+ "type": "string"
6728
+ },
6729
+ "name": {
6730
+ "type": "string"
6731
+ }
6732
+ },
6733
+ "additionalProperties": false
6734
+ },
5828
6735
  "nextCommand": {
5829
6736
  "type": "string"
5830
6737
  }
@@ -5851,6 +6758,9 @@ exports.RUNPANE_CONTRACT = {
5851
6758
  },
5852
6759
  "dryRun": {
5853
6760
  "type": "boolean"
6761
+ },
6762
+ "removeWorktree": {
6763
+ "type": "boolean"
5854
6764
  }
5855
6765
  },
5856
6766
  "additionalProperties": false
@@ -6023,7 +6933,15 @@ exports.RUNPANE_CONTRACT = {
6023
6933
  "failed",
6024
6934
  "timeout",
6025
6935
  "not-applicable"
6026
- ]
6936
+ ],
6937
+ "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."
6938
+ },
6939
+ "trashDeletion": {
6940
+ "enum": [
6941
+ "pending",
6942
+ "done"
6943
+ ],
6944
+ "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."
6027
6945
  },
6028
6946
  "worktreePath": {
6029
6947
  "type": "string"
@@ -6073,6 +6991,38 @@ exports.RUNPANE_CONTRACT = {
6073
6991
  },
6074
6992
  "additionalProperties": false
6075
6993
  }
6994
+ },
6995
+ "reason": {
6996
+ "enum": [
6997
+ "external-worktree",
6998
+ "main-repo",
6999
+ "missing-project-context",
7000
+ "git-error"
7001
+ ]
7002
+ },
7003
+ "worktreeWillRemain": {
7004
+ "const": true
7005
+ },
7006
+ "upstreamGone": {
7007
+ "type": "boolean",
7008
+ "description": "The branch had an upstream that no longer exists on the remote, so commits were compared with the base branch."
7009
+ },
7010
+ "mergedViaPr": {
7011
+ "type": "object",
7012
+ "description": "A merged pull request whose head commit is HEAD. Its commits are not counted as unpushed.",
7013
+ "required": [
7014
+ "number",
7015
+ "headOid"
7016
+ ],
7017
+ "properties": {
7018
+ "number": {
7019
+ "type": "number"
7020
+ },
7021
+ "headOid": {
7022
+ "type": "string"
7023
+ }
7024
+ },
7025
+ "additionalProperties": false
6076
7026
  }
6077
7027
  },
6078
7028
  "additionalProperties": false
@@ -6200,6 +7150,17 @@ exports.RUNPANE_CONTRACT = {
6200
7150
  },
6201
7151
  "additionalProperties": false
6202
7152
  }
7153
+ },
7154
+ "reason": {
7155
+ "enum": [
7156
+ "external-worktree",
7157
+ "main-repo",
7158
+ "missing-project-context",
7159
+ "git-error"
7160
+ ]
7161
+ },
7162
+ "worktreeWillRemain": {
7163
+ "const": true
6203
7164
  }
6204
7165
  },
6205
7166
  "additionalProperties": false
@@ -6266,6 +7227,17 @@ exports.RUNPANE_CONTRACT = {
6266
7227
  "agentType": {
6267
7228
  "type": "string"
6268
7229
  },
7230
+ "agentDetection": {
7231
+ "enum": [
7232
+ "declared",
7233
+ "command",
7234
+ "process",
7235
+ "screen"
7236
+ ]
7237
+ },
7238
+ "launchCommand": {
7239
+ "type": "string"
7240
+ },
6269
7241
  "isCliPanel": {
6270
7242
  "type": "boolean"
6271
7243
  },
@@ -6277,6 +7249,9 @@ exports.RUNPANE_CONTRACT = {
6277
7249
  },
6278
7250
  "lastActiveAt": {
6279
7251
  "type": "string"
7252
+ },
7253
+ "report": {
7254
+ "$ref": "#/jsonSchemas/agentReport"
6280
7255
  }
6281
7256
  },
6282
7257
  "additionalProperties": false
@@ -6373,6 +7348,9 @@ exports.RUNPANE_CONTRACT = {
6373
7348
  "ok": {
6374
7349
  "const": true
6375
7350
  },
7351
+ "generation": {
7352
+ "type": "number"
7353
+ },
6376
7354
  "panelId": {
6377
7355
  "type": "string"
6378
7356
  },
@@ -6617,6 +7595,9 @@ exports.RUNPANE_CONTRACT = {
6617
7595
  },
6618
7596
  "hasUndeliveredText": {
6619
7597
  "type": "boolean"
7598
+ },
7599
+ "ghostText": {
7600
+ "type": "string"
6620
7601
  }
6621
7602
  },
6622
7603
  "additionalProperties": false
@@ -6642,6 +7623,9 @@ exports.RUNPANE_CONTRACT = {
6642
7623
  },
6643
7624
  "input": {
6644
7625
  "type": "string"
7626
+ },
7627
+ "asFilePointer": {
7628
+ "type": "boolean"
6645
7629
  }
6646
7630
  },
6647
7631
  "additionalProperties": false
@@ -6674,23 +7658,79 @@ exports.RUNPANE_CONTRACT = {
6674
7658
  "type": "number"
6675
7659
  },
6676
7660
  "enter": {
6677
- "const": "cr"
7661
+ "enum": [
7662
+ "cr",
7663
+ "tab"
7664
+ ]
6678
7665
  },
6679
7666
  "sequenceName": {
6680
7667
  "enum": [
6681
7668
  "codex-ctrl-enter-cr",
6682
- "enter-cr"
7669
+ "enter-cr",
7670
+ "tab"
6683
7671
  ]
6684
7672
  },
6685
7673
  "verifiedSubmitted": {
6686
7674
  "type": "boolean"
6687
7675
  },
7676
+ "delivery": {
7677
+ "type": "object",
7678
+ "required": [
7679
+ "state",
7680
+ "evidence"
7681
+ ],
7682
+ "properties": {
7683
+ "state": {
7684
+ "enum": [
7685
+ "taken",
7686
+ "queued",
7687
+ "in-composer",
7688
+ "unknown"
7689
+ ]
7690
+ },
7691
+ "evidence": {
7692
+ "enum": [
7693
+ "transcript",
7694
+ "screen",
7695
+ "argv"
7696
+ ]
7697
+ }
7698
+ },
7699
+ "additionalProperties": false
7700
+ },
6688
7701
  "sentAt": {
6689
7702
  "type": "string"
6690
7703
  },
6691
7704
  "blocked": {
6692
7705
  "$ref": "#/jsonSchemas/panelSubmitComposerResult/properties/blocked"
6693
7706
  },
7707
+ "promptFile": {
7708
+ "type": "string"
7709
+ },
7710
+ "warnings": {
7711
+ "type": "array",
7712
+ "items": {
7713
+ "type": "object",
7714
+ "required": [
7715
+ "code",
7716
+ "message"
7717
+ ],
7718
+ "properties": {
7719
+ "code": {
7720
+ "enum": [
7721
+ "leading-bang-runs-shell",
7722
+ "leading-hash-memory",
7723
+ "leading-slash-command",
7724
+ "leading-at-mention"
7725
+ ]
7726
+ },
7727
+ "message": {
7728
+ "type": "string"
7729
+ }
7730
+ },
7731
+ "additionalProperties": false
7732
+ }
7733
+ },
6694
7734
  "nextCommand": {
6695
7735
  "type": "string"
6696
7736
  },
@@ -6833,6 +7873,81 @@ exports.RUNPANE_CONTRACT = {
6833
7873
  },
6834
7874
  "additionalProperties": false
6835
7875
  },
7876
+ "panelLastMessageResult": {
7877
+ "oneOf": [
7878
+ {
7879
+ "type": "object",
7880
+ "required": [
7881
+ "ok",
7882
+ "panelId",
7883
+ "paneId",
7884
+ "agentType",
7885
+ "text",
7886
+ "length",
7887
+ "limit",
7888
+ "truncated"
7889
+ ],
7890
+ "properties": {
7891
+ "ok": {
7892
+ "const": true
7893
+ },
7894
+ "panelId": {
7895
+ "type": "string"
7896
+ },
7897
+ "paneId": {
7898
+ "type": "string"
7899
+ },
7900
+ "agentType": {
7901
+ "enum": [
7902
+ "claude",
7903
+ "codex"
7904
+ ]
7905
+ },
7906
+ "text": {
7907
+ "type": "string"
7908
+ },
7909
+ "length": {
7910
+ "type": "number"
7911
+ },
7912
+ "limit": {
7913
+ "type": "number"
7914
+ },
7915
+ "truncated": {
7916
+ "type": "boolean"
7917
+ }
7918
+ },
7919
+ "additionalProperties": false
7920
+ },
7921
+ {
7922
+ "type": "object",
7923
+ "required": [
7924
+ "ok",
7925
+ "panelId",
7926
+ "paneId",
7927
+ "reason",
7928
+ "message"
7929
+ ],
7930
+ "properties": {
7931
+ "ok": {
7932
+ "const": false
7933
+ },
7934
+ "panelId": {
7935
+ "type": "string"
7936
+ },
7937
+ "paneId": {
7938
+ "type": "string"
7939
+ },
7940
+ "reason": {
7941
+ "const": "transcript-unavailable"
7942
+ },
7943
+ "message": {
7944
+ "type": "string"
7945
+ }
7946
+ },
7947
+ "additionalProperties": false
7948
+ }
7949
+ ]
7950
+ },
6836
7951
  "agentDoctorResult": {
6837
7952
  "type": "object",
6838
7953
  "required": [
@@ -7097,6 +8212,12 @@ exports.RUNPANE_CONTRACT = {
7097
8212
  },
7098
8213
  "additionalProperties": false
7099
8214
  },
8215
+ "promptFile": {
8216
+ "type": "string"
8217
+ },
8218
+ "warnings": {
8219
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/warnings"
8220
+ },
7100
8221
  "nextCommand": {
7101
8222
  "type": "string"
7102
8223
  }
@@ -7116,7 +8237,8 @@ exports.RUNPANE_CONTRACT = {
7116
8237
  "enum": [
7117
8238
  "auto",
7118
8239
  "codex-ctrl-enter",
7119
- "enter"
8240
+ "enter",
8241
+ "tab"
7120
8242
  ]
7121
8243
  }
7122
8244
  },
@@ -7152,18 +8274,23 @@ exports.RUNPANE_CONTRACT = {
7152
8274
  "strategy": {
7153
8275
  "enum": [
7154
8276
  "codex-ctrl-enter",
7155
- "enter"
8277
+ "enter",
8278
+ "tab"
7156
8279
  ]
7157
8280
  },
7158
8281
  "sequenceName": {
7159
8282
  "enum": [
7160
8283
  "codex-ctrl-enter-cr",
7161
- "enter-cr"
8284
+ "enter-cr",
8285
+ "tab"
7162
8286
  ]
7163
8287
  },
7164
8288
  "verifiedSubmitted": {
7165
8289
  "type": "boolean"
7166
8290
  },
8291
+ "delivery": {
8292
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/delivery"
8293
+ },
7167
8294
  "sentAt": {
7168
8295
  "type": "string"
7169
8296
  },
@@ -7179,6 +8306,7 @@ exports.RUNPANE_CONTRACT = {
7179
8306
  "codex-update",
7180
8307
  "agent-prompt",
7181
8308
  "submission_unverified",
8309
+ "composer-unknown",
7182
8310
  "unknown"
7183
8311
  ]
7184
8312
  },
@@ -7218,66 +8346,317 @@ exports.RUNPANE_CONTRACT = {
7218
8346
  "items": {
7219
8347
  "type": "object"
7220
8348
  }
7221
- },
7222
- "selectedSessionId": {
7223
- "type": "string"
8349
+ },
8350
+ "selectedSessionId": {
8351
+ "type": "string"
8352
+ }
8353
+ },
8354
+ "additionalProperties": false
8355
+ },
8356
+ "sessionResult": {
8357
+ "type": "object",
8358
+ "required": [
8359
+ "ok",
8360
+ "session"
8361
+ ],
8362
+ "properties": {
8363
+ "ok": {
8364
+ "const": true
8365
+ },
8366
+ "session": {
8367
+ "type": "object"
8368
+ },
8369
+ "panelId": {
8370
+ "type": "string"
8371
+ },
8372
+ "internalSessionId": {
8373
+ "type": "string"
8374
+ }
8375
+ },
8376
+ "additionalProperties": false
8377
+ },
8378
+ "sessionOverviewResult": {
8379
+ "type": "object",
8380
+ "required": [
8381
+ "ok",
8382
+ "session",
8383
+ "status",
8384
+ "panes",
8385
+ "activity",
8386
+ "refreshedAt"
8387
+ ],
8388
+ "properties": {
8389
+ "ok": {
8390
+ "const": true
8391
+ },
8392
+ "session": {
8393
+ "type": "object"
8394
+ },
8395
+ "status": {
8396
+ "type": "string"
8397
+ },
8398
+ "panes": {
8399
+ "type": "array"
8400
+ },
8401
+ "activity": {
8402
+ "type": "array"
8403
+ },
8404
+ "refreshedAt": {
8405
+ "type": "string"
8406
+ },
8407
+ "locks": {
8408
+ "type": "array",
8409
+ "items": {
8410
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8411
+ }
8412
+ }
8413
+ },
8414
+ "additionalProperties": false
8415
+ },
8416
+ "lockListResult": {
8417
+ "type": "object",
8418
+ "required": [
8419
+ "ok",
8420
+ "locks"
8421
+ ],
8422
+ "properties": {
8423
+ "ok": {
8424
+ "const": true
8425
+ },
8426
+ "locks": {
8427
+ "type": "array",
8428
+ "items": {
8429
+ "type": "object",
8430
+ "required": [
8431
+ "name",
8432
+ "scope",
8433
+ "owner",
8434
+ "acquiredAt",
8435
+ "expiresAt",
8436
+ "ttlMs"
8437
+ ],
8438
+ "properties": {
8439
+ "name": {
8440
+ "type": "string",
8441
+ "minLength": 1
8442
+ },
8443
+ "scope": {
8444
+ "enum": [
8445
+ "session",
8446
+ "global"
8447
+ ]
8448
+ },
8449
+ "sessionId": {
8450
+ "type": "string"
8451
+ },
8452
+ "owner": {
8453
+ "type": "object",
8454
+ "required": [
8455
+ "kind"
8456
+ ],
8457
+ "properties": {
8458
+ "kind": {
8459
+ "enum": [
8460
+ "pane",
8461
+ "external"
8462
+ ]
8463
+ },
8464
+ "paneId": {
8465
+ "type": "string"
8466
+ },
8467
+ "panelId": {
8468
+ "type": "string"
8469
+ },
8470
+ "label": {
8471
+ "type": "string"
8472
+ }
8473
+ },
8474
+ "additionalProperties": false
8475
+ },
8476
+ "note": {
8477
+ "type": "string"
8478
+ },
8479
+ "acquiredAt": {
8480
+ "type": "string"
8481
+ },
8482
+ "expiresAt": {
8483
+ "type": "string"
8484
+ },
8485
+ "ttlMs": {
8486
+ "type": "number"
8487
+ }
8488
+ },
8489
+ "additionalProperties": false
8490
+ }
7224
8491
  }
7225
8492
  },
7226
8493
  "additionalProperties": false
7227
8494
  },
7228
- "sessionResult": {
8495
+ "lockAcquireRequest": {
7229
8496
  "type": "object",
7230
8497
  "required": [
7231
- "ok",
7232
- "session"
8498
+ "name",
8499
+ "ttlMs",
8500
+ "owner"
7233
8501
  ],
7234
8502
  "properties": {
7235
- "ok": {
7236
- "const": true
8503
+ "name": {
8504
+ "type": "string",
8505
+ "minLength": 1
7237
8506
  },
7238
- "session": {
7239
- "type": "object"
8507
+ "ttlMs": {
8508
+ "type": "number"
7240
8509
  },
7241
- "panelId": {
7242
- "type": "string"
8510
+ "waitMs": {
8511
+ "type": "number"
7243
8512
  },
7244
- "internalSessionId": {
8513
+ "note": {
7245
8514
  "type": "string"
8515
+ },
8516
+ "owner": {
8517
+ "type": "object",
8518
+ "properties": {
8519
+ "paneId": {
8520
+ "type": "string"
8521
+ },
8522
+ "panelId": {
8523
+ "type": "string"
8524
+ },
8525
+ "label": {
8526
+ "type": "string"
8527
+ }
8528
+ },
8529
+ "additionalProperties": false
7246
8530
  }
7247
8531
  },
7248
8532
  "additionalProperties": false
7249
8533
  },
7250
- "sessionOverviewResult": {
7251
- "type": "object",
7252
- "required": [
7253
- "ok",
7254
- "session",
7255
- "status",
7256
- "panes",
7257
- "activity",
7258
- "refreshedAt"
7259
- ],
7260
- "properties": {
7261
- "ok": {
7262
- "const": true
7263
- },
7264
- "session": {
7265
- "type": "object"
7266
- },
7267
- "status": {
7268
- "type": "string"
7269
- },
7270
- "panes": {
7271
- "type": "array"
8534
+ "lockAcquireResult": {
8535
+ "oneOf": [
8536
+ {
8537
+ "type": "object",
8538
+ "required": [
8539
+ "ok",
8540
+ "acquired",
8541
+ "renewed",
8542
+ "waitedMs",
8543
+ "lock"
8544
+ ],
8545
+ "properties": {
8546
+ "ok": {
8547
+ "const": true
8548
+ },
8549
+ "acquired": {
8550
+ "const": true
8551
+ },
8552
+ "renewed": {
8553
+ "type": "boolean"
8554
+ },
8555
+ "waitedMs": {
8556
+ "type": "number"
8557
+ },
8558
+ "lock": {
8559
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8560
+ }
8561
+ },
8562
+ "additionalProperties": false
7272
8563
  },
7273
- "activity": {
7274
- "type": "array"
8564
+ {
8565
+ "type": "object",
8566
+ "required": [
8567
+ "ok",
8568
+ "acquired",
8569
+ "timedOut",
8570
+ "waitedMs",
8571
+ "heldBy",
8572
+ "expiresAt",
8573
+ "lock"
8574
+ ],
8575
+ "properties": {
8576
+ "ok": {
8577
+ "const": false
8578
+ },
8579
+ "acquired": {
8580
+ "const": false
8581
+ },
8582
+ "timedOut": {
8583
+ "type": "boolean"
8584
+ },
8585
+ "waitedMs": {
8586
+ "type": "number"
8587
+ },
8588
+ "heldBy": {
8589
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items/properties/owner"
8590
+ },
8591
+ "expiresAt": {
8592
+ "type": "string"
8593
+ },
8594
+ "lock": {
8595
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8596
+ }
8597
+ },
8598
+ "additionalProperties": false
8599
+ }
8600
+ ]
8601
+ },
8602
+ "lockReleaseResult": {
8603
+ "oneOf": [
8604
+ {
8605
+ "type": "object",
8606
+ "required": [
8607
+ "ok",
8608
+ "released",
8609
+ "forced"
8610
+ ],
8611
+ "properties": {
8612
+ "ok": {
8613
+ "const": true
8614
+ },
8615
+ "released": {
8616
+ "type": "boolean"
8617
+ },
8618
+ "forced": {
8619
+ "type": "boolean"
8620
+ },
8621
+ "lock": {
8622
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8623
+ }
8624
+ },
8625
+ "additionalProperties": false
7275
8626
  },
7276
- "refreshedAt": {
7277
- "type": "string"
8627
+ {
8628
+ "type": "object",
8629
+ "required": [
8630
+ "ok",
8631
+ "released",
8632
+ "reason",
8633
+ "heldBy",
8634
+ "expiresAt",
8635
+ "lock"
8636
+ ],
8637
+ "properties": {
8638
+ "ok": {
8639
+ "const": false
8640
+ },
8641
+ "released": {
8642
+ "const": false
8643
+ },
8644
+ "reason": {
8645
+ "const": "not-owner"
8646
+ },
8647
+ "heldBy": {
8648
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items/properties/owner"
8649
+ },
8650
+ "expiresAt": {
8651
+ "type": "string"
8652
+ },
8653
+ "lock": {
8654
+ "$ref": "#/jsonSchemas/lockListResult/properties/locks/items"
8655
+ }
8656
+ },
8657
+ "additionalProperties": false
7278
8658
  }
7279
- },
7280
- "additionalProperties": false
8659
+ ]
7281
8660
  },
7282
8661
  "daemonActionResult": {
7283
8662
  "type": "object",
@@ -7501,44 +8880,252 @@ exports.RUNPANE_CONTRACT = {
7501
8880
  "unknown"
7502
8881
  ]
7503
8882
  },
7504
- "screen": {
7505
- "type": "string"
7506
- },
7507
- "hasUndeliveredText": {
8883
+ "screen": {
8884
+ "type": "string"
8885
+ },
8886
+ "hasUndeliveredText": {
8887
+ "type": "boolean"
8888
+ },
8889
+ "link": {
8890
+ "type": "string"
8891
+ },
8892
+ "report": {
8893
+ "$ref": "#/jsonSchemas/agentReport"
8894
+ }
8895
+ },
8896
+ "additionalProperties": false
8897
+ },
8898
+ "agentSendResult": {
8899
+ "type": "object",
8900
+ "required": [
8901
+ "ok",
8902
+ "paneId",
8903
+ "panelId",
8904
+ "delivered"
8905
+ ],
8906
+ "properties": {
8907
+ "ok": {
8908
+ "type": "boolean"
8909
+ },
8910
+ "paneId": {
8911
+ "type": "string"
8912
+ },
8913
+ "panelId": {
8914
+ "type": "string"
8915
+ },
8916
+ "delivered": {
8917
+ "type": "boolean"
8918
+ },
8919
+ "delivery": {
8920
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/delivery"
8921
+ },
8922
+ "blocked": {
8923
+ "type": "string"
8924
+ },
8925
+ "promptFile": {
8926
+ "type": "string"
8927
+ },
8928
+ "warnings": {
8929
+ "$ref": "#/jsonSchemas/panelSubmitResult/properties/warnings"
8930
+ },
8931
+ "next": {
8932
+ "type": "string"
8933
+ }
8934
+ },
8935
+ "additionalProperties": false
8936
+ },
8937
+ "agentContextUnknownCommandError": {
8938
+ "type": "object",
8939
+ "required": [
8940
+ "ok",
8941
+ "code",
8942
+ "message",
8943
+ "candidates"
8944
+ ],
8945
+ "properties": {
8946
+ "ok": {
8947
+ "const": false
8948
+ },
8949
+ "code": {
8950
+ "const": "unknown_command"
8951
+ },
8952
+ "message": {
8953
+ "type": "string"
8954
+ },
8955
+ "candidates": {
8956
+ "type": "array",
8957
+ "items": {
8958
+ "type": "string"
8959
+ }
8960
+ }
8961
+ },
8962
+ "additionalProperties": false
8963
+ },
8964
+ "reportResult": {
8965
+ "type": "object",
8966
+ "required": [
8967
+ "ok",
8968
+ "paneId",
8969
+ "panelId",
8970
+ "report",
8971
+ "sessionIds"
8972
+ ],
8973
+ "properties": {
8974
+ "ok": {
8975
+ "const": true
8976
+ },
8977
+ "generation": {
8978
+ "type": "number"
8979
+ },
8980
+ "paneId": {
8981
+ "type": "string"
8982
+ },
8983
+ "panelId": {
8984
+ "type": "string"
8985
+ },
8986
+ "report": {
8987
+ "$ref": "#/jsonSchemas/agentReport"
8988
+ },
8989
+ "sessionIds": {
8990
+ "type": "array",
8991
+ "items": {
8992
+ "type": "string"
8993
+ }
8994
+ }
8995
+ },
8996
+ "additionalProperties": false
8997
+ },
8998
+ "paneArchiveBulkRequest": {
8999
+ "type": "object",
9000
+ "required": [
9001
+ "sessionId",
9002
+ "merged"
9003
+ ],
9004
+ "properties": {
9005
+ "sessionId": {
9006
+ "type": "string"
9007
+ },
9008
+ "merged": {
9009
+ "const": true
9010
+ },
9011
+ "source": {
9012
+ "enum": [
9013
+ "user",
9014
+ "agent"
9015
+ ]
9016
+ },
9017
+ "dryRun": {
7508
9018
  "type": "boolean"
7509
9019
  },
7510
- "link": {
7511
- "type": "string"
9020
+ "removeWorktree": {
9021
+ "type": "boolean"
7512
9022
  }
7513
9023
  },
7514
9024
  "additionalProperties": false
7515
9025
  },
7516
- "agentSendResult": {
9026
+ "paneArchiveBulkResult": {
7517
9027
  "type": "object",
7518
9028
  "required": [
7519
9029
  "ok",
7520
- "paneId",
7521
- "panelId",
7522
- "delivered"
9030
+ "sessionId",
9031
+ "merged",
9032
+ "removeWorktree",
9033
+ "archived",
9034
+ "skipped",
9035
+ "failed",
9036
+ "items"
7523
9037
  ],
7524
9038
  "properties": {
7525
9039
  "ok": {
7526
9040
  "type": "boolean"
7527
9041
  },
7528
- "paneId": {
9042
+ "sessionId": {
7529
9043
  "type": "string"
7530
9044
  },
7531
- "panelId": {
7532
- "type": "string"
9045
+ "merged": {
9046
+ "const": true
7533
9047
  },
7534
- "delivered": {
9048
+ "dryRun": {
9049
+ "const": true
9050
+ },
9051
+ "removeWorktree": {
7535
9052
  "type": "boolean"
7536
9053
  },
7537
- "blocked": {
7538
- "type": "string"
9054
+ "archived": {
9055
+ "type": "number",
9056
+ "description": "Panes archived, or that would be archived with --dry-run."
7539
9057
  },
7540
- "next": {
7541
- "type": "string"
9058
+ "skipped": {
9059
+ "type": "number"
9060
+ },
9061
+ "failed": {
9062
+ "type": "number"
9063
+ },
9064
+ "items": {
9065
+ "type": "array",
9066
+ "items": {
9067
+ "type": "object",
9068
+ "required": [
9069
+ "paneId",
9070
+ "outcome"
9071
+ ],
9072
+ "properties": {
9073
+ "paneId": {
9074
+ "type": "string"
9075
+ },
9076
+ "name": {
9077
+ "type": "string"
9078
+ },
9079
+ "outcome": {
9080
+ "enum": [
9081
+ "archived",
9082
+ "would-archive",
9083
+ "skipped",
9084
+ "failed"
9085
+ ]
9086
+ },
9087
+ "skipped": {
9088
+ "type": "object",
9089
+ "required": [
9090
+ "code",
9091
+ "message"
9092
+ ],
9093
+ "properties": {
9094
+ "code": {
9095
+ "enum": [
9096
+ "uncommitted-changes",
9097
+ "unpushed-commits",
9098
+ "uncommitted-and-unpushed",
9099
+ "status-unknown",
9100
+ "missing-pane",
9101
+ "already-archived",
9102
+ "main-repo"
9103
+ ]
9104
+ },
9105
+ "message": {
9106
+ "type": "string"
9107
+ }
9108
+ },
9109
+ "additionalProperties": false
9110
+ },
9111
+ "error": {
9112
+ "type": "string"
9113
+ },
9114
+ "safetyCheck": {
9115
+ "$ref": "#/jsonSchemas/paneArchiveResult/oneOf/0/properties/safetyCheck"
9116
+ },
9117
+ "worktreeCleanup": {
9118
+ "$ref": "#/jsonSchemas/paneArchiveResult/oneOf/0/properties/worktreeCleanup"
9119
+ },
9120
+ "trashDeletion": {
9121
+ "$ref": "#/jsonSchemas/paneArchiveResult/oneOf/0/properties/trashDeletion"
9122
+ },
9123
+ "worktreePath": {
9124
+ "type": "string"
9125
+ }
9126
+ },
9127
+ "additionalProperties": false
9128
+ }
7542
9129
  }
7543
9130
  },
7544
9131
  "additionalProperties": false
@@ -7551,7 +9138,7 @@ exports.RUNPANE_CONTRACT = {
7551
9138
  "rules": [
7552
9139
  "Start with `runpane doctor --json` to understand wrapper, platform, daemon reachability, and the next safe commands before mutating Pane state.",
7553
9140
  "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`.",
7554
- "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.",
9141
+ "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.",
7555
9142
  "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.",
7556
9143
  "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.",
7557
9144
  "Use `panes create` for separate visible Panes (Pane sessions) for feature/PR work. Pane creates and owns the worktree/branch for each new Pane.",
@@ -7569,7 +9156,8 @@ exports.RUNPANE_CONTRACT = {
7569
9156
  "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.",
7570
9157
  "Use `runpane panels input` only when exact bytes are required, such as Ctrl-C or handcrafted terminal input.",
7571
9158
  "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`.",
7572
- "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."
9159
+ "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.",
9160
+ "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."
7573
9161
  ],
7574
9162
  "detailCommand": "runpane agent-context --command <command> [--json]",
7575
9163
  "tools": [
@@ -7664,11 +9252,14 @@ exports.RUNPANE_CONTRACT = {
7664
9252
  },
7665
9253
  {
7666
9254
  "name": "panes archive",
7667
- "summary": "Archive a Pane exactly like the UI Archive action, including safe removal of its Pane-managed git worktree.",
9255
+ "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.",
7668
9256
  "arguments": [
7669
9257
  "--pane <pane-id>",
9258
+ "--session <id|name>",
9259
+ "--merged",
7670
9260
  "--source <user|agent>",
7671
9261
  "--force",
9262
+ "--remove-worktree",
7672
9263
  "--dry-run",
7673
9264
  "--yes",
7674
9265
  "--json"
@@ -7786,10 +9377,10 @@ exports.RUNPANE_CONTRACT = {
7786
9377
  },
7787
9378
  {
7788
9379
  "name": "panels submit-composer",
7789
- "summary": "Submit an agent composer with the correct key sequence, including Ctrl+Enter for Codex.",
9380
+ "summary": "Submit an agent composer with the key for its current state.",
7790
9381
  "arguments": [
7791
9382
  "--panel <panel-id>",
7792
- "--strategy <auto|codex-ctrl-enter|enter>",
9383
+ "--strategy <auto|codex-ctrl-enter|enter|tab>",
7793
9384
  "--yes",
7794
9385
  "--json"
7795
9386
  ]
@@ -7809,9 +9400,10 @@ exports.RUNPANE_CONTRACT = {
7809
9400
  },
7810
9401
  {
7811
9402
  "name": "watch",
7812
- "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.",
9403
+ "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.",
7813
9404
  "arguments": [
7814
9405
  "--follow",
9406
+ "--session <id|name>",
7815
9407
  "--self-test",
7816
9408
  "--kinds <kind,...>",
7817
9409
  "--settle <ms>",
@@ -7944,6 +9536,12 @@ exports.RUNPANE_CONTRACT = {
7944
9536
  "value": "<path>",
7945
9537
  "required": false,
7946
9538
  "description": "Ignored for version; retained only for parser compatibility."
9539
+ },
9540
+ {
9541
+ "name": "--pane-dir",
9542
+ "value": "<path>",
9543
+ "required": false,
9544
+ "description": "Accepted and ignored, so one --pane-dir can be passed to every runpane command."
7947
9545
  }
7948
9546
  ],
7949
9547
  "examples": [
@@ -8089,11 +9687,14 @@ exports.RUNPANE_CONTRACT = {
8089
9687
  ],
8090
9688
  "jsonSchemas": [
8091
9689
  "agentContextBriefResult",
8092
- "agentContextCommandResult"
9690
+ "agentContextCommandResult",
9691
+ "agentContextUnknownCommandError"
8093
9692
  ],
8094
9693
  "notes": [
8095
9694
  "Default output is brief so AGENTS.md can point here without bloating context.",
8096
- "`--command` accepts canonical spaced names and common copied forms, including `panes.create` and `runpane panes create`."
9695
+ "`--command` accepts canonical spaced names and common copied forms, including `panes.create` and `runpane panes create`.",
9696
+ "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.",
9697
+ "`--pane-dir <path>` is accepted and ignored, so one `--pane-dir` can be passed to every runpane command."
8097
9698
  ]
8098
9699
  },
8099
9700
  "mcp": {
@@ -8240,7 +9841,8 @@ exports.RUNPANE_CONTRACT = {
8240
9841
  "paneListResult"
8241
9842
  ],
8242
9843
  "notes": [
8243
- "Without --repo, this lists sessions across saved Pane repositories."
9844
+ "Without --repo, this lists sessions across saved Pane repositories.",
9845
+ "`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."
8244
9846
  ]
8245
9847
  },
8246
9848
  "panes cost": {
@@ -8306,11 +9908,23 @@ exports.RUNPANE_CONTRACT = {
8306
9908
  "required": true,
8307
9909
  "description": "Pane/session name."
8308
9910
  },
9911
+ {
9912
+ "name": "--base-branch",
9913
+ "value": "<branch>",
9914
+ "required": false,
9915
+ "description": "Branch the new worktree from this ref (for example origin/main or release/2.4) instead of the repository default."
9916
+ },
9917
+ {
9918
+ "name": "--worktree-name",
9919
+ "value": "<name>",
9920
+ "required": false,
9921
+ "description": "Worktree and branch name; defaults to --name. Characters outside [a-z0-9-] are removed."
9922
+ },
8309
9923
  {
8310
9924
  "name": "--agent",
8311
9925
  "value": "<codex|claude|cursor>",
8312
9926
  "required": false,
8313
- "description": "Built-in agent terminal template to open."
9927
+ "description": "Built-in agent terminal template to open. With --tool-command, the agent that command runs."
8314
9928
  },
8315
9929
  {
8316
9930
  "name": "--tool-command",
@@ -8318,6 +9932,24 @@ exports.RUNPANE_CONTRACT = {
8318
9932
  "required": false,
8319
9933
  "description": "Custom terminal command to run instead of a built-in agent."
8320
9934
  },
9935
+ {
9936
+ "name": "--base-branch",
9937
+ "value": "<ref>",
9938
+ "required": false,
9939
+ "description": "Ref to branch from, such as origin/main or release/foo. --base is an alias."
9940
+ },
9941
+ {
9942
+ "name": "--branch",
9943
+ "value": "<name>",
9944
+ "required": false,
9945
+ "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."
9946
+ },
9947
+ {
9948
+ "name": "--worktree-name",
9949
+ "value": "<name>",
9950
+ "required": false,
9951
+ "description": "Worktree directory name; defaults to --name."
9952
+ },
8321
9953
  {
8322
9954
  "name": "--prompt",
8323
9955
  "value": "<text>",
@@ -8328,7 +9960,12 @@ exports.RUNPANE_CONTRACT = {
8328
9960
  "name": "--initial-input-file",
8329
9961
  "value": "<path|->",
8330
9962
  "required": false,
8331
- "description": "Read initial input from a file or stdin."
9963
+ "description": "Read initial input from a file or stdin. --prompt-file is an alias."
9964
+ },
9965
+ {
9966
+ "name": "--as-file-pointer",
9967
+ "required": false,
9968
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
8332
9969
  },
8333
9970
  {
8334
9971
  "name": "--from-json",
@@ -8398,12 +10035,20 @@ exports.RUNPANE_CONTRACT = {
8398
10035
  "value": "<count>",
8399
10036
  "required": false,
8400
10037
  "description": "Accepted for compatibility. Pane currently serializes multi-pane session creation so queued jobs do not time out before starting."
10038
+ },
10039
+ {
10040
+ "name": "--pane-dir",
10041
+ "value": "<path>",
10042
+ "required": false,
10043
+ "description": "Connect to a specific Pane data directory."
8401
10044
  }
8402
10045
  ],
8403
10046
  "examples": [
8404
10047
  "runpane panes create --repo active --name issue-257 --agent <agent> --prompt \"Plan this issue\" --source agent --no-focus --wait-ready --yes --json",
10048
+ "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",
8405
10049
  "runpane panes create --from-json panes.json --yes --json",
8406
- "runpane panes create --repo active --name issue-123 --agent <agent> --prompt \"Plan this issue\" --source agent --no-focus --wait-ready --yes --json"
10050
+ "runpane panes create --repo active --name issue-123 --agent <agent> --prompt \"Plan this issue\" --source agent --no-focus --wait-ready --yes --json",
10051
+ "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"
8407
10052
  ],
8408
10053
  "jsonSchemas": [
8409
10054
  "paneCreateRequest",
@@ -8413,11 +10058,14 @@ exports.RUNPANE_CONTRACT = {
8413
10058
  "At least one of --agent or --tool-command is required unless --from-json is used.",
8414
10059
  "`panes create` is for user-visible Pane orchestration, not the agent's default private delegation mechanism.",
8415
10060
  "Register the saved base repository once. Pane creates and owns the worktree/branch for each new Pane.",
10061
+ "`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.",
8416
10062
  "Use `panels create` instead when a reviewer/helper should share an existing Pane's worktree.",
8417
10063
  "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.",
8418
10064
  "The built-in agent templates come from the runpane contract; custom terminal commands can pass agent-specific flags when requested by the user.",
8419
- "Use --initial-input-file for multi-line prompts or shell-sensitive initial input.",
8420
- "With --wait-ready, verifiedSubmitted is earned from delivery evidence; routing initial input alone does not imply verified submission.",
10065
+ "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.",
10066
+ "`--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.",
10067
+ "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.",
10068
+ "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.",
8421
10069
  "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.",
8422
10070
  "When the JSON result includes nextCommand, run it to validate that the terminal produced output before reporting success.",
8423
10071
  "Multi-pane requests are created sequentially today. The --concurrency flag is accepted for compatibility, but agents should not rely on parallel creation.",
@@ -8425,7 +10073,8 @@ exports.RUNPANE_CONTRACT = {
8425
10073
  "For Windows PowerShell command chaining, use a custom terminal command like `powershell -NoProfile -Command \"cmd1; if ($LASTEXITCODE) { exit $LASTEXITCODE }; cmd2\"`.",
8426
10074
  "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'`.",
8427
10075
  "Use --wait-ready when an agent needs to verify that an agent terminal started instead of only creating a pane.",
8428
- "If readiness returns blocked, inspect blocked.suggestedCommand rather than guessing which prompt to answer."
10076
+ "If readiness returns blocked, inspect blocked.suggestedCommand rather than guessing which prompt to answer.",
10077
+ "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."
8429
10078
  ]
8430
10079
  },
8431
10080
  "panes adopt": {
@@ -8456,8 +10105,14 @@ exports.RUNPANE_CONTRACT = {
8456
10105
  {
8457
10106
  "name": "--agent",
8458
10107
  "value": "<codex|claude|cursor>",
8459
- "required": true,
8460
- "description": "Agent whose terminal to create."
10108
+ "required": false,
10109
+ "description": "Agent whose terminal to create; with --tool-command, the agent that command runs."
10110
+ },
10111
+ {
10112
+ "name": "--tool-command",
10113
+ "value": "<command>",
10114
+ "required": false,
10115
+ "description": "Custom command to stage or launch instead of a built-in agent, such as a wrapper that runs one."
8461
10116
  },
8462
10117
  {
8463
10118
  "name": "--resume",
@@ -8474,7 +10129,30 @@ exports.RUNPANE_CONTRACT = {
8474
10129
  {
8475
10130
  "name": "--launch",
8476
10131
  "required": false,
8477
- "description": "Run the resume command immediately."
10132
+ "description": "Run the agent (or its resume command) immediately."
10133
+ },
10134
+ {
10135
+ "name": "--prompt",
10136
+ "value": "<text>",
10137
+ "required": false,
10138
+ "description": "Alias for --initial-input; sent once the launched agent is ready. Requires --launch."
10139
+ },
10140
+ {
10141
+ "name": "--prompt-file",
10142
+ "value": "<path|->",
10143
+ "required": false,
10144
+ "description": "Alias for --initial-input-file; read the prompt from a file or stdin. Requires --launch."
10145
+ },
10146
+ {
10147
+ "name": "--wait-ready",
10148
+ "required": false,
10149
+ "description": "Wait for the launched agent to be ready and the prompt submitted before returning. Requires --launch."
10150
+ },
10151
+ {
10152
+ "name": "--ready-timeout-ms",
10153
+ "value": "<ms>",
10154
+ "required": false,
10155
+ "description": "Readiness timeout; defaults to 30000."
8478
10156
  },
8479
10157
  {
8480
10158
  "name": "--no-pinned",
@@ -8500,31 +10178,46 @@ exports.RUNPANE_CONTRACT = {
8500
10178
  "name": "--json",
8501
10179
  "required": false,
8502
10180
  "description": "Print machine-readable output."
10181
+ },
10182
+ {
10183
+ "name": "--pane-dir",
10184
+ "value": "<path>",
10185
+ "required": false,
10186
+ "description": "Connect to a specific Pane data directory."
8503
10187
  }
8504
10188
  ],
8505
10189
  "examples": [
8506
- "runpane panes adopt --repo active --path /path/to/worktree --name imported --agent codex --resume <id> --yes --json"
10190
+ "runpane panes adopt --repo active --path /path/to/worktree --name imported --agent codex --resume <id> --yes --json",
10191
+ "runpane panes adopt --repo active --path /path/to/worktree --name imported --tool-command \"agent-farm run free-range\" --agent claude --launch --yes --json",
10192
+ "runpane panes adopt --repo active --path /path/to/worktree --name imported --agent claude --launch --prompt-file prompt.md --wait-ready --yes --json"
8507
10193
  ],
8508
10194
  "jsonSchemas": [
8509
10195
  "paneCreateResult"
8510
10196
  ],
8511
10197
  "notes": [
8512
10198
  "The resume command is staged without Enter unless --launch is passed.",
8513
- "Pane never removes an externally owned worktree."
10199
+ "Archiving never deletes an adopted worktree unless `runpane panes archive --remove-worktree` is used.",
10200
+ "One of --agent or --tool-command is required.",
10201
+ "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.",
10202
+ "--resume needs a built-in agent command; a wrapper command resumes its own way.",
10203
+ "The adopted Pane reports `status: running` in `panes list` while its terminal is live.",
10204
+ "A prompt (--prompt, --initial-input, --prompt-file, --initial-input-file) or --wait-ready needs --launch; without it adopt fails instead of dropping the prompt.",
10205
+ "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.",
10206
+ "To start new work on a named branch, prefer `panes create --base <ref> --branch <name>` over `git worktree add` plus adopt."
8514
10207
  ]
8515
10208
  },
8516
10209
  "panes archive": {
8517
10210
  "name": "panes archive",
8518
- "summary": "Archive a Pane (session) exactly like the UI Archive action, including safe removal of its Pane-managed git worktree.",
8519
- "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.",
10211
+ "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.",
10212
+ "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.",
8520
10213
  "requiresPaneDaemon": true,
8521
10214
  "mutates": true,
8522
10215
  "arguments": [
8523
10216
  {
8524
10217
  "name": "--pane",
8525
10218
  "value": "<pane-id>",
8526
- "required": true,
8527
- "description": "Pane/session id to archive."
10219
+ "required": false,
10220
+ "description": "Pane/session id to archive. Required unless --session is used."
8528
10221
  },
8529
10222
  {
8530
10223
  "name": "--source",
@@ -8537,6 +10230,22 @@ exports.RUNPANE_CONTRACT = {
8537
10230
  "required": false,
8538
10231
  "description": "Archive even if the pane's branch has uncommitted, untracked, or unpushed changes."
8539
10232
  },
10233
+ {
10234
+ "name": "--remove-worktree",
10235
+ "required": false,
10236
+ "description": "Also check and remove an adopted Pane's worktree. Pane-managed worktrees are always removed; the local branch is always kept."
10237
+ },
10238
+ {
10239
+ "name": "--session",
10240
+ "value": "<id|name>",
10241
+ "required": false,
10242
+ "description": "Archive the Panes associated with this named Session instead of one Pane. Requires --merged."
10243
+ },
10244
+ {
10245
+ "name": "--merged",
10246
+ "required": false,
10247
+ "description": "With --session, archive only Panes that are clean and pushed, or merged via a pull request; skip the rest with a reason."
10248
+ },
8540
10249
  {
8541
10250
  "name": "--yes",
8542
10251
  "required": false,
@@ -8551,24 +10260,39 @@ exports.RUNPANE_CONTRACT = {
8551
10260
  "name": "--json",
8552
10261
  "required": false,
8553
10262
  "description": "Print machine-readable output."
10263
+ },
10264
+ {
10265
+ "name": "--pane-dir",
10266
+ "value": "<path>",
10267
+ "required": false,
10268
+ "description": "Connect to a specific Pane data directory."
8554
10269
  }
8555
10270
  ],
8556
10271
  "examples": [
8557
10272
  "runpane panes archive --pane <pane-id> --source agent --yes --json",
8558
10273
  "runpane panes archive --pane <pane-id> --dry-run --json",
10274
+ "runpane panes archive --pane <pane-id> --remove-worktree --yes --json",
10275
+ "runpane panes archive --session <id|name> --merged --dry-run --json",
10276
+ "runpane panes archive --session <id|name> --merged --remove-worktree --yes --json",
8559
10277
  "runpane panes archive --pane <pane-id> --force --yes --json"
8560
10278
  ],
8561
10279
  "jsonSchemas": [
8562
10280
  "paneArchiveRequest",
8563
- "paneArchiveResult"
10281
+ "paneArchiveBulkRequest",
10282
+ "paneArchiveResult",
10283
+ "paneArchiveBulkResult"
8564
10284
  ],
8565
10285
  "notes": [
8566
10286
  "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.",
8567
10287
  "Inspect safetyCheck.unpushedCommitDetails for exact commit IDs and subjects; upstreamRefreshed confirms the tracking ref was refreshed first.",
8568
10288
  "A --dry-run result sets dryRun:true and wouldArchive without deleting the Pane or its worktree.",
8569
- "A successful archive waits for the Pane-managed worktree to be removed before returning; check worktreeCleanup in the result for the final outcome.",
10289
+ "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.",
10290
+ "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.",
10291
+ "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.",
10292
+ "With --session --merged, each item has outcome archived, would-archive (dry run), skipped (with skipped.code and skipped.message), or failed.",
8570
10293
  "Archiving a main-repo Pane (no Pane-managed worktree) always succeeds immediately since nothing is deleted from disk.",
8571
- "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."
10294
+ "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.",
10295
+ "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."
8572
10296
  ]
8573
10297
  },
8574
10298
  "panes pin": {
@@ -8598,6 +10322,12 @@ exports.RUNPANE_CONTRACT = {
8598
10322
  "name": "--json",
8599
10323
  "required": false,
8600
10324
  "description": "Print machine-readable output."
10325
+ },
10326
+ {
10327
+ "name": "--pane-dir",
10328
+ "value": "<path>",
10329
+ "required": false,
10330
+ "description": "Connect to a specific Pane data directory."
8601
10331
  }
8602
10332
  ],
8603
10333
  "examples": [
@@ -8640,6 +10370,12 @@ exports.RUNPANE_CONTRACT = {
8640
10370
  "name": "--json",
8641
10371
  "required": false,
8642
10372
  "description": "Print machine-readable output."
10373
+ },
10374
+ {
10375
+ "name": "--pane-dir",
10376
+ "value": "<path>",
10377
+ "required": false,
10378
+ "description": "Connect to a specific Pane data directory."
8643
10379
  }
8644
10380
  ],
8645
10381
  "examples": [
@@ -8688,6 +10424,12 @@ exports.RUNPANE_CONTRACT = {
8688
10424
  "name": "--json",
8689
10425
  "required": false,
8690
10426
  "description": "Print machine-readable output including the updated pane."
10427
+ },
10428
+ {
10429
+ "name": "--pane-dir",
10430
+ "value": "<path>",
10431
+ "required": false,
10432
+ "description": "Connect to a specific Pane data directory."
8691
10433
  }
8692
10434
  ],
8693
10435
  "examples": [
@@ -8737,6 +10479,12 @@ exports.RUNPANE_CONTRACT = {
8737
10479
  "name": "--json",
8738
10480
  "required": false,
8739
10481
  "description": "Print machine-readable output."
10482
+ },
10483
+ {
10484
+ "name": "--pane-dir",
10485
+ "value": "<path>",
10486
+ "required": false,
10487
+ "description": "Connect to a specific Pane data directory."
8740
10488
  }
8741
10489
  ],
8742
10490
  "examples": [
@@ -8785,7 +10533,8 @@ exports.RUNPANE_CONTRACT = {
8785
10533
  "panelListResult"
8786
10534
  ],
8787
10535
  "notes": [
8788
- "The ids returned here are stable inputs for `panels output` and `panels input`."
10536
+ "The ids returned here are stable inputs for `panels output` and `panels input`.",
10537
+ "`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."
8789
10538
  ]
8790
10539
  },
8791
10540
  "panels output": {
@@ -8981,14 +10730,14 @@ exports.RUNPANE_CONTRACT = {
8981
10730
  ],
8982
10731
  "notes": [
8983
10732
  "Use this before `panels output` when an agent only needs the latest visible/current state.",
8984
- "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.",
10733
+ "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⟩`.",
8985
10734
  "If hasMore is true and context is missing, rerun with a larger --limit or use `panels output`."
8986
10735
  ]
8987
10736
  },
8988
10737
  "panels submit": {
8989
10738
  "name": "panels submit",
8990
10739
  "summary": "Send and submit text to a terminal panel, including idle agent composers.",
8991
- "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`.",
10740
+ "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`.",
8992
10741
  "requiresPaneDaemon": true,
8993
10742
  "mutates": true,
8994
10743
  "arguments": [
@@ -9010,6 +10759,11 @@ exports.RUNPANE_CONTRACT = {
9010
10759
  "required": false,
9011
10760
  "description": "Read text from a file or stdin before Enter."
9012
10761
  },
10762
+ {
10763
+ "name": "--as-file-pointer",
10764
+ "required": false,
10765
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
10766
+ },
9013
10767
  {
9014
10768
  "name": "--yes",
9015
10769
  "required": false,
@@ -9029,16 +10783,20 @@ exports.RUNPANE_CONTRACT = {
9029
10783
  ],
9030
10784
  "examples": [
9031
10785
  "runpane panels submit --panel <panel-id> --text \"2\" --yes --json",
9032
- "printf \"echo hello\" | runpane panels submit --panel <panel-id> --input-file - --yes --json"
10786
+ "printf \"echo hello\" | runpane panels submit --panel <panel-id> --input-file - --yes --json",
10787
+ "runpane panels submit --panel <panel-id> --input-file brief.md --as-file-pointer --yes --json"
9033
10788
  ],
9034
10789
  "jsonSchemas": [
9035
10790
  "panelSubmitRequest",
9036
10791
  "panelSubmitResult"
9037
10792
  ],
9038
10793
  "notes": [
9039
- "The response includes sequenceName, verifiedSubmitted, and nextCommand. If ok is false, inspect blocked and do not assume the turn started.",
9040
- "Do not follow `panels submit` with `panels submit-composer`; Claude and idle Codex composer submission is handled atomically.",
9041
- "Use `panels input` for Ctrl-C, escape sequences, or any workflow requiring exact bytes."
10794
+ "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.",
10795
+ "Do not follow `panels submit` with `panels submit-composer`; Claude and Codex composer submission is handled atomically.",
10796
+ "Use `panels input` for Ctrl-C, escape sequences, or any workflow requiring exact bytes.",
10797
+ "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`.",
10798
+ "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.",
10799
+ "`--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."
9042
10800
  ]
9043
10801
  },
9044
10802
  "panels wait": {
@@ -9102,6 +10860,48 @@ exports.RUNPANE_CONTRACT = {
9102
10860
  "The default timeout and screen are intentionally small for agent context safety."
9103
10861
  ]
9104
10862
  },
10863
+ "panels last-message": {
10864
+ "name": "panels last-message",
10865
+ "summary": "Read an agent's last reply from its transcript, without scraping the screen.",
10866
+ "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.",
10867
+ "requiresPaneDaemon": true,
10868
+ "mutates": false,
10869
+ "arguments": [
10870
+ {
10871
+ "name": "--panel",
10872
+ "value": "<panel-id>",
10873
+ "required": true,
10874
+ "description": "Agent panel id."
10875
+ },
10876
+ {
10877
+ "name": "--limit",
10878
+ "value": "<count>",
10879
+ "required": false,
10880
+ "description": "Maximum characters to return; defaults to 20000. The end of the reply is kept."
10881
+ },
10882
+ {
10883
+ "name": "--json",
10884
+ "required": false,
10885
+ "description": "Print machine-readable output."
10886
+ },
10887
+ {
10888
+ "name": "--pane-dir",
10889
+ "value": "<path>",
10890
+ "required": false,
10891
+ "description": "Connect to a specific Pane data directory."
10892
+ }
10893
+ ],
10894
+ "examples": [
10895
+ "runpane panels last-message --panel <panel-id> --json"
10896
+ ],
10897
+ "jsonSchemas": [
10898
+ "panelLastMessageResult"
10899
+ ],
10900
+ "notes": [
10901
+ "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.",
10902
+ "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."
10903
+ ]
10904
+ },
9105
10905
  "panels create": {
9106
10906
  "name": "panels create",
9107
10907
  "summary": "Create a reviewer/helper terminal tab inside an existing Pane.",
@@ -9119,7 +10919,7 @@ exports.RUNPANE_CONTRACT = {
9119
10919
  "name": "--agent",
9120
10920
  "value": "<codex|claude|cursor>",
9121
10921
  "required": false,
9122
- "description": "Built-in agent command template to launch."
10922
+ "description": "Built-in agent command template to launch. With --tool-command, the agent that command runs."
9123
10923
  },
9124
10924
  {
9125
10925
  "name": "--tool-command",
@@ -9145,6 +10945,11 @@ exports.RUNPANE_CONTRACT = {
9145
10945
  "required": false,
9146
10946
  "description": "Read initial input from a file or stdin."
9147
10947
  },
10948
+ {
10949
+ "name": "--as-file-pointer",
10950
+ "required": false,
10951
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
10952
+ },
9148
10953
  {
9149
10954
  "name": "--source",
9150
10955
  "value": "<user|agent>",
@@ -9181,11 +10986,18 @@ exports.RUNPANE_CONTRACT = {
9181
10986
  "name": "--json",
9182
10987
  "required": false,
9183
10988
  "description": "Print machine-readable output."
10989
+ },
10990
+ {
10991
+ "name": "--pane-dir",
10992
+ "value": "<path>",
10993
+ "required": false,
10994
+ "description": "Connect to a specific Pane data directory."
9184
10995
  }
9185
10996
  ],
9186
10997
  "examples": [
9187
10998
  "runpane panels create --pane <pane-id> --agent <agent> --source agent --no-focus --wait-ready --yes --json",
9188
- "runpane panels create --pane <pane-id> --tool-command <command> --title <title> --source agent --no-focus --wait-ready --yes --json"
10999
+ "runpane panels create --pane <pane-id> --tool-command <command> --title <title> --source agent --no-focus --wait-ready --yes --json",
11000
+ "runpane panels create --pane <pane-id> --tool-command \"agent-farm run free-range\" --agent claude --source agent --no-focus --wait-ready --yes --json"
9189
11001
  ],
9190
11002
  "jsonSchemas": [
9191
11003
  "panelCreateRequest",
@@ -9195,13 +11007,14 @@ exports.RUNPANE_CONTRACT = {
9195
11007
  "Use this for same-pane reviewer loops after PR creation/testing.",
9196
11008
  "Panels share the existing Pane's worktree and branch.",
9197
11009
  "`panels create` is for visible helper/reviewer tabs, not the agent's default private delegation mechanism.",
9198
- "For agent-created panels, prefer --source agent or --no-focus to avoid stealing focus from the user or implementation tab."
11010
+ "For agent-created panels, prefer --source agent or --no-focus to avoid stealing focus from the user or implementation tab.",
11011
+ "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."
9199
11012
  ]
9200
11013
  },
9201
11014
  "panels submit-composer": {
9202
11015
  "name": "panels submit-composer",
9203
11016
  "summary": "Submit an agent composer using the panel-appropriate key sequence.",
9204
- "details": "Use this after sending text into an agent composer when plain Enter is not the right submit action. Agents should use --strategy auto; Pane owns per-agent submit sequences internally and verifies visible composer state when possible.",
11017
+ "details": "Use this after sending text into an agent composer. Auto uses Tab to queue while Codex is working and Enter when ready; Pane verifies that the text left the composer.",
9205
11018
  "requiresPaneDaemon": true,
9206
11019
  "mutates": true,
9207
11020
  "arguments": [
@@ -9213,7 +11026,7 @@ exports.RUNPANE_CONTRACT = {
9213
11026
  },
9214
11027
  {
9215
11028
  "name": "--strategy",
9216
- "value": "<auto|codex-ctrl-enter|enter>",
11029
+ "value": "<auto|codex-ctrl-enter|enter|tab>",
9217
11030
  "required": false,
9218
11031
  "description": "Composer submit key sequence strategy."
9219
11032
  },
@@ -9226,6 +11039,12 @@ exports.RUNPANE_CONTRACT = {
9226
11039
  "name": "--json",
9227
11040
  "required": false,
9228
11041
  "description": "Print machine-readable output."
11042
+ },
11043
+ {
11044
+ "name": "--pane-dir",
11045
+ "value": "<path>",
11046
+ "required": false,
11047
+ "description": "Connect to a specific Pane data directory."
9229
11048
  }
9230
11049
  ],
9231
11050
  "examples": [
@@ -9239,7 +11058,8 @@ exports.RUNPANE_CONTRACT = {
9239
11058
  "notes": [
9240
11059
  "Use `panels input` or `panels submit` to write prompt text first; this command only submits the current composer.",
9241
11060
  "Use --strategy auto for agent workflows; explicit strategies are diagnostic escape hatches.",
9242
- "The JSON result includes sequenceName and verifiedSubmitted. If ok is false, follow blocked.suggestedCommand instead of assuming submission happened."
11061
+ "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.",
11062
+ "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."
9243
11063
  ]
9244
11064
  },
9245
11065
  "workspace state": {
@@ -9259,6 +11079,12 @@ exports.RUNPANE_CONTRACT = {
9259
11079
  "name": "--json",
9260
11080
  "required": false,
9261
11081
  "description": "Print machine-readable output."
11082
+ },
11083
+ {
11084
+ "name": "--pane-dir",
11085
+ "value": "<path>",
11086
+ "required": false,
11087
+ "description": "Connect to a specific Pane data directory."
9262
11088
  }
9263
11089
  ],
9264
11090
  "examples": [
@@ -9279,7 +11105,7 @@ exports.RUNPANE_CONTRACT = {
9279
11105
  "name": "--as",
9280
11106
  "value": "<consumer-name>",
9281
11107
  "required": false,
9282
- "description": "Use a persisted named cursor (at-least-once delivery). Default: PANE_PANEL_ID under --follow when set, otherwise anonymous."
11108
+ "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."
9283
11109
  },
9284
11110
  {
9285
11111
  "name": "--since",
@@ -9308,7 +11134,7 @@ exports.RUNPANE_CONTRACT = {
9308
11134
  "name": "--heartbeat",
9309
11135
  "value": "<seconds>",
9310
11136
  "required": false,
9311
- "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."
11137
+ "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."
9312
11138
  },
9313
11139
  {
9314
11140
  "name": "--idle-after",
@@ -9320,19 +11146,19 @@ exports.RUNPANE_CONTRACT = {
9320
11146
  "name": "--settle",
9321
11147
  "value": "<milliseconds>",
9322
11148
  "required": false,
9323
- "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."
11149
+ "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."
9324
11150
  },
9325
11151
  {
9326
11152
  "name": "--blocked-settle",
9327
11153
  "value": "<milliseconds>",
9328
11154
  "required": false,
9329
- "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."
11155
+ "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."
9330
11156
  },
9331
11157
  {
9332
11158
  "name": "--min-interval",
9333
11159
  "value": "<milliseconds>",
9334
11160
  "required": false,
9335
- "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."
11161
+ "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."
9336
11162
  },
9337
11163
  {
9338
11164
  "name": "--idle-backoff",
@@ -9343,13 +11169,19 @@ exports.RUNPANE_CONTRACT = {
9343
11169
  "name": "--kinds",
9344
11170
  "required": false,
9345
11171
  "value": "<kind,...>",
9346
- "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."
11172
+ "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."
9347
11173
  },
9348
11174
  {
9349
11175
  "name": "--pane",
9350
11176
  "required": false,
9351
11177
  "value": "<pane-id>",
9352
- "description": "Limit to a Pane; repeatable. Default all managed panes."
11178
+ "description": "Limit to a Pane; repeatable. Default all managed panes. Cannot be combined with --session."
11179
+ },
11180
+ {
11181
+ "name": "--session",
11182
+ "required": false,
11183
+ "value": "<id|name>",
11184
+ "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."
9353
11185
  },
9354
11186
  {
9355
11187
  "name": "--exclude-pane",
@@ -9377,7 +11209,7 @@ exports.RUNPANE_CONTRACT = {
9377
11209
  {
9378
11210
  "name": "--all-managed",
9379
11211
  "required": false,
9380
- "description": "Explicit spelling for the all-managed default scope."
11212
+ "description": "Explicit spelling of the default scope: every non-archived, non-hidden managed Pane. Cannot be combined with --pane."
9381
11213
  },
9382
11214
  {
9383
11215
  "name": "--include-shells",
@@ -9404,12 +11236,12 @@ exports.RUNPANE_CONTRACT = {
9404
11236
  {
9405
11237
  "name": "--include-held-input",
9406
11238
  "required": false,
9407
- "description": "Include up to 120 characters of unsubmitted composer text in JSON entries. Default off (presence only)."
11239
+ "description": "Include up to 120 characters of unsubmitted composer text in JSON entries. Default off: under --follow, JSON entries carry only heldInputPresent: true."
9408
11240
  },
9409
11241
  {
9410
11242
  "name": "--no-held-input",
9411
11243
  "required": false,
9412
- "description": "Disable redacted STUCK detection in lines follow mode."
11244
+ "description": "Disable redacted held-input detection under --follow: no STUCK lines, and no heldInputPresent in JSON."
9413
11245
  },
9414
11246
  {
9415
11247
  "name": "--self-test",
@@ -9417,26 +11249,55 @@ exports.RUNPANE_CONTRACT = {
9417
11249
  "description": "Probe the watch path anonymously without advancing a named cursor; run it before arming --follow."
9418
11250
  },
9419
11251
  {
9420
- "name": "--json",
11252
+ "name": "--quiet",
11253
+ "required": false,
11254
+ "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."
11255
+ },
11256
+ {
11257
+ "name": "--json",
11258
+ "required": false,
11259
+ "description": "Emit structured NDJSON; held-input content remains opt-in."
11260
+ },
11261
+ {
11262
+ "name": "--pane-dir",
11263
+ "value": "<path>",
11264
+ "required": false,
11265
+ "description": "Connect to a specific Pane data directory."
11266
+ },
11267
+ {
11268
+ "name": "--pane-dir",
11269
+ "value": "<path>",
9421
11270
  "required": false,
9422
- "description": "Emit structured NDJSON; held-input content remains opt-in."
11271
+ "description": "Connect to a specific Pane data directory."
9423
11272
  }
9424
11273
  ],
9425
11274
  "examples": [
9426
11275
  "runpane watch --self-test",
9427
11276
  "runpane watch --follow",
9428
- "runpane watch --as monitor --follow --json",
9429
- "runpane watch --follow --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 180000 --blocked-settle 30000 --min-interval 600000 --idle-backoff"
11277
+ "runpane watch --as monitor --follow --quiet --json",
11278
+ "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",
11279
+ "runpane watch --follow --quiet --kinds agent.ready,agent.blocked,agent.idle,panel.exited,pane.gone --settle 60000 --blocked-settle 15000 --min-interval 120000",
11280
+ "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",
11281
+ "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"
9430
11282
  ],
9431
11283
  "notes": [
9432
11284
  "Defaults stay responsive: no settle, no batching, all kinds, IDLE every --idle-after. Cadence flags are opt-in for expensive consumers and require --follow.",
9433
- "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.",
9434
- "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.",
11285
+ "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.",
11286
+ "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.",
11287
+ "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.",
9435
11288
  "STUCK means real unsubmitted composer text. An agent prompt suggestion (for example a grey Try \"...\" hint) never counts.",
9436
11289
  "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.",
9437
11290
  "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.",
9438
11291
  "Journal loss is surfaced through reset and dropped metadata.",
9439
- "The daemon treats omitted idleAfterMs as disabled so older clients never receive agent.idle unexpectedly."
11292
+ "The daemon treats omitted idleAfterMs as disabled so older clients never receive agent.idle unexpectedly.",
11293
+ "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.",
11294
+ "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.",
11295
+ "--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.",
11296
+ "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.",
11297
+ "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.",
11298
+ "A daemon that predates --session returns no session field; runpane then fails with WATCH ERROR instead of watching every Pane.",
11299
+ "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.",
11300
+ "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."
9440
11301
  ]
9441
11302
  },
9442
11303
  "panes git-status": {
@@ -10409,6 +12270,11 @@ exports.RUNPANE_CONTRACT = {
10409
12270
  "required": true,
10410
12271
  "description": "The message to submit."
10411
12272
  },
12273
+ {
12274
+ "name": "--as-file-pointer",
12275
+ "required": false,
12276
+ "description": "Write the prompt or text to a private file under the Pane directory and send the one line `Read and follow <path>` instead."
12277
+ },
10412
12278
  {
10413
12279
  "name": "--yes",
10414
12280
  "required": false,
@@ -10427,14 +12293,96 @@ exports.RUNPANE_CONTRACT = {
10427
12293
  }
10428
12294
  ],
10429
12295
  "examples": [
10430
- "runpane agents send --pane <pane-id> --text \"Also add a test\" --yes --json"
12296
+ "runpane agents send --pane <pane-id> --text \"Also add a test\" --yes --json",
12297
+ "runpane agents send --pane <pane-id> --text \"$(cat review-notes.md)\" --as-file-pointer --yes --json"
10431
12298
  ],
10432
12299
  "jsonSchemas": [
10433
12300
  "agentSendResult"
10434
12301
  ],
10435
12302
  "notes": [
10436
- "`delivered` is true only when Pane saw the message leave the composer.",
10437
- "It types the text and presses Enter, so 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`."
12303
+ "`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.",
12304
+ "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`.",
12305
+ "`--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."
12306
+ ]
12307
+ },
12308
+ "report": {
12309
+ "name": "report",
12310
+ "summary": "Hand back a worker's structured report: state, PR, head commit, summary, and the question when blocked.",
12311
+ "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.",
12312
+ "requiresPaneDaemon": true,
12313
+ "mutates": true,
12314
+ "arguments": [
12315
+ {
12316
+ "name": "--state",
12317
+ "value": "<ready|blocked|failed|done>",
12318
+ "required": true,
12319
+ "description": "ready: work is ready for review; done: finished with nothing to review; blocked: needs an answer; failed: could not finish."
12320
+ },
12321
+ {
12322
+ "name": "--pr",
12323
+ "value": "<number>",
12324
+ "required": false,
12325
+ "description": "Pull request number."
12326
+ },
12327
+ {
12328
+ "name": "--head",
12329
+ "value": "<sha>",
12330
+ "required": false,
12331
+ "description": "Head commit the report is about, 7-40 hex characters."
12332
+ },
12333
+ {
12334
+ "name": "--summary",
12335
+ "value": "<text>",
12336
+ "required": false,
12337
+ "description": "Summary text; up to 16,000 characters are kept."
12338
+ },
12339
+ {
12340
+ "name": "--summary-file",
12341
+ "value": "<path|->",
12342
+ "required": false,
12343
+ "description": "Read the summary from a file or stdin; the absolute path is kept as summaryPath."
12344
+ },
12345
+ {
12346
+ "name": "--question",
12347
+ "value": "<text>",
12348
+ "required": false,
12349
+ "description": "What you need answered; required with --state blocked."
12350
+ },
12351
+ {
12352
+ "name": "--pane",
12353
+ "value": "<pane-id>",
12354
+ "required": false,
12355
+ "description": "Pane id when not running inside a Pane terminal (PANE_SESSION_ID)."
12356
+ },
12357
+ {
12358
+ "name": "--panel",
12359
+ "value": "<panel-id>",
12360
+ "required": false,
12361
+ "description": "Panel id when not running inside a Pane terminal (PANE_PANEL_ID)."
12362
+ },
12363
+ {
12364
+ "name": "--json",
12365
+ "required": false,
12366
+ "description": "Print machine-readable output."
12367
+ },
12368
+ {
12369
+ "name": "--pane-dir",
12370
+ "value": "<path>",
12371
+ "required": false,
12372
+ "description": "Connect to a specific Pane data directory."
12373
+ }
12374
+ ],
12375
+ "examples": [
12376
+ "runpane report --state ready --pr 747 --head fc5dce9 --summary-file /tmp/report.md --json",
12377
+ "runpane report --state blocked --question \"Should the migration drop the old column?\""
12378
+ ],
12379
+ "jsonSchemas": [
12380
+ "reportResult"
12381
+ ],
12382
+ "notes": [
12383
+ "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.",
12384
+ "Each report replaces the panel's previous one and survives a Pane restart.",
12385
+ "Watchers receive agent.report only when they list it in --kinds. REPORT lines skip the --min-interval batch."
10438
12386
  ]
10439
12387
  },
10440
12388
  "sessions list": {
@@ -10443,7 +12391,14 @@ exports.RUNPANE_CONTRACT = {
10443
12391
  "details": "List durable named orchestration Sessions.",
10444
12392
  "requiresPaneDaemon": true,
10445
12393
  "mutates": false,
10446
- "arguments": [],
12394
+ "arguments": [
12395
+ {
12396
+ "name": "--pane-dir",
12397
+ "value": "<path>",
12398
+ "required": false,
12399
+ "description": "Connect to a specific Pane data directory."
12400
+ }
12401
+ ],
10447
12402
  "examples": [
10448
12403
  "runpane sessions list [--json] [--pane-dir <path>]"
10449
12404
  ],
@@ -10458,7 +12413,14 @@ exports.RUNPANE_CONTRACT = {
10458
12413
  "details": "Create a durable named orchestration Session and its hidden terminal owner.",
10459
12414
  "requiresPaneDaemon": true,
10460
12415
  "mutates": true,
10461
- "arguments": [],
12416
+ "arguments": [
12417
+ {
12418
+ "name": "--pane-dir",
12419
+ "value": "<path>",
12420
+ "required": false,
12421
+ "description": "Connect to a specific Pane data directory."
12422
+ }
12423
+ ],
10462
12424
  "examples": [
10463
12425
  "runpane sessions create --from-json <path|-> [--json] [--pane-dir <path>]"
10464
12426
  ],
@@ -10473,7 +12435,14 @@ exports.RUNPANE_CONTRACT = {
10473
12435
  "details": "Read one durable named orchestration Session.",
10474
12436
  "requiresPaneDaemon": true,
10475
12437
  "mutates": false,
10476
- "arguments": [],
12438
+ "arguments": [
12439
+ {
12440
+ "name": "--pane-dir",
12441
+ "value": "<path>",
12442
+ "required": false,
12443
+ "description": "Connect to a specific Pane data directory."
12444
+ }
12445
+ ],
10477
12446
  "examples": [
10478
12447
  "runpane sessions get --session <id|name> [--json] [--pane-dir <path>]"
10479
12448
  ],
@@ -10488,7 +12457,14 @@ exports.RUNPANE_CONTRACT = {
10488
12457
  "details": "Update a Session overview from structured JSON.",
10489
12458
  "requiresPaneDaemon": true,
10490
12459
  "mutates": true,
10491
- "arguments": [],
12460
+ "arguments": [
12461
+ {
12462
+ "name": "--pane-dir",
12463
+ "value": "<path>",
12464
+ "required": false,
12465
+ "description": "Connect to a specific Pane data directory."
12466
+ }
12467
+ ],
10492
12468
  "examples": [
10493
12469
  "runpane sessions update --session <id|name> --from-json <path|-> [--json] [--pane-dir <path>]"
10494
12470
  ],
@@ -10503,7 +12479,14 @@ exports.RUNPANE_CONTRACT = {
10503
12479
  "details": "Switch the durable terminal agent for a named Session.",
10504
12480
  "requiresPaneDaemon": true,
10505
12481
  "mutates": true,
10506
- "arguments": [],
12482
+ "arguments": [
12483
+ {
12484
+ "name": "--pane-dir",
12485
+ "value": "<path>",
12486
+ "required": false,
12487
+ "description": "Connect to a specific Pane data directory."
12488
+ }
12489
+ ],
10507
12490
  "examples": [
10508
12491
  "runpane sessions set-agent --session <id|name> --agent <codex|claude|cursor> [--json] [--pane-dir <path>]"
10509
12492
  ],
@@ -10518,7 +12501,14 @@ exports.RUNPANE_CONTRACT = {
10518
12501
  "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`.",
10519
12502
  "requiresPaneDaemon": true,
10520
12503
  "mutates": true,
10521
- "arguments": [],
12504
+ "arguments": [
12505
+ {
12506
+ "name": "--pane-dir",
12507
+ "value": "<path>",
12508
+ "required": false,
12509
+ "description": "Connect to a specific Pane data directory."
12510
+ }
12511
+ ],
10522
12512
  "examples": [
10523
12513
  "runpane sessions associate --session <id|name> --pane <pane-id> [--json] [--pane-dir <path>]"
10524
12514
  ],
@@ -10533,7 +12523,14 @@ exports.RUNPANE_CONTRACT = {
10533
12523
  "details": "Detach a Pane from a named Session.",
10534
12524
  "requiresPaneDaemon": true,
10535
12525
  "mutates": true,
10536
- "arguments": [],
12526
+ "arguments": [
12527
+ {
12528
+ "name": "--pane-dir",
12529
+ "value": "<path>",
12530
+ "required": false,
12531
+ "description": "Connect to a specific Pane data directory."
12532
+ }
12533
+ ],
10537
12534
  "examples": [
10538
12535
  "runpane sessions detach --session <id|name> [--pane <pane-id>] [--json] [--pane-dir <path>]"
10539
12536
  ],
@@ -10548,13 +12545,190 @@ exports.RUNPANE_CONTRACT = {
10548
12545
  "details": "Read a live status, activity, git, and pull request overview for a named Session.",
10549
12546
  "requiresPaneDaemon": true,
10550
12547
  "mutates": false,
10551
- "arguments": [],
12548
+ "arguments": [
12549
+ {
12550
+ "name": "--pane-dir",
12551
+ "value": "<path>",
12552
+ "required": false,
12553
+ "description": "Connect to a specific Pane data directory."
12554
+ }
12555
+ ],
10552
12556
  "examples": [
10553
12557
  "runpane sessions overview --session <id|name> [--json] [--pane-dir <path>]"
10554
12558
  ],
10555
12559
  "jsonSchemas": [
10556
12560
  "sessionOverviewResult"
10557
12561
  ],
12562
+ "notes": [
12563
+ "The result includes `locks`: named locks scoped to the Session or held by its Panes (see `runpane lock`)."
12564
+ ]
12565
+ },
12566
+ "lock acquire": {
12567
+ "name": "lock acquire",
12568
+ "summary": "Acquire a named lock on a resource shared between agents, such as one test account, optionally waiting for it.",
12569
+ "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.",
12570
+ "requiresPaneDaemon": true,
12571
+ "mutates": true,
12572
+ "arguments": [
12573
+ {
12574
+ "name": "--name",
12575
+ "value": "<name>",
12576
+ "required": true,
12577
+ "description": "Lock name: 1-128 letters, digits, \".\", \"_\", or \"-\"."
12578
+ },
12579
+ {
12580
+ "name": "--ttl",
12581
+ "value": "<duration>",
12582
+ "required": true,
12583
+ "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."
12584
+ },
12585
+ {
12586
+ "name": "--wait",
12587
+ "value": "<milliseconds>",
12588
+ "required": false,
12589
+ "description": "Wait this long for the lock to come free. The CLI waits in daemon calls of up to 120 seconds each."
12590
+ },
12591
+ {
12592
+ "name": "--note",
12593
+ "value": "<text>",
12594
+ "required": false,
12595
+ "description": "What the lock is for, shown to other agents. Required outside a Pane terminal, where it also names the owner."
12596
+ },
12597
+ {
12598
+ "name": "--pane",
12599
+ "value": "<pane-id>",
12600
+ "required": false,
12601
+ "description": "Act for this Pane instead of $PANE_SESSION_ID."
12602
+ },
12603
+ {
12604
+ "name": "--panel",
12605
+ "value": "<panel-id>",
12606
+ "required": false,
12607
+ "description": "Act for this panel instead of $PANE_PANEL_ID."
12608
+ },
12609
+ {
12610
+ "name": "--json",
12611
+ "required": false,
12612
+ "description": "Print machine-readable output."
12613
+ },
12614
+ {
12615
+ "name": "--pane-dir",
12616
+ "value": "<path>",
12617
+ "required": false,
12618
+ "description": "Connect to a specific Pane data directory."
12619
+ }
12620
+ ],
12621
+ "examples": [
12622
+ "runpane lock acquire --name testing-account --ttl 30m --wait 1800000 --note \"call QA\" --json",
12623
+ "runpane lock acquire --name staging-db --ttl 10m --json"
12624
+ ],
12625
+ "jsonSchemas": [
12626
+ "lockAcquireRequest",
12627
+ "lockAcquireResult"
12628
+ ],
12629
+ "notes": [
12630
+ "Exit status is 0 only when the lock is yours; ok:false (exit 1) means another owner holds it, named by heldBy until expiresAt.",
12631
+ "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.",
12632
+ "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."
12633
+ ]
12634
+ },
12635
+ "lock release": {
12636
+ "name": "lock release",
12637
+ "summary": "Release a named lock you hold, or force-release another owner's lock.",
12638
+ "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.",
12639
+ "requiresPaneDaemon": true,
12640
+ "mutates": true,
12641
+ "arguments": [
12642
+ {
12643
+ "name": "--name",
12644
+ "value": "<name>",
12645
+ "required": true,
12646
+ "description": "Lock name."
12647
+ },
12648
+ {
12649
+ "name": "--force",
12650
+ "required": false,
12651
+ "description": "Release the lock even though another owner holds it."
12652
+ },
12653
+ {
12654
+ "name": "--session",
12655
+ "value": "<id|name>",
12656
+ "required": false,
12657
+ "description": "Session whose lock to release; defaults to the caller's Session, or global."
12658
+ },
12659
+ {
12660
+ "name": "--note",
12661
+ "value": "<text>",
12662
+ "required": false,
12663
+ "description": "Outside a Pane terminal, the note the lock was acquired with."
12664
+ },
12665
+ {
12666
+ "name": "--pane",
12667
+ "value": "<pane-id>",
12668
+ "required": false,
12669
+ "description": "Act for this Pane instead of $PANE_SESSION_ID."
12670
+ },
12671
+ {
12672
+ "name": "--panel",
12673
+ "value": "<panel-id>",
12674
+ "required": false,
12675
+ "description": "Act for this panel instead of $PANE_PANEL_ID."
12676
+ },
12677
+ {
12678
+ "name": "--json",
12679
+ "required": false,
12680
+ "description": "Print machine-readable output."
12681
+ },
12682
+ {
12683
+ "name": "--pane-dir",
12684
+ "value": "<path>",
12685
+ "required": false,
12686
+ "description": "Connect to a specific Pane data directory."
12687
+ }
12688
+ ],
12689
+ "examples": [
12690
+ "runpane lock release --name testing-account --json",
12691
+ "runpane lock release --name testing-account --session \"<session-id-or-name>\" --force --json"
12692
+ ],
12693
+ "jsonSchemas": [
12694
+ "lockReleaseResult"
12695
+ ],
12696
+ "notes": [
12697
+ "released:false with ok:true means no such lock was held. ok:false with reason not-owner (exit 1) means another owner holds it."
12698
+ ]
12699
+ },
12700
+ "lock list": {
12701
+ "name": "lock list",
12702
+ "summary": "List held named locks, optionally only one Session's.",
12703
+ "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.",
12704
+ "requiresPaneDaemon": true,
12705
+ "mutates": false,
12706
+ "arguments": [
12707
+ {
12708
+ "name": "--session",
12709
+ "value": "<id|name>",
12710
+ "required": false,
12711
+ "description": "Named Session id or exact name."
12712
+ },
12713
+ {
12714
+ "name": "--json",
12715
+ "required": false,
12716
+ "description": "Print machine-readable output."
12717
+ },
12718
+ {
12719
+ "name": "--pane-dir",
12720
+ "value": "<path>",
12721
+ "required": false,
12722
+ "description": "Connect to a specific Pane data directory."
12723
+ }
12724
+ ],
12725
+ "examples": [
12726
+ "runpane lock list --json",
12727
+ "runpane lock list --session \"<session-id-or-name>\" --json"
12728
+ ],
12729
+ "jsonSchemas": [
12730
+ "lockListResult"
12731
+ ],
10558
12732
  "notes": []
10559
12733
  }
10560
12734
  },