projmux 0.4.4 → 0.4.6

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.
@@ -0,0 +1,99 @@
1
+ # Install
2
+
3
+ The recommended install path is npm:
4
+
5
+ ```sh
6
+ npm install -g projmux
7
+ projmux version
8
+ ```
9
+
10
+ The `projmux` npm package installs a small Node.js shim plus one
11
+ platform-specific Go binary package for Linux and macOS on x64 or arm64. The
12
+ shim sets `PROJMUX_INSTALLER=npm` so Settings > About and `projmux update`
13
+ can use npm-aware update guidance.
14
+
15
+ After installing, run:
16
+
17
+ ```sh
18
+ projmux doctor
19
+ ```
20
+
21
+ `doctor` checks that runtime tools such as `tmux` and the junegunn/fzf CLI are
22
+ available and new enough.
23
+
24
+ ## Runtime Tools
25
+
26
+ Normal use needs:
27
+
28
+ - Node.js and npm for the npm install channel.
29
+ - tmux 3.4 or newer.
30
+ - fzf 0.65.0 or newer.
31
+
32
+ Useful optional tools:
33
+
34
+ - `git` for branch/status metadata.
35
+ - `kubectl` for the Kubernetes status segment.
36
+ - `notify-send` on Linux, or `powershell.exe` under WSL, for built-in desktop
37
+ notifications.
38
+
39
+ ## Go Install
40
+
41
+ Use this only when npm is not the right fit for your machine or workflow:
42
+
43
+ ```sh
44
+ go install github.com/crevissepartners/projmux/cmd/projmux@latest
45
+ ```
46
+
47
+ This requires Go 1.24 or newer. The binary is written to `$(go env GOBIN)` when
48
+ set, otherwise `$(go env GOPATH)/bin` (usually `~/go/bin`). Make sure that
49
+ directory is on `PATH`.
50
+
51
+ Go-managed installs can update through:
52
+
53
+ ```sh
54
+ projmux upgrade
55
+ ```
56
+
57
+ See [Upgrading](upgrading.md) for version pinning and installer-specific
58
+ update behavior.
59
+
60
+ ## Source Checkout
61
+
62
+ Source installs are for contributors or users who intentionally track a local
63
+ checkout:
64
+
65
+ ```sh
66
+ git clone https://github.com/crevissepartners/projmux.git
67
+ cd projmux
68
+ make install
69
+ ```
70
+
71
+ `make install` builds the binary, atomically replaces
72
+ `$(go env GOPATH)/bin/projmux`, runs `projmux tmux apply`, and reconciles the
73
+ notify queue. Override the destination with `INSTALL_DIR=/usr/local/bin`.
74
+
75
+ Update source checkouts with the repository workflow:
76
+
77
+ ```sh
78
+ git pull --ff-only
79
+ make install
80
+ ```
81
+
82
+ ## GitHub Release Binary
83
+
84
+ GitHub Release tarballs are supported by the updater when the install is
85
+ marked as release-managed:
86
+
87
+ ```sh
88
+ export PROJMUX_INSTALLER=github-release
89
+ ```
90
+
91
+ With that set, `projmux update apply` downloads the latest matching release
92
+ asset, replaces the current executable, and reapplies the live tmux config
93
+ unless `--no-apply` is used.
94
+
95
+ ## npm Packaging Details
96
+
97
+ Repository packaging and publish details are maintained in
98
+ [npm Distribution](npm-distribution.md). That document is for maintainers; end
99
+ users should not need it for installation.
@@ -0,0 +1,337 @@
1
+ # Terminal Keybindings
2
+
3
+ projmux is keyboard-driven. `projmux shell` writes a tmux config that owns
4
+ every binding listed here, so the keys are live the moment the app starts —
5
+ no extra setup in most terminals.
6
+
7
+ The recommended path when a key does not fire:
8
+
9
+ 1. Press the key inside `projmux shell` and see what works on your terminal
10
+ out of the box ([Quick start](#quick-start-no-setup)).
11
+ 2. If something is swallowed, run [`projmux setup`](#diagnose-projmux-setup)
12
+ outside tmux — it tells you exactly which sequences reach the process and
13
+ which the terminal is eating.
14
+ 3. For terminals projmux knows how to configure, run
15
+ [`projmux init [terminal]`](#auto-config-projmux-init) as the fallback:
16
+ preview first, then add `--apply` to merge the right bindings into your
17
+ terminal config with a timestamped backup.
18
+ 4. If your terminal is not in the init list (or you prefer to edit configs by
19
+ hand), use the [Manual fallback / advanced (CSI-u)](#manual-fallback--advanced-csi-u)
20
+ section.
21
+
22
+ > 한국어 요약: 대부분의 터미널은 `projmux shell` 만으로 아래 키가 바로 동작합니다.
23
+ > 동작하지 않으면 `projmux setup` 으로 어떤 키가 막혔는지 진단하고,
24
+ > `projmux init [terminal]` 으로 자동 설정하세요. 자동 설정이 없는 터미널은
25
+ > 마지막 [Manual fallback / advanced (CSI-u)](#manual-fallback--advanced-csi-u)
26
+ > 섹션의 매핑표를 참고해 직접 설정하면 됩니다.
27
+
28
+ The tmux **prefix** is the upstream default `Ctrl-b`. Inside the running
29
+ session, `Ctrl-b ?` lists every binding live.
30
+
31
+ ## Quick start (no setup)
32
+
33
+ These shortcuts are bound by projmux's generated tmux config. On terminals
34
+ that pass `Alt-*` and `Ctrl-*` chords through to the running process
35
+ unchanged (e.g. Linux gnome-terminal, foot, most stock Linux terminals),
36
+ they work the moment you launch `projmux shell` — no terminal config
37
+ required.
38
+
39
+ If a key does nothing, jump to
40
+ [Diagnose: `projmux setup`](#diagnose-projmux-setup) instead of guessing.
41
+
42
+ ### Pickers
43
+
44
+ These open the projmux popups and the sidebar. No prefix needed.
45
+
46
+ | Shortcut | Action |
47
+ | --- | --- |
48
+ | `Alt-1` | Project sidebar |
49
+ | `Alt-2` | Notify sidebar |
50
+ | `Alt-3` | Existing session popup |
51
+ | `Alt-4` | AI split picker |
52
+ | `Alt-5` | Settings |
53
+ | `Alt-6` | Project switcher popup |
54
+
55
+ The same surfaces are also available from the prefix table:
56
+
57
+ | Shortcut | Action |
58
+ | --- | --- |
59
+ | `Prefix F` | Project sidebar |
60
+ | `Prefix b` | Existing session popup |
61
+ | `Prefix f` | Project switcher popup |
62
+ | `Prefix g` | Jump to the current pane's project session |
63
+
64
+ ### Windows, panes, AI splits
65
+
66
+ | Shortcut | Action |
67
+ | --- | --- |
68
+ | `Ctrl-n` | New tmux window in the current pane's directory |
69
+ | `Alt-Shift-Left` / `Alt-Shift-Right` | Previous / next window |
70
+ | `Alt-Left` / `Right` / `Up` / `Down` | Move focus between panes |
71
+ | `Alt-r` | Rename the current window |
72
+ | `Prefix R` | Rename the current window |
73
+ | `Prefix r` | Open an AI split to the right |
74
+ | `Prefix l` | Open an AI split below |
75
+
76
+ When a pane closes, projmux re-spreads remaining panes so the surviving split
77
+ does not stretch lopsided.
78
+
79
+ ### Inside the pickers
80
+
81
+ | Surface | Shortcut | Action |
82
+ | --- | --- | --- |
83
+ | Existing session popup | `Ctrl-X` | Kill the focused session and reopen the popup |
84
+ | Existing session popup | `Left/Right` | Preview previous/next window |
85
+ | Existing session popup | `Alt-Up/Alt-Down` | Preview previous/next pane |
86
+ | Project switcher | `Ctrl-X` | Kill the focused existing session and reopen the picker |
87
+ | Project switcher | `Alt-P` | Pin or unpin the focused directory |
88
+
89
+ ### Conditional rename keys
90
+
91
+ These two only fire if your terminal forwards CSI-u sequences for `Ctrl-M`
92
+ and `Ctrl-Shift-M`. Without that wiring, plain `Ctrl-M` is just `Enter` and
93
+ `Ctrl-Shift-M` typically does nothing. `projmux init` configures this for
94
+ the terminals it supports; otherwise see
95
+ [Manual fallback / advanced (CSI-u)](#manual-fallback--advanced-csi-u).
96
+
97
+ | Shortcut | Action |
98
+ | --- | --- |
99
+ | `Ctrl-M` | Rename the current window (terminal must send `User10`) |
100
+ | `Ctrl-Shift-M` | Rename the current AI pane label / topic (terminal must send `User11`) |
101
+
102
+ ## Diagnose: `projmux setup`
103
+
104
+ Run `projmux setup` *outside* tmux (in your raw terminal window) to find out
105
+ which projmux keys actually reach the process. The command auto-detects your
106
+ terminal, then asks you to press each shortcut in turn and classifies the
107
+ result:
108
+
109
+ | Status | Meaning |
110
+ | --- | --- |
111
+ | `OK plain` | The terminal forwarded the bare escape (e.g. `\x1b1` for `Alt-1`); tmux's plain bind handles it. |
112
+ | `OK csi-u` | The terminal already forwards a `ESC [ NNNNu` sequence routed to a tmux `User*` key. You are fully wired. |
113
+ | `MISS timeout` | No bytes arrived — the terminal swallowed the key for its own action. |
114
+ | `MISS unknown` | Something arrived, but it does not match either expected sequence — the terminal bound this combo to a different action. |
115
+
116
+ The summary at the end lists the failing keys and a remediation hint
117
+ tailored to the detected terminal (Ghostty, WezTerm, kitty, iTerm2,
118
+ Alacritty, Windows Terminal, foot, VS Code, …). When projmux ships an init
119
+ adapter for the terminal, the summary gives both the dry-run preview and the
120
+ exact apply command, e.g. `projmux init ghostty --apply`.
121
+
122
+ Useful flags:
123
+
124
+ ```sh
125
+ projmux setup # interactive probe (default)
126
+ projmux setup --timeout 10s # wait longer per key
127
+ projmux setup --non-interactive # just print the expected key map and exit
128
+ ```
129
+
130
+ `--non-interactive` is handy when you only want to see, on this machine and
131
+ shell, which `plain` and `csi-u` byte sequences projmux is listening for —
132
+ useful for hand-rolling a config in a terminal projmux does not yet know
133
+ about.
134
+
135
+ > 한국어 요약: `projmux setup` 을 tmux *밖에서* 실행하면, 진단 대상 키를 차례로
136
+ > 누르며 어떤 키가 plain/CSI-u 로 도달하는지, 어떤 키가 swallow 되는지 표로
137
+ > 알려줍니다. 끝에서 터미널별 다음 단계를 제안합니다.
138
+
139
+ ## Auto-config: `projmux init`
140
+
141
+ `projmux init` is the supported fallback when `projmux setup` shows that a
142
+ terminal swallows shortcuts projmux already binds in tmux. It merges the
143
+ projmux CSI-u keybindings into a terminal emulator's config file. Default
144
+ mode is **dry-run** — nothing is written until you pass `--apply`. Applying
145
+ the merge always creates a timestamped backup of the previous file.
146
+
147
+ ```sh
148
+ projmux init # auto-detect + dry-run preview
149
+ projmux init ghostty # explicit terminal, dry-run preview
150
+ projmux init ghostty --apply # write changes (with .bak.<ts> backup)
151
+ projmux init --config /path/to/file # bypass auto-detected paths
152
+ projmux init --allow-symlink # opt in to merging through a symlink
153
+ projmux init --dry-run # force dry-run even with no other flag
154
+ ```
155
+
156
+ The merge is idempotent: bindings already pointing at the desired action are
157
+ no-ops, missing bindings are appended in a managed block, and triggers
158
+ already mapped to a *different* action are left untouched and reported as
159
+ `skip-conflict` warnings — projmux never silently overwrites your custom
160
+ mappings. Re-running `projmux init --apply` after editing the file refreshes
161
+ just the projmux-owned region.
162
+
163
+ ### Supported terminals
164
+
165
+ #### Ghostty
166
+
167
+ - Detection: `TERM_PROGRAM=ghostty` or `GHOSTTY_RESOURCES_DIR` set.
168
+ - Config candidates (resolved in this order):
169
+ 1. `<config-dir>/ghostty/config` — canonical default
170
+ 2. `<config-dir>/ghostty/config.ghostty` — common dotfiles convention
171
+
172
+ `<config-dir>` honours `$XDG_CONFIG_HOME` first, then `$HOME/.config`.
173
+ When both candidates exist, init refuses to guess and asks for
174
+ `--config <path>` to disambiguate.
175
+ - Idempotency marker: bindings live inside a managed block delimited by
176
+
177
+ ```text
178
+ # >>> projmux managed keybindings (do not edit between markers)
179
+ ...
180
+ # <<< projmux managed keybindings
181
+ ```
182
+
183
+ Edit anything *outside* those markers freely; init re-renders the inside
184
+ on every `--apply`.
185
+ - Symlink guard: if the resolved config path is a symlink (typical when
186
+ dotfiles users symlink the terminal config into a tracked repo), init
187
+ refuses by default to avoid silently mutating the symlink target. Pass
188
+ `--allow-symlink` to opt in, or `--config <path>` to point at a
189
+ non-symlinked file.
190
+
191
+ #### Windows Terminal (including WSL)
192
+
193
+ - Detection: `WT_SESSION` set (native Windows), or `WSL_DISTRO_NAME` /
194
+ `WSL_INTEROP` set (running from inside WSL where the host terminal is
195
+ Windows Terminal).
196
+ - Config resolution:
197
+ - Native Windows: `%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_*\LocalState\settings.json`.
198
+ - WSL: resolves `%LOCALAPPDATA%` through `cmd.exe /c echo %LOCALAPPDATA%`
199
+ interop, then translates `C:\Users\...` into `/mnt/c/Users/...` so the
200
+ Linux side can read/write the file directly.
201
+ - Merge model: settings.json is JSONC (allows `//` and `/* */` comments,
202
+ trailing commas). Init parses, locates `actions[]` and `keybindings[]`,
203
+ and merges entries identified by the `User.projmux*` ID prefix. Anything
204
+ outside that prefix is preserved verbatim, including comments and
205
+ formatting where reasonable.
206
+ - Conflicts: a key already mapped to a non-projmux action is skipped with a
207
+ warning, same as Ghostty.
208
+
209
+ ### Reading dry-run output
210
+
211
+ Each line of the dry-run plan prefixes the action with one of:
212
+
213
+ | Prefix | Meaning |
214
+ | --- | --- |
215
+ | `+` | New binding will be added. |
216
+ | `=` | Binding already matches; no change. |
217
+ | `!` | Trigger is already mapped to a *different* action; will be skipped. Resolve manually before applying. |
218
+
219
+ The trailing `note:` lines flag whether the config file does not yet exist
220
+ (it will be created), and the final line tells you whether you still need
221
+ `--apply` or whether the file is already up to date.
222
+
223
+ > 한국어 요약: `projmux init` 은 dry-run 이 기본이고 `--apply` 시 timestamped
224
+ > 백업 후 머지합니다. Ghostty 는 managed 블록 마커로 idempotent, 두 표준
225
+ > path 모두 인식하며 symlink 는 default 거절. Windows Terminal 은 WSL interop
226
+ > 으로 `/mnt/c/...` 경로까지 알아서 풀고, JSONC 형식의 `settings.json` 에
227
+ > `User.projmux*` prefix 로 머지합니다. 사용자가 같은 키를 다른 액션에 매핑한
228
+ > 경우 skip + warning.
229
+
230
+ ## Manual fallback / advanced (CSI-u)
231
+
232
+ Use this section when:
233
+
234
+ - your terminal is not yet supported by `projmux init`, or
235
+ - you prefer to manage the config by hand, or
236
+ - `projmux setup` shows specific keys still being swallowed and you want to
237
+ redirect just those.
238
+
239
+ The fix is to map the swallowed keystroke to a CSI-u sequence the terminal
240
+ forwards to tmux unchanged. projmux binds CSI-u escapes to tmux's
241
+ `User0`–`User11` keys, so once the terminal forwards the sequence the
242
+ action fires.
243
+
244
+ ### CSI-u Map
245
+
246
+ | CSI-u sequence | tmux key | Action |
247
+ | --- | --- | --- |
248
+ | `ESC [ 9001 u` | `User0` | Open AI split to the right |
249
+ | `ESC [ 9002 u` | `User1` | Open AI split below |
250
+ | `ESC [ 9003 u` | `User2` | Notify sidebar |
251
+ | `ESC [ 9004 u` | `User3` | Existing session popup |
252
+ | `ESC [ 9005 u` | `User4` | Project sidebar |
253
+ | `ESC [ 9006 u` | `User5` | AI split picker |
254
+ | `ESC [ 9007 u` | `User6` | Settings |
255
+ | `ESC [ 9008 u` | `User7` | New tmux window in the current pane directory |
256
+ | `ESC [ 9009 u` | `User8` | Previous tmux window |
257
+ | `ESC [ 9010 u` | `User9` | Next tmux window |
258
+ | `ESC [ 9011 u` | `User10` | Rename the current tmux window |
259
+ | `ESC [ 9012 u` | `User11` | Rename the current tmux pane label |
260
+ | `ESC [ 9013 u` | `User12` | Project switcher popup |
261
+
262
+ ### Ghostty (manual)
263
+
264
+ `projmux init ghostty` is the maintained path. The block below is what the
265
+ managed region in `~/.config/ghostty/config` ends up looking like — useful
266
+ if you want to author it by hand or vet what init produces. Ghostty
267
+ keybinds use `keybind = trigger=action`; the `csi:` action sends a CSI
268
+ sequence without the leading `ESC [` bytes.
269
+
270
+ ```text
271
+ keybind = alt+1=csi:9005u
272
+ keybind = alt+2=csi:9003u
273
+ keybind = alt+3=csi:9004u
274
+ keybind = alt+4=csi:9006u
275
+ keybind = alt+5=csi:9007u
276
+ keybind = alt+6=csi:9013u
277
+
278
+ keybind = ctrl+shift+r=csi:9001u
279
+ keybind = ctrl+shift+l=csi:9002u
280
+
281
+ keybind = ctrl+shift+n=csi:9008u
282
+ keybind = ctrl+m=csi:9011u
283
+ keybind = ctrl+shift+m=csi:9012u
284
+ keybind = alt+shift+left=csi:9009u
285
+ keybind = alt+shift+right=csi:9010u
286
+ ```
287
+
288
+ Reload Ghostty or restart the terminal after changing the config.
289
+
290
+ ### Windows Terminal (manual)
291
+
292
+ `projmux init windows-terminal` (which also covers WSL) is the maintained
293
+ path. Use the snippet below to author `settings.json` by hand. Add
294
+ `sendInput` actions and bind them from `keybindings`. Windows Terminal
295
+ works well with plain tmux escape sequences for the default `Alt`
296
+ shortcuts, while the split actions can send tmux prefix sequences directly. Escape bytes should be written as `\u001b`.
297
+
298
+ ```json
299
+ {
300
+ "actions": [
301
+ { "command": { "action": "sendInput", "input": "\u001b1" }, "id": "User.projmuxSidebar" },
302
+ { "command": { "action": "sendInput", "input": "\u001b2" }, "id": "User.projmuxNotifySidebar" },
303
+ { "command": { "action": "sendInput", "input": "\u001b3" }, "id": "User.projmuxSessions" },
304
+ { "command": { "action": "sendInput", "input": "\u001b4" }, "id": "User.projmuxAIPicker" },
305
+ { "command": { "action": "sendInput", "input": "\u001b5" }, "id": "User.projmuxSettings" },
306
+ { "command": { "action": "sendInput", "input": "\u001b6" }, "id": "User.projmuxSwitch" },
307
+ { "command": { "action": "sendInput", "input": "\u0002r" }, "id": "User.projmuxAISplitRight" },
308
+ { "command": { "action": "sendInput", "input": "\u0002l" }, "id": "User.projmuxAISplitDown" },
309
+ { "command": { "action": "sendInput", "input": "\u000e" }, "id": "User.projmuxNewWindow" },
310
+ { "command": { "action": "sendInput", "input": "\u001b[1;4D" }, "id": "User.projmuxPrevWindow" },
311
+ { "command": { "action": "sendInput", "input": "\u001b[1;4C" }, "id": "User.projmuxNextWindow" },
312
+ { "command": { "action": "sendInput", "input": "\u001b[9011u" }, "id": "User.projmuxRenameWindow" },
313
+ { "command": { "action": "sendInput", "input": "\u001b[9012u" }, "id": "User.projmuxRenamePane" }
314
+ ],
315
+ "keybindings": [
316
+ { "id": "User.projmuxSidebar", "keys": "alt+1" },
317
+ { "id": "User.projmuxNotifySidebar", "keys": "alt+2" },
318
+ { "id": "User.projmuxSessions", "keys": "alt+3" },
319
+ { "id": "User.projmuxAIPicker", "keys": "alt+4" },
320
+ { "id": "User.projmuxSettings", "keys": "alt+5" },
321
+ { "id": "User.projmuxSwitch", "keys": "alt+6" },
322
+ { "id": "User.projmuxAISplitRight", "keys": "ctrl+shift+r" },
323
+ { "id": "User.projmuxAISplitDown", "keys": "ctrl+shift+l" },
324
+ { "id": "User.projmuxNewWindow", "keys": "ctrl+n" },
325
+ { "id": "User.projmuxPrevWindow", "keys": "alt+shift+left" },
326
+ { "id": "User.projmuxNextWindow", "keys": "alt+shift+right" },
327
+ { "id": "User.projmuxRenameWindow", "keys": "ctrl+m" },
328
+ { "id": "User.projmuxRenamePane", "keys": "ctrl+shift+m" }
329
+ ]
330
+ }
331
+ ```
332
+
333
+ This example matches the default projmux app shortcuts without depending on
334
+ CSI-u support from Windows Terminal for the `Alt` shortcuts. `Ctrl-M` and
335
+ `Ctrl-Shift-M` still use CSI-u so tmux can distinguish rename commands from
336
+ plain Enter. If a key is already bound by Windows Terminal, remove or change
337
+ the conflicting `keybindings` entry before adding the projmux binding.
@@ -0,0 +1,82 @@
1
+ # Standalone Plan
2
+
3
+ ## Goal
4
+
5
+ Keep session-management product logic inside `projmux`.
6
+ The current target is a standalone app that can generate the tmux bindings and popup entry policy it needs.
7
+
8
+ ## What moves first
9
+
10
+ ### Phase 1
11
+ - session naming rules
12
+ - preview selection state
13
+ - pin state
14
+ - current-directory session jump
15
+ - tagged kill fallback logic
16
+
17
+ ### Phase 2
18
+ - candidate discovery
19
+ - sessionizer row building
20
+ - session popup row building
21
+ - preview rendering data model
22
+ - session create or switch orchestration
23
+
24
+ ### Phase 3
25
+ - popup toggle orchestration
26
+ - auto-attach logic
27
+ - ephemeral prune logic
28
+ - kube session helpers
29
+
30
+ ### Phase 4
31
+ - standalone tmux popup toggle entrypoints
32
+ - generated tmux binding snippet
33
+ - `projmux tmux install` include-file wiring
34
+
35
+ ### Phase 5
36
+ - pane attention toggle/clear/window badge commands
37
+ - generated tmux window-status and pane-focus hooks backed by `projmux attention`
38
+ - AI pane status, Codex title watcher, and desktop notification commands
39
+ - status bar git/kube segments
40
+
41
+ ## What stays outside standalone projmux
42
+
43
+ - shell startup hooks
44
+ - machine-specific install behavior
45
+ - optional OS or terminal integration scripts that are not session-management features
46
+
47
+ ## Compatibility strategy
48
+
49
+ - preserve the user-facing keybindings and popup flows
50
+ - route those flows through `projmux` commands
51
+ - provide `projmux tmux print-config` and `projmux tmux install` for generated tmux bindings
52
+ - remove shell implementation only after the Go behavior is verified by the standalone path
53
+
54
+ ## Expected first cut
55
+
56
+ The first useful milestone is not full parity.
57
+ It is:
58
+ - `projmux current`
59
+ - `projmux switch --ui=popup`
60
+ - `projmux sessions --ui=popup`
61
+ - pin persistence
62
+ - preview state persistence
63
+
64
+ ## Standalone tmux path
65
+
66
+ The standalone tmux path is:
67
+
68
+ 1. `projmux tmux print-config` prints bindings that call `projmux` directly.
69
+ 2. `projmux tmux install` writes that snippet to `~/.config/tmux/projmux.conf` and includes it from `~/.tmux.conf`.
70
+ 3. `projmux tmux popup-toggle <mode>` replaces `tmux-popup-toggle.sh` for sessionizer, session popup, sidebar, AI picker, and the unified settings popup.
71
+ 4. `projmux attention <toggle|clear|window>` replaces tmux attention wrapper scripts for pane focus hooks and window badges.
72
+ 5. `projmux ai status`, `projmux ai notify`, and `projmux ai watch-title` replace the AI pane state and notification shell scripts.
73
+ 6. `projmux status <git|kube>` replaces tmux status-bar segment scripts for git branch and kube context rendering.
74
+
75
+ ## App tmux runtime
76
+
77
+ The app runtime path is:
78
+
79
+ 1. `projmux shell` writes `~/.config/projmux/tmux.conf` and launches `tmux -L projmux -f ~/.config/projmux/tmux.conf new-session -A -s main`.
80
+ 2. `projmux tmux print-app-config` prints the config used by that isolated app server.
81
+ 3. `projmux tmux install-app` writes the app config without touching `~/.tmux.conf`.
82
+ 4. The app runtime uses a separate tmux socket and config from the user's normal tmux server, so projmux can own its status bar, bindings, badge, and popup behavior.