projmux 0.16.0 → 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/docs/agent-message-replies.md +77 -14
- package/docs/architecture.md +355 -31
- package/docs/claude-coordination-endpoints.md +35 -13
- package/docs/cli-guide.md +688 -122
- package/docs/cli.md +1114 -222
- package/docs/configuration.md +597 -48
- package/docs/globalization.md +7 -4
- package/docs/hooks.md +466 -50
- package/docs/keybindings.md +9 -5
- package/docs/npm-distribution.md +4 -0
- package/docs/operational-diagnostics.md +270 -7
- package/docs/release.md +4 -0
- package/docs/replacement-contract.md +6 -0
- package/docs/repo-layout.md +3 -0
- package/docs/resource-attribution.md +4 -0
- package/docs/session-restore.md +11 -7
- package/docs/statusbar.md +23 -19
- package/docs/testing.md +68 -18
- package/docs/theme-palette.md +6 -6
- package/docs/tmux-surface-inventory.md +13 -0
- package/docs/upgrading.md +25 -23
- package/docs/usage-tracking.md +16 -1
- package/package.json +5 -5
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:
|
|
@@ -52,9 +77,12 @@ for large mounts, WSL paths, NFS paths, or temporary project roots.
|
|
|
52
77
|
The saved workdir file is:
|
|
53
78
|
|
|
54
79
|
```text
|
|
55
|
-
|
|
80
|
+
$HOME/.config/projmux/workdirs
|
|
56
81
|
```
|
|
57
82
|
|
|
83
|
+
This file does not follow `XDG_CONFIG_HOME`; see
|
|
84
|
+
[Setting Layers](#setting-layers).
|
|
85
|
+
|
|
58
86
|
It stores one absolute path per line. Lines beginning with `#` are comments.
|
|
59
87
|
The file is read only when no env root list is set.
|
|
60
88
|
|
|
@@ -69,7 +97,7 @@ Projects sidebar registers that exact path. See
|
|
|
69
97
|
Pins are presentation preferences, stored typed:
|
|
70
98
|
|
|
71
99
|
```text
|
|
72
|
-
|
|
100
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/pins
|
|
73
101
|
```
|
|
74
102
|
|
|
75
103
|
```text
|
|
@@ -117,8 +145,9 @@ terminal-layer remediation, first try the key in `projmux shell`, then run
|
|
|
117
145
|
`projmux setup` from the raw terminal, then use `projmux setup terminal` for
|
|
118
146
|
supported terminal adapters.
|
|
119
147
|
|
|
120
|
-
|
|
121
|
-
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.
|
|
122
151
|
|
|
123
152
|
Supported schema:
|
|
124
153
|
|
|
@@ -223,13 +252,14 @@ Theme is a global user preference. The effective theme resolves from the global
|
|
|
223
252
|
user theme plus a built-in fallback only:
|
|
224
253
|
|
|
225
254
|
```text
|
|
226
|
-
|
|
255
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml
|
|
227
256
|
built-in fallback preset
|
|
228
257
|
```
|
|
229
258
|
|
|
230
|
-
Settings edits the global `[theme]` in
|
|
231
|
-
Effective theme
|
|
232
|
-
|
|
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
|
|
233
263
|
value live-applies it: projmux regenerates the generated tmux config and, when
|
|
234
264
|
Settings runs inside tmux, `tmux source-file`-reloads it so a running server
|
|
235
265
|
repaints immediately. Outside tmux the save still succeeds and the report
|
|
@@ -364,7 +394,7 @@ Preferred interactive path:
|
|
|
364
394
|
Global config path:
|
|
365
395
|
|
|
366
396
|
```text
|
|
367
|
-
|
|
397
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml
|
|
368
398
|
```
|
|
369
399
|
|
|
370
400
|
Schema:
|
|
@@ -442,21 +472,33 @@ or a method-not-found response are reported explicitly as unavailable. The
|
|
|
442
472
|
initial `review/start` response is projected into Agent interaction lifecycle;
|
|
443
473
|
the lifecycle observer described below owns later app-server terminal events.
|
|
444
474
|
|
|
445
|
-
A natively created or resumed Codex Agent keeps a
|
|
475
|
+
A natively created or resumed Codex Agent keeps a lifecycle
|
|
446
476
|
observer on its exact Agent UID, Pane UID/runtime handle, activation generation,
|
|
447
477
|
and thread ID. While its initialized proxy connection and snapshot are current,
|
|
448
478
|
the app server is the only attention authority: active, idle, waiting for input,
|
|
449
479
|
and exact unresolved approval requests project the Agent interaction and badge.
|
|
450
|
-
|
|
451
|
-
|
|
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
|
|
452
492
|
and thread unload first invalidate the epoch and clear stale attention, then
|
|
453
493
|
enable hook fallback. A reconnect starts a new epoch from `thread/read`; events
|
|
454
494
|
from older epochs or other identities are ignored.
|
|
455
495
|
|
|
456
496
|
`describe agent` and the Codex Agent event Settings page report the effective
|
|
457
497
|
lifecycle source, a closed reason, and active/pending/inactive epoch status.
|
|
458
|
-
|
|
459
|
-
|
|
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
|
|
460
502
|
`mixed` when native and fallback authority coexist.
|
|
461
503
|
|
|
462
504
|
Projmux does not install, bootstrap, restart, stop, or reconfigure the Codex
|
|
@@ -479,8 +521,8 @@ one writes only the global `[ai] split_cwd_from`.
|
|
|
479
521
|
Config paths (global and project both honored):
|
|
480
522
|
|
|
481
523
|
```text
|
|
482
|
-
|
|
483
|
-
<project>/.projmux/config.toml
|
|
524
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml # global
|
|
525
|
+
<project>/.projmux/config.toml # project
|
|
484
526
|
```
|
|
485
527
|
|
|
486
528
|
Schema:
|
|
@@ -538,6 +580,27 @@ that re-enables it.
|
|
|
538
580
|
`Settings > Global > AI > Enabled providers`. A missing file means every
|
|
539
581
|
provider is enabled; disabling every provider persists as none enabled.
|
|
540
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
|
+
|
|
541
604
|
## AI Resume Picker
|
|
542
605
|
|
|
543
606
|
The Agent resume picker lists the most recent
|
|
@@ -552,8 +615,8 @@ Preferred interactive path:
|
|
|
552
615
|
Config paths (global and project both honored):
|
|
553
616
|
|
|
554
617
|
```text
|
|
555
|
-
|
|
556
|
-
<project>/.projmux/config.toml
|
|
618
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml # global
|
|
619
|
+
<project>/.projmux/config.toml # project
|
|
557
620
|
```
|
|
558
621
|
|
|
559
622
|
Schema:
|
|
@@ -616,7 +679,7 @@ to the install path: every installer can be judged on either channel.
|
|
|
616
679
|
Files:
|
|
617
680
|
|
|
618
681
|
```text
|
|
619
|
-
|
|
682
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/config.toml # global/user
|
|
620
683
|
```
|
|
621
684
|
|
|
622
685
|
Schema:
|
|
@@ -650,7 +713,7 @@ installed; that install stays put until its stable line ships.
|
|
|
650
713
|
|
|
651
714
|
| Variable | Purpose |
|
|
652
715
|
| --- | --- |
|
|
653
|
-
| `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. |
|
|
654
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. |
|
|
655
718
|
| `TMUX_SESSIONIZER_ROOTS` | Legacy alias still honored at runtime for managed roots. |
|
|
656
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. |
|
|
@@ -729,6 +792,134 @@ set-option -g @projmux_projdir /path/to/repos
|
|
|
729
792
|
An env `PROJMUX_PROJDIR` value takes priority over the tmux option. The tmux
|
|
730
793
|
option takes priority over the saved projdir file.
|
|
731
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
|
+
|
|
732
923
|
## Notifications
|
|
733
924
|
|
|
734
925
|
When `PROJMUX_NOTIFY_HOOK` is unset, projmux uses:
|
|
@@ -813,6 +1004,11 @@ precedence only during hook fallback; catalog defaults do not override this
|
|
|
813
1004
|
semantic store. Saving this file does not infer from, rewrite, or normalize the
|
|
814
1005
|
raw hook override file.
|
|
815
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
|
+
|
|
816
1012
|
Delivery depends on the event handler. Specialized notify handlers, such as
|
|
817
1013
|
Codex `PermissionRequest` and `Stop`, can write the in-app notify queue and use
|
|
818
1014
|
the configured OS desktop notification path. Known Codex events without a
|
|
@@ -976,13 +1172,13 @@ Settings > Appearance controls optional icon decoration per surface:
|
|
|
976
1172
|
The per-surface saved values live at:
|
|
977
1173
|
|
|
978
1174
|
```text
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
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
|
|
982
1178
|
```
|
|
983
1179
|
|
|
984
|
-
The legacy
|
|
985
|
-
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.
|
|
986
1182
|
|
|
987
1183
|
## Row 0 HUD Visibility
|
|
988
1184
|
|
|
@@ -997,20 +1193,22 @@ independent global presentation preferences:
|
|
|
997
1193
|
The saved values are `on` or `off` in these files:
|
|
998
1194
|
|
|
999
1195
|
```text
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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
|
|
1008
1204
|
```
|
|
1009
1205
|
|
|
1010
|
-
Missing, empty, and invalid values
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
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
|
|
1014
1212
|
and standalone tmux output, and Settings source-reloads the generated app config
|
|
1015
1213
|
when it is running inside tmux.
|
|
1016
1214
|
|
|
@@ -1043,15 +1241,18 @@ components independently:
|
|
|
1043
1241
|
Their global saved values are `on` or `off` in:
|
|
1044
1242
|
|
|
1045
1243
|
```text
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
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
|
|
1051
1249
|
```
|
|
1052
1250
|
|
|
1053
|
-
Missing, empty, and invalid values
|
|
1054
|
-
|
|
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
|
|
1055
1256
|
atomic 0600 replacement, regenerates both app and standalone output, and
|
|
1056
1257
|
source-loads the generated app config when Settings is inside tmux. Off removes
|
|
1057
1258
|
the complete segment, including its mouse range and owned spacing. Working
|
|
@@ -1060,8 +1261,57 @@ text visible. Settings launcher `off` removes only its mouse chip; CLI and
|
|
|
1060
1261
|
keybinding entry remain.
|
|
1061
1262
|
|
|
1062
1263
|
Resources intentionally does not use one of these visibility files. Its
|
|
1063
|
-
existing
|
|
1064
|
-
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.
|
|
1065
1315
|
|
|
1066
1316
|
## Live System Resources
|
|
1067
1317
|
|
|
@@ -1069,7 +1319,7 @@ and controls both the segment and sampler/cache mutation.
|
|
|
1069
1319
|
CPU/memory segment on the lower status row. The saved global value is:
|
|
1070
1320
|
|
|
1071
1321
|
```text
|
|
1072
|
-
|
|
1322
|
+
${XDG_CONFIG_HOME:-$HOME/.config}/projmux/live-resources
|
|
1073
1323
|
```
|
|
1074
1324
|
|
|
1075
1325
|
Accepted values are `off` (default) and `on`. A missing, empty, or invalid
|
|
@@ -1104,15 +1354,314 @@ The CPU delta cache is internal state at
|
|
|
1104
1354
|
CPU reference samples older than 30 seconds are ignored and replaced on the
|
|
1105
1355
|
next refresh.
|
|
1106
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
|
+
|
|
1107
1650
|
## Setting Layers
|
|
1108
1651
|
|
|
1109
1652
|
Settings live in two layers:
|
|
1110
1653
|
|
|
1111
1654
|
| Layer | Where | What |
|
|
1112
1655
|
| --- | --- | --- |
|
|
1113
|
-
| central | `config.toml` central keys (`[ui] locale`, `[update]`, `[startup]`, `[hooks.*]`, `[env]`, `[ai] split_cwd_from`), `ai-enabled-agents`, `live-resources`, `projdir`, `workdirs`, `pins`, `tags`, `project-hooks`, `desktop-notify-mode`, `ai-notify-dedupe-seconds`, `ai-hook-actions.json`, `ai-semantic-policies.json`, `ai-hooks.d/`, `hooks/`, `personas/` | product behavior every surface shares |
|
|
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 |
|
|
1114
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 |
|
|
1115
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
|
+
|
|
1116
1665
|
TUI is the front layer: only the front entry points (`settings`, `shell`,
|
|
1117
1666
|
`switch`, `config render|apply|edit` and the internal namespace) read it. Every
|
|
1118
1667
|
other public route reads the central layer alone, except that a route opening a
|