projmux 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,20 +38,65 @@ The saved workdir file is:
38
38
  It stores one absolute path per line. Lines beginning with `#` are comments.
39
39
  The file is read only when no env root list is set.
40
40
 
41
+ ## Project Named Snapshots
42
+
43
+ Project open exposes reusable restore choices as named snapshots. Older
44
+ checkouts may already have named snapshots in the legacy storage directory:
45
+
46
+ ```text
47
+ <project>/.projmux/layouts/<name>.toml
48
+ ```
49
+
50
+ The project context comes from `PROJMUX_CWD` when set, otherwise projmux walks
51
+ upward from the current directory to the nearest `.projmux` or `.git` marker.
52
+ Files outside that project tree are not discovered. This storage is treated as
53
+ legacy import data for the `Named snapshot` row in Project open. New primary
54
+ user-facing surfaces describe the restore unit as a snapshot, not as a separate
55
+ layout or preset feature.
56
+
57
+ The legacy schema is intentionally close to the session-state snapshot shape:
58
+
59
+ ```toml
60
+ schema_version = 1
61
+ description = "Daily dev"
62
+ mode = "inherit-autosave" # default; or "fresh-each-time"
63
+ default_cwd = "${PROJMUX_CWD}"
64
+
65
+ [[windows]]
66
+ index = 0
67
+ name = "main"
68
+ layout = "..."
69
+ active_pane_index = 0
70
+
71
+ [[windows.panes]]
72
+ index = 0
73
+ cwd = "${PROJMUX_CWD}"
74
+ command = "make watch"
75
+ ```
76
+
77
+ `command` records a startup recipe, matching the supported session-state replay
78
+ recipe. Panes without `command` may use `recipe = "shell"`. Supported
79
+ interpolation placeholders are limited to `${PROJMUX_CWD}` and
80
+ `${PROJMUX_SESSION}`; other `${...}` values are rejected during load.
81
+
82
+ Unknown fields and unknown sections are ignored so future schema additions do
83
+ not break older files. The built-in parser only accepts quoted strings and
84
+ integer values for the known fields above; it does not implement the full TOML
85
+ language.
86
+
41
87
  ## Keymap File
42
88
 
43
- Settings > Keybindings is the normal in-app editor for tmux key chords. It
44
- lists each action, opens a detail screen, and lets you type `plain` or
45
- `prefix` tmux chord strings. Saving writes `~/.config/projmux/keymap.toml`,
89
+ Settings > Keybindings is the normal in-app editor for action keys. It lists
90
+ each action, opens a detail screen, and uses `Press new key` to capture one
91
+ keypress through the same controlling-TTY probe path as `projmux setup`.
92
+ Saving writes safe tmux plain chords to `~/.config/projmux/keymap.toml`,
46
93
  rewrites `~/.config/projmux/tmux.conf`, and, when Settings is running inside
47
- tmux, sources that app config so non-terminal-layer tmux chords take effect
48
- immediately.
94
+ tmux, sources that app config so tmux-level chords take effect immediately.
49
95
 
50
- Settings > Labs > Diagnose keybindings is the in-app diagnostic/remediation
51
- surface for the same catalog. It probes one action key at a time through the
52
- controlling TTY, reports whether the key arrived as a plain tmux chord, CSI-u
53
- fallback, unexpected sequence, or timeout, and delegates supported terminal
54
- fallback preview/apply operations to the `projmux init` engine.
96
+ Settings reports CSI-u/User-key captures as terminal fallback delivery and
97
+ does not write a keymap entry for them. Raw sequences that cannot be safely
98
+ represented as a tmux plain chord are not persisted; configure terminal
99
+ fallback with `projmux init` instead.
55
100
 
56
101
  `~/.config/projmux/keymap.toml` can also be edited by hand. When the file is
57
102
  absent, generated tmux config stays on the built-in defaults.
@@ -61,7 +106,6 @@ Supported schema:
61
106
  ```toml
62
107
  [bindings.sessionizer-sidebar]
63
108
  plain = "M-a"
64
- prefix = "A"
65
109
 
66
110
  [bindings.new-window]
67
111
  plain = "C-t"
@@ -72,7 +116,10 @@ Each table is `[bindings.<action-id>]`. Supported keys are:
72
116
  | Key | Meaning |
73
117
  | --- | --- |
74
118
  | `plain` | A no-prefix tmux chord such as `M-a`, `C-t`, or `M-S-Left`. |
75
- | `prefix` | A tmux prefix-table chord such as `A` or `r`. |
119
+
120
+ Legacy `prefix = ...` entries still parse during migration so existing files
121
+ do not break, but Settings no longer writes prefix keys and generated tmux
122
+ config no longer binds the old action prefix chords.
76
123
 
77
124
  Set a value to the empty string to disable that chord for the action:
78
125
 
@@ -81,12 +128,12 @@ Set a value to the empty string to disable that chord for the action:
81
128
  plain = ""
82
129
  ```
83
130
 
84
- In Settings, `Disable Plain/Prefix chord` writes the empty string override.
85
- `Reset Plain/Prefix chord` removes that override and returns to the built-in
86
- default. The Settings writer is deterministic and rewrites the supported
87
- subset only: `[bindings.<action-id>]` tables with `plain` and `prefix` string
88
- keys. If the existing file has parse errors or unknown action IDs, Settings
89
- shows the keymap error row and refuses to overwrite it until the file is fixed.
131
+ In Settings, `Disable` writes the empty plain override. `Reset default`
132
+ removes that override and returns to the built-in default. The Settings writer
133
+ is deterministic and rewrites the supported saved subset only:
134
+ `[bindings.<action-id>]` tables with `plain` string keys. If the existing file
135
+ has parse errors or unknown action IDs, Settings shows the keymap error row and
136
+ refuses to overwrite it until the file is fixed.
90
137
 
91
138
  The file currently affects generated tmux config from `projmux tmux
92
139
  print-config`, `projmux tmux install`, `projmux tmux print-app-config`,
@@ -107,13 +154,16 @@ configured key opens and closes the popup.
107
154
  | `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 `~/.config/projmux/projdir`. |
108
155
  | `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. |
109
156
  | `TMUX_SESSIONIZER_ROOTS` | Legacy alias still honored at runtime for managed roots. |
110
- | `PROJMUX_NOTIFY_HOOK` | External executable that receives AI desktop notifications instead of the built-in Linux/WSL sender. |
157
+ | `PROJMUX_NOTIFY_HOOK` | External executable that receives AI desktop notifications instead of the built-in Linux/WSL sender. Separate from declarative `[hooks.send-noti]`. |
158
+ | `PROJMUX_NOTIFY_HOOK_DEPTH` | Internal recursion guard for `send-noti` hooks. Depth `>= 1` suppresses nested hook dispatch while still allowing the queue write itself. |
111
159
  | `PROJMUX_DESKTOP_NOTIFY_MODE` | OS desktop notification mode override. `none` / `notify` / `raise` (case insensitive). When set, this takes priority over every other resolution rung. The in-app notify queue is not affected. |
112
160
  | `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. |
113
161
  | `PROJMUX_WSL_TOAST_ICON_DIR` | Directory used when copying the WSL toast icon into a Windows-readable path. |
114
162
  | `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. |
115
163
  | `PROJMUX_USAGE_DEBUG` | When non-empty, prints adapter errors from `projmux status usage` to stderr. |
116
164
  | `PROJMUX_USAGE_LIMITS_PATH` | Deprecated. Read but ignored; limits now come from upstream APIs and local Codex rollout state. |
165
+ | `PROJMUX_SESSIONSTATE_AUTOSAVE` | Session snapshot autosave override for the global fallback. Values such as `off`, `false`, or `0` disable autosave for projects that inherit the global setting; explicit project auto-save `on`/`off` still takes precedence. |
166
+ | `PROJMUX_SESSIONSTATE_DEBUG` | When non-empty, quiet autosave surfaces suppressed session-state errors to stderr. |
117
167
  | `PROJMUX_FOCUS_DEBUG` | When non-empty, `projmux focus` prints one telemetry line to stderr. |
118
168
  | `PROJMUX_PICKER_BACKEND` | Legacy picker backend override. Any value, including old `fzf` settings, now resolves to the native picker. |
119
169
  | `PROJMUX_INSTALLER` | Installer source hint used by update flows. npm installs set this automatically; advanced release installs can set `github-release`. |
@@ -151,6 +201,20 @@ When the hook is set, projmux invokes it with positional arguments:
151
201
  summary body urgency app-name tag group icon-path
152
202
  ```
153
203
 
204
+ This environment variable remains the imperative "replace desktop notification
205
+ sender" escape hatch. It does not run through the declarative hook trust/config
206
+ system and it does not receive the notify-queue JSON payload. For additive
207
+ forwarding after a successful queue write, prefer `[hooks.send-noti]` in
208
+ `config.toml`.
209
+
210
+ `[hooks.send-noti]` and `PROJMUX_NOTIFY_HOOK` can coexist:
211
+
212
+ - `PROJMUX_NOTIFY_HOOK` replaces the built-in Linux/WSL desktop sender.
213
+ - `[hooks.send-noti]` fires after the queue write and does not replace desktop
214
+ notifications.
215
+ - `PROJMUX_NOTIFY_HOOK_DEPTH` prevents a `send-noti` hook that calls
216
+ `projmux notify push` from recursively re-triggering itself.
217
+
154
218
  The app-name argument is `com.crevisse.projmux` (reverse-domain id used as
155
219
  the Linux `--app-name`, the macOS sender label, and the Windows
156
220
  `AppUserModelID`). Earlier releases used `projmux.TmuxCodex`; the new id
@@ -167,12 +231,12 @@ gated here.
167
231
  | Mode | On push | On click |
168
232
  | --- | --- | --- |
169
233
  | `none` | no toast | n/a |
170
- | `notify` | toast / notify-send fires | toast click invokes `projmux focus --uri` via the `projmux://` handler |
171
- | `raise` | toast / notify-send fires AND the host terminal is auto-raised via the osfocus chain | same as `notify` click is always available |
234
+ | `notify` | toast / notify-send fires | no click action |
235
+ | `raise` | toast / notify-send fires AND the host terminal is auto-raised via the osfocus chain | toast click invokes `projmux focus --uri` via the `projmux://` handler |
172
236
 
173
- Click activation is always wired. The `projmux://` URI handler is
174
- registered on the first Notify of each tmux server (gated by the
175
- `@projmux_uri_protocol_registered_v2` marker) regardless of mode. The
237
+ Click activation is wired only for `raise`. The `projmux://` URI handler is
238
+ registered on the first `raise` Notify of each tmux server (gated by the
239
+ `@projmux_uri_protocol_registered_v2` marker). The
176
240
  mode only controls whether a toast fires at all and whether to follow it
177
241
  up with an on-push auto-raise.
178
242
 
@@ -194,13 +258,16 @@ toggle set keep their behavior — `@projmux_desktop_notify=0` resolves to
194
258
  Settings press through the new row writes the new key and the legacy key
195
259
  goes unused. No eager rewrite of tmux state.
196
260
 
197
- Toggle from Settings > AI Settings > `Desktop notifications`. The
261
+ Toggle from Settings > Notifications > `Desktop notifications`. The
198
262
  Settings info row labels the effective source as `env`, `env (legacy)`,
199
263
  `setting`, `setting (legacy)`, or `default` so users see which rung of
200
264
  the cascade pinned the value.
201
265
 
202
266
  Hook details for new-session lifecycle hooks and project-local
203
267
  `.projmux/config.toml` live in [Hooks](hooks.md).
268
+ Settings names that entry point as **Project recipe** (search still matches
269
+ `config.toml` as an alias) to avoid leaking internal file names in the primary
270
+ Settings view.
204
271
 
205
272
  ### Toast click handler (WSL + Windows Terminal)
206
273
 
@@ -287,6 +354,82 @@ If the marker is missing, the next shell launch shows the welcome again. If the
287
354
  marker is corrupt or cannot be written, shell startup continues without the
288
355
  welcome.
289
356
 
357
+ The same guide is also available on demand through `projmux welcome`, and it is
358
+ linked from Settings > About as `Welcome`.
359
+
360
+ When `pending_attach_welcome` is true, the generated projmux shell tmux config
361
+ runs `projmux welcome --popup` asynchronously from the `client-attached` hook.
362
+ That helper atomically claims the pending marker, flips it off, and shows the
363
+ welcome guide in a tmux popup once for that version. Missing, corrupt, or
364
+ already-consumed state is a quiet no-op.
365
+
366
+ Set `PROJMUX_WELCOME=off` before launching or attaching to `projmux shell` to
367
+ suppress the automatic attach popup. The manual `projmux welcome` command still
368
+ prints the guide.
369
+
370
+ ## Session State
371
+
372
+ `projmux shell` autosaves session snapshots from the app tmux status tick. The
373
+ autosave command is quiet and debounced per session, and stores snapshots under
374
+ `${XDG_STATE_HOME:-$HOME/.local/state}/projmux/sessions`.
375
+
376
+ Global auto-save defaults to `off` on a fresh install. Project auto-save is an
377
+ override with `inherit`, `on`, and `off`; `inherit` follows the global value,
378
+ while `on` and `off` take precedence. Auto-save only updates the latest
379
+ snapshot. Named snapshots are manual and are never updated by auto-save.
380
+
381
+ Project open from the Alt-1 sidebar defaults to opening a closed project as an
382
+ `Empty session`. The optional `Settings > Labs > Sidebar startup picker` toggle
383
+ enables the native sidebar `Start project` step. Rows appear as `Latest
384
+ snapshot`, named snapshot rows, `Empty session`, and `Back`. `Latest snapshot`
385
+ is the snapshot auto-save that changes as auto-save runs; named snapshots are
386
+ fixed snapshots. Rows include saved-at date/time metadata when projmux can
387
+ determine it. `Back` returns to the project list without creating, replaying, or
388
+ opening a session. After the startup mode is selected, project hook/config trust
389
+ is evaluated if needed; approval continues the selected path and deny/cancel
390
+ aborts without session create, snapshot replay, or startup command. Existing
391
+ sessions switch directly without a startup picker.
392
+
393
+ Default `projmux shell` no longer opens a startup picker or replays session-state
394
+ snapshots before attach. It still derives the default app session identity and
395
+ startup directory from the current project context when available; otherwise it
396
+ uses the `home` target and home directory. Session-state restore selection is
397
+ limited to the Labs sidebar startup picker.
398
+
399
+ Settings > Session State is global settings only: global auto-save, auto-save
400
+ interval, and storage/retention policy. Settings > Project > Session State
401
+ is override/effective-focused: project identity, project auto-save
402
+ `inherit`/`on`/`off`, effective auto-save value/source, and snapshot save
403
+ actions. Snapshot inspection lives under `Projects > Sessions > State`, whose
404
+ overview shows latest/named snapshot status and the window -> pane read model
405
+ without immediate mutation.
406
+
407
+ The saved global toggles live under
408
+ `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-autosave`,
409
+ `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-autosave-interval`, and
410
+ `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sidebar-startup-picker`. Project
411
+ auto-save overrides live under
412
+ `${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sessionstate-projects/<session>/autosave`.
413
+ The environment variables above override the global files.
414
+
415
+ Manual snapshot actions are available from the CLI:
416
+
417
+ ```sh
418
+ projmux session-state status [--session <name>]
419
+ projmux session-state save
420
+ projmux session-state delete [--session <name>]
421
+ projmux session-state restore --dry-run [--session <name>]
422
+ ```
423
+
424
+ `status` prints the source label (`autosave`, `layout(<name>)`, or `fresh`), the
425
+ effective auto-save state, and a compact snapshot preview for the
426
+ target session. Older snapshots without a source field display as `autosave`.
427
+ `save` captures the current tmux session immediately and intentionally bypasses
428
+ the autosave debounce and disabled-autosave gate; it still requires a current
429
+ tmux session. `delete` removes the target snapshot without an interactive
430
+ confirmation. `restore --dry-run` is preview-only in this release and does not
431
+ create sessions or send tmux commands.
432
+
290
433
  ## Decoration Mode
291
434
 
292
435
  Settings > Appearance controls optional status and picker decoration: