projmux 0.15.3 → 0.16.0

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.
package/docs/cli-guide.md CHANGED
@@ -97,8 +97,9 @@ invocation context. Mixed Registry/Runtime pickers keep KIND in both profiles.
97
97
  Wide stdout preserves full values at every terminal width. See [Column profiles](column-profiles.md)
98
98
  for the exact per-kind matrix and migration from the previous default output.
99
99
 
100
- The resource routes (`get`, `describe`, `create`, `rename`, `rebind`, `delete`,
101
- `agent resume`) address stored resources through one shared selector grammar.
100
+ The resource routes (`get`, `describe`, `create`, `rename`, `label`, `rebind`,
101
+ `delete`, `agent resume`) address stored resources through one shared selector
102
+ grammar.
102
103
 
103
104
  The grammar in one paragraph: a value is either `uid:<uid>` or a bare
104
105
  `metadata.name`. There is no bare-uid form, values are never split on commas,
@@ -201,7 +202,7 @@ the item: only an exact UID-bound live Window name or Pane title sets
201
202
  `observed: true`; Project and Agent context, Registry fallbacks, and unmatched
202
203
  runtime objects remain unobserved. This is a read projection, not stored
203
204
  resource state or selector authority. It does not change `-o metadata`, the
204
- Registry or snapshot schema, singular `describe ... -o json`, or `get pane -o
205
+ Registry schema, singular `describe ... -o json`, or `get pane -o
205
206
  json`; an empty plural result remains one List document with `"items": []`.
206
207
 
207
208
  ### Reference scope: the active Project namespace
@@ -361,12 +362,19 @@ Every create is **detached**: no create moves the client. Use `focus pane` or
361
362
  `-o pane-id` when you want to end up in the new pane. One exception: the human
362
363
  intent route `internal tmux window-create` (the `window.create` key and the
363
364
  Window menu New At End) moves the pressing client to the new Window after its
364
- create commits; public `create` stays detached. A natural create validates
365
+ create commits and then opens that Window's first Pane with the saved launch
366
+ default; public `create` stays detached and never reads that saved default. A natural create validates
365
367
  the inherited exact route and Pane containment. An explicit resource scope
366
368
  binds the selected app resource route without letting unrelated inherited
367
369
  `TMUX`/`TMUX_PANE` choose or change the resource target; exact Project plus
368
370
  `--create-window` therefore uses the validated app logical `-L` route on its
369
- first attempt, with no `env -u` workaround. Runtime safety remains independent
371
+ first attempt, with no `env -u` workaround. `agent resume` binds the same way,
372
+ and for the same reason: the Agent it rebinds is one exact reference and the
373
+ Pane it splits is that Agent's Window's stored `spec.anchorPaneRef`, so no
374
+ anchor Pane has to be typed or inherited to name a target that is already
375
+ named. Unsetting `TMUX` is not a substitute for either — it selects the
376
+ detached branch, which asks for an explicit `--anchor %N` instead of asking for
377
+ less. Runtime safety remains independent
370
378
  and may refuse before mutation. An inherited app-owned `TMUX` socket/PID stays
371
379
  route evidence: projmux validates its exact `-S` path, ownership/logical
372
380
  markers, logical `-L` alias, and PID while ignoring unrelated `TMUX_PANE`
@@ -472,6 +480,42 @@ already committed, and names the same public reconcile route as the retry. A
472
480
  valid unique Project UID wins over the old path after rebind; unknown and
473
481
  duplicate UID claims remain fail-closed.
474
482
 
483
+ ### Labels after creation
484
+
485
+ `projmux label project|window|pane|agent` writes `metadata.labels` on exactly
486
+ one resolved resource. It is the post-creation half of `create --label`, which
487
+ keeps its exact behavior: the same field, written by two routes at two moments.
488
+ A label change has no live projection at all -- no tmux option, no tab, no pane
489
+ title -- so the Registry commit is the whole operation and there is nothing to
490
+ converge afterwards.
491
+
492
+ The operand grammar is Kubernetes': `key=value` sets a label, `key=` sets it to
493
+ the empty string, and `key-` removes it. Set and remove operands may be mixed in
494
+ one invocation, and a key named twice is refused rather than resolved by argv
495
+ order.
496
+
497
+ Two properties follow from that grammar and are worth stating outright:
498
+
499
+ - **Shape decides what a positional token is, never the Registry.** A token
500
+ carrying `=` is always a label operand, and it can never be a resource name
501
+ anyway, because `=` is not a legal name rune. A token ending in `-` is always
502
+ a removal. A resource whose `metadata.name` happens to end in `-` is therefore
503
+ addressed by `uid:<uid>` or by its scope flag rather than positionally.
504
+ - **There is no `--overwrite` guard and no value policy.** Setting a key that
505
+ already holds a value overwrites it, and removing a key that is absent
506
+ succeeds and changes nothing; both report the resulting label set. A label
507
+ value has no length or character-set rule here, unlike in Kubernetes. The
508
+ syntax is borrowed; the value constraints deliberately are not, because
509
+ `create --label` has never had them and one field must not have two contracts
510
+ depending on which route wrote it.
511
+
512
+ What belongs in a label is decided by one question: is this a value you will
513
+ ever filter on? `--selector key=value` reads labels and only labels, so
514
+ classification that selects (`role=epic-owner`, `phase=task-0`) belongs there.
515
+ A value that is unique per resource -- a link, an artifact path -- fills the
516
+ selector space with keys nothing will ever match and belongs in an annotation
517
+ instead.
518
+
475
519
  ### Agent topic, interaction, activation, and workspace
476
520
 
477
521
  `projmux agent capabilities --provider <codex|claude|antigravity>` prints the
@@ -533,7 +577,8 @@ id and one text input. Immediately before that write it reads one bounded,
533
577
  content-free lifecycle snapshot: fresh active/in-progress returns
534
578
  `turn-in-progress`, fresh idle/terminal repairs stale cached state and starts
535
579
  once, and an unavailable or inconsistent snapshot returns
536
- `turn-state-unavailable` with no turn mutation. `steer` also reads that
580
+ `turn-state-unavailable` with no turn mutation. Broker read admission refusals
581
+ remain visible as `lifecycle-retry` or `lifecycle-busy`. `steer` also reads that
537
582
  content-free snapshot before any write and submits exactly once only when it
538
583
  still proves the same exact active turn. Fresh idle, terminal, or different-turn
539
584
  state returns `no-active-turn`; an unavailable or inconsistent read, including
@@ -546,6 +591,12 @@ supplies the cached exact turn id without adopting the steer preflight in this
546
591
  phase. These commands never install sticky model, effort, cwd, sandbox,
547
592
  permission, or collaboration overrides.
548
593
 
594
+ Codex coordination delivery chooses start or steer inside one native control
595
+ operation from one lifecycle snapshot. If that read returns `lifecycle-retry`,
596
+ it waits through the fixed retry window and reads once more before any write;
597
+ no provider write is ever retried.
598
+ An older observer that refuses this operation with `invalid-operation` gets one legacy start attempt, followed by steer only for `turn-in-progress`.
599
+
549
600
  Approval review shows only the safe one-shot intersection supplied by the
550
601
  exact pending request. Command, file, and network requests are limited to
551
602
  `accept`, `decline`, and `cancel`; permission grants echo the received supported
@@ -596,7 +647,7 @@ with its live `$N/@N` in the same commit. A non-last Pane is removed while its d
596
647
  Agent is retained Offline with its conversation identity. For a last Pane, that evidence is retained until a
597
648
  matching `window-unlinked` hook removes the Window; a final Project Window also
598
649
  removes its Window descendants while retaining the exact Project uid, root,
599
- reservation, pins, snapshots, and external assets as a valid zero-Window
650
+ reservation, pins, and external assets as a valid zero-Window
600
651
  Project. Managed runtime Stop is different: it stops only the exact runtime and
601
652
  keeps the complete desired Project/Window/Pane graph closed for a same-UID
602
653
  Continue. Shell and Claude/Codex clean exit have the same result; `/exit`, pane
@@ -646,19 +697,31 @@ owner Project root from `get`/`describe`, and a successful resume persists that
646
697
  normalized effective workspace without changing Window Project ownership.
647
698
 
648
699
  When `create agent -- <initial-prompt>` is used, normal resource creation and
649
- provider activation are distinct. Projmux first waits up to five seconds for an
650
- exact provider `SessionStart`; that readiness evidence leaves activation
651
- `pending` and opens an independent five-second initial-task acknowledgement
700
+ provider activation are distinct. Projmux first waits up to thirty-five seconds
701
+ for an exact provider `SessionStart`; that readiness evidence leaves activation
702
+ `pending` and opens an independent twelve-second initial-task acknowledgement
652
703
  window. A `UserPromptSubmit` acknowledgement may also arrive directly before
653
704
  the readiness observer sees `SessionStart`. The two stages are independently
654
- bounded, so provider startup plus an acknowledgement later than two seconds may
655
- take more than five but never more than ten seconds. Neither stage captures pane
656
- content or stores the prompt. Acknowledgement returns success and the requested
657
- exact `%N` output. If
658
- activation cannot be confirmed, the command exits nonzero while naming the
659
- exact Agent UID and Pane plus safe provider retry and `delete agent ... --yes`
660
- cleanup options. The live resources remain explicit and retryable rather than
661
- being reported as an ordinary success.
705
+ bounded, so provider startup plus a late acknowledgement may take more than
706
+ either bound alone but never more than forty-seven seconds. Both bounds are
707
+ sized from measured provider startup on a loaded machine, with headroom past
708
+ the measured peak, because a provider that is merely slow is not a failed one;
709
+ they are not sized for a dead provider, which is why exceeding them still
710
+ reports failure. Neither stage captures pane content or stores the prompt.
711
+ Acknowledgement returns success and the requested exact `%N` output.
712
+
713
+ If activation still cannot be confirmed, the command exits nonzero. A nonzero
714
+ exit here does not mean the Agent is gone or unusable: the Agent and its
715
+ managed Pane were created and are still live, and nothing is rolled back. The
716
+ diagnostic therefore names the exact Agent UID and Pane first and orders the
717
+ remediation cheapest-first — re-read the committed activation with `projmux get
718
+ agent uid:<uid>`, since a provider hook that arrives after the bound still
719
+ refines the activation to `acknowledged`; then look at the Pane or the provider
720
+ transcript for the initial task and retry it through the provider if it never
721
+ arrived; and only when neither read shows activation evidence, clean up with
722
+ `projmux delete agent uid:<uid> --yes`. Deletion is the last option rather than
723
+ the first, because a caller that acts on the exit code alone would otherwise
724
+ remove an Agent that is already working.
662
725
 
663
726
  Activation metadata is bounded to provider-hook provenance and fixed
664
727
  acknowledged/timed-out/failed diagnostics. Provider error strings and initial
@@ -764,17 +827,16 @@ client only after it converges; a refusal, a failed preflight, or a rolled-back
764
827
  partial leaves the client where it was and reports the exact stage. The
765
828
  activation is pinned to the session the open targets, so a Project whose
766
829
  Registry projects a different session name is refused instead of populating a
767
- session the open never reaches. With no saved `sidebar-startup-picker`
768
- preference, the closed-Project startup screen has exactly two neutral actions;
769
- the missing-file default is read-only and does not create a config file. Saved
770
- `on` retains that explicit choice, while saved `off` skips the screen and keeps
771
- the registered-Continue/unregistered-Fresh automatic decision. `Continue
830
+ session the open never reaches. A registered closed Project always gets the
831
+ startup screen, which has exactly two neutral actions; a root that is not a
832
+ registered Project never gets it and opens fresh. There is no setting that
833
+ skips the screen. `Continue
772
834
  project` materializes current Registry desired state with the same Project UID.
773
835
  A retained graph keeps descendant UIDs; a
774
836
  zero-Window Project atomically receives a new canonical Window/shell UID chain.
775
- A deleted Project may use only the exact usable snapshot compatibility path;
776
- an unavailable Continue is an explicit zero-write refusal with no Fresh
777
- fallback. `Recreate Project` is the one startup row that replaces identity, and it asks
837
+ A root that is not a registered Project cannot be continued: Continue is an
838
+ explicit zero-write refusal that points to `Clear layout and open`, with no Fresh
839
+ fallback. `Clear layout and open` is the one startup row that replaces identity, and it asks
778
840
  before it does. Choosing it opens a confirmation naming the exact old Project
779
841
  UID and its Window/Pane/Agent counts; declining returns to the startup rows
780
842
  with zero Registry writes, and an unreadable confirmation declines rather than
@@ -782,7 +844,7 @@ proceeds. An unregistered root has no identity to replace and is not asked.
782
844
  Confirmed, it atomically replaces the same-root graph with a new Project UID
783
845
  and new canonical Window/shell UIDs, then hands off only after ordinary
784
846
  materialization. A repeat replaces identity again. The root, git/worktrees,
785
- trust decision, unrelated roots, and snapshot bytes remain unchanged.
847
+ trust decision, and unrelated roots remain unchanged.
786
848
 
787
849
  Materialization launches or resumes declared Agents through the canonical
788
850
  provider/trust path and creates their managed Agent-owned Panes. An individual
@@ -810,9 +872,12 @@ report a final-window cascade with its actual root kind.
810
872
  Pane and Agent Registry-only deletion is deliberately narrower. It accepts
811
873
  only an explicit exact `uid:` selector: a Pane must carry durable
812
874
  `MissingRuntime=True/RuntimeUnbound` evidence, and an Agent must be `Offline`
813
- with no `paneRef` (with every retained descendant Pane also marked
814
- `MissingRuntime`). The exact routed server must answer with a non-empty socket
815
- identity and a non-empty Pane inventory that proves the target has zero mirrors.
875
+ or `Failed` with no `paneRef` (with every retained descendant Pane also marked
876
+ `MissingRuntime`). Both phases are accepted under the same authority; the
877
+ reported evidence names the phase, such as `Failed` or
878
+ `Offline+MissingRuntime`. The exact routed server must answer with a non-empty
879
+ socket identity and a non-empty Pane inventory that proves the target has zero
880
+ mirrors.
816
881
  A missing server, empty or failed inventory, unavailable or permission-denied
817
882
  transport, implicit/name/scope/`--all` selection, and duplicate or foreign
818
883
  mirrors are not absence authority and make zero writes. Dry-run and apply sign
@@ -829,7 +894,7 @@ typed resource's exact form to run instead —
829
894
  `projmux delete pane|agent uid:<uid> --socket-path <server> --dry-run`, then the
830
895
  same command with `--yes` — and says which evidence qualifies it. A target the
831
896
  `uid:` form would refuse too, such as a Pane without `MissingRuntime` or a
832
- `Running` or `Failed` Agent, gets no such pointer.
897
+ `Running` Agent, gets no such pointer.
833
898
 
834
899
  `delete window|pane|agent` names the server its live half addresses the same
835
900
  way `reconcile resources` does: `--socket <name>`, `--socket-path <absolute>`,
@@ -1012,7 +1077,7 @@ hook payload, or a `make install` log.
1012
1077
 
1013
1078
  | Route | Purpose |
1014
1079
  | --- | --- |
1015
- | `internal tmux` | Generated config render/install/apply, popup entry helpers, pane rebalance/rename, snapshot autosave. |
1080
+ | `internal tmux` | Generated config render/install/apply, popup entry helpers, pane rebalance/rename, and the retained no-op `autosave-session-state`. |
1016
1081
  | `internal status` | Status bar segment renderers (`git`, `project`, `usage`, `notify`, `resources`). |
1017
1082
  | `internal statusbar` | Status bar click and shortcut dispatch (`click`, `usage-refresh`). |
1018
1083
  | `internal preview` | Persisted preview cursor (`cycle-pane`, `cycle-window`, `select`). |
@@ -1108,31 +1173,21 @@ shows every key arriving, skip terminal remediation.
1108
1173
  ## doctor
1109
1174
 
1110
1175
  ```
1111
- projmux doctor [--json] [--section deps|runtime|integrations|session-state|logs] [--verbose]
1176
+ projmux doctor [--json] [--section deps|runtime|integrations|logs] [--verbose]
1112
1177
  ```
1113
1178
 
1114
1179
  Runs read-only diagnostics, including a dependency check for `tmux ≥ 3.4`,
1115
1180
  `git`, and `stty` (POSIX only), then reports read-only AI notify integration diagnostics
1116
- for Codex hooks, Claude Code hooks, Antigravity hooks/statusline, and the tmux bell
1181
+ for Codex hooks, Claude Code hooks, Antigravity hooks, and the tmux bell
1117
1182
  fallback. AI notify integration statuses are `installed`, `missing`, or
1118
1183
  `conflict`; missing or conflicting integrations are informational and do not
1119
- make doctor fail. It also reports read-only Session State resume metadata
1120
- diagnostics for saved agent panes, including `available`, `stale`, or
1121
- `unavailable` status plus confidence, source, updated-at, and the affected
1122
- snapshot/window/pane.
1123
-
1124
- Session State preview and doctor report the resume source captured on the pane.
1125
- Live `hook`/`session-id` metadata is high confidence; DB-validated Antigravity
1126
- `antigravity-last-conversation` and `antigravity-conversation-metadata` picker
1127
- sources are medium confidence; legacy `antigravity-history` is low confidence.
1128
- Disk discovery never lowers or overwrites an already captured live source.
1184
+ make doctor fail.
1129
1185
 
1130
1186
  The default text report shows per-section summaries plus failing or warning
1131
1187
  items. `--verbose` adds successful checks and complete typed detail, including
1132
1188
  versions, paths, confidence/source metadata, and displayed remediation.
1133
1189
  `--section` projects the same inventory used by text and JSON: `deps` selects
1134
- dependencies, `integrations` selects AI notify integrations, and
1135
- `session-state` selects resume metadata plus retention guidance. `runtime`
1190
+ dependencies, and `integrations` selects AI notify integrations. `runtime`
1136
1191
  selects the fixed `tmux` backend, an actual one-second read-only probe of the
1137
1192
  app socket, generated-versus-live config digest state, and a
1138
1193
  `projmux_process_vintage` census of this executable's live children by role and
@@ -1156,8 +1211,7 @@ bits are authoritative on both, so a readable path always resolves to a
1156
1211
  private or insecure classification. Doctor never changes permissions.
1157
1212
 
1158
1213
  JSON reports have integer `schema_version: 2`. An unfiltered report retains the
1159
- existing typed `dependencies`, `ai_notify_integrations`,
1160
- `session_state_resume`, and `session_state_prune` detail and adds ordered
1214
+ existing typed `dependencies` and `ai_notify_integrations` detail and adds ordered
1161
1215
  `runtime` and `logs` finding arrays. Every finding has closed `severity`,
1162
1216
  stable `code`, and closed `remediation`; bounded aggregates may add `count`
1163
1217
  and `safe_codes`. A filtered report contains only the selected typed field(s).
@@ -1180,8 +1234,9 @@ diagnose terminal key delivery; use `projmux setup` for that.
1180
1234
 
1181
1235
  JSON migration: consumers must switch on `schema_version` before decoding.
1182
1236
  Version 2 changes the previously empty/reserved `runtime` and `logs` arrays to
1183
- the typed finding shape above; field meanings inside the version 1 dependency,
1184
- integration, and Session State inventories are unchanged. Consumers that only
1237
+ the typed finding shape above; field meanings inside the version 1 dependency
1238
+ and integration inventories are unchanged. The former `session_state_resume`
1239
+ and `session_state_prune` fields are no longer emitted. Consumers that only
1185
1240
  understand version 1 must reject version 2 rather than decoding the new arrays
1186
1241
  as the old empty placeholder shape.
1187
1242
 
@@ -1305,7 +1360,7 @@ before anything is materialized.
1305
1360
  declares exactly one runtime outcome, and reporting `runtime=stopped` for a
1306
1361
  session that was never running would be false. `unregister project` is the
1307
1362
  inverse -- it removes the Registry graph and deliberately leaves the running
1308
- session, the root, Git/worktrees, and snapshots exactly as they were.
1363
+ session, the root, and Git/worktrees exactly as they were.
1309
1364
 
1310
1365
  `delete project` is a deprecated alias of `unregister project`. It keeps its
1311
1366
  exact behavior and its exact stdout; it adds one deprecation line on stderr and
@@ -1315,6 +1370,15 @@ removal in this release.
1315
1370
  The reference for a Project can be `uid:<uid>`, a bare `metadata.name`, or the
1316
1371
  absolute root path the Project claims.
1317
1372
 
1373
+ A Project registered without `--name` -- by `create project`, by opening an
1374
+ unregistered directory, or by `Clear layout and open` -- is named after its root
1375
+ directory, sanitized into a valid name (`~/src/my repo` becomes `my-repo`). If
1376
+ that basename sanitizes to nothing or another Project already holds it, the new
1377
+ Project is named by its exact uid instead; a numbered variant is never invented.
1378
+ `Clear layout and open` keeps an operator-chosen name, but not a name shaped
1379
+ like a Project uid. Windows, Panes, and Agents keep their exact-uid automatic
1380
+ names.
1381
+
1318
1382
  ### Operation receipts
1319
1383
 
1320
1384
  Every create, rename, delete, and Project lifecycle route reports what it did
@@ -1450,7 +1514,7 @@ Authoritative AI account usage. See [usage-tracking.md](usage-tracking.md)
1450
1514
  for adapter detail.
1451
1515
 
1452
1516
  ```
1453
- projmux agent usage [--model codex|claude|antigravity|all] [--window 5h|weekly|context|quota|all]
1517
+ projmux agent usage [--model codex|claude|all] [--window 5h|weekly|context|quota|all]
1454
1518
  [--json] [--force|-f]
1455
1519
  ```
1456
1520
 
@@ -1508,7 +1572,7 @@ Defensive ambiguous attribution stays in its stable internal bucket, is
1508
1572
  included in Attributed totals, and appears only as a bounded CPU/RSS/pane
1509
1573
  diagnostic rather than a project row. Warming, partial, unavailable, unknown,
1510
1574
  and overage states also remain explicit. No process
1511
- command list, mutation, history, graph, daemon, persistence, or Session State
1575
+ command list, mutation, history, graph, daemon, or persistence
1512
1576
  telemetry is created. Linux/tmux provides attribution; unsupported platforms
1513
1577
  show an unavailable reason rather than zero metrics.
1514
1578
 
@@ -1541,9 +1605,8 @@ projmux internal status resources
1541
1605
  local changes, `+N` staged entries, and `↑N`/`↓N` ahead/behind counts, with
1542
1606
  compact per-token colors in tmux output.
1543
1607
  - `usage` — HUD-style provider blocks containing only official `5h` and
1544
- `weekly` windows. Antigravity's exact `quota/gemini-weekly` snapshot is
1545
- projected as `weekly` without changing its cached identity; other named
1546
- quotas and context never consume status width. Claude typed `limits[]`
1608
+ `weekly` windows from Claude and Codex; named quotas and context never
1609
+ consume status width. Claude typed `limits[]`
1547
1610
  named/model rows are likewise excluded, so only its aggregate `5h` and
1548
1611
  `weekly` rows reach the status line. Narrow tiers keep one primary window per
1549
1612
  provider (`5h`, otherwise `weekly`) before hard truncation.
@@ -1635,7 +1698,7 @@ projmux agent capabilities [<agent-ref> | --provider <codex|claude|antigravity>]
1635
1698
  projmux internal agent-hook watch-title [pane]
1636
1699
  projmux internal agent-hook ingest codex-hook [--pane <pane_uid|pane_id>] < payload.json
1637
1700
  projmux internal agent-hook ingest claude-hook [--pane <pane_uid|pane_id>] < payload.json
1638
- projmux internal agent-hook ingest antigravity-hook [--event <PreInvocation|PostInvocation|PostToolUse|Stop|Statusline>] [--pane <pane_uid|pane_id>] < payload.json
1701
+ projmux internal agent-hook ingest antigravity-hook [--event <PreInvocation|PostInvocation|PostToolUse|Stop>] [--pane <pane_uid|pane_id>] < payload.json
1639
1702
  projmux internal agent-hook ingest bell --pane <pane_id>
1640
1703
  projmux diagnostics agent-hook [--tail N] [--json] [--path]
1641
1704
  projmux agent integrate codex [--dry-run] [--remove]
@@ -1698,6 +1761,120 @@ plain Agent on purpose; it is Codex-only and equivalent on `create agent
1698
1761
  multi-operand payloads, `agent resume`, Claude, and Antigravity are unaffected.
1699
1762
  See [Codex Native-Required Create Migration](codex-native-required-migration.md).
1700
1763
 
1764
+ An Agent can be given a persona: `create agent --provider claude
1765
+ --persona <name>` (and `create claude --persona <name>`) appends the stored
1766
+ persona to the new session's system prompt through Claude's
1767
+ `--append-system-prompt-file`; it never replaces the system prompt, so Claude
1768
+ Code's own tool instructions stay. Personas are files in
1769
+ `<config dir>/personas/<name>.md` (by default `~/.config/projmux/personas/`),
1770
+ at most 64 KiB each, managed with `projmux persona list|show|edit|set|delete`
1771
+ (`edit` opens `$EDITOR`, then `$VISUAL`; `set <name> --file <path>` or `-` is
1772
+ the non-interactive write). A persona's content is fixed when it is given: the create
1773
+ copies the content to a content-addressed snapshot
1774
+ `<state dir>/personas/sha256-<hex>.md`, passes only that path on the Claude
1775
+ command line, and records `projmux.io/persona` and `projmux.io/persona-digest`
1776
+ on the Agent. `agent resume` and Continue/topology replay pass that same
1777
+ snapshot again, found from the recorded digest and never from the persona file,
1778
+ so editing or deleting the persona file later never changes an existing Agent.
1779
+ If the snapshot is gone, the resume still proceeds without the persona and
1780
+ discloses one `persona-unavailable` line (on stderr for `agent resume`, among
1781
+ the replay notices for Continue). A missing, oversized, or badly named persona
1782
+ refuses with `persona-not-found`, `persona-too-large`, or
1783
+ `persona-name-invalid`, all with zero Registry, tmux, and snapshot writes.
1784
+
1785
+ A Codex Agent can be given a persona too, on one lane: a create that carries a
1786
+ prompt (`create agent --provider codex --persona <name> -- <prompt>`, and
1787
+ `create codex --persona <name> -- <prompt>`). That is the lane that opens a
1788
+ thread of its own, and starting the thread is the only moment Codex accepts a
1789
+ persona: the create sends the snapshot content as the thread's
1790
+ `developerInstructions`, and the shared app server records it once as the
1791
+ thread's `developer` message. The content goes over that connection and
1792
+ nowhere else -- never onto a command line, where `ps` would publish it -- and
1793
+ the create records the same `projmux.io/persona` and `projmux.io/persona-digest`
1794
+ annotations Claude records. From then on the thread carries the persona
1795
+ itself: `agent resume`, Continue/topology replay, and a resume picked from the
1796
+ Codex catalog re-send nothing and disclose nothing, because nothing was lost.
1797
+ A conversation opened from the resume picker inherits the two persona keys
1798
+ from the Agents that already record it, so the new Agent reports the persona
1799
+ its thread is running; it inherits no other launch value. A Codex Agent's
1800
+ persona cannot be changed afterwards: the instructions are fixed when the
1801
+ thread starts, `agent persona attach|detach` stays Claude-only, and starting
1802
+ over means a new Agent.
1803
+
1804
+ Every other `--persona` create refuses with `persona-provider-unsupported` and
1805
+ zero Registry, tmux, and snapshot writes: a Codex create with no prompt or with
1806
+ `--interactive-only` (its plain lane would have to spell the persona into
1807
+ argv), `--dialogue-reply-only`, and any other provider.
1808
+
1809
+ An existing Claude Agent can take on a persona later, or drop it:
1810
+ `projmux agent persona attach <agent-ref> <persona>` and
1811
+ `projmux agent persona detach <agent-ref>` (both with `[--project <ref>]
1812
+ [--window <ref>] [--yes] [--dry-run] [-o json]`). The Agent keeps its uid and
1813
+ its provider conversation. A Running Agent's managed Pane is closed through
1814
+ `delete pane`, which leaves it Offline, and the Agent is resumed through the
1815
+ same rebind `agent resume` uses, on a new managed Pane; an Offline or Failed
1816
+ Agent is only resumed. Before that the command writes the snapshot and records
1817
+ `projmux.io/persona`, `projmux.io/persona-digest`, and
1818
+ `projmux.io/system-prompt-snapshot=off` in one Registry change (detach removes
1819
+ the first two). The last key is sticky and makes every later resume of that
1820
+ Agent pass `--system-prompt-snapshot off`: Claude records the system prompt of
1821
+ a conversation's first request and replays that record on resume, so without
1822
+ it a persona attached after the conversation started would be ignored on the
1823
+ next resume. In steady state that costs little: each resume re-creates a
1824
+ byte-identical system prompt, so the prompt cache still hits and the extra cost
1825
+ is a few dozen cache-creation tokens per resume (measured +4 to +45); after the
1826
+ environment context in the system prompt changes (date, git state, CLAUDE.md),
1827
+ the first resume can re-cache the prompt prefix once. A Running Agent whose
1828
+ interaction is not `idle` or
1829
+ `response_complete` -- `unknown` included -- is refused with
1830
+ `persona-agent-busy` unless `--yes` confirms cutting its turn, and `--dry-run`
1831
+ (`-o json` for scripts) reports the target, its interaction, the current and
1832
+ new persona, and whether that confirmation is required without changing
1833
+ anything. The Agent owning the Pane the command runs in is refused with
1834
+ `persona-self-target`; an Agent with no stored conversation is refused with
1835
+ `persona-no-conversation`. Attaching the persona an Agent already runs with,
1836
+ same name and same content digest, reports `unchanged` and restarts nothing;
1837
+ after the persona file is edited the digest differs and the attach restarts
1838
+ with the new snapshot. Outside tmux the stop needs `--socket <name>` or
1839
+ `--socket-path <absolute>`, exactly as `delete pane` does. Refusals leave no
1840
+ snapshot, Registry, or Pane change. If the resume fails after the stop, the
1841
+ Agent stays Offline with its new annotations and stderr prints the
1842
+ `projmux agent resume uid:<agent> --project uid:<project> --window uid:<window>`
1843
+ command that finishes the job with the persona. If closing the managed Pane
1844
+ reports an error, the command checks whether that Pane is still alive: if it
1845
+ is, the previous annotations are restored; if it is already closed, the new
1846
+ annotations are kept and the resume proceeds with a warning on stderr (a failed
1847
+ resume prints the recovery command above); if it cannot tell, the previous
1848
+ annotations are restored and stderr prints the command to re-run.
1849
+
1850
+ A Claude Agent created with `--effort <level>` records it as `projmux.io/effort`
1851
+ on the Agent, because Claude does not restore a conversation's effort on
1852
+ resume. Every resume passes it again as `--effort <level>`: `agent resume`,
1853
+ Continue/topology replay, and the restart of `agent persona attach|detach`. A
1854
+ recorded value that is not one of `low`, `medium`, `high`, `xhigh`, or `max` is
1855
+ skipped, the resume still proceeds, and one `effort-invalid` line is disclosed
1856
+ where a `persona-unavailable` line would be. The model given with `--model` is
1857
+ not recorded or passed again: Claude restores the conversation's model itself
1858
+ on resume, and passing the create-time model would override a `/model` switch
1859
+ made in the session.
1860
+
1861
+ A Claude conversation opened from the resume picker creates a new Agent, and
1862
+ when Agents in the Registry already record that conversation (in any Project or
1863
+ Window, live or not) the new Agent inherits their launch values: the persona
1864
+ and its snapshot (`projmux.io/persona`, `projmux.io/persona-digest`), the
1865
+ system prompt snapshot mode (`projmux.io/system-prompt-snapshot`), and the
1866
+ effort (`projmux.io/effort`). It launches with them and records them, so its own
1867
+ later resumes behave like theirs; a snapshot that is gone or an effort Claude
1868
+ would not take is disclosed with `persona-unavailable` or `effort-invalid`, as
1869
+ on `agent resume`. Inheritance happens only when every such Agent records the
1870
+ same values; if they disagree, nothing is inherited and one
1871
+ `launch-values-ambiguous` notice names them. The creator, topic, and
1872
+ labels of those Agents are never inherited, and they keep their conversation
1873
+ and annotations. A Codex picker selection inherits the two persona keys under
1874
+ the same agreement rule and nothing else -- the snapshot mode and the effort
1875
+ are Claude launch options -- and it changes no argv, because the thread
1876
+ already carries the persona. Antigravity picker selections inherit nothing.
1877
+
1701
1878
  Automation callers get the new pane's handle from `-o pane-id` on the canonical
1702
1879
  create routes: `projmux create agent --provider <p> --placement right -o pane-id`
1703
1880
  and `projmux create pane --placement right -o pane-id` each print exactly the
@@ -1743,7 +1920,7 @@ other case reports review as unavailable without changing the Agent. This route
1743
1920
  projects only the initial response into interaction status. It does not claim
1744
1921
  the later notification-driven completion lifecycle.
1745
1922
 
1746
- Live Antigravity hook/session-state resume metadata remains a separate,
1923
+ Live Antigravity hook resume metadata remains a separate,
1747
1924
  high-confidence lane; it is not enumerated from disk by the picker. Within the
1748
1925
  picker's disk discovery, source order is the workspace-to-latest-UUID mapping
1749
1926
  in `cache/last_conversations.json`, workspace-bearing summarized rows in
@@ -1757,13 +1934,18 @@ conversation history. Cache rows have medium confidence and blank turns;
1757
1934
  summary. Legacy history is low confidence. Missing/malformed cache, stale
1758
1935
  missing-DB mappings, workspace-less metadata, and unknown fields degrade
1759
1936
  without failing Claude/Codex or legacy discovery.
1760
- Settings > AI Settings > Enabled agents controls Claude/Codex/Antigravity launch
1761
- visibility. Disabled agents are hidden from the selective picker and from the
1937
+ `Settings > Global > AI > Enabled providers`, or
1938
+ `projmux config providers [--enable <id> | --disable <id>]` through the same
1939
+ writer, controls Claude/Codex/Antigravity launch visibility. Disabled
1940
+ providers are hidden from the selective picker and from the
1762
1941
  default-mode picker. A saved default that later becomes disabled fails clearly
1763
1942
  instead of falling back to another agent. Direct
1764
1943
  Canonical `create agent --provider <p>` launches and the provider shortcuts also
1765
1944
  fail when disabled. If all AI agents are disabled, the selective picker still offers the
1766
1945
  plain `shell` split and shows guidance to re-enable Claude/Codex/Antigravity.
1946
+ While at least one agent is enabled, the selective picker also offers a `resume`
1947
+ row between the agents and `shell`; it opens the resume session list in the
1948
+ same popup.
1767
1949
  For user-level skill, slash-command, editor, or launcher registrations that
1768
1950
  call this contract, see [AI Agent Shortcuts](ai-agent-shortcuts.md).
1769
1951
 
@@ -1823,22 +2005,21 @@ precedence over catalog `action` for known Claude events too; for example a
1823
2005
  noisy notify event can be made state-only or quiet without changing installed
1824
2006
  Claude hook commands.
1825
2007
 
1826
- `ingest antigravity-hook` is the hook/statusline entrypoint for
2008
+ `ingest antigravity-hook` is the hook entrypoint for
1827
2009
  Antigravity CLI `agy` payloads. Official v1.1.12 hook commands must pass their
1828
2010
  event identity explicitly, for example
1829
2011
  `projmux internal agent-hook ingest antigravity-hook --event Stop`; the official stdin payload
1830
2012
  does not carry an event field. The explicit selector is authoritative, while
1831
2013
  payload `eventName` and its legacy aliases remain fallback inputs for existing
1832
2014
  manual wiring. `projmux agent integrate antigravity` manages exactly the named
1833
- `projmux` entry in `~/.gemini/config/hooks.json` and, separately, exactly the
1834
- `statusLine` member in `~/.gemini/antigravity-cli/settings.json`. The managed
1835
- statusline uses the official v1.1.12 `{type:"command", enabled:true,
1836
- stack_with_default:true}` shape and an absolute direct ingest command whose
1837
- stdout is empty, so the built-in statusline remains visible. It preserves every
2015
+ `projmux` entry in `~/.gemini/config/hooks.json`. It never creates or writes
2016
+ `~/.gemini/antigravity-cli/settings.json` and does not judge its `statusLine`;
2017
+ only `--remove` also strips a `statusLine` that an older projmux installed
2018
+ (its command carries `projmux-managed:antigravity-statusline:v1`), and
2019
+ `projmux config apply` removes that legacy entry on upgrade. It preserves every
1838
2020
  other named entry and unknown JSON value, resolves the running projmux
1839
2021
  executable to a stable absolute path, and supports `--dry-run` and `--remove`.
1840
- An existing unmanaged custom `statusLine` is an actionable conflict and is
1841
- never chained, wrapped, or rewritten. An existing
2022
+ An existing
1842
2023
  unmanaged `projmux` entry, another Antigravity projmux ingest command, malformed
1843
2024
  JSON, symlinks, and read/write permission failures are reported without
1844
2025
  rewriting the file. Doctor and Settings also report a managed entry as `stale`
@@ -1849,8 +2030,8 @@ The embedded v1.1.12 catalog contains the five official events `PreToolUse`,
1849
2030
  `PostToolUse`, `PreInvocation`, `PostInvocation`, and `Stop`. The managed entry
1850
2031
  installs `PreInvocation`, `PostInvocation`, `PostToolUse`, and `Stop`, each with
1851
2032
  an explicit `--event`; `PreToolUse` remains disabled because its response can
1852
- change permission policy. `Statusline` remains an explicit statusline selector
1853
- outside that official hook catalog.
2033
+ change permission policy. A leftover `--event Statusline` call from an older
2034
+ statusLine bridge exits 0 with empty stdout and changes nothing.
1854
2035
 
1855
2036
  `PreInvocation` moves the matched pane to thinking/busy without notifying.
1856
2037
  `PostInvocation` and `PostToolUse` remain quiet bookkeeping paths, with tool
@@ -1858,13 +2039,9 @@ errors retained in ingest diagnostics. `Stop` keeps the completion/error notify
1858
2039
  classification. Hook stdout is `{}` for the three non-Stop managed events and
1859
2040
  `{"decision":"stop"}` for Stop, including a shell fallback if ingest fails, so
1860
2041
  the hook cannot force continuation or synthesize a permission decision.
1861
- Official statusline `agent_state` values `thinking`, `working`, and `tool_use`
1862
- map to thinking/busy unless the pane already holds a terminal completion or
1863
- approval state; this prevents a late statusline refresh from regressing `Stop`.
1864
2042
  A new `PreInvocation` resets the pane to thinking for the next generation.
1865
- `idle` is quiet and does not clear an existing completion or approval state.
1866
- `tool_confirmation_pending=true` produces a stable-ID,
1867
- deduped approval-required row; false never produces a notification.
2043
+ Antigravity has no official approval-required or mid-turn busy event, so
2044
+ projmux reports neither for Antigravity.
1868
2045
 
1869
2046
  The managed JSON is the install source of truth. The command
1870
2047
  `agy -p '/hooks' --output-format json` is a read-only runtime diagnostic for
@@ -1880,19 +2057,11 @@ unknown reasons remain info completions with diagnostic metadata rather than
1880
2057
  being promoted to critical. Official camelCase fields retained by the parser
1881
2058
  also include `artifactDirectoryPath`, `modelName`, `invocationNum`,
1882
2059
  `initialNumSteps`, `toolCall`, `stepIdx`, `executionNum`, and `fullyIdle`.
1883
- Antigravity notify metadata uses `agent=antigravity`. Phase 3 session-state
1884
- restore is included: Antigravity ingest stores `conversationId` as pane thread
1885
- metadata for matching and as session-state resume metadata. Restore uses
1886
- `agy --conversation <uuid>` when that id is present and UUID-shaped; otherwise
1887
- session-state preview/doctor render `resume unavailable`. Structured statusline
1888
- `context_window.used_percentage` is persisted with its conversation id as
1889
- private hook/notify diagnostic metadata and is not surfaced as account usage.
1890
- The official `quota` map is persisted independently and surfaces each valid entry as
1891
- `quota/<exact bucket ID>` with independently retained absolute and relative
1892
- reset values. Bucket IDs are never mapped to `5h`/`weekly`, and account quota
1893
- is never inferred from the conversation-local gauge.
1894
- The earlier string percentage form remains a compatibility fallback.
1895
- Transcript contents are not read.
2060
+ Antigravity notify metadata uses `agent=antigravity`. Antigravity ingest stores
2061
+ `conversationId` as pane thread metadata for matching and as Agent resume
2062
+ metadata. Resume uses `agy --conversation <uuid>` when that id is present and
2063
+ UUID-shaped and is refused otherwise. projmux records no Antigravity usage,
2064
+ context, or quota. Transcript contents are not read.
1896
2065
 
1897
2066
  The canonical `internal agent-hook ingest bell --pane <pane_id>` route is the
1898
2067
  narrow tmux-bell fallback ingest path.
@@ -2236,7 +2405,7 @@ The live tmux inventory is under `runtime`: `runtime sessions`, `runtime
2236
2405
  attach`, `runtime stop`, `runtime tag`, and `runtime prune`. Project pins use
2237
2406
  `pin project list|add|remove|toggle|clear|migrate`; `list` takes `--kind
2238
2407
  project|candidate` and `migrate` takes `--dry-run`. Resource retention uses `prune
2239
- project|snapshot`, while explicit snapshot deletion uses `delete snapshot`.
2408
+ agent|project`.
2240
2409
 
2241
2410
  Popup-marker, preview, status, and tmux configuration plumbing is hidden under
2242
2411
  `internal session-popup`, `internal preview`, `internal status`, `internal
@@ -2249,35 +2418,24 @@ human configuration work should prefer `config render` and `config apply`.
2249
2418
  generated config. The generated app config uses absolute `$SHELL` as the
2250
2419
  tmux default shell when set, otherwise `/bin/sh`. `shell` starts or attaches
2251
2420
  the app session directly after resolving the target app session name and
2252
- startup directory. With no saved startup preference, Alt-1 sidebar project
2253
- open defaults to a two-action picker containing exactly `Continue project`
2254
- and `Recreate Project`; Esc returns to Projects without writing config. Saved `on`
2255
- keeps that picker, while saved `off` skips it and preserves the existing
2256
- automatic registered-Continue/unregistered-Fresh decision. `Continue
2257
- project` restores a deleted Project only from its usable exact snapshot and
2258
- otherwise refuses with zero Registry writes. `Recreate Project` confirms the
2421
+ startup directory. Alt-1 sidebar open of a registered closed Project shows a
2422
+ two-action picker containing exactly `Continue project` and
2423
+ `Clear layout and open`; Esc returns to Projects without writing config. A
2424
+ root that is not a registered Project skips the picker and opens fresh.
2425
+ `Continue
2426
+ project` on a root that is not a registered Project, including a deleted one,
2427
+ refuses with zero Registry writes and points to `Clear layout and open`. `Clear layout and open` confirms the
2259
2428
  exact old Project UID and its counts, then atomically replaces the Project
2260
2429
  with a new Project/Window/shell UID chain and one same-root claimant. A
2261
2430
  declined confirmation returns to the startup rows and writes nothing.
2262
- Repeating it allocates another new identity. Neither action modifies snapshot
2263
- bytes, the project directory, git/worktrees, unrelated roots, or trust state.
2264
- - `quit` — open an action picker with `Save Project snapshots and quit`, `Quit
2265
- without saving`, and `Cancel`. The safe first action takes one complete,
2266
- exact-socket Registry/resource-graph observation, freezes every live managed
2267
- Project session in Project UID/session order, and captures each latest
2268
- snapshot even when auto-save is off. Home/control, ephemeral, unattributed,
2269
- recoverable, foreign, and offline sessions are excluded and reported as
2270
- bounded class counts. Every target is attempted. A failed capture leaves the
2271
- successful per-session atomic files in place, reports the exact failed
2272
- session, and does not stop the app; retry captures every target again. Only an
2273
- all-success ledger reaches the existing physical-socket, app-marker, and
2274
- logical-route guarded shutdown. Named snapshots and Registry bytes are never
2275
- written, and the batch is not a multi-file transaction or topology freeze.
2276
- `Quit without saving` preserves the earlier guarded shutdown behavior:
2277
- missing servers and runtimes without the app marker are no-ops. Existing
2278
- non-interactive `--yes` and `--force` callers retain that same snapshot-free
2279
- behavior and exact shutdown route; the default command always uses the
2280
- action picker.
2431
+ Repeating it allocates another new identity. Neither action modifies the
2432
+ project directory, git/worktrees, unrelated roots, or trust state.
2433
+ - `quit` — open an action picker with `Quit projmux` and `Cancel`. `Quit
2434
+ projmux` runs the physical-socket, app-marker, and logical-route guarded
2435
+ shutdown; missing servers and runtimes without the app marker are no-ops.
2436
+ Quit never saves Project state. Non-interactive `--yes` and
2437
+ `--force` callers use the same shutdown route without the picker; the
2438
+ default command always uses the action picker.
2281
2439
  - `attach project <ref>` — enter a Project runtime from outside tmux.
2282
2440
  Automatic live-runtime attachment is `runtime attach`.
2283
2441
  - `settings` — interactive configuration UI for the project picker, AI