projmux 0.10.0 → 0.11.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/README-ko.md +90 -72
- package/README.md +24 -16
- package/docs/agent-workflow.md +86 -23
- package/docs/ai-agent-shortcuts.md +63 -278
- package/docs/architecture.md +678 -16
- package/docs/cli-guide.md +1367 -0
- package/docs/cli.md +1239 -1091
- package/docs/configuration.md +185 -136
- package/docs/globalization.md +16 -12
- package/docs/hooks.md +90 -67
- package/docs/install.md +22 -6
- package/docs/keybindings.md +223 -60
- package/docs/legacy-cli-retirement.md +64 -0
- package/docs/legacy-diagnostics-inventory.md +23 -0
- package/docs/migration-plan.md +6 -3
- package/docs/notify-os-focus-poc.md +36 -15
- package/docs/notify-queue.md +21 -19
- package/docs/operational-diagnostics.md +190 -11
- package/docs/repo-layout.md +4 -1
- package/docs/resource-attribution.md +16 -0
- package/docs/session-restore.md +27 -9
- package/docs/settings-ia.md +232 -162
- package/docs/statusbar.md +228 -48
- package/docs/testing.md +9 -9
- package/docs/theme-palette.md +0 -3
- package/docs/tmux-surface-inventory.md +2 -2
- package/docs/upgrading.md +138 -23
- package/docs/usage-tracking.md +120 -34
- package/package.json +5 -5
|
@@ -0,0 +1,1367 @@
|
|
|
1
|
+
# CLI Task Guide
|
|
2
|
+
|
|
3
|
+
The hand-maintained half of the CLI documentation: what each command is for,
|
|
4
|
+
which flags change its behavior, and the contracts a route listing cannot
|
|
5
|
+
express.
|
|
6
|
+
|
|
7
|
+
The route inventory itself is not here. [CLI Reference](cli.md) is generated
|
|
8
|
+
from the command manifest the binary renders its own help from, so it is the
|
|
9
|
+
authority on which routes, sub-routes, output modes, and field projections
|
|
10
|
+
exist in a given build. This guide is the authority on everything a one-line
|
|
11
|
+
summary leaves out. When the two disagree about whether a route exists, the
|
|
12
|
+
generated page is right and this one is stale.
|
|
13
|
+
|
|
14
|
+
Run `projmux help` for the live top-level list, or `projmux <cmd> --help` /
|
|
15
|
+
`projmux <cmd> help` for the per-command usage string. See
|
|
16
|
+
[Help boundary](#help-boundary) for the exit-code and stream contract shared by
|
|
17
|
+
every `--help` invocation.
|
|
18
|
+
|
|
19
|
+
Exit codes:
|
|
20
|
+
|
|
21
|
+
- `0` — success.
|
|
22
|
+
- `1` — runtime failure.
|
|
23
|
+
- `2` — usage error (unknown flag, bad enum, missing required flag) or a
|
|
24
|
+
deterministic semantic exit (e.g. `focus` cannot resolve the target).
|
|
25
|
+
|
|
26
|
+
## Help boundary
|
|
27
|
+
|
|
28
|
+
Help is handled once, at the root, from the shared command manifest rather than
|
|
29
|
+
by each leaf parser. Matching is on the flag **name** — the part after the
|
|
30
|
+
leading dashes and before any `=` — so every spelling the Go `flag` package
|
|
31
|
+
treats as help goes through this one boundary: `--help`, `-help`, `--h`, `-h`,
|
|
32
|
+
and any `=value` form of those (`--help=true`, `--help=false`, ...). `flag`
|
|
33
|
+
returns its help result for all of them regardless of the value, so aligning
|
|
34
|
+
with it keeps one notion of help; the boundary never interprets a flag value:
|
|
35
|
+
|
|
36
|
+
- Every help invocation exits `0`, writes to **stdout** only, records no
|
|
37
|
+
operational error, and performs no tmux, runtime, or lifecycle-migration
|
|
38
|
+
access. This includes nested routes (`projmux config edit --help`) and the
|
|
39
|
+
hidden internal namespace (`projmux internal popup-wait-key --help`).
|
|
40
|
+
- Help resolves to the deepest documented route and shows its summary, usage
|
|
41
|
+
synopsis, sub-routes, route-local output projections, and the canonical route
|
|
42
|
+
spelling it will move to. The synopsis names the route's flags (for example
|
|
43
|
+
`projmux setup terminal [terminal] [--apply] [--config <path>]
|
|
44
|
+
[--allow-symlink]`); the per-flag prose descriptions come from the command's
|
|
45
|
+
own parser and are not reproduced here.
|
|
46
|
+
- A help flag after the first bare `--` is payload, not help:
|
|
47
|
+
`projmux create agent -- --help` forwards `--help` to the launched process
|
|
48
|
+
unchanged.
|
|
49
|
+
- An unknown command keeps its `unknown command: <token>` error and exit `1`
|
|
50
|
+
even with `--help`, and `projmux help` / bare `projmux` keep printing the
|
|
51
|
+
top-level list. A bare `help` word nested under a command
|
|
52
|
+
(`projmux pin help`) still reaches that command's own handler.
|
|
53
|
+
- Because a help invocation runs no handler, it is never recorded as a state
|
|
54
|
+
change in the operations journal, at any depth — `projmux agent topic set --help`
|
|
55
|
+
logs neither an error nor a state-changing success.
|
|
56
|
+
|
|
57
|
+
## Command inventory
|
|
58
|
+
|
|
59
|
+
The full route list -- every public top-level command, its sub-routes, its
|
|
60
|
+
usage synopsis, its shared `-o` output modes, and its route-local field
|
|
61
|
+
projections -- lives in the generated [CLI Reference](cli.md). That page is
|
|
62
|
+
rendered from the same command manifest the binary renders `projmux help`
|
|
63
|
+
from and is verified against it on every `make test`, so it cannot drift.
|
|
64
|
+
Nothing in this guide restates it.
|
|
65
|
+
|
|
66
|
+
## Resource selectors and the active target
|
|
67
|
+
|
|
68
|
+
The resource routes (`get`, `describe`, `create`, `rename`, `rebind`, `delete`,
|
|
69
|
+
`agent resume`) address stored resources through one shared selector grammar.
|
|
70
|
+
|
|
71
|
+
The grammar in one paragraph: a value is either `uid:<uid>` or a bare
|
|
72
|
+
`metadata.name`. There is no bare-uid form, values are never split on commas,
|
|
73
|
+
and a `displayName`, a `spec.root` path, or a raw tmux `%N`/`@N`/`$N` handle
|
|
74
|
+
never resolves anything. `--project` occurs at most once and fixes the scope;
|
|
75
|
+
`--window` and `--pane` repeat and union in argv order; `--selector key=value`
|
|
76
|
+
repeats and ANDs. A singular route also accepts the target as a positional
|
|
77
|
+
`<ref>`, which may appear before or after the flags. How many resolved targets
|
|
78
|
+
each `<verb, kind>` pair accepts is a declared matrix, not a per-route rule, and
|
|
79
|
+
a violation is exit `2` with a candidate listing bounded to five rows.
|
|
80
|
+
|
|
81
|
+
### Empty selector: the active tmux target
|
|
82
|
+
|
|
83
|
+
Inside tmux, an invocation that carries **no selector at all** addresses the
|
|
84
|
+
resource you are looking at instead of the whole registry:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
projmux describe pane # the active pane
|
|
88
|
+
projmux describe window # the window the active pane is in
|
|
89
|
+
projmux describe project # the Project that owns that window
|
|
90
|
+
projmux describe agent # the Agent that owns the active pane
|
|
91
|
+
projmux rename pane --name build # renames the active pane
|
|
92
|
+
projmux rebind project --root /new/path
|
|
93
|
+
projmux get pane -o uid
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The contract:
|
|
97
|
+
|
|
98
|
+
- **Omission is the only spelling.** There is no `--pane current` and no
|
|
99
|
+
`--pane active`. Those are legal `metadata.name` values today — `rename pane
|
|
100
|
+
--name current` succeeds — so a sentinel token would silently shadow a real
|
|
101
|
+
resource.
|
|
102
|
+
- **"No selector at all" means exactly that.** Any positional `<ref>`, any
|
|
103
|
+
`--project`/`--window`/`--pane`, or any `--selector` label keeps the
|
|
104
|
+
pre-existing behavior unchanged. The fallback is never blended into a
|
|
105
|
+
partially specified selector.
|
|
106
|
+
- **Only the singular routes.** The plural reads (`get projects|windows|panes|
|
|
107
|
+
agents`) stay 0..N inventories over their whole scope. `delete` and `create`
|
|
108
|
+
are unchanged: `create`'s omitted `--pane` selects a split anchor inside an
|
|
109
|
+
already-chosen Window, which is not the same question.
|
|
110
|
+
- **Inside tmux is decided by `$TMUX_PANE` plus `$TMUX`**, not by whether a tmux
|
|
111
|
+
server answers. A bare `display-message` from outside a client still succeeds
|
|
112
|
+
and answers for the most-recently-used session; projmux never uses that.
|
|
113
|
+
Outside tmux the empty-selector invocations keep their previous
|
|
114
|
+
`matched N ..., want exactly one` error and exit `2`.
|
|
115
|
+
- **No persistent scope.** There is no `set-context` equivalent and no stored
|
|
116
|
+
"current pane": the target is read from tmux focus on every invocation, so
|
|
117
|
+
there is nothing to go stale and nothing to invalidate.
|
|
118
|
+
- **`projmux describe pane` with no selector is the preview.** Because every
|
|
119
|
+
verb in this family resolves through the same seam, whatever `describe pane`
|
|
120
|
+
shows is exactly what `rename pane --name X` will act on;
|
|
121
|
+
`projmux get pane -o uid` (or `-o name`) gives the same answer as a scalar.
|
|
122
|
+
|
|
123
|
+
Resolution reads only two tmux options — `@projmux_pane_uid` on the active pane
|
|
124
|
+
and `@projmux_window_uid` on its window — and derives every ancestor from
|
|
125
|
+
registry `ownerRef`. The session-scoped `@projmux_project_uid` is deliberately
|
|
126
|
+
not consulted.
|
|
127
|
+
|
|
128
|
+
### Rename and rebind live convergence
|
|
129
|
+
|
|
130
|
+
`rename project|window|pane` commits the selected Registry `metadata.name` and
|
|
131
|
+
then updates only its exact UID-bound live transport field:
|
|
132
|
+
|
|
133
|
+
- Project: `@projmux_project_name` (never the tmux session name)
|
|
134
|
+
- Window: `@projmux_window_name` (never `metadata.displayName` or tmux
|
|
135
|
+
`window_name`)
|
|
136
|
+
- Pane: `@projmux_pane_label` (never raw `pane_title`)
|
|
137
|
+
|
|
138
|
+
`rename agent` changes only the Agent's stable Window-scoped `metadata.name`.
|
|
139
|
+
It does not change the Agent topic, provider, lifecycle state, or managed Pane
|
|
140
|
+
name/title. `rebind project` preserves uid and session name, moves no files,
|
|
141
|
+
and updates only `spec.root` plus the exact session's
|
|
142
|
+
`@projmux_project_path` anchor.
|
|
143
|
+
|
|
144
|
+
The Registry commit is authoritative. Inside tmux, immediate convergence uses
|
|
145
|
+
only the inherited absolute socket path (`tmux -S`) and stable `$N`/`@N`/`%N`
|
|
146
|
+
handles. Outside tmux the command probes no default server and remains
|
|
147
|
+
Registry-only. If the exact UID is not present on that transport, or its
|
|
148
|
+
inventory cannot establish that it is live, the command succeeds with offline
|
|
149
|
+
drift that a later explicit-socket `projmux reconcile resources` can converge.
|
|
150
|
+
If an exact live target is found but its option write fails, or more than one
|
|
151
|
+
live object claims the UID, the command exits nonzero, states that Registry data
|
|
152
|
+
already committed, and names the same public reconcile route as the retry. A
|
|
153
|
+
valid unique Project UID wins over the old path after rebind; unknown and
|
|
154
|
+
duplicate UID claims remain fail-closed.
|
|
155
|
+
|
|
156
|
+
### When the active target is not a Projmux resource
|
|
157
|
+
|
|
158
|
+
A pane created outside the registry-backed routes carries no
|
|
159
|
+
`@projmux_pane_uid`, so "the active pane is not a Pane resource" is an ordinary
|
|
160
|
+
situation rather than a corner case. When that happens the command **refuses**:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
$ projmux describe pane
|
|
164
|
+
resolve pane: no selector was given and the active tmux pane %46 carries no
|
|
165
|
+
@projmux_pane_uid; nothing was selected, so pass an explicit resource reference
|
|
166
|
+
or --selector
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
It exits `2`, writes nothing to stdout, selects no other resource, and creates
|
|
170
|
+
and mutates nothing. The message is deliberately *not* the
|
|
171
|
+
`matched N ..., want exactly one` ambiguity error: that wording plus its
|
|
172
|
+
candidate listing would read as ordinary ambiguity and hide the real cause. The
|
|
173
|
+
variants name what was inspected — a missing `@projmux_window_uid`, a mirrored
|
|
174
|
+
uid the registry does not hold, or an active pane that is a shell Pane with no
|
|
175
|
+
owning Agent.
|
|
176
|
+
|
|
177
|
+
### `get pane --current` is a different route
|
|
178
|
+
|
|
179
|
+
`projmux get pane --current -o cwd` is unrelated to the fallback and is not
|
|
180
|
+
deprecated by it. It never reads the resource registry: it prints the live tmux
|
|
181
|
+
`#{pane_current_path}` of the focused pane as a bare path scalar, and `cwd` is
|
|
182
|
+
the only projection it accepts. `projmux get pane` with no selector resolves a
|
|
183
|
+
registry **Pane resource** and renders the shared resource projection. Different
|
|
184
|
+
source, different output, different failure surface — both stay.
|
|
185
|
+
|
|
186
|
+
## reconcile resources
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
projmux reconcile resources [--dry-run] [--socket <name> | --socket-path <absolute>] [-o json]
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`reconcile resources` is the explicit repair boundary for drift between the
|
|
193
|
+
authoritative resource Registry and one exact tmux server. `--dry-run` and the
|
|
194
|
+
default execute mode use the same deterministic plan. The plan classifies
|
|
195
|
+
missing, stale, foreign, and orphan state; separates Registry changes from tmux
|
|
196
|
+
mirror writes; and reports the target plus changed, no-op, and failed counts.
|
|
197
|
+
`-o json` emits the same item keys, order, outcomes, remaining drift, completed
|
|
198
|
+
stages, and retry command as structured data.
|
|
199
|
+
|
|
200
|
+
Socket selection is fail closed:
|
|
201
|
+
|
|
202
|
+
- `--socket <name>` means exactly `tmux -L <name>`.
|
|
203
|
+
- `--socket-path <absolute>` means exactly `tmux -S <absolute>`.
|
|
204
|
+
- The two flags are mutually exclusive.
|
|
205
|
+
- With neither flag, an invocation inside tmux inherits only the absolute
|
|
206
|
+
socket path from `$TMUX` and uses `-S`.
|
|
207
|
+
- With neither flag outside tmux, the command is a usage error before the
|
|
208
|
+
Registry, filesystem, or tmux is mutated. There is no default-socket guess or
|
|
209
|
+
fallback to another server.
|
|
210
|
+
|
|
211
|
+
Dry-run performs only reads: Registry bytes, tmux options/window names, and
|
|
212
|
+
other filesystem state stay unchanged. Execute rebuilds the plan from current
|
|
213
|
+
state while holding the Registry lock, commits Registry authority first, then
|
|
214
|
+
prevalidates every exact live UID target before replaying the planned mirror
|
|
215
|
+
writes. A repeat against converged state is a no-op. Foreign or ambiguous live
|
|
216
|
+
UIDs are reported and refused rather than merged or replaced; unrelated
|
|
217
|
+
resources and sockets are not touched.
|
|
218
|
+
|
|
219
|
+
If Registry commit or a live mirror write fails, the result identifies the
|
|
220
|
+
completed stages, replans the remaining drift, and prints an exact
|
|
221
|
+
`projmux reconcile resources ...` retry. Registry commit failure publishes no
|
|
222
|
+
planned UID into tmux; a later tmux failure leaves the already durable Registry
|
|
223
|
+
identity authoritative and retryable.
|
|
224
|
+
|
|
225
|
+
`doctor`, `get`, and `describe` remain read-only. `doctor` reports general
|
|
226
|
+
runtime/integration health; `reconcile resources` is the opt-in repair command.
|
|
227
|
+
It does not run `config apply`, reload unrelated configuration, reconstruct a
|
|
228
|
+
missing Registry, heuristically merge identities, or turn a read verb into a
|
|
229
|
+
write transaction.
|
|
230
|
+
|
|
231
|
+
## Internal plumbing (`projmux internal ...`)
|
|
232
|
+
|
|
233
|
+
`internal` is a hidden namespace for the routes generated tmux config, tmux
|
|
234
|
+
hooks, popup payloads, and provider hooks invoke. Nothing under it is meant to
|
|
235
|
+
be typed at a prompt, so it is absent from `projmux help` and from the
|
|
236
|
+
generated [CLI Reference](cli.md). It is listed here because operators still
|
|
237
|
+
have to recognize these spellings when they show up in a generated config, a
|
|
238
|
+
hook payload, or a `make install` log.
|
|
239
|
+
|
|
240
|
+
| Route | Purpose |
|
|
241
|
+
| --- | --- |
|
|
242
|
+
| `internal tmux` | Generated config render/install/apply, popup entry helpers, pane rebalance/rename, snapshot autosave. |
|
|
243
|
+
| `internal status` | Status bar segment renderers (`git`, `project`, `usage`, `notify`, `resources`). |
|
|
244
|
+
| `internal statusbar` | Status bar click and shortcut dispatch (`click`, `usage-refresh`). |
|
|
245
|
+
| `internal preview` | Persisted preview cursor (`cycle-pane`, `cycle-window`, `select`). |
|
|
246
|
+
| `internal session-popup` | Session popup preview/open and popup cursor movement. |
|
|
247
|
+
| `internal agent-hook` | Provider hook ingest (`ingest`) and the Agent pane title watcher (`watch-title`). |
|
|
248
|
+
| `internal focus` | Machine focus ingress used by statusbar and notification-sidebar actions. |
|
|
249
|
+
| `internal key-broker` | Darwin physical key transport. |
|
|
250
|
+
| `internal popup-wait-key` | Single-key reader that closes a display-only popup. |
|
|
251
|
+
|
|
252
|
+
The old pre-namespace top-level aliases have been removed. Invoking `status`,
|
|
253
|
+
`statusbar`, `preview`, `session-popup`, `tmux`, `key-broker`, or
|
|
254
|
+
`popup-wait-key` as the first token is an unknown command (exit 1). Generated
|
|
255
|
+
payloads use the `internal` routes above.
|
|
256
|
+
|
|
257
|
+
The tmux plumbing has public equivalents where an operator needs them:
|
|
258
|
+
|
|
259
|
+
| internal spelling | public spelling |
|
|
260
|
+
| --- | --- |
|
|
261
|
+
| `projmux internal tmux print-config` | `projmux config render standalone` |
|
|
262
|
+
| `projmux internal tmux print-app-config` | `projmux config render app` |
|
|
263
|
+
| `projmux internal tmux apply` | `projmux config apply` |
|
|
264
|
+
| `projmux internal tmux install` | *(none — installer plumbing)* |
|
|
265
|
+
| `projmux internal tmux install-app` | *(none — installer plumbing)* |
|
|
266
|
+
|
|
267
|
+
The public spellings forward to the same internal handlers. `make install`
|
|
268
|
+
calls `projmux config apply`.
|
|
269
|
+
|
|
270
|
+
The complete compatibility-to-canonical removal record, including intentional
|
|
271
|
+
error differences, is maintained in the [Legacy CLI Retirement Ledger](legacy-cli-retirement.md).
|
|
272
|
+
|
|
273
|
+
`install` and `install-app` deliberately have no public spelling. They write and
|
|
274
|
+
wire up config files as part of the install pipeline rather than answering an
|
|
275
|
+
operator's question, so they stay reachable only as `projmux internal tmux ...`.
|
|
276
|
+
|
|
277
|
+
## switch
|
|
278
|
+
|
|
279
|
+
```
|
|
280
|
+
projmux switch [--ui=popup|sidebar]
|
|
281
|
+
projmux switch open <path>
|
|
282
|
+
projmux switch toggle-tag | toggle-pin | kill | settings | preview
|
|
283
|
+
projmux switch cycle-pane | cycle-window | sidebar-focus
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Project picker. With no positional argument, opens the configured picker popup
|
|
287
|
+
or sidebar (depending on entry helper). `switch open <path>` jumps directly. The
|
|
288
|
+
sub-verbs are entry hooks invoked by tmux keybindings (e.g.
|
|
289
|
+
`sidebar-focus` is wired to the sidebar's focus binding so navigation keeps
|
|
290
|
+
the active session in sync).
|
|
291
|
+
|
|
292
|
+
Settings > Labs remains available for experimental settings, but picker
|
|
293
|
+
selection/source rows have been retired. The native picker is always used, and
|
|
294
|
+
there is no picker selection configuration or migration behavior.
|
|
295
|
+
|
|
296
|
+
## setup
|
|
297
|
+
|
|
298
|
+
```
|
|
299
|
+
projmux setup [--timeout DURATION] [--non-interactive]
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Probes the guaranteed launch defaults (`Alt-1..5`) plus transport candidates
|
|
303
|
+
such as `Ctrl-N`, `Ctrl-Shift-{R,L,M}`, `Ctrl-M`, and
|
|
304
|
+
`Alt-Shift-{Left,Right}`. Reports whether each key arrived as the expected
|
|
305
|
+
plain bytes, an unsupported legacy/app-specific sequence, an unknown sequence,
|
|
306
|
+
or a timeout. `--non-interactive` skips the TTY probe and prints the expected
|
|
307
|
+
key map. Default `--timeout` is `5s`. Run it outside tmux after trying
|
|
308
|
+
`projmux shell`; `Alt-1..5` are the only guaranteed zero-config defaults.
|
|
309
|
+
Settings > Keybindings edits in-app action aliases; terminal delivery
|
|
310
|
+
diagnostics stay in this CLI flow.
|
|
311
|
+
|
|
312
|
+
## setup terminal
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
projmux setup terminal [terminal] [--apply] [--config <path>]
|
|
316
|
+
[--allow-symlink]
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Previews or applies terminal-specific key delivery mappings for supported
|
|
320
|
+
terminals when `projmux setup` reports swallowed shortcuts. When `terminal` is
|
|
321
|
+
omitted, autodetects from `$TERM_PROGRAM`/`$TERMINAL_EMULATOR`.
|
|
322
|
+
Known terminals: `ghostty`, `windows-terminal`. Default is a read-only
|
|
323
|
+
preview; pass `--apply` to write (timestamped `.bak.<timestamp>` is created). Refuses to
|
|
324
|
+
write through a symlink unless `--allow-symlink` is passed (dotfiles repos).
|
|
325
|
+
`--config <path>` overrides the candidate list when the adapter has more
|
|
326
|
+
than one default location (Ghostty `config` vs `config.ghostty`). If setup
|
|
327
|
+
shows every key arriving, skip terminal remediation.
|
|
328
|
+
|
|
329
|
+
## doctor
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
projmux doctor [--json] [--section deps|runtime|integrations|session-state|logs] [--verbose]
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Runs read-only diagnostics, including a dependency check for `tmux ≥ 3.4`,
|
|
336
|
+
`git`, and `stty` (POSIX only), then reports read-only AI notify integration diagnostics
|
|
337
|
+
for Codex hooks, Claude Code hooks, Antigravity hooks/statusline, and the tmux bell
|
|
338
|
+
fallback. AI notify integration statuses are `installed`, `missing`, or
|
|
339
|
+
`conflict`; missing or conflicting integrations are informational and do not
|
|
340
|
+
make doctor fail. It also reports read-only Session State resume metadata
|
|
341
|
+
diagnostics for saved agent panes, including `available`, `stale`, or
|
|
342
|
+
`unavailable` status plus confidence, source, updated-at, and the affected
|
|
343
|
+
snapshot/window/pane.
|
|
344
|
+
|
|
345
|
+
Session State preview and doctor report the resume source captured on the pane.
|
|
346
|
+
Live `hook`/`session-id` metadata is high confidence; DB-validated Antigravity
|
|
347
|
+
`antigravity-last-conversation` and `antigravity-conversation-metadata` picker
|
|
348
|
+
sources are medium confidence; legacy `antigravity-history` is low confidence.
|
|
349
|
+
Disk discovery never lowers or overwrites an already captured live source.
|
|
350
|
+
|
|
351
|
+
The default text report shows per-section summaries plus failing or warning
|
|
352
|
+
items. `--verbose` adds successful checks and complete typed detail, including
|
|
353
|
+
versions, paths, confidence/source metadata, and displayed remediation.
|
|
354
|
+
`--section` projects the same inventory used by text and JSON: `deps` selects
|
|
355
|
+
dependencies, `integrations` selects AI notify integrations, and
|
|
356
|
+
`session-state` selects resume metadata plus retention guidance. `runtime`
|
|
357
|
+
selects the fixed `tmux` backend, an actual one-second read-only probe of the
|
|
358
|
+
app socket, and generated-versus-live config digest state. `logs` selects the
|
|
359
|
+
state/log/journal presence, private permissions and metadata-only writability
|
|
360
|
+
checks plus a bounded aggregate of recent safe operational error codes. These
|
|
361
|
+
sections expose only closed status codes and counts: no path, socket name,
|
|
362
|
+
routing identity, message, config content, or argv is rendered.
|
|
363
|
+
The recent-error count is the size of the newest 20-record window, not a
|
|
364
|
+
lifetime total; `logs.recent-errors.bounded` means older errors were omitted.
|
|
365
|
+
The probe captures at most 4 KiB, generated config inspection reads at most
|
|
366
|
+
1 MiB, and the journal seam reads at most 5 MiB.
|
|
367
|
+
Symlinks and non-regular inputs are rejected without following or blocking on
|
|
368
|
+
them. On Windows, POSIX mode bits cannot establish ACL privacy, so otherwise
|
|
369
|
+
valid paths report the closed `privacy-unverified` warning rather than a false
|
|
370
|
+
private/insecure classification, followed by a separate metadata-only `ready`
|
|
371
|
+
or `not-writable` finding; Doctor never changes ACLs.
|
|
372
|
+
|
|
373
|
+
JSON reports have integer `schema_version: 2`. An unfiltered report retains the
|
|
374
|
+
existing typed `dependencies`, `ai_notify_integrations`,
|
|
375
|
+
`session_state_resume`, and `session_state_prune` detail and adds ordered
|
|
376
|
+
`runtime` and `logs` finding arrays. Every finding has closed `severity`,
|
|
377
|
+
stable `code`, and closed `remediation`; bounded aggregates may add `count`
|
|
378
|
+
and `safe_codes`. A filtered report contains only the selected typed field(s).
|
|
379
|
+
`--verbose` is accepted with `--json` but does not change JSON fields or values.
|
|
380
|
+
|
|
381
|
+
Default and verbose text exit non-zero only when their projected dependency
|
|
382
|
+
inventory contains a required missing or stale dependency. A non-`deps`
|
|
383
|
+
section exits `0`. JSON preserves its successful exit after emitting a report,
|
|
384
|
+
even when required dependencies are missing or stale.
|
|
385
|
+
|
|
386
|
+
Doctor is read-only for every flag combination. It never creates or repairs
|
|
387
|
+
state/log paths, installs packages, runs displayed remediation, changes
|
|
388
|
+
terminal or tmux state, generates/applies config, migrates files, or writes
|
|
389
|
+
operational-log outcomes. Missing, malformed, or permission-denied journals
|
|
390
|
+
degrade to typed log findings without failing the command. The removed `--install-missing`,
|
|
391
|
+
`--include-optional`, and Doctor `--dry-run` mutation flags fail as unknown
|
|
392
|
+
usage with an exact instruction to remove the flag and run displayed
|
|
393
|
+
remediation explicitly outside Doctor; they are never ignored. Doctor does not
|
|
394
|
+
diagnose terminal key delivery; use `projmux setup` for that.
|
|
395
|
+
|
|
396
|
+
JSON migration: consumers must switch on `schema_version` before decoding.
|
|
397
|
+
Version 2 changes the previously empty/reserved `runtime` and `logs` arrays to
|
|
398
|
+
the typed finding shape above; field meanings inside the version 1 dependency,
|
|
399
|
+
integration, and Session State inventories are unchanged. Consumers that only
|
|
400
|
+
understand version 1 must reject version 2 rather than decoding the new arrays
|
|
401
|
+
as the old empty placeholder shape.
|
|
402
|
+
|
|
403
|
+
`Settings > Notifications > Delivery sources` shows active Codex, Claude, and
|
|
404
|
+
Antigravity hooks plus tmux statuses, conflicts, config paths, and
|
|
405
|
+
copyable AI integration commands where available. Its summary/detail also shows
|
|
406
|
+
whether `PROJMUX_NOTIFY_HOOK` overrides the built-in desktop sender. Settings
|
|
407
|
+
does not install or remove external Codex, Claude, Antigravity, or tmux notify
|
|
408
|
+
wiring. Pending in-app queue rows remain owned by the statusbar/sidebar rather
|
|
409
|
+
than a standalone Settings row.
|
|
410
|
+
|
|
411
|
+
## diagnostics
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
projmux diagnostics log [--tail N] [--json]
|
|
415
|
+
[--level info|error] [--component NAME] [--path]
|
|
416
|
+
projmux diagnostics report [--output <path>]
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Reads the local operational event journal through the same tolerant JSONL
|
|
420
|
+
reader used by every output mode. The default text view shows the newest 50
|
|
421
|
+
valid records. `--tail N` changes that bound, `--json` emits the selected
|
|
422
|
+
records as JSONL, and `--level` / `--component` filter before tailing. `--path`
|
|
423
|
+
prints the resolved path without creating or reading the log.
|
|
424
|
+
|
|
425
|
+
Successful state-changing top-level commands produce one `info` outcome, and
|
|
426
|
+
every top-level command error produces one `error` outcome. Successful
|
|
427
|
+
high-frequency/read-only commands such as `internal status`, `internal
|
|
428
|
+
agent-hook ingest`, `attention arm`/`clear`/`window`, `internal tmux
|
|
429
|
+
autosave-session-state`, `window record`, and
|
|
430
|
+
successful `diagnostics log` views do not produce an event. Errors from those
|
|
431
|
+
automatic hook/poll paths still produce one safe `error` outcome. Successful
|
|
432
|
+
direct command help and explicit `--dry-run` preview modes also remain
|
|
433
|
+
read-only and do not produce an event. Journal failures are a best-effort side
|
|
434
|
+
channel and never change command output or exit status. See
|
|
435
|
+
[operational-diagnostics.md](operational-diagnostics.md) for the file,
|
|
436
|
+
retention, concurrency, and privacy contracts.
|
|
437
|
+
|
|
438
|
+
`internal agent-hook watch-title` emits a bounded common lifecycle: one start, one terminal
|
|
439
|
+
pane-gone/hook-active stop, and at most one copy of each closed watcher failure
|
|
440
|
+
tuple per process. Normal polling iterations emit nothing. AI hook ingest emits
|
|
441
|
+
common events only for malformed/read/oversized payloads, unmatched or invalid
|
|
442
|
+
targets, unsupported event classification, and route failures. Provider event
|
|
443
|
+
names, payloads, prompt/tool/transcript values, notification text, pane
|
|
444
|
+
metadata, paths, UUIDs, and conversation/session IDs are never stored. Normal
|
|
445
|
+
state/notify/quiet/dedupe hook results stay zero-volume in the common AI family;
|
|
446
|
+
the existing notify transition remains the owner when notification behavior
|
|
447
|
+
occurs.
|
|
448
|
+
|
|
449
|
+
Session create/attach/switch/kill and `config apply` use correlated
|
|
450
|
+
`lifecycle.start`/`lifecycle.outcome` records instead of a duplicate generic
|
|
451
|
+
top-level outcome. The text and JSONL views expose only the closed safe
|
|
452
|
+
`operation` and optional `code` enums; session names, socket paths, tmux
|
|
453
|
+
targets, subprocess argv, and generated configuration are never recorded.
|
|
454
|
+
|
|
455
|
+
`diagnostics report` is the explicit consent boundary for creating one local
|
|
456
|
+
private `tar.gz` support archive. The invocation first prints a redacted
|
|
457
|
+
destination label, the complete included/omitted entry list, stable omission reasons, report
|
|
458
|
+
schema, and redaction mode; the first parent/temp/archive write happens only
|
|
459
|
+
after that preview is successfully written. `--output` selects the local
|
|
460
|
+
destination. Without it, the command uses a timestamped archive in the current
|
|
461
|
+
directory. Existing destinations are never replaced.
|
|
462
|
+
|
|
463
|
+
The archive contains `manifest.json`, safe projmux version/platform/backend
|
|
464
|
+
metadata, a redacted projection of Doctor JSON schema version 2,
|
|
465
|
+
config presence states (never values), up to 50 recent errors from the existing
|
|
466
|
+
bounded operations reader, and count-only AI ingest diagnostics. Paths,
|
|
467
|
+
session/window/pane/thread/routing identifiers, run IDs, tool/version output,
|
|
468
|
+
commands, guidance, reasons, and other free text are field-scoped hashes unless they
|
|
469
|
+
match a closed diagnostic enum/static-name allowlist. Raw config/environment
|
|
470
|
+
values, argv/stdin, prompts, notification text, pane output, transcripts, and
|
|
471
|
+
hook payloads are never collected. Missing, corrupt, or unreadable sources are
|
|
472
|
+
recorded as stable manifest omissions. Report collection does not repair source
|
|
473
|
+
permissions, migrate hooks, append an operational outcome, contact a network,
|
|
474
|
+
upload, create an issue, or run in the background; only the explicitly selected
|
|
475
|
+
output parent/temp/archive can be written.
|
|
476
|
+
|
|
477
|
+
The redacted Doctor projection keeps `schema_version`, closed runtime/log
|
|
478
|
+
finding enums, and structural/count
|
|
479
|
+
numbers as numbers. Numeric routing fields such as `window_index` and
|
|
480
|
+
`pane_index` become field-scoped hash strings under `default-hash-v1`; consumers
|
|
481
|
+
must treat this support projection as redacted evidence rather than decoding it
|
|
482
|
+
back into the unredacted Doctor Go types.
|
|
483
|
+
|
|
484
|
+
## focus
|
|
485
|
+
|
|
486
|
+
```
|
|
487
|
+
projmux focus project <ref> [--socket <path>] [--client <tty>] [--json]
|
|
488
|
+
projmux focus window <ref> --project <ref> [--socket <path>] [--client <tty>] [--json]
|
|
489
|
+
projmux focus pane <ref> --project <ref> --window <ref> [--socket <path>] [--json]
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
Moves one attached client to an exact live Project, Window, or Pane. It never
|
|
493
|
+
materializes an offline resource or force-detaches another client. `--socket`
|
|
494
|
+
is explicit; when omitted, it is derived from `$TMUX`.
|
|
495
|
+
|
|
496
|
+
Generated statusbar and notification-sidebar payloads use the hidden
|
|
497
|
+
`projmux internal focus` spelling. The old public `focus --target|--uri`
|
|
498
|
+
machine argv has been removed.
|
|
499
|
+
|
|
500
|
+
`projmux focus` stops at the tmux layer. It never asks the host terminal
|
|
501
|
+
window to come forward, in any Desktop notification mode.
|
|
502
|
+
|
|
503
|
+
`--client` is a preferred origin tmux client. In-app consumers such as the
|
|
504
|
+
status bar and notify sidebar pass the clicked client so focus redirects that
|
|
505
|
+
display first. If that client is gone, focus falls back to an attached client
|
|
506
|
+
already viewing the target session, then the stable first attached client.
|
|
507
|
+
Toast clicks do not pass `--client`.
|
|
508
|
+
|
|
509
|
+
The removed public `--uri`/`--target` ingress is not accepted here. Generated
|
|
510
|
+
machine payloads use `projmux internal focus`; human callers select an exact
|
|
511
|
+
Project, Window, or Pane with the public kind routes above.
|
|
512
|
+
|
|
513
|
+
Exit codes:
|
|
514
|
+
|
|
515
|
+
- `0` — focused (or the notify-only fallback fired).
|
|
516
|
+
- `2` — target session/window/pane could not be resolved
|
|
517
|
+
(`focusExitNotResolved`).
|
|
518
|
+
|
|
519
|
+
`--source`/`--kind` are telemetry labels logged when
|
|
520
|
+
`PROJMUX_FOCUS_DEBUG` is set. `--json` prints a single-line JSON payload
|
|
521
|
+
with `{ok, fallback, target, socket, resolved_session, client, dispatch,
|
|
522
|
+
session_state, window_state, pane_state, reason, note}`. Callers can
|
|
523
|
+
distinguish unresolved sessions (`reason=session-unresolved`, exit 2),
|
|
524
|
+
session rename/prefix fallback (`session_state=fallback`), window index
|
|
525
|
+
fallback (`window_state=index-fallback-session`), pane index fallback
|
|
526
|
+
(`pane_state=index-fallback-window`), and explicit id failures
|
|
527
|
+
(`window-id-unresolved` / `pane-id-unresolved`, exit 2).
|
|
528
|
+
|
|
529
|
+
## notification queue
|
|
530
|
+
|
|
531
|
+
Pending AI notification queue. `attention` is live tmux pane state; the queue is
|
|
532
|
+
the explicit-ack pending notification source of truth used by the status-bar
|
|
533
|
+
notify segment and notify sidebar. It is not the source of truth for all live pane attention. See
|
|
534
|
+
[notify-queue.md](notify-queue.md) for the full data model.
|
|
535
|
+
|
|
536
|
+
Use only the canonical queue spellings:
|
|
537
|
+
|
|
538
|
+
```
|
|
539
|
+
projmux create notification --text <s> --target <SESSION[:WINDOW[.PANE]]> ...
|
|
540
|
+
projmux get notifications [--live] [--json] [--limit N] ...
|
|
541
|
+
projmux notification ack <id> | --all
|
|
542
|
+
projmux notification reconcile [--json]
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
- `create notification` — append (or refresh, with `--id`) one entry. `--ttl` defaults to
|
|
546
|
+
`600` seconds as freshness metadata; expiration does not remove rows from
|
|
547
|
+
`get notifications` and is considered only by reconcile together with a gone
|
|
548
|
+
target. Reconcile also retains only the newest 256 rows. `--text` is hard-capped to 80 runes (longer text is
|
|
549
|
+
truncated server-side). After a successful queue write, projmux sends a
|
|
550
|
+
best-effort refresh event to open native notify sidebars and fires
|
|
551
|
+
declarative `[hooks.send-noti]` asynchronously if configured. Event delivery
|
|
552
|
+
failure does not fail the queue write; reopening the sidebar still shows the
|
|
553
|
+
latest queue. The hook gets a JSON payload on stdin plus
|
|
554
|
+
`PROJMUX_NOTIFY_*` env vars, and it does not replace the normal desktop
|
|
555
|
+
notification path.
|
|
556
|
+
- `get notifications` — newest-first pending queue table `ID AGE SEV SRC TARGET TEXT`
|
|
557
|
+
(or JSON). `--severity` and `--source` are repeatable filters.
|
|
558
|
+
`--live` adds a non-mutating explanation table (or JSON report) that
|
|
559
|
+
compares queued entries with live pane attention. It calls out manual
|
|
560
|
+
reply badges that do not queue because no AI agent is attached, live AI
|
|
561
|
+
reply panes missing a queue entry, matched AI reply entries, inactive
|
|
562
|
+
(`queue-stale`) queue entries whose live pane EXISTS but no longer matches
|
|
563
|
+
reply+agent state, and gone (`queue-gone`) entries whose pane is absent from
|
|
564
|
+
the real tmux live pane inventory (or which have no routable target).
|
|
565
|
+
`--ui=sidebar` opens the compact interactive notify list where Enter
|
|
566
|
+
focuses and acks live or inactive-routable targets, cleans gone/unroutable
|
|
567
|
+
targets without focusing, `a` acks the selected row, `x` clears non-critical
|
|
568
|
+
rows, and `Ctrl-X` clears all; opening or navigating the sidebar does not ack.
|
|
569
|
+
While open, the native
|
|
570
|
+
sidebar refreshes its row list on successful queue-write events without an
|
|
571
|
+
Alt-2 close/reopen toggle, using the same deferred refresh path as `a` and
|
|
572
|
+
`x`. The sidebar is a pane/session-grouped inbox whose collapsed rows are
|
|
573
|
+
fixed three-line cards: project/session, agent/provider, and newest age on
|
|
574
|
+
line 1; topic/pane-title/task context plus severity/live-state metadata on
|
|
575
|
+
line 2; and the latest notification preview on line 3. Hidden queue ids
|
|
576
|
+
remain action values, but the sidebar has no search input. `--client` is used
|
|
577
|
+
by tmux popup launchers to keep row-select focus on the clicked client.
|
|
578
|
+
- `ack <id>` removes one entry; `--all` flushes the queue.
|
|
579
|
+
- `reconcile` — walks `tmux list-panes -a` and back-fills entries for
|
|
580
|
+
panes whose attention state is `reply` AND whose AI agent option is
|
|
581
|
+
set, reporting stale `ai:` entries that no longer match a live pane without
|
|
582
|
+
acking them.
|
|
583
|
+
Soft-fails (no error, populated `errors` field in the summary) when
|
|
584
|
+
tmux is not running. Use this as the recovery path when the queue and
|
|
585
|
+
live pane state drift.
|
|
586
|
+
|
|
587
|
+
## agent usage
|
|
588
|
+
|
|
589
|
+
Authoritative AI account usage. See [usage-tracking.md](usage-tracking.md)
|
|
590
|
+
for adapter detail.
|
|
591
|
+
|
|
592
|
+
```
|
|
593
|
+
projmux agent usage [--model codex|claude|antigravity|all] [--window 5h|weekly|context|quota|all]
|
|
594
|
+
[--json] [--force|-f]
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
Renders a tab-aligned `MODEL WINDOW PCT RESETS_AT RESET_IN STALE` table; appends a
|
|
598
|
+
backoff note when an adapter is in 429 cooldown. `--force` clears any
|
|
599
|
+
active backoff and bypasses the per-adapter throttle floor (Claude `5m`,
|
|
600
|
+
Codex shares the global `30s`). `--json` emits the snapshot array; when
|
|
601
|
+
backoff is active the wrapper `{snapshots, backoff}` object is emitted
|
|
602
|
+
instead.
|
|
603
|
+
|
|
604
|
+
Claude keeps the canonical aggregate `5h` and `weekly` rows and projects each
|
|
605
|
+
valid typed upstream `limits[]` entry as a named `quota/<exact group>` row.
|
|
606
|
+
Model-scoped rows append the exact upstream model display identity in text
|
|
607
|
+
output; terminal controls are escaped and the visible label is bounded without
|
|
608
|
+
normalizing the stored identity. JSON preserves the typed named-quota metadata,
|
|
609
|
+
including nullable scope/model ID/surface, reset, `updated_at`, and `stale`.
|
|
610
|
+
These percent-only rows never synthesize token counts. A malformed limits block
|
|
611
|
+
fails that adapter refresh so the prior complete Claude slice remains visible;
|
|
612
|
+
a valid aggregate-only response replaces and removes obsolete named rows.
|
|
613
|
+
|
|
614
|
+
Antigravity emits official account rows labelled
|
|
615
|
+
`quota/<upstream bucket ID>`. Conversation-local context remains private
|
|
616
|
+
hook/notify diagnostic metadata and legacy cached context rows are suppressed
|
|
617
|
+
from text and JSON output. `--window quota` selects named account rows; opaque
|
|
618
|
+
IDs such as `weekly` are not aliases for the fixed `weekly` window. Used
|
|
619
|
+
percent is `100 * (1 - remaining_fraction)`. `--window context` remains
|
|
620
|
+
accepted for compatibility and returns no Usage rows.
|
|
621
|
+
`reset_time` and optional `reset_in_seconds` are preserved independently,
|
|
622
|
+
including the distinction between absent and explicit zero. Invalid,
|
|
623
|
+
disabled, missing, or empty quota data degrades without reinterpreting the
|
|
624
|
+
private conversation context diagnostic.
|
|
625
|
+
|
|
626
|
+
## resources
|
|
627
|
+
|
|
628
|
+
```
|
|
629
|
+
projmux resources
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
Opens the native, read-only Resource Inspector. It samples only while this
|
|
633
|
+
interactive process is alive, paints `warming` immediately, then refreshes at
|
|
634
|
+
a non-overlapping two-second cadence. Right or Enter drills Project → Window →
|
|
635
|
+
Pane → Pane detail; Left returns (and is a no-op at the root), while Esc closes
|
|
636
|
+
the popup at every depth. Search matches the current scope's display name and
|
|
637
|
+
stable tmux id. Tab cycles CPU, Memory, and Name sorting; Ctrl-R requests an
|
|
638
|
+
immediate refresh. A plain `r` remains search input.
|
|
639
|
+
|
|
640
|
+
CPU list values are host-capacity share; pane detail also shows
|
|
641
|
+
core-equivalent CPU. Project and window rows count panes, while pane rows count
|
|
642
|
+
the attributed processes. Pane rows and detail share the resolved pane identity
|
|
643
|
+
and label the tmux current command, PID/SID, pane id, and TTY separately. Memory
|
|
644
|
+
is explicitly an RSS sum (shared pages can be counted more than once) plus its
|
|
645
|
+
host ratio. `No project match`, `Multiple project matches`, and non-drillable
|
|
646
|
+
`Other / unattributed` remain explicit. The first two are display labels over
|
|
647
|
+
stable internal attribution keys. Warming, partial, unavailable, unknown, and
|
|
648
|
+
overage states also remain explicit. No process
|
|
649
|
+
command list, mutation, history, graph, daemon, persistence, or Session State
|
|
650
|
+
telemetry is created. Linux/tmux provides attribution; unsupported platforms
|
|
651
|
+
show an unavailable reason rather than zero metrics.
|
|
652
|
+
|
|
653
|
+
Only Resource Inspector anomalies (`unavailable`, `partial`, `stale`, closed
|
|
654
|
+
collection-stage errors, and scan-budget exhaustion) enter the private bounded
|
|
655
|
+
operations journal. Identical persistent anomalies are transition-coalesced;
|
|
656
|
+
healthy periodic samples and refreshes emit zero records. These records contain
|
|
657
|
+
no CPU/RSS values, PID/process detail, project/tmux identity, path/title/command,
|
|
658
|
+
or arbitrary error/status text. `diagnostics report` includes only error-level
|
|
659
|
+
closed resource outcomes; local-only partial/stale info rows are omitted.
|
|
660
|
+
|
|
661
|
+
This is distinct from `projmux internal status resources`, which remains the short
|
|
662
|
+
host-only statusbar renderer.
|
|
663
|
+
|
|
664
|
+
## internal status
|
|
665
|
+
|
|
666
|
+
Per-segment status-bar renderers. All are silent on failure — the
|
|
667
|
+
tmux status interval polls them and must never produce a stack trace.
|
|
668
|
+
|
|
669
|
+
```
|
|
670
|
+
projmux internal status git [path]
|
|
671
|
+
projmux internal status usage [--max-width N] [--force|-f]
|
|
672
|
+
projmux internal status notify [--max-width N]
|
|
673
|
+
projmux internal status resources
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
- `git` — `#[bold,fg=colour16,bg=colour45] <branch> <state> #[default]` for
|
|
677
|
+
the pane's `pane_current_path` (or the supplied path). Empty when not in a
|
|
678
|
+
repo. `<state>` is omitted when clean, otherwise it may include `*` for
|
|
679
|
+
local changes, `+N` staged entries, and `↑N`/`↓N` ahead/behind counts, with
|
|
680
|
+
compact per-token colors in tmux output.
|
|
681
|
+
- `usage` — HUD-style provider blocks containing only official `5h` and
|
|
682
|
+
`weekly` windows. Antigravity's exact `quota/gemini-weekly` snapshot is
|
|
683
|
+
projected as `weekly` without changing its cached identity; other named
|
|
684
|
+
quotas and context never consume status width. Claude typed `limits[]`
|
|
685
|
+
named/model rows are likewise excluded, so only its aggregate `5h` and
|
|
686
|
+
`weekly` rows reach the status line. Narrow tiers keep one primary window per
|
|
687
|
+
provider (`5h`, otherwise `weekly`) before hard truncation.
|
|
688
|
+
Triggers an opportunistic, throttled refresh (per-adapter
|
|
689
|
+
throttle, `30s` floor) so a stale cache self-heals.
|
|
690
|
+
- `notify` — newest-first HUD block with project, state, optional agent, text,
|
|
691
|
+
age, and `+<extras>`. Window/pane ids remain routable metadata but are not
|
|
692
|
+
displayed in the compact HUD. Degrades through width tiers; default
|
|
693
|
+
`--max-width` is `200` runes.
|
|
694
|
+
- `resources` — macOS/Linux/WSL aggregate `CPU N% MEM N%`. Linux uses
|
|
695
|
+
`/proc/stat` and `/proc/meminfo`; macOS uses native Mach host statistics.
|
|
696
|
+
CPU needs two invocations to establish a delta and renders `--` for the first
|
|
697
|
+
sample. CPU independently warns at 70–89% and becomes bold critical at 90% or
|
|
698
|
+
above; memory independently warns at 75–89% and becomes bold critical at 90%
|
|
699
|
+
or above. Normal and unavailable values use the secondary status-text role.
|
|
700
|
+
These values are host-scoped rather than pane/window/project/session
|
|
701
|
+
attribution. WSL reports the Linux guest/VM view. Unsupported platforms and
|
|
702
|
+
unreadable system metrics produce no error output.
|
|
703
|
+
|
|
704
|
+
## internal statusbar
|
|
705
|
+
|
|
706
|
+
```
|
|
707
|
+
projmux internal statusbar click <range-id> [--socket <s>] [--mouse-window <id>]
|
|
708
|
+
[--client <tty>] [--mouse-x N] [--mouse-y N]
|
|
709
|
+
projmux internal statusbar usage-refresh
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
Click/keyboard dispatcher for the two-line status bar. Implemented range ids:
|
|
713
|
+
`session pwd git resources usage notify settings`. The bare `window` /
|
|
714
|
+
`window|<idx>` token (tmux's built-in window-list range) and the empty
|
|
715
|
+
range fall through to `select-window -t @<mouse_window>` so the native
|
|
716
|
+
click-to-switch tab affordance is preserved on row 1. Unknown range ids are
|
|
717
|
+
non-specialized placeholders and no-op. `session` opens the existing-session
|
|
718
|
+
popup; `pwd` shows the current pane path in a native-framed display-only
|
|
719
|
+
popup; `git` opens the project switcher popup;
|
|
720
|
+
`settings` toggles the settings popup for the tmux client; `usage` opens the
|
|
721
|
+
detailed cached account-usage popup. Legacy context rows are suppressed and
|
|
722
|
+
named quotas retain exact identity/reset/freshness values. Claude model-scoped
|
|
723
|
+
rows distinguish the exact group and model display identity with bounded,
|
|
724
|
+
terminal-safe labels; JSON retains their full typed metadata. `USED`, `LIMIT`,
|
|
725
|
+
and `LEFT` appear together only when at least one displayed row has real
|
|
726
|
+
absolute counts; percent-only datasets omit those columns rather than
|
|
727
|
+
synthesizing counts.
|
|
728
|
+
`notify` focuses and acks the newest actionable queue target. The internal `usage-refresh` shortcut entry point
|
|
729
|
+
runs the same throttled, per-adapter collection policy as `internal status usage` and
|
|
730
|
+
then reopens the display-only usage popup from cache.
|
|
731
|
+
`MouseDown1Status` errors are
|
|
732
|
+
swallowed and surfaced as `display-message` toasts so a transient
|
|
733
|
+
failure does not raise a tmux error popup. See [statusbar.md](statusbar.md).
|
|
734
|
+
|
|
735
|
+
## attention
|
|
736
|
+
|
|
737
|
+
```
|
|
738
|
+
projmux attention toggle [pane]
|
|
739
|
+
projmux attention clear [pane]
|
|
740
|
+
projmux attention arm [pane]
|
|
741
|
+
projmux attention list [--json] [--all]
|
|
742
|
+
projmux attention window [window]
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
Toggles the `✳` pane title prefix and the `@projmux_attention_state` pane
|
|
746
|
+
option. `toggle` flips between cleared and `reply`; `clear` always
|
|
747
|
+
clears; `arm` sets a pre-reply armed state used by the AI flow. The
|
|
748
|
+
producer side pushes the matching entry into the notify queue when the pane
|
|
749
|
+
has an associated AI agent option; clearing attention does not ack the queue
|
|
750
|
+
row (manual toggles on shell panes do not push). `list` reads `tmux list-panes -a` and shows live pane
|
|
751
|
+
attention state without reading or mutating the notify queue; by default
|
|
752
|
+
it shows panes with an attention option or title marker, and `--all`
|
|
753
|
+
includes every pane. `window` renders the status-bar window badge for the
|
|
754
|
+
supplied window.
|
|
755
|
+
|
|
756
|
+
## Agent creation and hook ingress
|
|
757
|
+
|
|
758
|
+
```
|
|
759
|
+
projmux create agent --provider <claude|codex|antigravity> [--placement right|down] ...
|
|
760
|
+
projmux create pane [--placement right|down] ...
|
|
761
|
+
projmux config edit [--get|--set <mode>]
|
|
762
|
+
projmux agent status set <thinking|waiting|idle> [pane]
|
|
763
|
+
projmux agent topic ...
|
|
764
|
+
projmux internal agent-hook watch-title [pane]
|
|
765
|
+
projmux internal agent-hook ingest codex-hook < payload.json
|
|
766
|
+
projmux internal agent-hook ingest claude-hook < payload.json
|
|
767
|
+
projmux internal agent-hook ingest antigravity-hook [--event <PreInvocation|PostInvocation|PostToolUse|Stop|Statusline>] < payload.json
|
|
768
|
+
projmux internal agent-hook ingest bell --pane <pane_id>
|
|
769
|
+
projmux diagnostics agent-hook [--tail N] [--json] [--path]
|
|
770
|
+
projmux agent integrate codex [--dry-run] [--remove]
|
|
771
|
+
projmux agent integrate claude [--dry-run] [--remove]
|
|
772
|
+
projmux agent integrate antigravity [--dry-run] [--remove]
|
|
773
|
+
projmux agent integrate tmux-bell [--dry-run] [--remove]
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
These routes manage the Agent lifecycle and the per-pane state machine that drives
|
|
777
|
+
the `attention` badge, the `notify` queue producer, and the desktop
|
|
778
|
+
notifier. `status set waiting` is the trigger that flips a pane to the
|
|
779
|
+
reply-ready state — that transition pushes an `ai:<session>:<pane>`
|
|
780
|
+
entry into the notify queue.
|
|
781
|
+
Use `projmux diagnostics agent-hook` for the bounded ingest journal.
|
|
782
|
+
The durable semantic status badge is stored separately in
|
|
783
|
+
`@projmux_ai_badge_kind` as `approval_required`, `input_required`,
|
|
784
|
+
`response_complete`, `in_progress`, or unset. The live status surfaces color
|
|
785
|
+
those values with action-required amber-orange, success green, and progress
|
|
786
|
+
yellow respectively. That palette is independent from notify queue
|
|
787
|
+
`--severity` and from OS desktop notification urgency; a critical approval row
|
|
788
|
+
can still render a non-red action-required status badge.
|
|
789
|
+
|
|
790
|
+
`create agent --provider ...` selects a provider without changing the saved
|
|
791
|
+
default. Concrete provider invocations create a new managed
|
|
792
|
+
agent pane every time; existing managed AI panes in the same project/session are
|
|
793
|
+
not selected or reused.
|
|
794
|
+
The provider picker and plain Pane creation remain available through the
|
|
795
|
+
canonical create workflow. Arguments after `--` are extra arguments appended to
|
|
796
|
+
the resolved `claude`, `codex`, or `agy` executable inside the managed wrapper;
|
|
797
|
+
projmux still sets the context directory, tmux title, AI pane metadata, title
|
|
798
|
+
watcher, and split layout.
|
|
799
|
+
|
|
800
|
+
Automation callers can add `--print-pane-id` to an explicit direct
|
|
801
|
+
`--agent claude|codex|antigravity|shell` launch. On success, stdout contains
|
|
802
|
+
exactly the new `%N` pane id followed by one newline. The value comes directly
|
|
803
|
+
from tmux's existing
|
|
804
|
+
`split-window -P -F '#{pane_id}'` result. If tmux returns no valid pane id, the
|
|
805
|
+
command fails non-zero with tmux-specific guidance and writes no
|
|
806
|
+
success value. Without `--print-pane-id`, successful split invocations keep the
|
|
807
|
+
existing empty-stdout behavior.
|
|
808
|
+
|
|
809
|
+
`--print-pane-id` is not available for the saved default mode or for
|
|
810
|
+
`--agent selective|resume`, because those paths may open a picker and launch
|
|
811
|
+
only after a later user selection. Those combinations fail before opening a
|
|
812
|
+
picker or creating a pane. Arguments after `--` keep their existing argv-tail
|
|
813
|
+
meaning when the flag is used with a concrete AI agent.
|
|
814
|
+
The resume picker lists the newest deduplicated Claude, Codex, and Antigravity
|
|
815
|
+
resume sessions for the current project, with `[+ New Session]` pinned first.
|
|
816
|
+
If there are no resume sessions it goes straight to the existing selective
|
|
817
|
+
picker. Selecting a row directly starts `claude --resume <id>`,
|
|
818
|
+
`codex resume <id>`, or `agy --conversation <uuid>`.
|
|
819
|
+
|
|
820
|
+
Live Antigravity hook/session-state resume metadata remains a separate,
|
|
821
|
+
high-confidence lane; it is not enumerated from disk by the picker. Within the
|
|
822
|
+
picker's disk discovery, source order is the workspace-to-latest-UUID mapping
|
|
823
|
+
in `cache/last_conversations.json`, workspace-bearing summarized rows in
|
|
824
|
+
`cache/conversation_metadata.json`, then legacy `history.jsonl`. The two cache
|
|
825
|
+
sources require a normalized UUID and an exact regular
|
|
826
|
+
`conversations/<uuid>.db`; only DB existence and mtime are read. SQLite content,
|
|
827
|
+
prompt/transcript text, sidecars, symlinks, and arbitrary paths are never used.
|
|
828
|
+
The cache is only the history floor exposed by upstream v1.1.12, not a complete
|
|
829
|
+
conversation history. Cache rows have medium confidence and blank turns;
|
|
830
|
+
`last_conversations` uses a short UUID title, while metadata uses only a safe
|
|
831
|
+
summary. Legacy history is low confidence. Missing/malformed cache, stale
|
|
832
|
+
missing-DB mappings, workspace-less metadata, and unknown fields degrade
|
|
833
|
+
without failing Claude/Codex or legacy discovery.
|
|
834
|
+
Settings > AI Settings > Enabled agents controls Claude/Codex/Antigravity launch
|
|
835
|
+
visibility. Disabled agents are hidden from the selective picker and from the
|
|
836
|
+
default-mode picker. A saved default that later becomes disabled fails clearly
|
|
837
|
+
instead of falling back to another agent. Direct
|
|
838
|
+
`--agent claude|codex|antigravity` launches also fail when disabled, including
|
|
839
|
+
shortcuts that call the same command. For a deliberate one-shot direct CLI
|
|
840
|
+
launch, pass `--force-agent`; picker and saved default paths do not use this
|
|
841
|
+
override. If all AI agents are disabled, the selective picker still offers the
|
|
842
|
+
plain `shell` split and shows guidance to re-enable Claude/Codex/Antigravity.
|
|
843
|
+
For user-level skill, slash-command, editor, or launcher registrations that
|
|
844
|
+
call this contract, see [AI Agent Shortcuts](ai-agent-shortcuts.md).
|
|
845
|
+
|
|
846
|
+
`ingest codex-hook` is the hook-facing entrypoint for Codex hooks-engine JSON.
|
|
847
|
+
It reads one JSON payload from stdin and handles the default Codex hook catalog
|
|
848
|
+
`PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`,
|
|
849
|
+
`SessionStart`, `UserPromptSubmit`, and `Stop` as exposed by Codex CLI 0.130.0.
|
|
850
|
+
It accepts the common Codex hook fields `hook_event_name`/`event_name`,
|
|
851
|
+
`thread_id`, `session_id`, `turn_id`, `cwd`, `transcript_path`, `model`,
|
|
852
|
+
`tool_name`, nested `tool.name`, `tool_input`, and `input`. `UserPromptSubmit`
|
|
853
|
+
marks the matched pane hook-active and moves it to thinking/busy without
|
|
854
|
+
pushing a queue entry. `Stop` pushes an info completion row. `PermissionRequest`
|
|
855
|
+
pushes a critical approval row with the tool name and concise action summary.
|
|
856
|
+
The other Codex events are quiet: they mark the pane hook-active and write
|
|
857
|
+
ingest diagnostics, but do not push notify queue entries.
|
|
858
|
+
For event names without a specialized notify/state handler, ingest falls back
|
|
859
|
+
to quiet/log-only handling. A local catalog entry with `"action": "quiet"`
|
|
860
|
+
therefore lets newly discovered events be installed and observed without
|
|
861
|
+
creating notification noise; `"notify"` and `"state"` still require a built-in
|
|
862
|
+
handler before they can change pane state or push queue rows.
|
|
863
|
+
Runtime action overrides from
|
|
864
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-hook-actions.json` take
|
|
865
|
+
precedence over catalog `action` during ingest, including known events such as
|
|
866
|
+
`Stop` and `PermissionRequest`. These overrides are managed by
|
|
867
|
+
`Settings > Notifications > Agent event behavior` and do not change the catalog
|
|
868
|
+
`install` field used by `projmux agent integrate codex`. A runtime `notify`
|
|
869
|
+
override for a known Codex event without a specialized handler, such as
|
|
870
|
+
`PreToolUse` or `PostToolUse`, pushes a short generic in-app row like
|
|
871
|
+
`PreToolUse · Bash` with agent/category metadata. Generic rows are
|
|
872
|
+
queue/sidebar/statusbar only and
|
|
873
|
+
do not dispatch OS desktop notifications, `PROJMUX_NOTIFY_HOOK`, or
|
|
874
|
+
`[hooks.send-noti]`.
|
|
875
|
+
|
|
876
|
+
`ingest claude-hook` is the hook-facing entrypoint for Claude Code hooks. It
|
|
877
|
+
reads one JSON payload from stdin and handles the default Claude Code 2.1.140
|
|
878
|
+
hook catalog: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`,
|
|
879
|
+
`PostToolBatch`, `PermissionDenied`, `Notification`, `UserPromptSubmit`,
|
|
880
|
+
`UserPromptExpansion`, `SessionStart`, `Stop`, `StopFailure`,
|
|
881
|
+
`SubagentStart`, `SubagentStop`, `PreCompact`, `PostCompact`, `SessionEnd`,
|
|
882
|
+
`PermissionRequest`, `Setup`, `TeammateIdle`, `TaskCreated`,
|
|
883
|
+
`TaskCompleted`, `Elicitation`, `ElicitationResult`, `ConfigChange`,
|
|
884
|
+
`InstructionsLoaded`, `WorktreeCreate`, `WorktreeRemove`, `CwdChanged`, and
|
|
885
|
+
`FileChanged`. It uses the same pane matching order as Codex ingest
|
|
886
|
+
(`$TMUX_PANE`, payload `cwd`, then cached session id), marks matched panes
|
|
887
|
+
hook-active, and writes metadata-bearing notify queue entries only for
|
|
888
|
+
reply-ready, input-ready, approval-required, error, and teammate-idle events.
|
|
889
|
+
`SubagentStop` and the other lifecycle/tool events are quiet: they mark the
|
|
890
|
+
pane hook-active and write ingest diagnostics, but do not push notify queue
|
|
891
|
+
entries. `UserPromptSubmit` only moves the pane to thinking/busy and does not
|
|
892
|
+
push a queue entry.
|
|
893
|
+
Unknown Claude events also fall back to quiet/log-only handling after pane
|
|
894
|
+
matching. Catalog `action` is honored for quiet fallback events; notify/state
|
|
895
|
+
actions need built-in handlers for event-specific body text and state changes.
|
|
896
|
+
Runtime action overrides from
|
|
897
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-hook-actions.json` take
|
|
898
|
+
precedence over catalog `action` for known Claude events too; for example a
|
|
899
|
+
noisy notify event can be made state-only or quiet without changing installed
|
|
900
|
+
Claude hook commands.
|
|
901
|
+
|
|
902
|
+
`ingest antigravity-hook` is the hook/statusline entrypoint for
|
|
903
|
+
Antigravity CLI `agy` payloads. Official v1.1.12 hook commands must pass their
|
|
904
|
+
event identity explicitly, for example
|
|
905
|
+
`projmux internal agent-hook ingest antigravity-hook --event Stop`; the official stdin payload
|
|
906
|
+
does not carry an event field. The explicit selector is authoritative, while
|
|
907
|
+
payload `eventName` and its legacy aliases remain fallback inputs for existing
|
|
908
|
+
manual wiring. `projmux agent integrate antigravity` manages exactly the named
|
|
909
|
+
`projmux` entry in `~/.gemini/config/hooks.json` and, separately, exactly the
|
|
910
|
+
`statusLine` member in `~/.gemini/antigravity-cli/settings.json`. The managed
|
|
911
|
+
statusline uses the official v1.1.12 `{type:"command", enabled:true,
|
|
912
|
+
stack_with_default:true}` shape and an absolute direct ingest command whose
|
|
913
|
+
stdout is empty, so the built-in statusline remains visible. It preserves every
|
|
914
|
+
other named entry and unknown JSON value, resolves the running projmux
|
|
915
|
+
executable to a stable absolute path, and supports `--dry-run` and `--remove`.
|
|
916
|
+
An existing unmanaged custom `statusLine` is an actionable conflict and is
|
|
917
|
+
never chained, wrapped, or rewritten. An existing
|
|
918
|
+
unmanaged `projmux` entry, another Antigravity projmux ingest command, malformed
|
|
919
|
+
JSON, symlinks, and read/write permission failures are reported without
|
|
920
|
+
rewriting the file. Doctor and Settings also report a managed entry as `stale`
|
|
921
|
+
when its absolute executable, event/schema wiring, or stdout fallback differs
|
|
922
|
+
from the current plan; the displayed install command refreshes it.
|
|
923
|
+
|
|
924
|
+
The embedded v1.1.12 catalog contains the five official events `PreToolUse`,
|
|
925
|
+
`PostToolUse`, `PreInvocation`, `PostInvocation`, and `Stop`. The managed entry
|
|
926
|
+
installs `PreInvocation`, `PostInvocation`, `PostToolUse`, and `Stop`, each with
|
|
927
|
+
an explicit `--event`; `PreToolUse` remains disabled because its response can
|
|
928
|
+
change permission policy. `Statusline` remains an explicit statusline selector
|
|
929
|
+
outside that official hook catalog.
|
|
930
|
+
|
|
931
|
+
`PreInvocation` moves the matched pane to thinking/busy without notifying.
|
|
932
|
+
`PostInvocation` and `PostToolUse` remain quiet bookkeeping paths, with tool
|
|
933
|
+
errors retained in ingest diagnostics. `Stop` keeps the completion/error notify
|
|
934
|
+
classification. Hook stdout is `{}` for the three non-Stop managed events and
|
|
935
|
+
`{"decision":"stop"}` for Stop, including a shell fallback if ingest fails, so
|
|
936
|
+
the hook cannot force continuation or synthesize a permission decision.
|
|
937
|
+
Official statusline `agent_state` values `thinking`, `working`, and `tool_use`
|
|
938
|
+
map to thinking/busy unless the pane already holds a terminal completion or
|
|
939
|
+
approval state; this prevents a late statusline refresh from regressing `Stop`.
|
|
940
|
+
A new `PreInvocation` resets the pane to thinking for the next generation.
|
|
941
|
+
`idle` is quiet and does not clear an existing completion or approval state.
|
|
942
|
+
`tool_confirmation_pending=true` produces a stable-ID,
|
|
943
|
+
deduped approval-required row; false never produces a notification.
|
|
944
|
+
|
|
945
|
+
The managed JSON is the install source of truth. The command
|
|
946
|
+
`agy -p '/hooks' --output-format json` is a read-only runtime diagnostic for
|
|
947
|
+
confirming loaded event names and sources; projmux never uses `/hooks` output
|
|
948
|
+
to rewrite `hooks.json`.
|
|
949
|
+
|
|
950
|
+
`workspacePaths` uses the first non-empty path as a cwd matching candidate;
|
|
951
|
+
an absent or empty array does not invent a cwd. Inherited `$TMUX_PANE` remains
|
|
952
|
+
the first pane attribution source. A Stop with non-empty `error`, explicit
|
|
953
|
+
`ERROR`, or a `MAX_STEPS_EXCEEDED` family reason pushes a critical error row.
|
|
954
|
+
`NO_TOOL_CALL`, `MODEL_STOP`, and known normal reasons push an info completion;
|
|
955
|
+
unknown reasons remain info completions with diagnostic metadata rather than
|
|
956
|
+
being promoted to critical. Official camelCase fields retained by the parser
|
|
957
|
+
also include `artifactDirectoryPath`, `modelName`, `invocationNum`,
|
|
958
|
+
`initialNumSteps`, `toolCall`, `stepIdx`, `executionNum`, and `fullyIdle`.
|
|
959
|
+
Antigravity notify metadata uses `agent=antigravity`. Phase 3 session-state
|
|
960
|
+
restore is included: Antigravity ingest stores `conversationId` as pane thread
|
|
961
|
+
metadata for matching and as session-state resume metadata. Restore uses
|
|
962
|
+
`agy --conversation <uuid>` when that id is present and UUID-shaped; otherwise
|
|
963
|
+
session-state preview/doctor render `resume unavailable`. Structured statusline
|
|
964
|
+
`context_window.used_percentage` is persisted with its conversation id as
|
|
965
|
+
private hook/notify diagnostic metadata and is not surfaced as account usage.
|
|
966
|
+
The official `quota` map is persisted independently and surfaces each valid entry as
|
|
967
|
+
`quota/<exact bucket ID>` with independently retained absolute and relative
|
|
968
|
+
reset values. Bucket IDs are never mapped to `5h`/`weekly`, and account quota
|
|
969
|
+
is never inferred from the conversation-local gauge.
|
|
970
|
+
The earlier string percentage form remains a compatibility fallback.
|
|
971
|
+
Transcript contents are not read.
|
|
972
|
+
|
|
973
|
+
The canonical `internal agent-hook ingest bell --pane <pane_id>` route is the
|
|
974
|
+
narrow tmux-bell fallback ingest path.
|
|
975
|
+
It does not require the pane to be AI-managed. Projmux resolves session,
|
|
976
|
+
window, pane, title, command, and socket metadata from tmux, pushes an info
|
|
977
|
+
queue row such as `bell · <pane title>`, and suppresses repeat bell rows from
|
|
978
|
+
the same pane for 5 seconds.
|
|
979
|
+
|
|
980
|
+
`diagnostics agent-hook` prints recent ingest diagnostics from
|
|
981
|
+
`$XDG_STATE_HOME/projmux/ai-ingest.log`, or `~/.local/state/projmux/ai-ingest.log`
|
|
982
|
+
when `XDG_STATE_HOME` is unset. Ingest paths append compact JSONL records for
|
|
983
|
+
parse errors, unsupported events, missing pane matches, deduped bells,
|
|
984
|
+
state-only transitions, quiet high-volume events, and notify pushes. Raw hook
|
|
985
|
+
payloads are not stored. The log is capped at 1 MiB and trimmed to the most
|
|
986
|
+
recent roughly 512 KiB when it grows past the cap. Use `--json` for raw JSONL
|
|
987
|
+
and `--path` to print the resolved file path.
|
|
988
|
+
|
|
989
|
+
The bounded log and its 1 MiB/roughly 512 KiB retention remain available to the
|
|
990
|
+
canonical diagnostics consumer and support-report count summary. The common
|
|
991
|
+
operations journal carries only the safe anomalous classification and watcher
|
|
992
|
+
lifecycle described above; both diagnostic stores continue to run in parallel.
|
|
993
|
+
See [legacy-diagnostics-inventory.md](legacy-diagnostics-inventory.md).
|
|
994
|
+
|
|
995
|
+
For `Stop`, projmux reads `transcript_path` when present and extracts the last
|
|
996
|
+
assistant text from the transcript tail; if that is unavailable, it falls back
|
|
997
|
+
to a generic Claude completion row. `PermissionRequest` rows expose the tool
|
|
998
|
+
name plus a concise input summary, preferring Bash commands, file paths, and
|
|
999
|
+
URLs when those fields exist.
|
|
1000
|
+
|
|
1001
|
+
Hook row text is intentionally compact: agent label, event category, then the
|
|
1002
|
+
best available summary. Structured details remain in queue metadata and are
|
|
1003
|
+
available from `get notifications --json`; the sidebar does not add a separate
|
|
1004
|
+
metadata detail view.
|
|
1005
|
+
|
|
1006
|
+
The extra Claude events accept conservative field aliases while Claude's event
|
|
1007
|
+
schemas settle. `StopFailure` reads `error_type`/`errorType`/`failure_type` and
|
|
1008
|
+
`error_message`/`errorMessage`/`message`/`reason`, plus nested
|
|
1009
|
+
`error.type|name|code` and `error.message|text|reason`. `SubagentStop` reads
|
|
1010
|
+
`subagent_type`/`subagentType`/`agent_type`, `subagent_id`/`subagentId`, and
|
|
1011
|
+
nested `subagent.type|name|kind|id`. `TeammateIdle` reads
|
|
1012
|
+
`teammate_name`/`teammateName`, `teammate_id`/`teammateId`,
|
|
1013
|
+
`teammate_context`/`teammateContext`/`context`/`reason`/`message`, and nested
|
|
1014
|
+
`teammate.name|id|context|status|reason|message`.
|
|
1015
|
+
|
|
1016
|
+
Claude Code hook ingest is available through `ingest claude-hook`, but
|
|
1017
|
+
`integrate claude` is the opt-in user-level wiring command for
|
|
1018
|
+
`~/.claude/settings.json`. It installs command hooks for every event whose
|
|
1019
|
+
effective Claude hook catalog entry has `"install": true`. The embedded default
|
|
1020
|
+
catalog is based on Claude Code 2.1.140 and lives at
|
|
1021
|
+
`internal/app/ai_hook_catalogs/claude.json`; a local override may be placed at
|
|
1022
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-hooks.d/claude.json` to disable
|
|
1023
|
+
or add events before projmux itself is released:
|
|
1024
|
+
|
|
1025
|
+
```json
|
|
1026
|
+
{
|
|
1027
|
+
"provider": "claude",
|
|
1028
|
+
"events": [
|
|
1029
|
+
{ "name": "Stop", "install": false, "action": "notify" },
|
|
1030
|
+
{ "name": "FutureEvent", "install": true, "action": "quiet" }
|
|
1031
|
+
]
|
|
1032
|
+
}
|
|
1033
|
+
```
|
|
1034
|
+
|
|
1035
|
+
The embedded Claude catalog contains all 29 Claude Code 2.1.140 events:
|
|
1036
|
+
`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PostToolBatch`,
|
|
1037
|
+
`PermissionDenied`, `Notification`, `UserPromptSubmit`,
|
|
1038
|
+
`UserPromptExpansion`, `SessionStart`, `Stop`, `StopFailure`,
|
|
1039
|
+
`SubagentStart`, `SubagentStop`, `PreCompact`, `PostCompact`, `SessionEnd`,
|
|
1040
|
+
`PermissionRequest`, `Setup`, `TeammateIdle`, `TaskCreated`,
|
|
1041
|
+
`TaskCompleted`, `Elicitation`, `ElicitationResult`, `ConfigChange`,
|
|
1042
|
+
`InstructionsLoaded`, `WorktreeCreate`, `WorktreeRemove`, `CwdChanged`, and
|
|
1043
|
+
`FileChanged`. `SubagentStop` remains quiet/log-only.
|
|
1044
|
+
|
|
1045
|
+
The managed command receives Claude's hook JSON on stdin, keeps stdout/stderr
|
|
1046
|
+
quiet, and exits successfully even if ingest fails so it does not block Claude
|
|
1047
|
+
Code behavior. `--dry-run` previews the JSON update, and `--remove` deletes
|
|
1048
|
+
only commands carrying the projmux marker. Removal and unmanaged conflict
|
|
1049
|
+
detection scan every `hooks` event in the settings file rather than trusting the
|
|
1050
|
+
current catalog, so stale managed events from older catalogs are still removed.
|
|
1051
|
+
Existing unrelated Claude settings and hooks are preserved. If any event already
|
|
1052
|
+
contains an unmanaged `projmux internal agent-hook ingest claude-hook` command, projmux refuses
|
|
1053
|
+
to install over it and leaves the settings file untouched.
|
|
1054
|
+
|
|
1055
|
+
`projmux agent integrate codex` manages a hooks-engine
|
|
1056
|
+
block in `~/.codex/config.toml`. It enables `[features] hooks = true`,
|
|
1057
|
+
merging into an existing `[features]` table when present, and installs broad
|
|
1058
|
+
command hooks for every event whose effective Codex hook catalog entry has
|
|
1059
|
+
`"install": true`. The embedded default catalog is based on Codex CLI 0.130.0
|
|
1060
|
+
and lives at `internal/app/ai_hook_catalogs/codex.json`; a local override may
|
|
1061
|
+
be placed at `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-hooks.d/codex.json`:
|
|
1062
|
+
|
|
1063
|
+
```json
|
|
1064
|
+
{
|
|
1065
|
+
"provider": "codex",
|
|
1066
|
+
"events": [
|
|
1067
|
+
{ "name": "Stop", "install": false, "action": "notify" },
|
|
1068
|
+
{ "name": "FutureEvent", "install": true, "action": "quiet" }
|
|
1069
|
+
]
|
|
1070
|
+
}
|
|
1071
|
+
```
|
|
1072
|
+
|
|
1073
|
+
The embedded Codex catalog contains the 8 Codex CLI 0.130.0 events
|
|
1074
|
+
`PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`,
|
|
1075
|
+
`PostCompact`, `SessionStart`, `UserPromptSubmit`, and `Stop`.
|
|
1076
|
+
|
|
1077
|
+
```toml
|
|
1078
|
+
[features]
|
|
1079
|
+
hooks = true
|
|
1080
|
+
|
|
1081
|
+
[[hooks.PreToolUse]]
|
|
1082
|
+
matcher = "*"
|
|
1083
|
+
[[hooks.PreToolUse.hooks]]
|
|
1084
|
+
type = "command"
|
|
1085
|
+
command = "projmux internal agent-hook ingest codex-hook >/dev/null 2>&1 || true"
|
|
1086
|
+
|
|
1087
|
+
[[hooks.PermissionRequest]]
|
|
1088
|
+
matcher = "*"
|
|
1089
|
+
[[hooks.PermissionRequest.hooks]]
|
|
1090
|
+
type = "command"
|
|
1091
|
+
command = "projmux internal agent-hook ingest codex-hook >/dev/null 2>&1 || true"
|
|
1092
|
+
|
|
1093
|
+
[[hooks.PostToolUse]]
|
|
1094
|
+
matcher = "*"
|
|
1095
|
+
[[hooks.PostToolUse.hooks]]
|
|
1096
|
+
type = "command"
|
|
1097
|
+
command = "projmux internal agent-hook ingest codex-hook >/dev/null 2>&1 || true"
|
|
1098
|
+
|
|
1099
|
+
[[hooks.PreCompact]]
|
|
1100
|
+
matcher = "*"
|
|
1101
|
+
[[hooks.PreCompact.hooks]]
|
|
1102
|
+
type = "command"
|
|
1103
|
+
command = "projmux internal agent-hook ingest codex-hook >/dev/null 2>&1 || true"
|
|
1104
|
+
|
|
1105
|
+
[[hooks.PostCompact]]
|
|
1106
|
+
matcher = "*"
|
|
1107
|
+
[[hooks.PostCompact.hooks]]
|
|
1108
|
+
type = "command"
|
|
1109
|
+
command = "projmux internal agent-hook ingest codex-hook >/dev/null 2>&1 || true"
|
|
1110
|
+
|
|
1111
|
+
[[hooks.SessionStart]]
|
|
1112
|
+
matcher = "*"
|
|
1113
|
+
[[hooks.SessionStart.hooks]]
|
|
1114
|
+
type = "command"
|
|
1115
|
+
command = "projmux internal agent-hook ingest codex-hook >/dev/null 2>&1 || true"
|
|
1116
|
+
|
|
1117
|
+
[[hooks.UserPromptSubmit]]
|
|
1118
|
+
matcher = "*"
|
|
1119
|
+
[[hooks.UserPromptSubmit.hooks]]
|
|
1120
|
+
type = "command"
|
|
1121
|
+
command = "projmux internal agent-hook ingest codex-hook >/dev/null 2>&1 || true"
|
|
1122
|
+
|
|
1123
|
+
[[hooks.Stop]]
|
|
1124
|
+
matcher = "*"
|
|
1125
|
+
[[hooks.Stop.hooks]]
|
|
1126
|
+
type = "command"
|
|
1127
|
+
command = "projmux internal agent-hook ingest codex-hook >/dev/null 2>&1 || true"
|
|
1128
|
+
```
|
|
1129
|
+
|
|
1130
|
+
Codex hooks are the default integration mode. The hooks install is idempotent,
|
|
1131
|
+
preserves unrelated Codex config and unmanaged hook entries, and refuses to
|
|
1132
|
+
install over unmanaged projmux Codex hook commands it cannot safely own.
|
|
1133
|
+
`--remove` removes projmux-managed Codex hooks wiring. `--dry-run` prints the
|
|
1134
|
+
planned change without writing. Codex may still require reviewing or trusting
|
|
1135
|
+
the hook through its `/hooks` flow before commands run.
|
|
1136
|
+
|
|
1137
|
+
`integrate tmux-bell` is opt-in server-level tmux wiring for arbitrary tools
|
|
1138
|
+
that emit BEL or OSC 9. It applies `allow-passthrough on`, `monitor-bell on`,
|
|
1139
|
+
`bell-action other`, and appends a marked `alert-bell` hook that invokes
|
|
1140
|
+
`projmux internal agent-hook ingest bell --pane "#{pane_id}"`. `--dry-run` prints the tmux
|
|
1141
|
+
commands. tmux `alert-bell` is a window alert and does not expose
|
|
1142
|
+
`#{hook_pane}` on tmux 3.4, so `#{pane_id}` is the best available pane context.
|
|
1143
|
+
`--remove` unsets only hook entries carrying the projmux marker and leaves
|
|
1144
|
+
user-owned `alert-bell` hooks alone.
|
|
1145
|
+
|
|
1146
|
+
## internal tmux
|
|
1147
|
+
|
|
1148
|
+
```
|
|
1149
|
+
projmux internal tmux popup-toggle [--client <key>] <mode>
|
|
1150
|
+
projmux internal tmux popup-switch
|
|
1151
|
+
projmux internal tmux popup-sessions
|
|
1152
|
+
projmux internal tmux popup-preview <session>
|
|
1153
|
+
projmux internal tmux rebalance-panes
|
|
1154
|
+
projmux internal tmux rename-pane <pane> <label>
|
|
1155
|
+
projmux internal tmux print-config [--bin <path>]
|
|
1156
|
+
projmux internal tmux print-app-config [--bin <path>]
|
|
1157
|
+
projmux internal tmux install [--bin <path>] [--config <path>] [--include <path>]
|
|
1158
|
+
projmux internal tmux install-app [--bin <path>] [--config <path>]
|
|
1159
|
+
projmux internal tmux apply
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
Helpers tmux's keybindings and the install pipeline call into. Modes
|
|
1163
|
+
accepted by `popup-toggle` mirror the historical sessionizer surface:
|
|
1164
|
+
`session-popup`, `sessionizer`, `sessionizer-sidebar`,
|
|
1165
|
+
`notify-sidebar`, `recent-windows`, `resource-inspector`, `ai-split-picker-right`,
|
|
1166
|
+
`ai-split-picker-down`, `ai-split-resume-right`, `ai-split-resume-down`,
|
|
1167
|
+
`ai-split-settings`.
|
|
1168
|
+
`rename-pane` sets only the pane-scoped user label
|
|
1169
|
+
`@projmux_pane_label`; an empty label clears the option. It does not change the
|
|
1170
|
+
raw tmux pane title, AI topic, or AI topic manual-ownership flag. The canonical
|
|
1171
|
+
keybinding action id is `rename-pane-label`. The retired `rename-pane-topic`
|
|
1172
|
+
keymap action is no longer accepted: replace a stale
|
|
1173
|
+
`[bindings.rename-pane-topic]` table with `[bindings.rename-pane-label]`.
|
|
1174
|
+
The `projmux agent topic set/clear` commands keep
|
|
1175
|
+
AI topic ownership separate from the user pane label and raw pane title.
|
|
1176
|
+
`apply` regenerates the app tmux config and reloads the live `-L projmux`
|
|
1177
|
+
server without restarting it. `make install` and `projmux update apply` invoke it
|
|
1178
|
+
after replacing the binary. Settings > Keybindings normally runs the same
|
|
1179
|
+
save/config/reload flow automatically; use `projmux config apply` (or its
|
|
1180
|
+
hidden equivalent `projmux internal tmux apply`) as the CLI recovery or sync path after
|
|
1181
|
+
hand-editing `keymap.toml`, after saving Settings outside tmux, or after
|
|
1182
|
+
resolving a reported config-generation or live-reload failure. Reload also
|
|
1183
|
+
removes the known retired no-prefix `C-t` pane-label binding from older live
|
|
1184
|
+
servers before installing current bindings. If the current keymap assigns `C-t`
|
|
1185
|
+
to another action, that current action is bound after cleanup and remains the
|
|
1186
|
+
owner.
|
|
1187
|
+
|
|
1188
|
+
## config
|
|
1189
|
+
|
|
1190
|
+
```
|
|
1191
|
+
projmux config edit [--get|--set <mode>]
|
|
1192
|
+
projmux config render standalone [--bin <path>]
|
|
1193
|
+
projmux config render app [--bin <path>]
|
|
1194
|
+
projmux config apply [--bin <path>] [--config <path>] [--socket <name>]
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
The public configuration domain. Every route here is a parity alias over the
|
|
1198
|
+
handler that already owned the behavior — identical stdout, stderr, exit code,
|
|
1199
|
+
and side effects. `edit` forwards to the existing AI split-mode settings
|
|
1200
|
+
picker and preserves its `--get`/`--set` forms; `render` and `apply` forward to
|
|
1201
|
+
the existing `tmux` handler. The general `settings` UI remains a separate
|
|
1202
|
+
shortcut and is not renamed by this route.
|
|
1203
|
+
|
|
1204
|
+
`render` takes the artifact as a positional token because projmux generates two
|
|
1205
|
+
different tmux configs, not two views of one:
|
|
1206
|
+
|
|
1207
|
+
- `standalone` is the snippet you source from your own `~/.tmux.conf`. It prints
|
|
1208
|
+
to stdout and writes nothing. Equivalent to `projmux internal tmux print-config`.
|
|
1209
|
+
- `app` is the config the app-owned `-L projmux` server runs from. It carries the
|
|
1210
|
+
default shell and the app-only bindings on top of the standalone content, and
|
|
1211
|
+
it also only prints. Equivalent to `projmux internal tmux print-app-config`.
|
|
1212
|
+
|
|
1213
|
+
A bare `projmux config render` is a usage error (exit 2) listing the two
|
|
1214
|
+
artifacts. There is deliberately no default: silently choosing one would leave
|
|
1215
|
+
the other with no obvious public spelling, which is the gap this route exists to
|
|
1216
|
+
close.
|
|
1217
|
+
|
|
1218
|
+
`apply` takes no artifact. It writes the app tmux config and reloads the live
|
|
1219
|
+
`-L projmux` server, which is one operation over one file. Equivalent to
|
|
1220
|
+
`projmux internal tmux apply`.
|
|
1221
|
+
|
|
1222
|
+
Writing the standalone snippet and wiring the `source-file` line into your
|
|
1223
|
+
`~/.tmux.conf` is `projmux internal tmux install`, and writing the app config without
|
|
1224
|
+
reloading is `projmux internal tmux install-app`. Both are install-pipeline plumbing and
|
|
1225
|
+
have no public spelling; see
|
|
1226
|
+
[Internal plumbing](#internal-plumbing-projmux-internal-).
|
|
1227
|
+
|
|
1228
|
+
## update
|
|
1229
|
+
|
|
1230
|
+
```
|
|
1231
|
+
projmux update status [--json]
|
|
1232
|
+
projmux update check [--json]
|
|
1233
|
+
projmux update apply [--dry-run] [--no-apply]
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
Installer-aware update status foundation. `status` is read-only: it
|
|
1237
|
+
prints the current version, cached latest GitHub Release tag when present,
|
|
1238
|
+
cache freshness (`fresh`, `stale`, or `unknown`), update state, detected
|
|
1239
|
+
installer source, and cache path. It never reaches the network, so it is
|
|
1240
|
+
safe for interactive use and shell startup paths.
|
|
1241
|
+
|
|
1242
|
+
`check` fetches the latest GitHub Release metadata for
|
|
1243
|
+
`crevissepartners/projmux`, atomically writes
|
|
1244
|
+
`${XDG_CACHE_HOME:-~/.cache}/projmux/update.json`, then prints the concise
|
|
1245
|
+
latest/update/cache result. `--json` emits the same machine-readable
|
|
1246
|
+
status shape for both subcommands.
|
|
1247
|
+
|
|
1248
|
+
`projmux shell` reads the same cache before opening the isolated tmux app.
|
|
1249
|
+
When the cache is missing or stale, shell startup attempts a bounded
|
|
1250
|
+
best-effort refresh, then continues even if the network check fails. When a
|
|
1251
|
+
fresh cached update is available, the shell welcome uses Enter=Continue,
|
|
1252
|
+
`u`=Upgrade, and `s`=Skip until next. Upgrade invokes only
|
|
1253
|
+
`projmux update apply`; Skip until next writes the latest release tag to
|
|
1254
|
+
`${XDG_CACHE_HOME:-~/.cache}/projmux/update-skip.json` and suppresses that tag
|
|
1255
|
+
until a newer latest release appears.
|
|
1256
|
+
|
|
1257
|
+
Installer detection honors an explicit
|
|
1258
|
+
`PROJMUX_INSTALLER=npm|go|github-release|source` first. When it is unset,
|
|
1259
|
+
detection falls back to inspecting the running binary: an npm install tree
|
|
1260
|
+
(`node_modules/@projmux/...`) is reported as `npm`, a `go install …@latest`
|
|
1261
|
+
binary in `$GOBIN`/`$GOPATH/bin`/`~/go/bin` as `go`, and a local `go build`
|
|
1262
|
+
(`make install`) — which reports a `(devel)` main-module version — as `source`.
|
|
1263
|
+
`github-release` installs are indistinguishable from a hand-placed binary and
|
|
1264
|
+
still require an explicit `PROJMUX_INSTALLER=github-release`. Anything else is
|
|
1265
|
+
reported as `unknown` with guidance.
|
|
1266
|
+
`apply` is installer-aware and only runs after explicit user selection.
|
|
1267
|
+
For npm installs, it runs `npm install -g projmux@latest` (which reliably
|
|
1268
|
+
crosses minor/major versions where `npm update -g` does not, and re-resolves
|
|
1269
|
+
the per-platform optional dependency) and then runs the new binary's
|
|
1270
|
+
`projmux config apply`. With `--no-apply`, that convergence step uses
|
|
1271
|
+
`--no-reload`: it still migrates marker-owned files and writes generated
|
|
1272
|
+
configuration without accessing live tmux. For Go installs, it uses the existing atomic
|
|
1273
|
+
replacement implementation. For `github-release` installs, it downloads the latest
|
|
1274
|
+
matching `projmux_<version>_<goos>_<goarch>.tar.gz` release asset, extracts the
|
|
1275
|
+
binary, atomically replaces the current executable, then performs the same
|
|
1276
|
+
apply/`--no-reload` convergence. `source` installs report an
|
|
1277
|
+
actionable error to update the checkout with `git pull --ff-only && make install`.
|
|
1278
|
+
|
|
1279
|
+
## welcome
|
|
1280
|
+
|
|
1281
|
+
```
|
|
1282
|
+
projmux welcome [--popup [--force]]
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
Prints the shell-entry release prompt and bootstrap reminder without starting
|
|
1286
|
+
tmux. This is useful when you want to revisit the welcome view at any time.
|
|
1287
|
+
|
|
1288
|
+
`--popup` is the tmux attach-helper form. It shows the popup only when a
|
|
1289
|
+
pending attach welcome marker exists. `--popup --force` opens the popup without
|
|
1290
|
+
consulting pending or skip state. Passing positional arguments prints usage and
|
|
1291
|
+
returns a usage error.
|
|
1292
|
+
|
|
1293
|
+
## runtime / pin / prune / internal helpers
|
|
1294
|
+
|
|
1295
|
+
The live tmux inventory is under `runtime`: `runtime sessions`, `runtime
|
|
1296
|
+
attach`, `runtime stop`, `runtime tag`, and `runtime prune`. Project pins use
|
|
1297
|
+
`pin project list|add|remove|toggle|clear`. Resource retention uses `prune
|
|
1298
|
+
project|snapshot`, while explicit snapshot deletion uses `delete snapshot`.
|
|
1299
|
+
|
|
1300
|
+
Popup-marker, preview, status, and tmux configuration plumbing is hidden under
|
|
1301
|
+
`internal session-popup`, `internal preview`, `internal status`, `internal
|
|
1302
|
+
statusbar`, and `internal tmux`. Generated configuration is their producer;
|
|
1303
|
+
human configuration work should prefer `config render` and `config apply`.
|
|
1304
|
+
|
|
1305
|
+
## shell / attach / settings / quit
|
|
1306
|
+
|
|
1307
|
+
- `shell` — boot the isolated `-L projmux` tmux server with the
|
|
1308
|
+
generated config. The generated app config uses absolute `$SHELL` as the
|
|
1309
|
+
tmux default shell when set, otherwise `/bin/sh`. `shell` starts or attaches
|
|
1310
|
+
the app session directly after resolving the target app session name and
|
|
1311
|
+
startup directory. Alt-1 sidebar project open defaults to `Empty session`; the
|
|
1312
|
+
Session State `Sidebar startup picker` opt-in shows `Latest snapshot`, `Named
|
|
1313
|
+
snapshot`, and `Empty session` before creating a closed project session.
|
|
1314
|
+
`Latest snapshot` is auto-saved; named snapshots are fixed until the user
|
|
1315
|
+
saves or replaces them.
|
|
1316
|
+
- `quit` — open an action picker with `Quit projmux` and `Cancel`. Selecting
|
|
1317
|
+
`Quit projmux` terminates only a `tmux -L projmux` runtime whose global
|
|
1318
|
+
`@projmux_app` option is set by the generated app config. Missing servers,
|
|
1319
|
+
default tmux servers, embedded tmux servers, and other tmux runtimes without
|
|
1320
|
+
that marker are no-ops. Non-interactive callers must pass `--yes` or
|
|
1321
|
+
`--force`; the default command always goes through the action picker.
|
|
1322
|
+
- `attach project <ref>` — enter a Project runtime from outside tmux.
|
|
1323
|
+
Automatic live-runtime attachment is `runtime attach`.
|
|
1324
|
+
- `settings` — interactive configuration UI for the project picker, AI
|
|
1325
|
+
splits, Notifications, Appearance mode, Project Root management, the
|
|
1326
|
+
switcher's saved workdirs list, Labs (experimental), Settings > Keybindings,
|
|
1327
|
+
and About/Update status. The keybinding flow is a single
|
|
1328
|
+
`Settings > Keybindings` action list with simplified action details for
|
|
1329
|
+
aliases and reset. Key save/reset automatically writes the key list,
|
|
1330
|
+
regenerates the app config, and reloads the running tmux session when
|
|
1331
|
+
possible; skipped or failed stages show `projmux config apply` as the recovery
|
|
1332
|
+
or sync command. Terminal diagnostics and terminal mapping application stay
|
|
1333
|
+
in the `projmux shell` -> `projmux setup` -> `projmux setup terminal`
|
|
1334
|
+
remediation path.
|
|
1335
|
+
The compact About section contains Version, Source, real update
|
|
1336
|
+
status/actions, Welcome, and Quit. It does not duplicate static setup or
|
|
1337
|
+
diagnostics guides: use `projmux setup` for key-delivery diagnosis,
|
|
1338
|
+
`projmux setup terminal` for supported terminal remediation, and the
|
|
1339
|
+
read-only `projmux doctor` report for dependency/runtime diagnostics. In Project
|
|
1340
|
+
Picker, `Project Root` manages the saved
|
|
1341
|
+
primary root (`~/.config/projmux/projdir`) and displays whether the effective
|
|
1342
|
+
value comes from `PROJMUX_PROJDIR`, tmux `@projmux_projdir`, saved config, or
|
|
1343
|
+
no configured source. When no source is configured, the direct-set prompt
|
|
1344
|
+
starts with `$HOME` as an editable fallback, but `$HOME` is not used as the
|
|
1345
|
+
effective root unless saved. `Workdirs` remains separate: those entries are
|
|
1346
|
+
additional search roots, not the primary root. Appearance stores per-surface
|
|
1347
|
+
path/git/notify icon decoration as `off` (default), `symbol`, or `emoji` and
|
|
1348
|
+
updates the matching live tmux option when available. Labs remains
|
|
1349
|
+
available for experimental settings. The About section reads the cached
|
|
1350
|
+
update status without network access;
|
|
1351
|
+
selecting Check Updates runs `projmux update check`, Update Now runs
|
|
1352
|
+
`projmux update apply`, and Welcome opens a Settings-native viewer
|
|
1353
|
+
independent of shell skip state. `Settings > About > Quit projmux` routes
|
|
1354
|
+
through the same `projmux quit` action picker. Settings mutations surface
|
|
1355
|
+
their handled success/failure as a transient passive row inside the native
|
|
1356
|
+
popup; selecting the next action clears or replaces that row.
|
|
1357
|
+
|
|
1358
|
+
## See also
|
|
1359
|
+
|
|
1360
|
+
- [cli.md](cli.md) — the generated CLI reference: the authoritative route,
|
|
1361
|
+
sub-route, output-mode, and field-projection inventory for this build.
|
|
1362
|
+
- [npm-distribution.md](npm-distribution.md) — npm binary package layout.
|
|
1363
|
+
- [statusbar.md](statusbar.md) — two-line layout and click range catalogue.
|
|
1364
|
+
- [notify-queue.md](notify-queue.md) — queue file format and lifecycle.
|
|
1365
|
+
- [usage-tracking.md](usage-tracking.md) — adapter HTTP/file behaviour.
|
|
1366
|
+
- [keybindings.md](keybindings.md) — terminal key delivery and aliases.
|
|
1367
|
+
- [hooks.md](hooks.md) — lifecycle hooks, startup commands, and `send-noti` payload contract.
|