projmux 0.15.3 → 0.16.1
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 +3 -4
- package/README.md +3 -3
- package/docs/agent-message-replies.md +149 -6
- package/docs/ai-agent-shortcuts.md +6 -5
- package/docs/architecture.md +467 -66
- package/docs/claude-coordination-endpoints.md +192 -20
- package/docs/cli-guide.md +872 -148
- package/docs/cli.md +1459 -485
- package/docs/codex-installed-compatibility.md +6 -11
- package/docs/codex-native-required-migration.md +1 -59
- package/docs/configuration.md +694 -222
- package/docs/globalization.md +18 -5
- package/docs/hooks.md +529 -62
- package/docs/keybindings.md +74 -4
- package/docs/legacy-cli-retirement.md +3 -3
- package/docs/legacy-diagnostics-inventory.md +4 -4
- package/docs/native-picker.md +3 -5
- package/docs/notify-queue.md +1 -1
- package/docs/npm-distribution.md +4 -0
- package/docs/operational-diagnostics.md +319 -34
- package/docs/pr-guideline.md +66 -22
- package/docs/release.md +101 -0
- package/docs/replacement-contract.md +72 -58
- package/docs/repo-layout.md +3 -0
- package/docs/resource-attribution.md +6 -2
- package/docs/session-restore.md +50 -80
- package/docs/settings-ia.md +14 -22
- package/docs/statusbar.md +38 -37
- package/docs/testing.md +83 -18
- package/docs/theme-palette.md +6 -6
- package/docs/tmux-surface-inventory.md +21 -10
- package/docs/troubleshooting.md +2 -4
- package/docs/upgrading.md +161 -24
- package/docs/usage-tracking.md +40 -49
- package/package.json +5 -5
- package/docs/agent-workflow.md +0 -2596
- package/docs/codex-generation-pool.md +0 -623
- package/docs/codex-stored-qualification.md +0 -45
package/docs/configuration.md
CHANGED
|
@@ -4,6 +4,31 @@ Most users can configure projmux from `projmux settings`. Environment variables
|
|
|
4
4
|
are available for repeatable shell setup, managed machines, or advanced
|
|
5
5
|
overrides.
|
|
6
6
|
|
|
7
|
+
## XDG Base Directories
|
|
8
|
+
|
|
9
|
+
Paths in this guide written as `${XDG_CONFIG_HOME:-$HOME/.config}` and the like
|
|
10
|
+
follow one rule for `XDG_CONFIG_HOME`, `XDG_STATE_HOME`, `XDG_DATA_HOME`, and
|
|
11
|
+
`XDG_CACHE_HOME`. Surrounding whitespace is trimmed, and the value is used only
|
|
12
|
+
when it is an absolute path. An unset, empty, blank, or relative value
|
|
13
|
+
(`rel`, `./rel`, or an unexpanded `~/x`) is ignored as unset, as the
|
|
14
|
+
[XDG Base Directory specification](https://specifications.freedesktop.org/basedir-spec/latest/)
|
|
15
|
+
requires, and the default under `$HOME` applies instead:
|
|
16
|
+
|
|
17
|
+
| Variable | Default |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `XDG_CONFIG_HOME` | `$HOME/.config` |
|
|
20
|
+
| `XDG_STATE_HOME` | `$HOME/.local/state` |
|
|
21
|
+
| `XDG_DATA_HOME` | `$HOME/.local/share` |
|
|
22
|
+
| `XDG_CACHE_HOME` | `$HOME/.cache` |
|
|
23
|
+
|
|
24
|
+
When `HOME` is unset or empty and the variable a path needs is not an
|
|
25
|
+
absolute path, that path has no location, and projmux never falls back to a
|
|
26
|
+
path relative to the working directory. A read of saved settings or state
|
|
27
|
+
keeps the built-in default and touches no file. A write writes nothing and
|
|
28
|
+
exits non-zero with a one-line reason naming the variables, such as
|
|
29
|
+
`HOME or an absolute XDG_CONFIG_HOME is required`. A path display such as
|
|
30
|
+
`projmux hook list` shows that reason in place of the path.
|
|
31
|
+
|
|
7
32
|
## Operational diagnostics state
|
|
8
33
|
|
|
9
34
|
Projmux keeps a private bounded operational journal at:
|
|
@@ -38,25 +63,30 @@ those folders exist:
|
|
|
38
63
|
|
|
39
64
|
It does not assume a canonical repo root.
|
|
40
65
|
|
|
41
|
-
Use Settings >
|
|
66
|
+
Use `Settings > Global > Projects` for the normal interactive flow:
|
|
42
67
|
|
|
43
|
-
- `
|
|
44
|
-
-
|
|
45
|
-
|
|
68
|
+
- `Primary discovery root` sets, changes, or clears the saved primary root.
|
|
69
|
+
- `Additional discovery roots > Add path` appends one directory to the saved
|
|
70
|
+
workdirs list.
|
|
71
|
+
- `Additional discovery roots` reviews saved workdirs; each root's
|
|
72
|
+
`Remove discovery root` removes it.
|
|
46
73
|
|
|
47
|
-
`Add
|
|
74
|
+
`Add path > Type path manually...` skips the filesystem scan and is useful
|
|
48
75
|
for large mounts, WSL paths, NFS paths, or temporary project roots.
|
|
49
76
|
|
|
50
77
|
The saved workdir file is:
|
|
51
78
|
|
|
52
79
|
```text
|
|
53
|
-
|
|
80
|
+
$HOME/.config/projmux/workdirs
|
|
54
81
|
```
|
|
55
82
|
|
|
83
|
+
This file does not follow `XDG_CONFIG_HOME`; see
|
|
84
|
+
[Setting Layers](#setting-layers).
|
|
85
|
+
|
|
56
86
|
It stores one absolute path per line. Lines beginning with `#` are comments.
|
|
57
87
|
The file is read only when no env root list is set.
|
|
58
88
|
|
|
59
|
-
|
|
89
|
+
Saved workdirs are a **scan source and nothing else**. Adding a root, and scanning one,
|
|
60
90
|
never registers a Registry Project: a discovered child is an unregistered
|
|
61
91
|
candidate until `projmux create project --root <path>` or opening it once from the
|
|
62
92
|
Projects sidebar registers that exact path. See
|
|
@@ -67,7 +97,7 @@ Projects sidebar registers that exact path. See
|
|
|
67
97
|
Pins are presentation preferences, stored typed:
|
|
68
98
|
|
|
69
99
|
```text
|
|
70
|
-
|
|
100
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/pins
|
|
71
101
|
```
|
|
72
102
|
|
|
73
103
|
```text
|
|
@@ -92,51 +122,11 @@ request with `projmux pin project migrate`; see
|
|
|
92
122
|
[upgrading.md](upgrading.md#pins-are-typed-and-migrate-on-request) for the
|
|
93
123
|
per-line outcomes and the ambiguity refusal.
|
|
94
124
|
|
|
95
|
-
## Legacy Project Layout
|
|
96
|
-
|
|
97
|
-
Older checkouts may already have named layout snapshots in the legacy storage
|
|
98
|
-
directory:
|
|
99
|
-
|
|
100
|
-
```text
|
|
101
|
-
<project>/.projmux/layouts/<name>.toml
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
The project context comes from `PROJMUX_CWD` when set, otherwise projmux walks
|
|
105
|
-
upward from the current directory to the nearest `.projmux` or `.git` marker.
|
|
106
|
-
Files outside that project tree are not discovered. This storage is treated as
|
|
107
|
-
legacy import data for explicit conversion and preview. Closed-Project startup
|
|
108
|
-
does not expose legacy snapshot choices; current user-facing surfaces describe
|
|
109
|
-
the restore unit as a snapshot, not as a separate layout or preset feature.
|
|
110
|
-
|
|
111
|
-
The legacy schema is intentionally close to the session-state snapshot shape:
|
|
125
|
+
## Legacy Project Layout Files
|
|
112
126
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
mode = "inherit-autosave" # default; or "fresh-each-time"
|
|
117
|
-
default_cwd = "${PROJMUX_CWD}"
|
|
118
|
-
|
|
119
|
-
[[windows]]
|
|
120
|
-
index = 0
|
|
121
|
-
name = "main"
|
|
122
|
-
layout = "..."
|
|
123
|
-
active_pane_index = 0
|
|
124
|
-
|
|
125
|
-
[[windows.panes]]
|
|
126
|
-
index = 0
|
|
127
|
-
cwd = "${PROJMUX_CWD}"
|
|
128
|
-
command = "make watch"
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
`command` records a startup recipe, matching the supported session-state replay
|
|
132
|
-
recipe. Panes without `command` may use `recipe = "shell"`. Supported
|
|
133
|
-
interpolation placeholders are limited to `${PROJMUX_CWD}` and
|
|
134
|
-
`${PROJMUX_SESSION}`; other `${...}` values are rejected during load.
|
|
135
|
-
|
|
136
|
-
Unknown fields and unknown sections are ignored so future schema additions do
|
|
137
|
-
not break older files. The built-in parser only accepts quoted strings and
|
|
138
|
-
integer values for the known fields above; it does not implement the full TOML
|
|
139
|
-
language.
|
|
127
|
+
Older checkouts may still have named layout files under
|
|
128
|
+
`<project>/.projmux/layouts/*.toml`. projmux no longer reads, writes, trusts,
|
|
129
|
+
or deletes them; they have no effect and can be removed by hand.
|
|
140
130
|
|
|
141
131
|
## Keymap File
|
|
142
132
|
|
|
@@ -155,8 +145,9 @@ terminal-layer remediation, first try the key in `projmux shell`, then run
|
|
|
155
145
|
`projmux setup` from the raw terminal, then use `projmux setup terminal` for
|
|
156
146
|
supported terminal adapters.
|
|
157
147
|
|
|
158
|
-
|
|
159
|
-
absent, generated tmux config stays on the built-in
|
|
148
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/keymap.toml` can also be edited by
|
|
149
|
+
hand. When the file is absent, generated tmux config stays on the built-in
|
|
150
|
+
defaults.
|
|
160
151
|
|
|
161
152
|
Supported schema:
|
|
162
153
|
|
|
@@ -234,7 +225,7 @@ popup action with no built-in shortcut. Every configured alias renders the
|
|
|
234
225
|
canonical client-scoped body
|
|
235
226
|
`projmux internal tmux popup-toggle --client #{client_tty} resource-inspector`; pressing
|
|
236
227
|
the same alias again closes only that client's popup. It remains available on
|
|
237
|
-
Linux/tmux even when the
|
|
228
|
+
Linux/tmux even when the `Status Bar > Resources` live-resource segment is off.
|
|
238
229
|
|
|
239
230
|
The Settings writer is deterministic and rewrites the supported saved subset
|
|
240
231
|
only. If the existing file has parse errors or unknown action IDs, Settings
|
|
@@ -261,13 +252,14 @@ Theme is a global user preference. The effective theme resolves from the global
|
|
|
261
252
|
user theme plus a built-in fallback only:
|
|
262
253
|
|
|
263
254
|
```text
|
|
264
|
-
|
|
255
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml
|
|
265
256
|
built-in fallback preset
|
|
266
257
|
```
|
|
267
258
|
|
|
268
|
-
Settings edits the global `[theme]` in
|
|
269
|
-
Effective theme
|
|
270
|
-
|
|
259
|
+
Settings edits the global `[theme]` in
|
|
260
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml`. The Effective theme
|
|
261
|
+
view shows the final global > built-in fallback value for each field with
|
|
262
|
+
source labels: `global` or `fallback`. Saving or resetting a theme
|
|
271
263
|
value live-applies it: projmux regenerates the generated tmux config and, when
|
|
272
264
|
Settings runs inside tmux, `tmux source-file`-reloads it so a running server
|
|
273
265
|
repaints immediately. Outside tmux the save still succeeds and the report
|
|
@@ -402,7 +394,7 @@ Preferred interactive path:
|
|
|
402
394
|
Global config path:
|
|
403
395
|
|
|
404
396
|
```text
|
|
405
|
-
|
|
397
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml
|
|
406
398
|
```
|
|
407
399
|
|
|
408
400
|
Schema:
|
|
@@ -465,30 +457,11 @@ in-flight process decision, then retries proxy initialization with a bounded
|
|
|
465
457
|
backoff. Projmux never automatically stops, kills, restarts, adopts, or enables
|
|
466
458
|
remote control on the shared app server.
|
|
467
459
|
|
|
468
|
-
The
|
|
460
|
+
The `Codex` row in the provider picker launches immediately through the
|
|
469
461
|
canonical create route. It does not start or probe the app-server, call
|
|
470
462
|
`model/list`, or add `--model` or `model_reasoning_effort`; the Codex process
|
|
471
|
-
therefore keeps its own configured defaults.
|
|
472
|
-
|
|
473
|
-
The separate `Codex advanced launch` action uses the readiness path to read
|
|
474
|
-
every page of the current app-server `model/list`. Its second picker shows only
|
|
475
|
-
visible models and their advertised reasoning efforts. The display also carries
|
|
476
|
-
the advertised default, supported input modalities, and whether personality is
|
|
477
|
-
supported; the boolean personality capability is not expanded into invented
|
|
478
|
-
personality choices. The selected model and effort are launch-only CLI
|
|
479
|
-
overrides (`--model` and `--config model_reasoning_effort=...`); Projmux never
|
|
480
|
-
writes a Codex configuration file. Each normalized catalog is tied to its live
|
|
481
|
-
connection and negotiated-version epoch. Projmux retains that connection from
|
|
482
|
-
picker render through pre-create validation and refreshes `model/list` before
|
|
483
|
-
building argv, so a disconnect or removed option invalidates the selection. If
|
|
484
|
-
advanced discovery fails, is empty, or comes from an older Codex, that action
|
|
485
|
-
reports the exact unavailable reason and creates nothing; the separate default
|
|
486
|
-
`Codex` row remains available.
|
|
487
|
-
|
|
488
|
-
Picker chrome and semantic annotations such as default, unspecified modality,
|
|
489
|
-
and personality support use the Projmux message catalog. Model display names,
|
|
490
|
-
effort identifiers, and advertised modality tags remain exact provider data and
|
|
491
|
-
are not translated.
|
|
463
|
+
therefore keeps its own configured defaults. The picker has no per-launch model
|
|
464
|
+
or effort row.
|
|
492
465
|
|
|
493
466
|
`projmux agent review` starts `review/start` only for a Running Codex Agent whose
|
|
494
467
|
Registry Agent, owned Pane, activation generation, stored thread, and live Pane
|
|
@@ -499,21 +472,33 @@ or a method-not-found response are reported explicitly as unavailable. The
|
|
|
499
472
|
initial `review/start` response is projected into Agent interaction lifecycle;
|
|
500
473
|
the lifecycle observer described below owns later app-server terminal events.
|
|
501
474
|
|
|
502
|
-
A natively created or resumed Codex Agent keeps a
|
|
475
|
+
A natively created or resumed Codex Agent keeps a lifecycle
|
|
503
476
|
observer on its exact Agent UID, Pane UID/runtime handle, activation generation,
|
|
504
477
|
and thread ID. While its initialized proxy connection and snapshot are current,
|
|
505
478
|
the app server is the only attention authority: active, idle, waiting for input,
|
|
506
479
|
and exact unresolved approval requests project the Agent interaction and badge.
|
|
507
|
-
|
|
508
|
-
|
|
480
|
+
The native observer refreshes a continuing turn or wait before the 30-minute
|
|
481
|
+
interaction freshness window expires. A `requestUserInput` request projects
|
|
482
|
+
`input_required` even before a separate thread-status update arrives; its
|
|
483
|
+
resolution or the turn's completion releases that state. When the question
|
|
484
|
+
channel is on, blocking Codex questions can be listed and answered through
|
|
485
|
+
`agent question list` and `agent question answer`.
|
|
486
|
+
An exact successful `turn/completed` projects response-complete and queues a
|
|
487
|
+
completion notification with the last agent message (or `Ready` if none is
|
|
488
|
+
available). A failed turn or `systemError` queues a critical `error` notification
|
|
489
|
+
and sends an OS notification when desktop delivery is enabled. HTTP 401 is
|
|
490
|
+
identified without copying the provider error text or credentials. Interrupted
|
|
491
|
+
turns become idle. Disconnect
|
|
509
492
|
and thread unload first invalidate the epoch and clear stale attention, then
|
|
510
493
|
enable hook fallback. A reconnect starts a new epoch from `thread/read`; events
|
|
511
494
|
from older epochs or other identities are ignored.
|
|
512
495
|
|
|
513
496
|
`describe agent` and the Codex Agent event Settings page report the effective
|
|
514
497
|
lifecycle source, a closed reason, and active/pending/inactive epoch status.
|
|
515
|
-
|
|
516
|
-
|
|
498
|
+
The observer holds the latest agent message only until completion delivery;
|
|
499
|
+
the notify queue applies its 80-rune text limit. These diagnostics never retain
|
|
500
|
+
prompts, reasoning, output, approval reasons, or diff content. Settings
|
|
501
|
+
aggregates multiple live Codex Panes as counts and says
|
|
517
502
|
`mixed` when native and fallback authority coexist.
|
|
518
503
|
|
|
519
504
|
Projmux does not install, bootstrap, restart, stop, or reconfigure the Codex
|
|
@@ -536,8 +521,8 @@ one writes only the global `[ai] split_cwd_from`.
|
|
|
536
521
|
Config paths (global and project both honored):
|
|
537
522
|
|
|
538
523
|
```text
|
|
539
|
-
|
|
540
|
-
<project>/.projmux/config.toml
|
|
524
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml # global
|
|
525
|
+
<project>/.projmux/config.toml # project
|
|
541
526
|
```
|
|
542
527
|
|
|
543
528
|
Schema:
|
|
@@ -582,6 +567,40 @@ with `--cwd-from pane`, and as one client message for a split started from the
|
|
|
582
567
|
UI. A split is never refused for this reason. `--cwd` on `create agent` still
|
|
583
568
|
names the Agent working directory outright and ignores this setting.
|
|
584
569
|
|
|
570
|
+
## Enabled AI Providers
|
|
571
|
+
|
|
572
|
+
Disabled providers are a central policy, stored in
|
|
573
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-enabled-agents`, that the CLI
|
|
574
|
+
honors as well as the UI: `create agent`, `create window --provider`, and
|
|
575
|
+
`agent resume` refuse a disabled provider, and the refusal names the command
|
|
576
|
+
that re-enables it.
|
|
577
|
+
`projmux config providers` lists every provider as `<id> enabled` or
|
|
578
|
+
`<id> disabled`; `projmux config providers --enable <id>` and
|
|
579
|
+
`--disable <id>` change one through the same writer as
|
|
580
|
+
`Settings > Global > AI > Enabled providers`. A missing file means every
|
|
581
|
+
provider is enabled; disabling every provider persists as none enabled.
|
|
582
|
+
|
|
583
|
+
## New AI Window Default
|
|
584
|
+
|
|
585
|
+
The mode a new AI window opens with has a central default, one word stored
|
|
586
|
+
at:
|
|
587
|
+
|
|
588
|
+
```text
|
|
589
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-new-window-mode
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
The word is one of `claude`, `codex`, `antigravity`, `selective`, `resume`,
|
|
593
|
+
or `shell`. In the terminal the mode resolves in this order: the TUI split
|
|
594
|
+
default `tmux-ai-split-mode` when it holds one of those words, then this
|
|
595
|
+
central file, then `selective`. A missing, empty, or invalid TUI value falls
|
|
596
|
+
through to the central file; a missing, empty, or invalid central file means
|
|
597
|
+
not set.
|
|
598
|
+
|
|
599
|
+
`projmux settings` and `projmux config edit --set` keep writing
|
|
600
|
+
`tmux-ai-split-mode`. `projmux config edit --set` rejects any other word with
|
|
601
|
+
exit 2 and leaves the file unchanged. No command writes the central file yet;
|
|
602
|
+
edit it by hand or from another front end.
|
|
603
|
+
|
|
585
604
|
## AI Resume Picker
|
|
586
605
|
|
|
587
606
|
The Agent resume picker lists the most recent
|
|
@@ -591,13 +610,13 @@ the defaults are 30 rows and depth 0 (the current directory only).
|
|
|
591
610
|
|
|
592
611
|
Preferred interactive path:
|
|
593
612
|
|
|
594
|
-
- `Settings > AI
|
|
613
|
+
- `Settings > Global > AI > Agent Resume Picker` (`Picker limit`, `Scan depth`)
|
|
595
614
|
|
|
596
615
|
Config paths (global and project both honored):
|
|
597
616
|
|
|
598
617
|
```text
|
|
599
|
-
|
|
600
|
-
<project>/.projmux/config.toml
|
|
618
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml # global
|
|
619
|
+
<project>/.projmux/config.toml # project
|
|
601
620
|
```
|
|
602
621
|
|
|
603
622
|
Schema:
|
|
@@ -649,17 +668,8 @@ existence/mtime. They do not open SQLite content and do not treat `.db-wal`,
|
|
|
649
668
|
latest-session floor rather than complete history. Missing/malformed cache,
|
|
650
669
|
workspace-less metadata, and stale mappings degrade to legacy `history.jsonl`
|
|
651
670
|
without changing the shared exact/depth/sort/cap behavior.
|
|
652
|
-
Live hook
|
|
653
|
-
|
|
654
|
-
its source is persisted so Session State preview and doctor can report medium
|
|
655
|
-
confidence for DB-validated cache sources or low confidence for legacy history.
|
|
656
|
-
|
|
657
|
-
Session State saves the exact bound Codex session/thread id before considering
|
|
658
|
-
discovery. An existing bound session id or persisted resume id is replayed
|
|
659
|
-
without an app-server read. Only a thread-only candidate is validated with
|
|
660
|
-
`thread/read` and `includeTurns=false`; this validation is probe-only and never
|
|
661
|
-
starts the shared daemon. Failure retains the persisted id or uses the current
|
|
662
|
-
rollout fallback, and a read response can never substitute a different id.
|
|
671
|
+
Live hook resume metadata is a separate high-confidence lane and is not a
|
|
672
|
+
disk-picker candidate.
|
|
663
673
|
|
|
664
674
|
## Release channel
|
|
665
675
|
|
|
@@ -669,7 +679,7 @@ to the install path: every installer can be judged on either channel.
|
|
|
669
679
|
Files:
|
|
670
680
|
|
|
671
681
|
```text
|
|
672
|
-
|
|
682
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml # global/user
|
|
673
683
|
```
|
|
674
684
|
|
|
675
685
|
Schema:
|
|
@@ -703,7 +713,7 @@ installed; that install stays put until its stable line ships.
|
|
|
703
713
|
|
|
704
714
|
| Variable | Purpose |
|
|
705
715
|
| --- | --- |
|
|
706
|
-
| `PROJMUX_PROJDIR` | Explicit primary project root. Accepts an OS-native PATH-style multi-value: the first non-empty entry is the primary root and later entries are prepended to managed-root discovery. The primary value is memoized to
|
|
716
|
+
| `PROJMUX_PROJDIR` | Explicit primary project root. Accepts an OS-native PATH-style multi-value: the first non-empty entry is the primary root and later entries are prepended to managed-root discovery. The primary value is memoized to `$HOME/.config/projmux/projdir` (see [Setting Layers](#setting-layers)). The legacy `PROJDIR` and `RP` env vars are no longer honored. |
|
|
707
717
|
| `PROJMUX_MANAGED_ROOTS` | Search-root override. Uses the OS-native path-list separator and takes priority over the saved workdirs file and default weak probes. |
|
|
708
718
|
| `TMUX_SESSIONIZER_ROOTS` | Legacy alias still honored at runtime for managed roots. |
|
|
709
719
|
| `PROJMUX_LOCALE` | UI locale override. `auto` resumes detection; `en-US` and `ko-KR` pin supported locales. Unsupported tags fall back to `en-US` and surface a Settings warning. |
|
|
@@ -715,12 +725,12 @@ installed; that install stays put until its stable line ships.
|
|
|
715
725
|
| `PROJMUX_DESKTOP_NOTIFY_MODE` | OS desktop notification mode override. `off` / `none` / `notify` (case insensitive). When set, this takes priority over every other resolution rung. The in-app notify queue is not affected. The retired `raise` / `auto-raise` / `autoraise` literals are still accepted and read as `notify`. |
|
|
716
726
|
| `PROJMUX_DESKTOP_NOTIFY` | Legacy on/off override kept for backward compatibility. `on` maps to `notify`, `off` maps to `none`. Honored only when `PROJMUX_DESKTOP_NOTIFY_MODE` is unset. |
|
|
717
727
|
| `PROJMUX_WSL_TOAST_ICON_DIR` | Directory used when copying the WSL toast icon into a Windows-readable path. |
|
|
718
|
-
| `PROJMUX_USAGE_STATE_DIR` | Override directory for AI usage snapshots. Defaults to `<state>/projmux/usage`. Point this at a synced directory to share authoritative usage across machines. |
|
|
728
|
+
| `PROJMUX_USAGE_STATE_DIR` | Override directory for AI usage snapshots. Defaults to `<state>/projmux/usage`. Point this at a synced directory to share authoritative usage across machines. The value is used as given, with no `~` expansion. |
|
|
719
729
|
| `PROJMUX_USAGE_DEBUG` | When non-empty, prints adapter errors from the `projmux internal status usage` renderer to stderr. |
|
|
720
730
|
| `PROJMUX_USAGE_LIMITS_PATH` | Deprecated. Read but ignored; limits now come from upstream APIs and local Codex rollout state. |
|
|
721
|
-
| `PROJMUX_SESSIONSTATE_AUTOSAVE` |
|
|
722
|
-
| `PROJMUX_SESSIONSTATE_DEBUG` |
|
|
723
|
-
| `PROJMUX_FOCUS_DEBUG` | When non-empty, `projmux focus` prints one telemetry line to stderr. |
|
|
731
|
+
| `PROJMUX_SESSIONSTATE_AUTOSAVE` | Ignored. Project snapshots and their auto-save were removed. |
|
|
732
|
+
| `PROJMUX_SESSIONSTATE_DEBUG` | Ignored. It only gated stderr for the removed quiet autosave. |
|
|
733
|
+
| `PROJMUX_FOCUS_DEBUG` | When non-empty, `projmux focus` prints one telemetry line to stderr with the target, session, window, pane, socket, client, source, and kind. |
|
|
724
734
|
| `PROJMUX_INSTALLER` | Installer source hint used by update flows. npm installs set this automatically; advanced release installs can set `github-release`. |
|
|
725
735
|
| `PROJMUX_RELEASE_CHANNEL` | Release channel the update judgment is made against, orthogonal to `PROJMUX_INSTALLER`. Only an exact `rc` opts in; unset, empty, and unrecognised values all mean the default `stable` channel, which never sees a prerelease. An rc install is answered with whichever of the stable and rc lines is newer, so it returns to stable as soon as that line ships. Read only until `[update] release_channel` exists; see [Release channel](#release-channel). |
|
|
726
736
|
| `PROJMUX_SHELL_UPDATE_CHECK_TIMEOUT_MS` | Timeout in milliseconds for the best-effort release check attempted by `projmux shell` when the update cache is missing or stale. Invalid, zero, or negative values use the default. |
|
|
@@ -771,7 +781,7 @@ export PROJMUX_PROJDIR="/main/repos:/srv/work/repos"
|
|
|
771
781
|
On Linux and macOS the separator is `:`. On Windows-style paths the separator
|
|
772
782
|
is `;`.
|
|
773
783
|
|
|
774
|
-
## tmux
|
|
784
|
+
## tmux Primary Discovery Root Option
|
|
775
785
|
|
|
776
786
|
The switch command also reads this tmux option:
|
|
777
787
|
|
|
@@ -782,6 +792,134 @@ set-option -g @projmux_projdir /path/to/repos
|
|
|
782
792
|
An env `PROJMUX_PROJDIR` value takes priority over the tmux option. The tmux
|
|
783
793
|
option takes priority over the saved projdir file.
|
|
784
794
|
|
|
795
|
+
The saved projdir file is `$HOME/.config/projmux/projdir`. It does not follow
|
|
796
|
+
`XDG_CONFIG_HOME`; see [Setting Layers](#setting-layers).
|
|
797
|
+
|
|
798
|
+
## Agent Question Answering
|
|
799
|
+
|
|
800
|
+
How a Claude Agent's `AskUserQuestion` or a Codex Agent's blocking
|
|
801
|
+
`requestUserInput` is answered is one word stored at:
|
|
802
|
+
|
|
803
|
+
```text
|
|
804
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/agent-question-answering
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
| Value | Way | Meaning |
|
|
808
|
+
| --- | --- | --- |
|
|
809
|
+
| `claude` (default) | 1 | The provider shows its own question prompt; projmux stays out of it |
|
|
810
|
+
| `projmux` | 2 | projmux records the question for `projmux agent question list` and `answer`; Claude and native Codex also open the question picker in a tmux popup |
|
|
811
|
+
|
|
812
|
+
Set it with `projmux config agent-questions --answering <claude|projmux>`,
|
|
813
|
+
or write the file. The setting applies to every Claude and native Codex Agent on this machine. The value
|
|
814
|
+
is read case-insensitively with surrounding whitespace ignored. A
|
|
815
|
+
missing, empty, or unreadable file, and any other value, is way 1. An Agent
|
|
816
|
+
opted in with `projmux agent question enable` is way 2 whatever the file
|
|
817
|
+
says. Codex handles only blocking app-server requests; a Codex Agent on the
|
|
818
|
+
plain CLI lane has no app-server question channel. A Codex question set with an
|
|
819
|
+
`isSecret` question stays in Codex's own input surface: projmux does not open
|
|
820
|
+
an unmasked popup. `agent question list` points the operator to that window,
|
|
821
|
+
and `agent question answer` refuses that set so secret text is not passed in
|
|
822
|
+
command arguments. Other blocking Codex questions use the same popup and CLI
|
|
823
|
+
answer paths as Claude. For Claude, the setting
|
|
824
|
+
applies only to a projmux Agent's own conversation; other Claude sessions and
|
|
825
|
+
subagents always get way 1. See
|
|
826
|
+
[hooks.md](hooks.md#answering-askuserquestion-in-projmux).
|
|
827
|
+
|
|
828
|
+
## Agent Question Window
|
|
829
|
+
|
|
830
|
+
In way 2 the Claude question hook or Codex native observer holds the question
|
|
831
|
+
for a command-line answer for a seconds window stored at:
|
|
832
|
+
|
|
833
|
+
```text
|
|
834
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/agent-question-window-seconds
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
Set it with `projmux config agent-questions --window <seconds|unlimited>`, or
|
|
838
|
+
write the file. The value is integer seconds, default `900`, in `60`–`86400`, or the
|
|
839
|
+
word `unlimited` (case-insensitive), which holds the question until it is
|
|
840
|
+
answered. Claude Code has no "no timeout" hook value, so `unlimited` is
|
|
841
|
+
effectively capped at `604785` seconds (about 7 days): the installed hook
|
|
842
|
+
timeout ceiling less the 15 second margin that lets the hook, not Claude Code,
|
|
843
|
+
end the wait. A value outside the range, or a file that holds neither one
|
|
844
|
+
integer nor `unlimited`, reads as `900`; a projmux older than the word also
|
|
845
|
+
reads `unlimited` as `900`, and a projmux from before the maximum was raised
|
|
846
|
+
from `3600` reads a value above `3600` as `900`, so downgrading only shortens
|
|
847
|
+
the wait. It applies only in way 2 (see
|
|
848
|
+
[Agent Question Answering](#agent-question-answering)); way 1 never waits.
|
|
849
|
+
For Codex, an expired or disabled held request is closed in the question list.
|
|
850
|
+
The same question remains visible and answerable in Codex's own input surface;
|
|
851
|
+
projmux does not send a substitute answer. The Codex turn continues when the
|
|
852
|
+
operator answers there.
|
|
853
|
+
If Codex's input surface answers first, the question list records
|
|
854
|
+
`answered-elsewhere`, and a later `agent question answer` is refused with that
|
|
855
|
+
reason. A resolution after the command-line deadline remains `expired`.
|
|
856
|
+
|
|
857
|
+
The installed Claude Code hook `timeout` is the fixed ceiling `604800` seconds
|
|
858
|
+
(7 days) and does not depend on this file. The ceiling is the safety net for a
|
|
859
|
+
stuck hook, and this hook has no recover: 7 days is 7 times the longest
|
|
860
|
+
bounded window (86400 seconds), so it never cuts a normal window, while a
|
|
861
|
+
broken hook is reclaimed within a week. The hook rereads the window for every
|
|
862
|
+
question, so a changed window applies to the next question without re-running
|
|
863
|
+
`projmux agent integrate claude`.
|
|
864
|
+
|
|
865
|
+
Hooks installed by an older projmux carry an old timeout: the window read at
|
|
866
|
+
integration plus 15 seconds (`915` by default), or the earlier, longer
|
|
867
|
+
ceiling of about 25 days. After installing this version, run
|
|
868
|
+
`projmux agent integrate claude` once to rewrite either entry to the
|
|
869
|
+
ceiling; until then Claude Code still ends the hook at the old timeout and a
|
|
870
|
+
longer window gives the question back to the ordinary prompt then.
|
|
871
|
+
See [hooks.md](hooks.md#answering-askuserquestion-in-projmux).
|
|
872
|
+
|
|
873
|
+
## Agent Approval Answering
|
|
874
|
+
|
|
875
|
+
How an Agent's permission request ("Do you want to proceed?") is answered is
|
|
876
|
+
one word stored at:
|
|
877
|
+
|
|
878
|
+
```text
|
|
879
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/agent-approval-answering
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
It is a separate setting from [Agent Question Answering](#agent-question-answering).
|
|
883
|
+
Its effect is to capture Claude permission requests and to allow remote
|
|
884
|
+
(non-interactive) answers with `projmux agent approval answer` for both Claude
|
|
885
|
+
and Codex Agents. Codex approvals are never captured, since the Codex
|
|
886
|
+
app-server holds them: `projmux agent approval list` shows them and
|
|
887
|
+
`projmux agent approval review` answers them in either way.
|
|
888
|
+
|
|
889
|
+
| Value | Meaning |
|
|
890
|
+
| --- | --- |
|
|
891
|
+
| `claude` (default) | Claude Code shows its own permission prompt; the permission hook prints nothing and records nothing; `projmux agent approval answer` is refused for Claude and Codex Agents |
|
|
892
|
+
| `projmux` | projmux also records a Claude request, and `projmux agent approval answer` can allow or deny it once; it can also allow once (`accept`) or deny a pending Codex approval (`decline` when offered, otherwise `cancel`, which also interrupts the turn). The provider's own prompt stays usable, and the first answer wins |
|
|
893
|
+
|
|
894
|
+
Set it with `projmux config agent-approvals --answering <claude|projmux>`, or
|
|
895
|
+
write the file. The value is read case-insensitively with surrounding
|
|
896
|
+
whitespace ignored; a missing, empty, or unreadable file, and any other value,
|
|
897
|
+
is `claude`. It applies to every Claude Agent on this machine, but only to
|
|
898
|
+
requests from a projmux Claude Agent's own conversation, including its
|
|
899
|
+
subagents; other Claude sessions, and a session in `bypassPermissions` or
|
|
900
|
+
`dontAsk` mode, never have a request captured. See
|
|
901
|
+
[hooks.md](hooks.md#answering-claude-permission-requests-in-projmux).
|
|
902
|
+
|
|
903
|
+
## Agent Approval Window
|
|
904
|
+
|
|
905
|
+
While the setting is `projmux`, the permission hook holds each request open
|
|
906
|
+
for an answer for a seconds window stored at:
|
|
907
|
+
|
|
908
|
+
```text
|
|
909
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/agent-approval-window-seconds
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
Set it with `projmux config agent-approvals --window <seconds>`, or write the
|
|
913
|
+
file. The value is integer seconds in `60`–`3600`, default `900`. There is no
|
|
914
|
+
`unlimited` value: a value outside the range, `unlimited`, and a file that does
|
|
915
|
+
not hold one integer read as `900`. A request nobody answers in the window
|
|
916
|
+
expires with no decision, and Claude Code's own prompt decides it.
|
|
917
|
+
|
|
918
|
+
The installed hook `timeout` is the fixed ceiling `3615` seconds (the longest
|
|
919
|
+
window plus a 15 second margin) and does not depend on this file. The hook
|
|
920
|
+
rereads the window for every request, so a changed window applies to the next
|
|
921
|
+
request without re-running `projmux agent integrate claude`.
|
|
922
|
+
|
|
785
923
|
## Notifications
|
|
786
924
|
|
|
787
925
|
When `PROJMUX_NOTIFY_HOOK` is unset, projmux uses:
|
|
@@ -833,7 +971,8 @@ seconds window. Resolution priority is:
|
|
|
833
971
|
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-notify-dedupe-seconds`
|
|
834
972
|
3. default `120`
|
|
835
973
|
|
|
836
|
-
Settings exposes this at
|
|
974
|
+
Settings exposes this at
|
|
975
|
+
`Settings > Global > Notifications > Desktop delivery > Dedupe window`.
|
|
837
976
|
The value is stored as integer seconds and applies only to AI desktop
|
|
838
977
|
notification dispatch. The tmux bell fallback keeps its fixed 5 second
|
|
839
978
|
dedupe window.
|
|
@@ -865,6 +1004,11 @@ precedence only during hook fallback; catalog defaults do not override this
|
|
|
865
1004
|
semantic store. Saving this file does not infer from, rewrite, or normalize the
|
|
866
1005
|
raw hook override file.
|
|
867
1006
|
|
|
1007
|
+
Codex native failures are always delivered as critical `error` notifications,
|
|
1008
|
+
independent of those two completion/approval policy choices. A hook fallback
|
|
1009
|
+
`Stop` uses Codex's `last-assistant-message` payload when present; without it,
|
|
1010
|
+
the completion text is `Ready`.
|
|
1011
|
+
|
|
868
1012
|
Delivery depends on the event handler. Specialized notify handlers, such as
|
|
869
1013
|
Codex `PermissionRequest` and `Stop`, can write the in-app notify queue and use
|
|
870
1014
|
the configured OS desktop notification path. Known Codex events without a
|
|
@@ -918,7 +1062,7 @@ Settings press through the new row writes `desktop-notify-mode`, mirrors the
|
|
|
918
1062
|
new value into `@projmux_desktop_notify_mode` when tmux is live, and leaves the
|
|
919
1063
|
legacy key unused. No eager rewrite of tmux state.
|
|
920
1064
|
|
|
921
|
-
|
|
1065
|
+
Choose it from `Settings > Global > Notifications > Desktop delivery > Delivery mode`. The
|
|
922
1066
|
Settings info row labels the effective source as `env`, `env (legacy)`,
|
|
923
1067
|
`setting`, `setting (legacy)`, or `default` so users see which rung of
|
|
924
1068
|
the cascade pinned the value. `projmux config apply` regenerates the live tmux
|
|
@@ -964,28 +1108,35 @@ ${PROJMUX_USAGE_STATE_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/projmux/usage}/
|
|
|
964
1108
|
See [Usage tracking](usage-tracking.md) for adapter behavior, throttling, and
|
|
965
1109
|
failure handling.
|
|
966
1110
|
|
|
967
|
-
##
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
`
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1111
|
+
## Project Startup
|
|
1112
|
+
|
|
1113
|
+
The Registry (`registry.json`) is the only saved Project state; see
|
|
1114
|
+
[session-restore.md](session-restore.md). projmux keeps no separate Project
|
|
1115
|
+
snapshot store. Nothing reads the former
|
|
1116
|
+
`${XDG_STATE_HOME:-$HOME/.local/state}/projmux/sessions/*.json` snapshot
|
|
1117
|
+
files; they are removed by `config apply`. The app tmux status tick saves
|
|
1118
|
+
nothing: generated status lines carry no auto-save job, and the hidden
|
|
1119
|
+
`internal tmux autosave-session-state` route that older generated configs
|
|
1120
|
+
still call is a silent no-op that writes nothing and records no diagnostics.
|
|
1121
|
+
The `sessionstate-autosave` and `sessionstate-autosave-interval` files and the
|
|
1122
|
+
per-Project `sessionstate-projects/<session>/autosave` files are removed by
|
|
1123
|
+
`config apply`, together with the `sessions/` and `sessionstate-projects/`
|
|
1124
|
+
directories once they are empty. Any other entry there is kept, and listed
|
|
1125
|
+
by the apply that removes the files.
|
|
1126
|
+
`PROJMUX_SESSIONSTATE_AUTOSAVE` is still ignored without a warning.
|
|
1127
|
+
|
|
1128
|
+
Opening a registered closed Project from the Alt-1 sidebar shows a native
|
|
1129
|
+
`Start project` step with exactly `Continue project` and
|
|
1130
|
+
`Clear layout and open`. A root that is not a registered Project skips that
|
|
1131
|
+
step and opens fresh, which registers it. There is no setting that skips the
|
|
1132
|
+
step for a registered Project.
|
|
1133
|
+
An explicit `Continue project` on a root that is not a registered Project
|
|
1134
|
+
refuses with zero writes and points to `Clear layout and open`.
|
|
1135
|
+
`Clear layout and open` clears only the saved Window and Agent layout: the
|
|
1136
|
+
folder, its files, `.projmux/config.toml`, and trust stay. It confirms first,
|
|
1137
|
+
then atomically replaces the old Project graph
|
|
987
1138
|
with a new Project UID and a new canonical Window/shell UID pair. Exactly one
|
|
988
|
-
same-root Project claimant remains.
|
|
1139
|
+
same-root Project claimant remains. The root directory,
|
|
989
1140
|
Git/worktree data, and the trust decision remain unchanged. Esc returns to
|
|
990
1141
|
Projects with zero writes. After
|
|
991
1142
|
the startup mode is selected, project automation trust is evaluated if needed.
|
|
@@ -997,62 +1148,17 @@ Deny/cancel refreshes the original sidebar query/selection context with a
|
|
|
997
1148
|
visible status message. Existing sessions switch directly without a startup
|
|
998
1149
|
picker.
|
|
999
1150
|
|
|
1000
|
-
Default `projmux shell`
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
operation that requires both the source session and the exact target Project;
|
|
1005
|
-
it is not a Project-startup choice.
|
|
1006
|
-
|
|
1007
|
-
Settings > Session State is global settings only: global auto-save, auto-save
|
|
1008
|
-
interval, and storage/retention policy. Settings > Project > Session State
|
|
1009
|
-
is override/effective-focused: project identity, project auto-save
|
|
1010
|
-
`inherit`/`on`/`off`, effective auto-save value/source, and snapshot save
|
|
1011
|
-
actions. Snapshot inspection lives under `Projects > Sessions > State`, whose
|
|
1012
|
-
overview shows latest/named snapshot status and the window -> pane read model
|
|
1013
|
-
without immediate mutation.
|
|
1014
|
-
|
|
1015
|
-
The saved global toggles live under
|
|
1016
|
-
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-autosave`,
|
|
1017
|
-
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-autosave-interval`, and
|
|
1018
|
-
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sidebar-startup-picker`. Project
|
|
1019
|
-
auto-save overrides live under
|
|
1020
|
-
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-projects/<session>/autosave`.
|
|
1021
|
-
The environment variables above override the global files.
|
|
1022
|
-
`sidebar-startup-picker` accepts the existing `on` and `off` bytes; absence is a
|
|
1023
|
-
read-only effective `on - default`, not a migration or an implicit write.
|
|
1024
|
-
|
|
1025
|
-
Manual snapshot actions are available from the CLI:
|
|
1151
|
+
Default `projmux shell` does not open a startup picker before attach. It
|
|
1152
|
+
derives the default app session identity and startup directory from the
|
|
1153
|
+
current project context when available; otherwise it uses the `home` target
|
|
1154
|
+
and home directory.
|
|
1026
1155
|
|
|
1027
|
-
|
|
1028
|
-
projmux
|
|
1029
|
-
|
|
1030
|
-
projmux delete snapshot [--session <name>]
|
|
1031
|
-
projmux restore snapshot --session <snapshot-session> [--project <ref> | -p <ref>] --dry-run
|
|
1032
|
-
projmux restore snapshot --session <snapshot-session> [--project <ref> | -p <ref>] --yes [--client <tmux-client>]
|
|
1033
|
-
```
|
|
1156
|
+
The retired closed-Project startup setting's file under
|
|
1157
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/` is not read, and `config apply`
|
|
1158
|
+
removes it; see [Upgrading](upgrading.md#closed-project-startup-setting-removed).
|
|
1034
1159
|
|
|
1035
|
-
`
|
|
1036
|
-
|
|
1037
|
-
target session. Older snapshots without a source field display as `autosave`.
|
|
1038
|
-
`save` captures the current tmux session immediately and intentionally bypasses
|
|
1039
|
-
the autosave debounce and disabled-autosave gate; it still requires a current
|
|
1040
|
-
tmux session. `delete` removes the target snapshot without an interactive
|
|
1041
|
-
confirmation. Restore treats the snapshot as desired-state input for one exact
|
|
1042
|
-
closed Project, never as a global Registry replacement or tmux replay.
|
|
1043
|
-
`--dry-run` prints scoped projection counts with zero writes. `--yes` commits
|
|
1044
|
-
that target subtree atomically, runs the ordinary materializer, and performs an
|
|
1045
|
-
explicit client handoff last when `--client` is present. Restore never modifies
|
|
1046
|
-
or deletes the source snapshot.
|
|
1047
|
-
|
|
1048
|
-
Interactive `projmux quit` also offers `Save Project snapshots and quit`. It
|
|
1049
|
-
recaptures the latest snapshot for every live Registry-bound Project on the
|
|
1050
|
-
exact app server, regardless of the global or Project auto-save toggle, and
|
|
1051
|
-
stops the server only after all captures succeed. A partial failure keeps the
|
|
1052
|
-
server running and keeps each successful atomic snapshot for inspection or
|
|
1053
|
-
retry. Control/Home, ephemeral, unmanaged, conflicted, and sibling-server
|
|
1054
|
-
sessions are never promoted into Project snapshots. `Quit without saving`,
|
|
1055
|
-
`quit --yes`, and `quit --force` perform no snapshot inventory or store I/O.
|
|
1160
|
+
Interactive `projmux quit` offers only the quit row and `Cancel`. Neither it
|
|
1161
|
+
nor `quit --yes` / `quit --force` saves Project state.
|
|
1056
1162
|
|
|
1057
1163
|
## Decoration Mode
|
|
1058
1164
|
|
|
@@ -1066,13 +1172,13 @@ Settings > Appearance controls optional icon decoration per surface:
|
|
|
1066
1172
|
The per-surface saved values live at:
|
|
1067
1173
|
|
|
1068
1174
|
```text
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1175
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-decoration-cwd
|
|
1176
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-decoration-git
|
|
1177
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-decoration-notify
|
|
1072
1178
|
```
|
|
1073
1179
|
|
|
1074
|
-
The legacy
|
|
1075
|
-
fallback default when a per-surface file is absent.
|
|
1180
|
+
The legacy `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-decoration`
|
|
1181
|
+
value is still read as the fallback default when a per-surface file is absent.
|
|
1076
1182
|
|
|
1077
1183
|
## Row 0 HUD Visibility
|
|
1078
1184
|
|
|
@@ -1081,29 +1187,28 @@ independent global presentation preferences:
|
|
|
1081
1187
|
|
|
1082
1188
|
- `Notifications HUD > Visible`
|
|
1083
1189
|
- `Agent Usage HUD > Visible`
|
|
1084
|
-
- `Agent Usage HUD > Claude|Codex
|
|
1085
|
-
- each provider's supported HUD windows (`
|
|
1086
|
-
`Antigravity`: `Weekly`)
|
|
1190
|
+
- `Agent Usage HUD > Claude|Codex > Visible`
|
|
1191
|
+
- each provider's supported HUD windows (`5h`, `Weekly`)
|
|
1087
1192
|
|
|
1088
1193
|
The saved values are `on` or `off` in these files:
|
|
1089
1194
|
|
|
1090
1195
|
```text
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
~/.config/projmux/statusbar-visibility-agent-usage-window-codex-weekly
|
|
1100
|
-
~/.config/projmux/statusbar-visibility-agent-usage-window-antigravity-weekly
|
|
1196
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-notifications-hud
|
|
1197
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-agent-usage-hud
|
|
1198
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-agent-usage-provider-claude
|
|
1199
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-agent-usage-provider-codex
|
|
1200
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-agent-usage-window-claude-5h
|
|
1201
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-agent-usage-window-claude-weekly
|
|
1202
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-agent-usage-window-codex-5h
|
|
1203
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-agent-usage-window-codex-weekly
|
|
1101
1204
|
```
|
|
1102
1205
|
|
|
1103
|
-
Missing, empty, and invalid values
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1206
|
+
Missing, empty, and invalid values fall back to the
|
|
1207
|
+
[central status bar default](#central-status-bar-defaults) for that file, and
|
|
1208
|
+
without one resolve to `on` except the Codex `5h` window, whose ambient HUD
|
|
1209
|
+
default is `off`; an explicit saved `on` restores it. Settings shows whether
|
|
1210
|
+
the effective value came from `saved`, `central`, or `default` and marks an
|
|
1211
|
+
invalid saved value as ignored. Saving a toggle regenerates the app
|
|
1107
1212
|
and standalone tmux output, and Settings source-reloads the generated app config
|
|
1108
1213
|
when it is running inside tmux.
|
|
1109
1214
|
|
|
@@ -1111,8 +1216,9 @@ Parent visibility gates only the effective projection. Turning the overall HUD
|
|
|
1111
1216
|
or a provider off does not rewrite its provider/window leaf files; turning the
|
|
1112
1217
|
parent back on restores the saved child selection. Provider rows follow the
|
|
1113
1218
|
usage-supported provider catalog. Window rows come only from the explicit HUD
|
|
1114
|
-
capability map, so opaque quota buckets never create settings
|
|
1115
|
-
|
|
1219
|
+
capability map, so opaque quota buckets never create settings. Antigravity has
|
|
1220
|
+
no usage source; `statusbar-visibility-agent-usage-*-antigravity*` files left by
|
|
1221
|
+
older releases are ignored and never deleted.
|
|
1116
1222
|
|
|
1117
1223
|
Visibility does not enable or disable either producer. Hiding Notifications HUD
|
|
1118
1224
|
does not change the persistent queue, desktop delivery, or Notification
|
|
@@ -1135,15 +1241,18 @@ components independently:
|
|
|
1135
1241
|
Their global saved values are `on` or `off` in:
|
|
1136
1242
|
|
|
1137
1243
|
```text
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1244
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-project
|
|
1245
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-working-directory
|
|
1246
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-git
|
|
1247
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-clock
|
|
1248
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-visibility-settings-launcher
|
|
1143
1249
|
```
|
|
1144
1250
|
|
|
1145
|
-
Missing, empty, and invalid values
|
|
1146
|
-
|
|
1251
|
+
Missing, empty, and invalid values fall back to the
|
|
1252
|
+
[central status bar default](#central-status-bar-defaults) for that file, and
|
|
1253
|
+
without one resolve to `on`; the settings launcher has no central default.
|
|
1254
|
+
Settings reports the effective value and whether it came from `saved`,
|
|
1255
|
+
`central`, or `default`. Each save is an
|
|
1147
1256
|
atomic 0600 replacement, regenerates both app and standalone output, and
|
|
1148
1257
|
source-loads the generated app config when Settings is inside tmux. Off removes
|
|
1149
1258
|
the complete segment, including its mouse range and owned spacing. Working
|
|
@@ -1152,8 +1261,57 @@ text visible. Settings launcher `off` removes only its mouse chip; CLI and
|
|
|
1152
1261
|
keybinding entry remain.
|
|
1153
1262
|
|
|
1154
1263
|
Resources intentionally does not use one of these visibility files. Its
|
|
1155
|
-
existing
|
|
1156
|
-
and controls both the segment and sampler/cache
|
|
1264
|
+
existing `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/live-resources` value is
|
|
1265
|
+
the only enabled source and controls both the segment and sampler/cache
|
|
1266
|
+
mutation.
|
|
1267
|
+
|
|
1268
|
+
## Central Status Bar Defaults
|
|
1269
|
+
|
|
1270
|
+
The status bar visibility files above, except the settings launcher, have a
|
|
1271
|
+
central default layer under them in:
|
|
1272
|
+
|
|
1273
|
+
```text
|
|
1274
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/statusbar-defaults.json
|
|
1275
|
+
```
|
|
1276
|
+
|
|
1277
|
+
It holds `on` or `off` per visibility file, keyed by the file name without its
|
|
1278
|
+
`statusbar-visibility-` prefix (`clock`, `agent-usage-window-codex-5h`):
|
|
1279
|
+
|
|
1280
|
+
```json
|
|
1281
|
+
{
|
|
1282
|
+
"visibility": {
|
|
1283
|
+
"clock": "off"
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
```
|
|
1287
|
+
|
|
1288
|
+
A visibility value resolves in this order: a valid value in the file above,
|
|
1289
|
+
then its central default, then the built-in default. Values other than `on` or
|
|
1290
|
+
`off` in the central file are ignored.
|
|
1291
|
+
|
|
1292
|
+
Nothing edits the central file yet. `projmux config apply` fills it once from
|
|
1293
|
+
the valid values of the visibility files, so it starts out matching what the
|
|
1294
|
+
status bar shows:
|
|
1295
|
+
|
|
1296
|
+
- Once. A record at
|
|
1297
|
+
`${XDG_STATE_HOME:-~/.local/state}/projmux/statusbar-defaults-seeded` marks
|
|
1298
|
+
the copy done, and later applies copy nothing, whatever the visibility files
|
|
1299
|
+
say by then. The two copies may drift apart after that.
|
|
1300
|
+
- Per key, never overwriting. A central value already stored stays.
|
|
1301
|
+
- Valid values only. A missing, empty, or invalid visibility file copies
|
|
1302
|
+
nothing, so that key keeps following the built-in default.
|
|
1303
|
+
|
|
1304
|
+
When it copies anything, the apply prints one
|
|
1305
|
+
`seeded central status bar defaults: copied N TUI value(s)` line. A failure is
|
|
1306
|
+
reported on the same line, never fails the apply, and writes no record, so the
|
|
1307
|
+
next apply tries again. Deleting both the central file and the record makes the
|
|
1308
|
+
next apply copy again.
|
|
1309
|
+
|
|
1310
|
+
`make install` and `projmux update apply` run `projmux config apply`, so an
|
|
1311
|
+
install through either copies right away. A plain `npm install -g projmux` runs
|
|
1312
|
+
no install script, so it copies on the next `projmux config apply`. Until then
|
|
1313
|
+
the central file is empty and the status bar is unchanged, because the
|
|
1314
|
+
visibility files still decide.
|
|
1157
1315
|
|
|
1158
1316
|
## Live System Resources
|
|
1159
1317
|
|
|
@@ -1161,7 +1319,7 @@ and controls both the segment and sampler/cache mutation.
|
|
|
1161
1319
|
CPU/memory segment on the lower status row. The saved global value is:
|
|
1162
1320
|
|
|
1163
1321
|
```text
|
|
1164
|
-
|
|
1322
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/live-resources
|
|
1165
1323
|
```
|
|
1166
1324
|
|
|
1167
1325
|
Accepted values are `off` (default) and `on`. A missing, empty, or invalid
|
|
@@ -1196,12 +1354,326 @@ The CPU delta cache is internal state at
|
|
|
1196
1354
|
CPU reference samples older than 30 seconds are ignored and replaced on the
|
|
1197
1355
|
next refresh.
|
|
1198
1356
|
|
|
1357
|
+
## Agent Profiles
|
|
1358
|
+
|
|
1359
|
+
An Agent profile is a named set of Agent start settings stored at
|
|
1360
|
+
`<config dir>/profiles/<name>.toml` (by default
|
|
1361
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/profiles/`).
|
|
1362
|
+
Manage profiles with `projmux profile list|show|set|delete`, and start an
|
|
1363
|
+
Agent from one with `projmux create agent --profile <name>` or a `role` label
|
|
1364
|
+
(see [CLI guide](cli-guide.md#agent-profiles-at-create)).
|
|
1365
|
+
|
|
1366
|
+
A profile is one combination: the provider it is for, the stored instructions
|
|
1367
|
+
it starts with, its model and effort, the roles that select it, and its
|
|
1368
|
+
permissions. Every key is optional. Which items each provider applies, and
|
|
1369
|
+
which it discloses as not applied or refuses, is in the
|
|
1370
|
+
[CLI guide](cli-guide.md#agent-profiles-at-create).
|
|
1371
|
+
|
|
1372
|
+
A profile file is a strict subset of TOML:
|
|
1373
|
+
|
|
1374
|
+
- blank lines and `#` comments, on their own line or after a value;
|
|
1375
|
+
- top-level `key = value` lines with a bare key;
|
|
1376
|
+
- at most one `[permissions]` table; every key after it belongs to that table;
|
|
1377
|
+
- values that are double-quoted strings or arrays of them. The only escapes are
|
|
1378
|
+
`\"` and `\\`; tabs, other control characters, and line breaks inside a
|
|
1379
|
+
string are refused. An array may span lines, hold comments, and end with a
|
|
1380
|
+
trailing comma.
|
|
1381
|
+
|
|
1382
|
+
Everything else is refused: unknown keys or tables, a second `[permissions]`, a
|
|
1383
|
+
key given twice, quoted or dotted keys, literal or multi-line strings, numbers,
|
|
1384
|
+
booleans, and inline tables. The file limit is 64 KiB.
|
|
1385
|
+
|
|
1386
|
+
| Key | Value |
|
|
1387
|
+
| --- | --- |
|
|
1388
|
+
| `provider` | the Agent provider the profile is for: one of the ids `create agent --provider` accepts (`claude`, `codex`, `antigravity`), spelled exactly. Omitted, the profile is provider-neutral |
|
|
1389
|
+
| `instructions` | the name of stored instructions (`projmux instructions list`); the file must exist |
|
|
1390
|
+
| `model` | a Claude model alias or name, the same shape `create --model` accepts; `projmux agent models` lists suggestions, and names outside that list are accepted too |
|
|
1391
|
+
| `effort` | `low`, `medium`, `high`, `xhigh`, or `max` |
|
|
1392
|
+
| `roles` | array of role names; each non-empty, without surrounding whitespace, listed once, and not listed by another profile |
|
|
1393
|
+
| `[permissions]` `sandbox` | `read-only`, `workspace-write`, or `full-access` |
|
|
1394
|
+
| `[permissions]` `approval` | `never`, `on-request`, or `untrusted` |
|
|
1395
|
+
| `[permissions]` `allow`, `deny` | arrays of Claude permission rules: a tool name (`[A-Za-z][A-Za-z0-9_-]*`) optionally followed by one non-empty `(...)` specifier, such as `Edit`, `Bash(git status *)`, `Read(./docs/**)`, `WebFetch(domain:example.com)`, or `mcp__srv__tool` |
|
|
1396
|
+
|
|
1397
|
+
```toml
|
|
1398
|
+
provider = "claude"
|
|
1399
|
+
instructions = "reviewer"
|
|
1400
|
+
model = "opus"
|
|
1401
|
+
effort = "high"
|
|
1402
|
+
roles = ["review"]
|
|
1403
|
+
|
|
1404
|
+
[permissions]
|
|
1405
|
+
sandbox = "workspace-write"
|
|
1406
|
+
approval = "on-request"
|
|
1407
|
+
allow = ["Bash(git status *)", "Read(./docs/**)"]
|
|
1408
|
+
deny = ["WebFetch(domain:example.com)"]
|
|
1409
|
+
```
|
|
1410
|
+
|
|
1411
|
+
`provider` binds the profile to one provider. A create of any other provider
|
|
1412
|
+
-- `create agent --provider`, a `create <provider>` shortcut, a `role` label,
|
|
1413
|
+
or a create from the UI -- refuses with exit 2 (`profile-provider-mismatch`,
|
|
1414
|
+
naming both providers) before anything is written. A profile without
|
|
1415
|
+
`provider` applies to every provider, and parses, digests, and applies exactly
|
|
1416
|
+
as it did before the key existed. `create agent` may omit `--provider` when
|
|
1417
|
+
the profile it selects names one: the profile's `provider` is then the Agent's
|
|
1418
|
+
provider. A provider-neutral profile does not choose one, so `create agent`
|
|
1419
|
+
still needs `--provider` with it. `profile set` refuses an unknown value with
|
|
1420
|
+
exit 2 (`profile-provider-unknown`, listing the accepted providers) and writes
|
|
1421
|
+
nothing. `model` is checked only for its shape, whatever the provider, and
|
|
1422
|
+
`effort` takes the one vocabulary above.
|
|
1423
|
+
|
|
1424
|
+
`instructions` names the stored files `projmux instructions` manages: one
|
|
1425
|
+
store, `<config dir>/personas/<name>.md`, and one profile key. What the
|
|
1426
|
+
instructions do depends on the lane, exactly as for `create --instructions`:
|
|
1427
|
+
Claude appends them to the system prompt, and
|
|
1428
|
+
Codex takes them only on a prompted create that opens its own thread (see
|
|
1429
|
+
[CLI guide](cli-guide.md#agent-profiles-at-create)); a promptless Codex create
|
|
1430
|
+
with Profile instructions is refused before creating anything. Codex keeps
|
|
1431
|
+
the developer instructions recorded when the thread started; a relaunch and a
|
|
1432
|
+
resume cannot replace them (`codex-instructions-immutable`). A profile
|
|
1433
|
+
keeps the instructions it names: `instructions delete <name>` refuses with
|
|
1434
|
+
exit 2 (`profile-instructions-in-use`) while any stored profile that parses
|
|
1435
|
+
names them, valid or not, and names each such profile. Change the profile with
|
|
1436
|
+
`projmux profile set <name>` or remove it with `projmux profile delete <name>
|
|
1437
|
+
--yes` first. Instructions removed by hand still make the profile invalid
|
|
1438
|
+
(`profile-instructions-not-found`), and Agents that record it then refuse to
|
|
1439
|
+
resume (`profile-resume-unavailable`) rather than resume without its
|
|
1440
|
+
permissions.
|
|
1441
|
+
|
|
1442
|
+
Roles fail closed. Every profile that parses holds the roles it lists, valid
|
|
1443
|
+
or not: `profile set` refuses a role another profile lists
|
|
1444
|
+
(`profile-role-claimed`), `profile list` shows an invalid profile's roles, and
|
|
1445
|
+
a `role` label whose one listing profile is invalid refuses the create
|
|
1446
|
+
(`profile-role-profile-invalid`, naming the profile and its reason) instead of
|
|
1447
|
+
creating the Agent without a profile. A valid profile that shares a role with
|
|
1448
|
+
an invalid one is marked `profile-role-claimed`; the invalid one keeps its own
|
|
1449
|
+
reason. Pass `--profile none` to create without a profile.
|
|
1450
|
+
|
|
1451
|
+
Profile names follow the instructions name rule, and `none` is reserved.
|
|
1452
|
+
No profile is compiled into projmux: every profile is a file in
|
|
1453
|
+
`<config dir>/profiles/`, and a name without a file is `profile-not-found`.
|
|
1454
|
+
A profile that lets an Agent read and never write lists no roles and sets
|
|
1455
|
+
only its permissions:
|
|
1456
|
+
|
|
1457
|
+
```toml
|
|
1458
|
+
# readonly.toml
|
|
1459
|
+
[permissions]
|
|
1460
|
+
sandbox = "read-only"
|
|
1461
|
+
approval = "never"
|
|
1462
|
+
deny = ["Edit", "Write", "NotebookEdit"]
|
|
1463
|
+
```
|
|
1464
|
+
|
|
1465
|
+
Store it with `projmux profile set readonly --file readonly.toml`.
|
|
1466
|
+
|
|
1467
|
+
When a profile with `allow` or `deny` rules is applied to a Claude Agent, its
|
|
1468
|
+
rules are written as a Claude settings file,
|
|
1469
|
+
`{"permissions":{"allow":[...],"deny":[...]}}` (an empty list left out), to
|
|
1470
|
+
`${XDG_STATE_HOME:-~/.local/state}/projmux/profile-settings/sha256-<hex>.json`
|
|
1471
|
+
(directory 0700, file 0600, named by the sha256 of the bytes), and Claude is
|
|
1472
|
+
started with `--settings <that file>`. Each resume writes it again from the
|
|
1473
|
+
current profile.
|
|
1474
|
+
|
|
1475
|
+
When a profile with `sandbox` or `approval` is applied to a Codex Agent, the
|
|
1476
|
+
native lane sends them as the thread's `sandbox` and `approvalPolicy` on
|
|
1477
|
+
`thread/start` and every native `thread/resume`. The thread's answer must
|
|
1478
|
+
report the same policy, or create or resume is refused
|
|
1479
|
+
(`codex-thread-policy-mismatch`). Promptless and `--interactive-only` creates,
|
|
1480
|
+
and CLI resumes, pass the current profile policy as `codex -s <sandbox> -a
|
|
1481
|
+
<approval>` or `codex -s <sandbox> -a <approval> resume`. On both lanes,
|
|
1482
|
+
`full-access` becomes Codex's `danger-full-access`. Codex CLI accepts
|
|
1483
|
+
`approval = "on-request"` and `"never"`; a profile with `approval = "untrusted"`
|
|
1484
|
+
is refused on CLI lanes (`codex-cli-untrusted-approval-unsupported`) before
|
|
1485
|
+
creating a Pane or resuming the Agent. The native lane still accepts it.
|
|
1486
|
+
`allow` and `deny` are not given to Codex and appear as not applied in create
|
|
1487
|
+
receipts.
|
|
1488
|
+
|
|
1489
|
+
## Project Link Rules
|
|
1490
|
+
|
|
1491
|
+
Project link rules turn a Project's labels into links, for example a
|
|
1492
|
+
`jira=ABC-123` label into `https://jira.example.com/browse/ABC-123`. Each
|
|
1493
|
+
Project has at most one rule file, `<config dir>/project-links/<project-uid>.json`
|
|
1494
|
+
(by default `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/project-links/`), named
|
|
1495
|
+
by the Project UID (`proj-...`) so renaming the Project or moving its root
|
|
1496
|
+
keeps its rules. The rules belong to the Project, and every surface shares
|
|
1497
|
+
them: a Claude Agent's system prompt shows them (see below), and a client that
|
|
1498
|
+
edits them, such as the web client, reads and writes this same file. There is
|
|
1499
|
+
no CLI command that edits them. A missing file means the Project has no rules.
|
|
1500
|
+
|
|
1501
|
+
```json
|
|
1502
|
+
{
|
|
1503
|
+
"jira": ["https://jira.example.com", "https://jira.partner.example.com"],
|
|
1504
|
+
"repo": ["https://github.com/example/repo"],
|
|
1505
|
+
"urls": {"wiki": "https://wiki.example.com/spaces/APP"},
|
|
1506
|
+
"links": [
|
|
1507
|
+
{"labelKey": "jira", "template": "{jira}/browse/{value}"},
|
|
1508
|
+
{"labelKey": "partner", "template": "{jira[1]}/browse/{value}"},
|
|
1509
|
+
{"labelKey": "pr", "template": "{repo}/pull/{value}"},
|
|
1510
|
+
{"labelKey": "doc", "template": "{wiki}/{project.labels.team}/{value}"}
|
|
1511
|
+
]
|
|
1512
|
+
}
|
|
1513
|
+
```
|
|
1514
|
+
|
|
1515
|
+
`jira` and `repo` are lists of base URLs, and `urls` names more base URLs.
|
|
1516
|
+
projmux always writes all four fields.
|
|
1517
|
+
|
|
1518
|
+
| Placeholder | Becomes |
|
|
1519
|
+
| --- | --- |
|
|
1520
|
+
| `{value}` | The label value, path-escaped (`a/b c` becomes `a%2Fb%20c`). Required in every template. |
|
|
1521
|
+
| `{jira[N]}`, `{repo[N]}` | The `N`th URL of `jira` or `repo`, counting from 0. `N` is decimal with no leading zero (`{jira[01]}` is refused). |
|
|
1522
|
+
| `{jira}`, `{repo}` | The same as `{jira[0]}` and `{repo[0]}`. |
|
|
1523
|
+
| `{<name>}` | The URL `urls` names `<name>`, such as `{wiki}`. |
|
|
1524
|
+
| `{project.uid}` | The Project UID, path-escaped. |
|
|
1525
|
+
| `{project.name}` | The Project name, path-escaped. |
|
|
1526
|
+
| `{project.labels.<key>}` | The value of the Project's label `<key>`, path-escaped. |
|
|
1527
|
+
|
|
1528
|
+
A base URL is substituted with any trailing `/` trimmed. Every placeholder is
|
|
1529
|
+
substituted in one pass, so text a substitution inserts is never expanded
|
|
1530
|
+
again. A label value is one value: `a,b` makes one link (`a%2Cb`), not two.
|
|
1531
|
+
|
|
1532
|
+
The Project variables are the Project's UID, name and labels in the Registry,
|
|
1533
|
+
and nothing else: its root directory, its annotations and its Windows are not
|
|
1534
|
+
placeholders, and `{project.root}` is refused. A label whose rule uses a
|
|
1535
|
+
Project label the Project does not have, or has empty, gets no link.
|
|
1536
|
+
|
|
1537
|
+
A rule file must pass these checks, both when it is written and when it is
|
|
1538
|
+
read; a file that fails them, is not one JSON object of exactly these fields,
|
|
1539
|
+
or is larger than 64 KiB is an error, never treated as empty. An error names
|
|
1540
|
+
the field as a JSON path, such as `jira[3]`, `urls.wiki` or
|
|
1541
|
+
`links[2].template`.
|
|
1542
|
+
|
|
1543
|
+
- `jira` and `repo` hold at most 16 URLs each, and `urls` at most 32. Each
|
|
1544
|
+
URL is an absolute `http` or `https` URL with a host, at most 2048 bytes,
|
|
1545
|
+
with no credentials (`user@`), no query, no fragment and no `{` or `}`.
|
|
1546
|
+
- A `urls` name is a lowercase ASCII letter followed by at most 31 lowercase
|
|
1547
|
+
letters, digits, `_` or `-`. `value`, `jira`, `repo` and `project` are
|
|
1548
|
+
reserved and refused.
|
|
1549
|
+
- `links` holds at most 64 rules.
|
|
1550
|
+
- `labelKey` is 1 to 64 ASCII letters, digits, `.`, `_` or `-`, compared
|
|
1551
|
+
exactly (case-sensitive), and unique in the file.
|
|
1552
|
+
- `template` is at most 2048 bytes, contains `{value}`, has no `{` or `}`
|
|
1553
|
+
outside a placeholder, and uses only the placeholders above: an index within
|
|
1554
|
+
its list (`{jira}` needs at least one Jira URL), a name `urls` defines, and
|
|
1555
|
+
a Project field that exists. `{project.labels.<key>}` is checked only for
|
|
1556
|
+
its key's syntax (the `labelKey` rules), because the label may be added
|
|
1557
|
+
later. Expanded with a sample value and a sample Project, the template is an
|
|
1558
|
+
absolute `http` or `https` URL without credentials.
|
|
1559
|
+
|
|
1560
|
+
Removing a URL that a template still uses is refused, like any other invalid
|
|
1561
|
+
rule set, and leaves the file as it was.
|
|
1562
|
+
|
|
1563
|
+
### Rules in a Claude Agent's system prompt
|
|
1564
|
+
|
|
1565
|
+
A Claude Agent gets its Project's current rules in its system prompt: the
|
|
1566
|
+
heading, the placeholders, the Jira and Repo URLs with their indices, the
|
|
1567
|
+
named URLs, the Project variables with their current values, and each rule
|
|
1568
|
+
with an example link resolved for that Project, as text appended with
|
|
1569
|
+
`--append-system-prompt-file`. The Project is the one that owns
|
|
1570
|
+
the Agent's Window in the Registry, never the one its working directory is
|
|
1571
|
+
under. Only Claude Agents get the rules; Codex Agents and the Claude
|
|
1572
|
+
reply-only lane do not.
|
|
1573
|
+
|
|
1574
|
+
- Create passes the rules and records their digest on the Agent
|
|
1575
|
+
(`projmux.io/project-link-rules-digest`). With instructions too, Claude is
|
|
1576
|
+
given one file holding the instructions, a `---` separator, and the rules,
|
|
1577
|
+
because Claude keeps only the last `--append-system-prompt-file`. A
|
|
1578
|
+
resume-picker create also runs with the system prompt snapshot off, since
|
|
1579
|
+
the picked conversation recorded a prompt without the rules.
|
|
1580
|
+
- A running Agent is not restarted when the rules change. The change applies
|
|
1581
|
+
from its next resume (`agent resume`, Continue, or the resume picker): when
|
|
1582
|
+
the Project's rules differ from the recorded digest (added, changed or
|
|
1583
|
+
removed, or the Project renamed or its labels changed, since the Project
|
|
1584
|
+
variables are part of the rendered rules), that resume passes the current
|
|
1585
|
+
rules, runs with `--system-prompt-snapshot off`, and records the new digest
|
|
1586
|
+
and `projmux.io/system-prompt-snapshot=off`, which stays off from then on.
|
|
1587
|
+
Rules equal to the recorded digest change nothing.
|
|
1588
|
+
- A rule file that cannot be read does not stop the Agent: it starts without
|
|
1589
|
+
the rules, one `project-link-rules-unavailable` line on stderr says so, and
|
|
1590
|
+
its recorded digest is left as it was.
|
|
1591
|
+
|
|
1592
|
+
The rendered rules and the instructions-and-rules files are content-addressed
|
|
1593
|
+
below the state directory, in `project-links/`.
|
|
1594
|
+
|
|
1595
|
+
## Agent Guidance
|
|
1596
|
+
|
|
1597
|
+
Every managed Claude Agent gets a short agent guidance text at the front of
|
|
1598
|
+
its system prompt, and a Codex Agent gets it at the front of its thread's
|
|
1599
|
+
developer instructions when it starts its own thread. It tells the Agent to
|
|
1600
|
+
create other agents with `projmux create agent` instead of a subagent built
|
|
1601
|
+
into its provider, and to
|
|
1602
|
+
message them with `projmux agent message send` instead of a message channel
|
|
1603
|
+
local to its provider. The guidance lives in one file,
|
|
1604
|
+
`<config dir>/agent-guidance.md` (by default
|
|
1605
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/agent-guidance.md`), and there is no
|
|
1606
|
+
CLI command that edits it.
|
|
1607
|
+
|
|
1608
|
+
| File | Guidance |
|
|
1609
|
+
| --- | --- |
|
|
1610
|
+
| Missing | The built-in default text. This is the state of a new install. |
|
|
1611
|
+
| Only whitespace (an empty file included) | Off: nothing is added and nothing is recorded. |
|
|
1612
|
+
| Any other content | That content, byte for byte, in place of the default. |
|
|
1613
|
+
|
|
1614
|
+
To turn the guidance off, leave the file empty (`: > agent-guidance.md`). To
|
|
1615
|
+
use your own text, write it to the file. To go back to the default, delete
|
|
1616
|
+
the file. The file is at most 64 KiB.
|
|
1617
|
+
|
|
1618
|
+
- The guidance, the instructions and the Project's label link rules reach Claude
|
|
1619
|
+
as one `--append-system-prompt-file`, in that order, each present only when
|
|
1620
|
+
the Agent has it and separated by a `---` line, because Claude keeps only
|
|
1621
|
+
the last file it is given.
|
|
1622
|
+
- Create passes the current guidance and records its digest on the Agent
|
|
1623
|
+
(`projmux.io/agent-guidance-digest`).
|
|
1624
|
+
- A change applies from the next Claude create or resume (`agent resume`,
|
|
1625
|
+
`agent relaunch`, Continue, or the resume picker). Running sessions are not
|
|
1626
|
+
restarted. A resume whose guidance differs from the recorded digest (changed,
|
|
1627
|
+
added to an Agent created before the guidance existed, or turned off) passes
|
|
1628
|
+
the current guidance, runs with `--system-prompt-snapshot off`, and records
|
|
1629
|
+
the new digest (or removes it) and `projmux.io/system-prompt-snapshot=off`.
|
|
1630
|
+
A resume-picker create always runs with the snapshot off while the guidance
|
|
1631
|
+
is on, since the picked conversation's recorded prompt cannot be shown to
|
|
1632
|
+
hold it. Guidance equal to the recorded digest changes nothing.
|
|
1633
|
+
- A guidance file that cannot be read, is not a regular file, or is larger
|
|
1634
|
+
than 64 KiB does not stop the Agent: it starts without the guidance, one
|
|
1635
|
+
`agent-guidance-unavailable` line on stderr says so, and nothing is
|
|
1636
|
+
recorded.
|
|
1637
|
+
- A Codex Agent receives the guidance on a fresh create that starts its own
|
|
1638
|
+
thread (a create with a prompt): the guidance and the instructions go to that
|
|
1639
|
+
thread as its developer instructions, in that order, each present only when
|
|
1640
|
+
the Agent has it and separated by the same `---` line, and the Agent records
|
|
1641
|
+
the guidance digest. A Codex resume, and a Codex create without a prompt or
|
|
1642
|
+
with `--interactive-only`, do not receive it. A thread keeps the developer
|
|
1643
|
+
instructions it was started with, so a changed guidance reaches a Codex
|
|
1644
|
+
Agent only through a new create.
|
|
1645
|
+
- The Claude reply-only lane does not receive the guidance.
|
|
1646
|
+
|
|
1647
|
+
The guidance and the files composed from it are content-addressed below the
|
|
1648
|
+
state directory, in `agent-guidance/`.
|
|
1649
|
+
|
|
1650
|
+
## Setting Layers
|
|
1651
|
+
|
|
1652
|
+
Settings live in two layers:
|
|
1653
|
+
|
|
1654
|
+
| Layer | Where | What |
|
|
1655
|
+
| --- | --- | --- |
|
|
1656
|
+
| central | `config.toml` central keys (`[ui] locale`, `[update]`, `[startup]`, `[hooks.*]`, `[env]`, `[ai] split_cwd_from`), `ai-enabled-agents`, `ai-new-window-mode`, `live-resources`, `statusbar-defaults.json`, `projdir`, `workdirs`, `pins`, `tags`, `project-hooks`, `desktop-notify-mode`, `ai-notify-dedupe-seconds`, `agent-question-window-seconds`, `agent-question-answering`, `agent-approval-window-seconds`, `agent-approval-answering`, `ai-hook-actions.json`, `ai-semantic-policies.json`, `ai-hooks.d/`, `hooks/`, `personas/`, `profiles/`, `project-links/` | product behavior every surface shares |
|
|
1657
|
+
| TUI | `statusbar-visibility-*`, `statusbar-decoration*`, `ai-badge-style`, `runtime-diagnostics-visibility`, `keymap.toml`, `tmux-ai-split-mode`, `config.toml` `[theme]`, `[ui] native_keys`, `[ai] resume_*` | how the terminal looks and launches |
|
|
1658
|
+
|
|
1659
|
+
Central files live under `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/`, except
|
|
1660
|
+
`projdir` and `workdirs`, which always live under `$HOME/.config/projmux/` and
|
|
1661
|
+
do not follow `XDG_CONFIG_HOME`.
|
|
1662
|
+
|
|
1663
|
+
Named Agent instructions continue to use the central `personas/` directory, which keeps its older name. The `projmux instructions` commands read and write its files.
|
|
1664
|
+
|
|
1665
|
+
TUI is the front layer: only the front entry points (`settings`, `shell`,
|
|
1666
|
+
`switch`, `config render|apply|edit` and the internal namespace) read it. Every
|
|
1667
|
+
other public route reads the central layer alone, except that a route opening a
|
|
1668
|
+
picker may read that picker's theme and keys to paint it.
|
|
1669
|
+
|
|
1670
|
+
|
|
1199
1671
|
## Rare Tunables
|
|
1200
1672
|
|
|
1201
1673
|
These are intended for debugging or local policy, not routine setup:
|
|
1202
1674
|
|
|
1203
1675
|
| Variable | Purpose |
|
|
1204
1676
|
| --- | --- |
|
|
1205
|
-
| `PROJMUX_TMUX_NOTIFY_DEDUPE_SECONDS` | Override the Settings/default collapse window for duplicate AI desktop notifications keyed on the pane-local AI notification key. |
|
|
1677
|
+
| `PROJMUX_TMUX_NOTIFY_DEDUPE_SECONDS` | Override the Settings/default collapse window for duplicate AI desktop notifications keyed on the pane-local AI notification key. The Settings value and default apply only when this env is unset or not a positive integer. |
|
|
1206
1678
|
| `PROJMUX_CODEX_TITLE_WATCH_INTERVAL` | Title-watch loop pacing for Codex panes. |
|
|
1207
1679
|
| `PROJMUX_CODEX_REPLY_SETTLE_LOOPS` | Reply-detection settle-loop pacing for Codex panes. |
|