projmux 0.6.6 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-ko.md +36 -5
- package/README.md +40 -12
- package/docs/agent-workflow.md +24 -16
- package/docs/ai-agent-shortcuts.md +11 -6
- package/docs/architecture.md +4 -3
- package/docs/assets/projmux-ai-attention.gif +0 -0
- package/docs/assets/projmux-skill-workflow.gif +0 -0
- package/docs/cli.md +89 -41
- package/docs/configuration.md +51 -22
- package/docs/hooks.md +33 -0
- package/docs/install.md +8 -8
- package/docs/keybindings.md +59 -33
- package/docs/native-picker-no-fzf-poc.md +3 -2
- package/docs/native-picker-parity.md +6 -3
- package/docs/notify-queue.md +99 -26
- package/docs/session-restore.md +8 -4
- package/docs/settings-ia.md +17 -7
- package/docs/statusbar.md +34 -7
- package/docs/testing.md +10 -3
- package/docs/upgrading.md +10 -4
- package/docs/usage-tracking.md +42 -13
- package/package.json +5 -5
- package/docs/assets/projmux-shell-sidebar.gif +0 -0
- package/docs/readme-hero-gif-recording.md +0 -97
package/docs/notify-queue.md
CHANGED
|
@@ -13,6 +13,7 @@ via `projmux focus`, and feeds the HUD pill rendered by
|
|
|
13
13
|
```
|
|
14
14
|
${XDG_STATE_HOME:-$HOME/.local/state}/projmux/notify.json
|
|
15
15
|
${XDG_STATE_HOME:-$HOME/.local/state}/projmux/notify.json.lock
|
|
16
|
+
${XDG_STATE_HOME:-$HOME/.local/state}/projmux/notify-queue-events/refresh-*.sock
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
The lock file is acquired via `O_CREATE|O_EXCL` with bounded retry
|
|
@@ -24,6 +25,13 @@ The queue file is a pretty-printed JSON array of `Notification`
|
|
|
24
25
|
objects, sorted newest-first on read. `expires_at` is freshness metadata;
|
|
25
26
|
expired entries are not filtered or deleted by `list`.
|
|
26
27
|
|
|
28
|
+
Open native notify sidebars also create per-process Unix datagram sockets for
|
|
29
|
+
queue-write refresh events. If the state-dir socket path would exceed Unix
|
|
30
|
+
socket path limits, projmux uses a short per-state-dir temp runtime path for
|
|
31
|
+
the socket directory. These sockets are transient UI delivery endpoints only:
|
|
32
|
+
they are not queue state, do not change the JSON schema, and are removed when
|
|
33
|
+
the sidebar exits.
|
|
34
|
+
|
|
27
35
|
## Data model
|
|
28
36
|
|
|
29
37
|
`internal/core/notify`:
|
|
@@ -58,11 +66,17 @@ exit code 2.
|
|
|
58
66
|
routing/debug context such as `agent`, `thread_id`, `turn_id`, `cwd`,
|
|
59
67
|
`model`, and `client`; Claude hook rows also carry event-specific keys such as
|
|
60
68
|
`tool_name`, `tool_input.command`, `error_type`, `subagent_type`, and
|
|
61
|
-
`teammate_name`.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
`teammate_name`. Antigravity manual hook rows carry `agent=antigravity`,
|
|
70
|
+
`conversation_id`, `termination_reason`, `fully_idle`,
|
|
71
|
+
`tool_confirmation_pending`, `agent_state`, and `context_window` when present.
|
|
72
|
+
The same `conversation_id` can seed session-state restore via
|
|
73
|
+
`agy --conversation <uuid>` when it is UUID-shaped; Antigravity quota usage
|
|
74
|
+
remains unsupported because `context_window` is not 5-hour/weekly quota data.
|
|
75
|
+
Tmux bell fallback rows carry `agent=bell`, `event=bell`, and tmux target
|
|
76
|
+
context such as pane title, command, session, window, pane, and socket.
|
|
77
|
+
`notify list --json` includes this metadata as the structured data channel
|
|
78
|
+
while human table/sidebar output keeps the compact text body. Existing entries
|
|
79
|
+
without metadata remain valid.
|
|
66
80
|
|
|
67
81
|
## CLI surface
|
|
68
82
|
|
|
@@ -92,18 +106,56 @@ table `ID AGE SEV SRC TARGET TEXT`. `--severity` / `--source` are
|
|
|
92
106
|
repeatable filters. Without `--live`, this command reads only the queue and
|
|
93
107
|
preserves the stable JSON array used by scripts.
|
|
94
108
|
|
|
95
|
-
`--ui=sidebar` opens the notify queue as an interactive right-side
|
|
96
|
-
run inside the tmux popup surface.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
and
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
`--ui=sidebar` opens the notify queue as an interactive right-side pane/session
|
|
110
|
+
inbox when run inside the tmux popup surface. The queue source of truth remains
|
|
111
|
+
flat; the sidebar builds a read-only grouped view for display. The first screen
|
|
112
|
+
shows collapsed group rows keyed by pane when available, then window, then
|
|
113
|
+
session/external fallback. Each group row is a fixed three-line card: line 1
|
|
114
|
+
keeps project/session plus agent/provider with newest age, line 2 keeps
|
|
115
|
+
topic/pane-title/task context plus severity/live-state aggregate
|
|
116
|
+
metadata, and line 3 keeps the latest notification preview. Collapsed group
|
|
117
|
+
cards do not promote window/pane ids as primary information. A `+N` badge is
|
|
118
|
+
shown only when the group can unfold, and `N` is the number of child
|
|
119
|
+
notification rows that will appear; one-notification group headers omit both
|
|
120
|
+
the count badge and strong fold marker. Right/Left show and hide child rows for
|
|
121
|
+
foldable groups inside the native sidebar only; this fold state is
|
|
122
|
+
session-local and is not persisted. Right on a childless group refreshes
|
|
123
|
+
without adding rows. Enter on a group row, whether folded or expanded, focuses
|
|
124
|
+
the group's representative pane and acknowledges every visible notification in
|
|
125
|
+
that group only after focus succeeds. Inactive means an `ai:` queue entry points
|
|
126
|
+
to a pane that no longer matches live reply+agent state; it is not a time-age
|
|
127
|
+
TTL state, and Enter still focuses the target when it is routable. If the
|
|
128
|
+
representative target is gone/unroutable, Enter treats the selected pane inbox
|
|
129
|
+
as explicit cleanup and acknowledges/prunes the visible group without focusing,
|
|
130
|
+
including critical notifications. If a live- or inactive-looking representative target
|
|
131
|
+
disappears during focus, Enter uses the same gone-group cleanup policy. Other
|
|
132
|
+
focus failures keep the group pending, show a clear message, and refresh/prune
|
|
133
|
+
the list. Expanded child notification rows are compact event rows with age,
|
|
134
|
+
message preview, and severity/state while keeping the existing focus/ack-one
|
|
135
|
+
behavior. The surface actions
|
|
136
|
+
`NotifySidebar:Ack`, `NotifySidebar:AckGroup`,
|
|
137
|
+
`NotifySidebar:ClearNonCritical`, and `NotifySidebar:ClearAll` are internal
|
|
138
|
+
picker actions; direct launch aliases are edited in Settings, while internal
|
|
139
|
+
picker aliases are adjusted in `keymap.toml` when needed.
|
|
140
|
+
`NotifySidebar:AckGroup` defaults to uppercase `A` and explicitly
|
|
141
|
+
acknowledges every visible notification in the selected group, including
|
|
142
|
+
critical notifications. Runtime footer key guides read the merged keymap and
|
|
143
|
+
show the default alias when present, otherwise the first configured alias, so
|
|
144
|
+
custom aliases do not make the UI stale.
|
|
145
|
+
`NotifySidebar:Ack`, `NotifySidebar:AckGroup`, and
|
|
146
|
+
`NotifySidebar:ClearNonCritical` refresh rows, live state, and selection inside
|
|
147
|
+
the same native picker session; `NotifySidebar:ClearAll` still closes the
|
|
148
|
+
popup and prints a summary. Rows are intentionally compact: hidden queue ids
|
|
149
|
+
remain action values but the sidebar has no search input and intentionally does
|
|
150
|
+
not expose a separate metadata detail view.
|
|
151
|
+
|
|
152
|
+
When a new pending notification is successfully pushed by any app producer
|
|
153
|
+
(`notify push`, reply-ready, reconcile backfill, or bell fallback), open native
|
|
154
|
+
notify sidebars receive a best-effort queue-write event and rerun the same
|
|
155
|
+
`DeferredUpdate` row/live-state refresh path used by `a` ack and `x`
|
|
156
|
+
non-critical clear. Event delivery errors are ignored after the queue write:
|
|
157
|
+
the push still succeeds, and reopening the sidebar remains the recovery path
|
|
158
|
+
for seeing the latest queue.
|
|
107
159
|
|
|
108
160
|
`--live` adds a non-mutating explanation view that reads
|
|
109
161
|
`tmux list-panes -a` and compares the queue with live reply-state panes. It
|
|
@@ -117,11 +169,20 @@ output becomes `{queue, live, rows, errors}`. Typical states:
|
|
|
117
169
|
queue entry.
|
|
118
170
|
- `live-ai-reply-missing-queue` — a live AI reply pane lacks the derived
|
|
119
171
|
queue entry; run `projmux notify reconcile` to back-fill it.
|
|
120
|
-
- `queue-stale` —
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
172
|
+
- `queue-stale` — preserved machine-readable state for an inactive target:
|
|
173
|
+
an `ai:` queue entry whose pane still EXISTS in the live tmux pane inventory,
|
|
174
|
+
but no longer matches reply+agent state. It is not TTL/time age. Surfaced in
|
|
175
|
+
the sidebar/statusbar as `INACTIVE` / `INA`; Enter still focuses and acks if
|
|
176
|
+
the target is routable.
|
|
177
|
+
- `queue-gone` — the queue entry's target is gone. This is now determined two
|
|
178
|
+
ways: (a) the entry has no routable target (empty session), or (b) the entry
|
|
179
|
+
carries a pane target whose pane id is absent from the real tmux live pane
|
|
180
|
+
inventory (`tmux list-panes -a`). Surfaced as `GONE` / `GON`, and Enter/ack
|
|
181
|
+
cleans it up without focusing. The inventory check is best-effort: when the
|
|
182
|
+
pane inventory cannot be read (tmux error, or an empty/unrecognized reply),
|
|
183
|
+
membership-based GONE is skipped so a missing tmux server never falsely
|
|
184
|
+
dims/gones every row, and only pane-target rows are eligible (window/session-
|
|
185
|
+
only rows keep the empty-session check only).
|
|
125
186
|
- `queue-only` — a non-AI/external queue entry is pending and has no live AI
|
|
126
187
|
reply-pane requirement.
|
|
127
188
|
|
|
@@ -151,7 +212,11 @@ path), then:
|
|
|
151
212
|
- pushes/refreshes one `ai:<session>:<pane>` entry for every pane
|
|
152
213
|
whose attention state is `reply` AND whose agent option is non-empty;
|
|
153
214
|
- reports every existing queue entry whose id starts with `ai:` and whose
|
|
154
|
-
pane no longer matches that condition as stale
|
|
215
|
+
pane no longer matches that condition as inactive/`queue-stale`, without
|
|
216
|
+
acking it.
|
|
217
|
+
|
|
218
|
+
Successful backfill pushes publish the same best-effort open-sidebar refresh
|
|
219
|
+
event as other pending queue additions.
|
|
155
220
|
|
|
156
221
|
Soft-fails when tmux is not running (returns a populated `errors`
|
|
157
222
|
field rather than a non-zero exit) so the post-install hook does not
|
|
@@ -180,7 +245,10 @@ an entry with:
|
|
|
180
245
|
When the pane leaves the reply state (manual `attention clear`,
|
|
181
246
|
`status set idle`, or a window close), `AckReplyReady` intentionally does not
|
|
182
247
|
remove the entry. The user consumes it through explicit ack. Store errors are
|
|
183
|
-
swallowed so the live tmux UI never blocks on disk IO.
|
|
248
|
+
swallowed so the live tmux UI never blocks on disk IO. After a successful
|
|
249
|
+
queue write and same-pane non-critical compaction, the producer publishes the
|
|
250
|
+
same best-effort notify-sidebar queue-write refresh event used by
|
|
251
|
+
`projmux notify push`.
|
|
184
252
|
|
|
185
253
|
Manual `projmux attention toggle` on a pane without an agent option
|
|
186
254
|
does NOT push — the queue is intentionally AI-driven; reconcile honours
|
|
@@ -200,7 +268,9 @@ tmux and writes an info/source-ai row with:
|
|
|
200
268
|
Unlike reply-ready reconcile, bell ingest does not require AI pane metadata.
|
|
201
269
|
It is intentionally available for arbitrary CLIs that only signal attention
|
|
202
270
|
through BEL or OSC 9. Repeated bells from the same pane are suppressed for 5
|
|
203
|
-
seconds before a later bell refreshes the stable queue id.
|
|
271
|
+
seconds before a later bell refreshes the stable queue id. Successful
|
|
272
|
+
non-deduped bell queue writes publish the same best-effort open-sidebar
|
|
273
|
+
refresh event as other pending queue additions.
|
|
204
274
|
|
|
205
275
|
## Consumer (status-bar click)
|
|
206
276
|
|
|
@@ -230,8 +300,11 @@ Outcomes:
|
|
|
230
300
|
|
|
231
301
|
The same consume policy is shared by notify-sidebar Enter and OS
|
|
232
302
|
click-to-focus Toast callbacks after a real tmux focus dispatch succeeds.
|
|
303
|
+
OS Toast click-to-focus is only registered when Desktop notification mode is
|
|
304
|
+
`raise`; the in-app sidebar/statusbar consume path works in every mode.
|
|
233
305
|
Pane focus hooks and attention clear paths remain live-attention-only and do
|
|
234
|
-
not ack the notify queue
|
|
306
|
+
not ack the notify queue; their response-complete badge consume is limited to
|
|
307
|
+
live tmux pane badge/state options. Non-critical AI completion producers also compact
|
|
235
308
|
older same-pane non-critical AI rows after replacing/pushing their latest row,
|
|
236
309
|
so reply-ready/stop/bell-style completion rows stay latest-state centered
|
|
237
310
|
without changing the queue schema or TTL contract.
|
package/docs/session-restore.md
CHANGED
|
@@ -51,8 +51,12 @@ CLI for inspection/actions.
|
|
|
51
51
|
Agent restore direct-starts supported resume commands when creating fresh tmux
|
|
52
52
|
panes, matching the `projmux ai split` wrapper shape: the wrapper prepends the
|
|
53
53
|
agent binary directory to `PATH`, changes to the saved cwd, sets the terminal
|
|
54
|
-
and tmux pane title from the saved agent topic, then execs `codex resume <id
|
|
55
|
-
|
|
54
|
+
and tmux pane title from the saved agent topic, then execs `codex resume <id>`,
|
|
55
|
+
`claude --resume <id>`, or `agy --conversation <uuid>`. Antigravity restore
|
|
56
|
+
uses only the stable statusline `conversation_id` or hook `conversationId`
|
|
57
|
+
metadata captured as the pane resume id; missing or non-UUID Antigravity ids
|
|
58
|
+
render as `resume unavailable` rather than falling back silently to a shell
|
|
59
|
+
recipe. This avoids typing agent resumes with
|
|
56
60
|
`tmux send-keys`. The restore wrapper is still a non-interactive shell command
|
|
57
61
|
tail, so it does not replay the original pane's interactive shell startup,
|
|
58
62
|
environment, shell functions, aliases, or live process state. Startup recipes
|
|
@@ -74,7 +78,7 @@ when building `Named snapshot` candidates; new primary surfaces should describe
|
|
|
74
78
|
the restore unit as a snapshot, not as a separate layout or preset feature.
|
|
75
79
|
|
|
76
80
|
Project open from the Alt-1 sidebar defaults to opening a closed project as an
|
|
77
|
-
`Empty session`. `Settings >
|
|
81
|
+
`Empty session`. `Settings > Session State > Sidebar startup picker` is an opt-in toggle;
|
|
78
82
|
when it is on, closed project open advances inside the sidebar to the native
|
|
79
83
|
`Start project` step. Rows are ordered `Latest snapshot`, named snapshot rows,
|
|
80
84
|
`Empty session`, then `Back`. `Latest snapshot` is the auto-saved snapshot that
|
|
@@ -98,5 +102,5 @@ directly without a startup picker or trust gate.
|
|
|
98
102
|
Default `projmux shell` no longer opens a compatibility startup picker and no
|
|
99
103
|
longer accepts startup selector flags for session-state restore. It always
|
|
100
104
|
follows the normal empty attach path after resolving the target app session name
|
|
101
|
-
and startup directory. Use `Settings >
|
|
105
|
+
and startup directory. Use `Settings > Session State > Sidebar startup picker` for
|
|
102
106
|
interactive Latest snapshot / Named snapshot / Empty session selection.
|
package/docs/settings-ia.md
CHANGED
|
@@ -24,16 +24,22 @@ view-first layout:
|
|
|
24
24
|
commands, `Pane navigation`, `Window navigation`, and `Rename` groups or
|
|
25
25
|
equivalent searchable rows.
|
|
26
26
|
- `Settings > Keybindings > Action` keeps the user-facing edit path small:
|
|
27
|
-
action,
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
action label, state, a flat Keys list, Options, and a collapsed
|
|
28
|
+
Troubleshooting row. Keys shows only currently active/effective keys plus
|
|
29
|
+
`+ Add key`. Pressing a key row opens key detail, where Remove key and Test
|
|
30
|
+
key live. Options offers Unbind and Reset to default/Use default when
|
|
31
|
+
state-appropriate. Add key opens the default Press a key flow with Cancel and
|
|
32
|
+
Advanced...; typed key-name entry and raw diagnostics live under Advanced. It
|
|
33
|
+
does not expose Default key, Apply State, Delivery, Advanced Delivery,
|
|
34
|
+
key-role replacement, terminal mapping preview, or terminal mapping apply
|
|
35
|
+
rows as always-visible sections.
|
|
30
36
|
- Terminal delivery remediation lives outside Settings primary flow. The
|
|
31
37
|
supported order is `projmux shell` first, then `projmux setup`, then
|
|
32
38
|
`projmux init` for supported terminal adapters.
|
|
33
39
|
- Rows that cannot safely be edited still stay visible. Mark diagnostic-only
|
|
34
40
|
rows with the delivery path and reason instead of hiding them or turning them
|
|
35
|
-
into unsupported editable
|
|
36
|
-
|
|
41
|
+
into unsupported editable keys. Transport-dependent rows stay visible with
|
|
42
|
+
their default transport key and additive custom-key entry; replacing or
|
|
37
43
|
disabling the transport default is not exposed.
|
|
38
44
|
- `Alt-1..5` are the only guaranteed zero-config launch defaults. `UserN` and
|
|
39
45
|
`CSI-u` are legacy/removal/unsupported targets, not supported fallback
|
|
@@ -62,6 +68,9 @@ view-first layout:
|
|
|
62
68
|
runtime action values and writes only
|
|
63
69
|
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/ai-hook-actions.json`. It does not
|
|
64
70
|
edit catalog `install` values or run agent install/remove commands.
|
|
71
|
+
- `Settings > Session State > Sidebar startup picker` controls the Alt-1
|
|
72
|
+
project-open startup selector. The saved file remains
|
|
73
|
+
`${XDG_CONFIG_HOME:-$HOME/.config}/projmux/sidebar-startup-picker`.
|
|
65
74
|
- `Settings > Labs` keeps experimental toggles, but keybindings no longer have a
|
|
66
75
|
visible Labs row. The hidden compatibility action redirects to the
|
|
67
76
|
`Settings > Keybindings` action list, not to a diagnostic default.
|
|
@@ -107,5 +116,6 @@ Shell bootstrap UX is phase-split:
|
|
|
107
116
|
- `projmux welcome` remains the stdout revisit command.
|
|
108
117
|
- `Settings > About > Welcome` opens a visible native viewer independent of
|
|
109
118
|
shell skip state.
|
|
110
|
-
-
|
|
111
|
-
|
|
119
|
+
- Legacy shell `skip_version` state remains readable for compatibility but no
|
|
120
|
+
longer suppresses the automatic `projmux shell` prompt; release skips live in
|
|
121
|
+
`update-skip.json` and do not hide manual revisit surfaces.
|
package/docs/statusbar.md
CHANGED
|
@@ -46,6 +46,9 @@ row 1 [#S] #{pane_current_path} ⎈ <ctx>/<ns> <git> %H:%M
|
|
|
46
46
|
notify queue segment and from notify queue severity or desktop notification
|
|
47
47
|
urgency. For example, an approval request may remain a critical queued
|
|
48
48
|
notification while its live status badge renders action-required amber-orange.
|
|
49
|
+
Pane focus hooks and `projmux attention clear` consume only the
|
|
50
|
+
response-complete live badge, including stale `@projmux_ai_state=waiting`
|
|
51
|
+
fallback state; action-required and in-progress live badges remain visible.
|
|
49
52
|
Window-list badges and app pane-border badges use the same semantic priority,
|
|
50
53
|
with display style controlled by Settings > Appearance > AI badge style and persisted in
|
|
51
54
|
`~/.config/projmux/ai-badge-style`. The default is `dot`; `emoji` renders
|
|
@@ -138,13 +141,35 @@ last collect timestamp when present, falls back to the cache file mtime when
|
|
|
138
141
|
needed, and keeps stale sync metadata muted instead of escalating it to a
|
|
139
142
|
warning color.
|
|
140
143
|
The notification HUD detail surface opens the right-side notification popup
|
|
141
|
-
through the notify sidebar action,
|
|
142
|
-
attention-tinted title. When notification
|
|
143
|
-
`emoji`, the bell appears before the title text.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
render
|
|
147
|
-
|
|
144
|
+
through the notify sidebar action, showing the grouped pane/session inbox with
|
|
145
|
+
collapsed group rows and the same attention-tinted title. When notification
|
|
146
|
+
icon decoration is `symbol` or `emoji`, the bell appears before the title text.
|
|
147
|
+
Foldable group rows show `+N`, where `N` is the number of child notification
|
|
148
|
+
rows shown after Right. One-notification group headers omit the count and do
|
|
149
|
+
not render as strongly foldable. Right/Left show and hide child rows locally
|
|
150
|
+
inside the native sidebar; Right on a childless group refreshes without adding
|
|
151
|
+
rows. Enter on a group row, whether folded or expanded, focuses the group's
|
|
152
|
+
representative pane and acknowledges every visible notification in that group
|
|
153
|
+
only after focus succeeds. Inactive means an `ai:` queue entry no longer
|
|
154
|
+
matches live reply+agent state (its pane still EXISTS in tmux), not that the
|
|
155
|
+
row is old; if the target remains routable, Enter and statusbar clicks still
|
|
156
|
+
focus and then ack. Gone means the target is unroutable (empty session) or the
|
|
157
|
+
row's pane id is absent from the real tmux live pane inventory
|
|
158
|
+
(`tmux list-panes -a`). The inventory check is best-effort: an unreadable or
|
|
159
|
+
empty/unrecognized tmux reply is treated as "unavailable", so a missing tmux
|
|
160
|
+
server never falsely gones routable rows. If the
|
|
161
|
+
representative target is gone/unroutable, Enter cleans up the selected group
|
|
162
|
+
without focusing and acknowledges every visible notification in that group,
|
|
163
|
+
including critical notifications. A
|
|
164
|
+
target-gone focus race follows the same cleanup policy; other focus failures
|
|
165
|
+
keep the group pending and show a clear message before refresh/prune. Enter on
|
|
166
|
+
a child notification preserves the existing focus and ack-one behavior.
|
|
167
|
+
`NotifySidebar:AckGroup` remains the explicit group ack action and acknowledges
|
|
168
|
+
every visible notification in the selected group, including critical
|
|
169
|
+
notifications.
|
|
170
|
+
Internal notify commands use `NotifySidebar:*` IDs in `keymap.toml`; runtime
|
|
171
|
+
footers render key guides from the merged keymap and prefer the default alias
|
|
172
|
+
when it is still configured.
|
|
148
173
|
|
|
149
174
|
Empty `#{mouse_status_range}` (a click on whitespace) falls through to
|
|
150
175
|
`select-window -t @<mouse_window>` when `--mouse-window` is non-empty,
|
|
@@ -177,6 +202,8 @@ them as `display-message` toasts:
|
|
|
177
202
|
|
|
178
203
|
- `notify` click whose focus dispatch exits 2 (target unresolved):
|
|
179
204
|
ack the entry, toast `notify target gone; cleared`.
|
|
205
|
+
- `notify` click whose AI target is inactive because it no longer matches live
|
|
206
|
+
reply+agent state: focus and ack when the target is still routable.
|
|
180
207
|
- Any other focus failure: keep the entry, toast `focus failed:
|
|
181
208
|
<reason>`.
|
|
182
209
|
- `session`, `kube`, or `git` popup launch failure: toast
|
package/docs/testing.md
CHANGED
|
@@ -21,6 +21,10 @@ and humans run the same entrypoints.
|
|
|
21
21
|
`test/e2e/linux-smoke.sh`. It validates a minimal real-tmux workflow:
|
|
22
22
|
sessions, panes, config sourcing, reply-state notify reconciliation, focus
|
|
23
23
|
notify fallback, and status notify rendering.
|
|
24
|
+
- `make deadcode` runs `go tool deadcode` (pinned via the go.mod tool
|
|
25
|
+
directive) over the module and reports unreachable functions, filtering out
|
|
26
|
+
the intentional/MUST-KEEP baseline in `.deadcode-allowlist.txt`; it fails
|
|
27
|
+
only on NEW dead code, and `make fix` runs it after `go fix`.
|
|
24
28
|
|
|
25
29
|
## Docker-Covered Checks
|
|
26
30
|
|
|
@@ -90,7 +94,7 @@ Observe:
|
|
|
90
94
|
|
|
91
95
|
- `Alt-1` opens the project sidebar.
|
|
92
96
|
- `Alt-2` opens the notification sidebar.
|
|
93
|
-
- `Alt-3` opens
|
|
97
|
+
- `Alt-3` opens Recent Windows.
|
|
94
98
|
- `Alt-4` opens the AI split picker.
|
|
95
99
|
- `Alt-5` opens Settings.
|
|
96
100
|
- Pressing the same launch key again closes the popup instead of typing escape
|
|
@@ -117,12 +121,15 @@ Observe:
|
|
|
117
121
|
`"reason":"no-attached-client"`.
|
|
118
122
|
- Windows shows a short projmux toast with `session ready:
|
|
119
123
|
projmux-host-smoke`.
|
|
124
|
+
- In `notify` mode, the toast has no click-to-focus action and should not
|
|
125
|
+
auto-raise the host terminal.
|
|
120
126
|
- No visible PowerShell or console window remains open after the toast.
|
|
121
127
|
|
|
122
128
|
If the PR changes click-to-focus behavior, repeat with
|
|
123
129
|
`PROJMUX_DESKTOP_NOTIFY_MODE=raise`, click the toast, and record whether the
|
|
124
|
-
host terminal returns to the target.
|
|
125
|
-
|
|
130
|
+
host terminal returns to the target. `raise` should also be the only mode where
|
|
131
|
+
`projmux focus` performs post-switch osfocus. Otherwise leave click callbacks
|
|
132
|
+
marked as manual/not run.
|
|
126
133
|
|
|
127
134
|
### macOS GUI Notification
|
|
128
135
|
|
package/docs/upgrading.md
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
projmux has two update surfaces:
|
|
4
4
|
|
|
5
5
|
- `projmux shell` reads the cached release status before opening the app. When
|
|
6
|
-
the cache is
|
|
7
|
-
|
|
6
|
+
the cache is missing or stale, startup attempts a short best-effort refresh
|
|
7
|
+
and continues if it fails. When a newer release is available, the shell
|
|
8
|
+
welcome offers Continue, Upgrade, and Skip until next actions.
|
|
8
9
|
- Settings > About > Update shows the current version, detected installer,
|
|
9
10
|
cached latest version, Check Updates, and Update Now actions.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
Refresh the cache explicitly when you want a full foreground GitHub Releases
|
|
13
|
+
check:
|
|
13
14
|
|
|
14
15
|
```sh
|
|
15
16
|
projmux update check
|
|
@@ -24,6 +25,11 @@ projmux update apply
|
|
|
24
25
|
Use `--dry-run` to see the planned action and `--no-apply` to skip reloading
|
|
25
26
|
the live tmux config after the binary changes.
|
|
26
27
|
|
|
28
|
+
Shell Upgrade invokes only `projmux update apply`. Shell Skip until next stores
|
|
29
|
+
the current latest release tag in `update-skip.json`; the prompt appears again
|
|
30
|
+
when the cached latest tag changes. For `source` and unknown installer sources,
|
|
31
|
+
Upgrade prints guidance and continues shell entry without applying anything.
|
|
32
|
+
|
|
27
33
|
## npm Installs
|
|
28
34
|
|
|
29
35
|
The recommended install path is:
|
package/docs/usage-tracking.md
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
# Usage tracking
|
|
2
2
|
|
|
3
3
|
`projmux usage` and `projmux status usage` report authoritative 5-hour
|
|
4
|
-
and weekly utilisation for
|
|
5
|
-
|
|
4
|
+
and weekly utilisation for enabled AI agents. `--model all`, the tmux
|
|
5
|
+
HUD, and the statusbar usage popup use Settings > AI Settings > Enabled
|
|
6
|
+
agents as the source of truth, so disabled Claude/Codex providers are
|
|
7
|
+
not refreshed or rendered on ambient/all surfaces. Explicit read-only
|
|
8
|
+
requests such as `projmux usage --model claude` or `--model codex`
|
|
9
|
+
still collect and render that provider even when it is disabled.
|
|
10
|
+
|
|
11
|
+
Both adapters read from the upstream's own view of the account so the
|
|
6
12
|
percentages match what `claude /usage` and `codex` show natively.
|
|
7
13
|
|
|
14
|
+
Antigravity is intentionally not registered as a 5-hour/weekly quota adapter.
|
|
15
|
+
The only stable Phase 0b usage signal is statusline `context_window`, which is
|
|
16
|
+
conversation context-window usage, not account quota usage. `projmux usage
|
|
17
|
+
--model antigravity` and ambient all-model table output therefore render an
|
|
18
|
+
explicit unsupported note when Antigravity is enabled. The statusbar usage
|
|
19
|
+
popup shows an `Antigravity ctx ... unsupported` row, while the compact tmux
|
|
20
|
+
status segment stays silent unless Claude/Codex quota rows exist. Projmux does
|
|
21
|
+
not infer quota, reset timestamps, or account limits from screen scraping,
|
|
22
|
+
tokens, history, OAuth/cache files, or binary strings.
|
|
23
|
+
|
|
8
24
|
## Adapters
|
|
9
25
|
|
|
10
26
|
### Claude (`internal/core/usage/adapters/claude`)
|
|
@@ -79,12 +95,13 @@ across machines (Dropbox, iCloud Drive).
|
|
|
79
95
|
### `projmux usage`
|
|
80
96
|
|
|
81
97
|
```
|
|
82
|
-
projmux usage [--model codex|claude|all] [--window 5h|weekly|all]
|
|
98
|
+
projmux usage [--model codex|claude|antigravity|all] [--window 5h|weekly|all]
|
|
83
99
|
[--json] [--force|-f]
|
|
84
100
|
```
|
|
85
101
|
|
|
86
|
-
|
|
87
|
-
|
|
102
|
+
For `--model all`, calls `Manager.Collect` (or `ForceCollect` with
|
|
103
|
+
`--force`) only for providers enabled in Settings > AI Settings >
|
|
104
|
+
Enabled agents, filters by window, and renders the tab-aligned table:
|
|
88
105
|
|
|
89
106
|
```
|
|
90
107
|
MODEL WINDOW PCT RESETS_AT STALE
|
|
@@ -103,16 +120,27 @@ instead. A backoff note is appended to the human table:
|
|
|
103
120
|
claude is in backoff, try again in 30m (use --force to bypass)
|
|
104
121
|
```
|
|
105
122
|
|
|
123
|
+
When no AI agents are enabled, all-model table output contains no
|
|
124
|
+
provider rows and prints a short Settings hint. `--json` returns an
|
|
125
|
+
empty array. Explicit `--model claude` and `--model codex` bypass the
|
|
126
|
+
enabled-agent filter for read-only inspection and collect/render only
|
|
127
|
+
the requested adapter. Explicit `--model antigravity` renders the same
|
|
128
|
+
unsupported/context-window-only note even when Antigravity is disabled, because
|
|
129
|
+
there is no supported Antigravity quota adapter to collect.
|
|
130
|
+
|
|
106
131
|
### `projmux status usage`
|
|
107
132
|
|
|
108
133
|
```
|
|
109
134
|
projmux status usage [--max-width N] [--force|-f]
|
|
110
135
|
```
|
|
111
136
|
|
|
112
|
-
The HUD bar wired to the tmux status interval.
|
|
113
|
-
opportunistic refresh:
|
|
114
|
-
per-adapter throttle and active
|
|
115
|
-
|
|
137
|
+
The HUD bar wired to the tmux status interval. It scopes the registry to
|
|
138
|
+
enabled AI agents, then triggers an opportunistic refresh:
|
|
139
|
+
`MaybeCollect(throttle=30s)` (subject to per-adapter throttle and active
|
|
140
|
+
backoff). Disabled providers are not refreshed just to be hidden. Errors
|
|
141
|
+
are swallowed unless `PROJMUX_USAGE_DEBUG` is set. Then it loads the
|
|
142
|
+
cache, filters to the same enabled-agent scope, and renders. If no AI
|
|
143
|
+
agents are enabled, the status segment emits nothing.
|
|
116
144
|
|
|
117
145
|
Output degrades through six tiers as `--max-width` shrinks:
|
|
118
146
|
|
|
@@ -132,10 +160,11 @@ because the rollout file is always near-current (no throttle gap to report).
|
|
|
132
160
|
### Statusbar usage popup
|
|
133
161
|
|
|
134
162
|
`projmux statusbar click usage` renders a native-framed popup from the same
|
|
135
|
-
cache instead of shelling out to `projmux usage`.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
163
|
+
cache instead of shelling out to `projmux usage`. The popup filters rows and
|
|
164
|
+
sync metadata to the same enabled-agent scope as the ambient HUD. This keeps
|
|
165
|
+
`projmux usage --json` backwards-compatible for CLI consumers while giving the
|
|
166
|
+
tmux click path a structured table with aligned rows, right-aligned numeric
|
|
167
|
+
values, dim unavailable cells, amber usage at 80%, and red usage at 95%.
|
|
139
168
|
|
|
140
169
|
The popup sync line uses the maximum authoritative `LastCollect` timestamp from
|
|
141
170
|
the cache. If that field is unavailable, it falls back to the snapshots file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projmux",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "tmux project session manager",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/crevissepartners/projmux#readme",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"package:npm:pack": "scripts/package-npm.sh --pack"
|
|
29
29
|
},
|
|
30
30
|
"optionalDependencies": {
|
|
31
|
-
"@projmux/linux-x64": "0.
|
|
32
|
-
"@projmux/linux-arm64": "0.
|
|
33
|
-
"@projmux/darwin-x64": "0.
|
|
34
|
-
"@projmux/darwin-arm64": "0.
|
|
31
|
+
"@projmux/linux-x64": "0.7.0",
|
|
32
|
+
"@projmux/linux-arm64": "0.7.0",
|
|
33
|
+
"@projmux/darwin-x64": "0.7.0",
|
|
34
|
+
"@projmux/darwin-arm64": "0.7.0"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
Binary file
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# README Hero GIF Recording
|
|
2
|
-
|
|
3
|
-
This recipe records the README hero GIF:
|
|
4
|
-
|
|
5
|
-
- `docs/assets/projmux-ai-attention.gif`
|
|
6
|
-
|
|
7
|
-
The maintained recorder is kept in the local dotfiles checkout at:
|
|
8
|
-
|
|
9
|
-
```sh
|
|
10
|
-
/home/es5h/dotfiles/bin/projmux/projmux-record-readme-gifs.py
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Prerequisites
|
|
14
|
-
|
|
15
|
-
Install or verify these local tools before recording:
|
|
16
|
-
|
|
17
|
-
- `python3`
|
|
18
|
-
- `git`
|
|
19
|
-
- `tmux`
|
|
20
|
-
- `ffmpeg` and `ffprobe`
|
|
21
|
-
- `Xvfb`
|
|
22
|
-
- `openbox`
|
|
23
|
-
- `ghostty`
|
|
24
|
-
- `xdotool`
|
|
25
|
-
- `xwininfo`
|
|
26
|
-
- `script` from util-linux
|
|
27
|
-
- authenticated `codex`
|
|
28
|
-
|
|
29
|
-
Build the local projmux binary first:
|
|
30
|
-
|
|
31
|
-
```sh
|
|
32
|
-
make build
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
The script expects `.bin/projmux` by default. Override paths only when needed:
|
|
36
|
-
|
|
37
|
-
```sh
|
|
38
|
-
PROJMUX_RECORD_REPO=/path/to/projmux \
|
|
39
|
-
PROJMUX_RECORD_BIN=/path/to/projmux \
|
|
40
|
-
PROJMUX_RECORD_DISPLAY=117 \
|
|
41
|
-
PROJMUX_RECORD_SCREEN=2560x1440x24 \
|
|
42
|
-
PROJMUX_RECORD_KEEP_TMP=1 \
|
|
43
|
-
python3 /home/es5h/dotfiles/bin/projmux/projmux-record-readme-gifs.py
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
For the normal checkout, run:
|
|
47
|
-
|
|
48
|
-
```sh
|
|
49
|
-
python3 /home/es5h/dotfiles/bin/projmux/projmux-record-readme-gifs.py
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Scenario Contract
|
|
53
|
-
|
|
54
|
-
The recording uses a private demo home, XDG config/state dirs, demo git
|
|
55
|
-
projects, and an isolated `CODEX_HOME`. It copies the local Codex auth/config
|
|
56
|
-
into that isolated home, trusts the demo projects/hooks, and seeds usage cache
|
|
57
|
-
data so the tmux status line shows the Codex HUD during the capture.
|
|
58
|
-
|
|
59
|
-
The scenario records the AI attention flow:
|
|
60
|
-
|
|
61
|
-
1. Start in `mobile-client` with no pending notification.
|
|
62
|
-
2. Open the AI picker and launch a real Codex pane.
|
|
63
|
-
3. Ask Codex to do a short task.
|
|
64
|
-
4. Use the projmux sessionizer sidebar to move to `atlas-api`.
|
|
65
|
-
5. Keep working in zsh while Codex finishes in the previous project.
|
|
66
|
-
6. When the Codex completion notification exists, open the notification sidebar.
|
|
67
|
-
7. Select the notification and return focus to the original Codex pane.
|
|
68
|
-
|
|
69
|
-
## Visual Guardrails
|
|
70
|
-
|
|
71
|
-
- Keep the native picker UI native. The script runs picker commands through
|
|
72
|
-
`script(1)` with a fixed PTY size so fzf/terminal UI rendering is captured
|
|
73
|
-
instead of degraded line-mode output.
|
|
74
|
-
- Keep the terminal in zsh with the demo prompt so the project and git branch
|
|
75
|
-
are visible.
|
|
76
|
-
- Keep the Codex usage HUD visible in the tmux status line.
|
|
77
|
-
- Use the sessionizer sidebar for project movement in 4a.
|
|
78
|
-
- Capture the Ghostty X11 window geometry with `xwininfo` and feed that exact
|
|
79
|
-
rectangle to ffmpeg. This prevents the GIF from drifting away from `(0, 0)`.
|
|
80
|
-
|
|
81
|
-
## Verification
|
|
82
|
-
|
|
83
|
-
After recording, inspect the resulting streams:
|
|
84
|
-
|
|
85
|
-
```sh
|
|
86
|
-
ffprobe -v error -select_streams v:0 \
|
|
87
|
-
-show_entries stream=width,height,nb_frames,duration \
|
|
88
|
-
-of default=noprint_wrappers=1 \
|
|
89
|
-
docs/assets/projmux-ai-attention.gif
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Expected final shape is roughly 1110px wide and about 16-18 seconds, with the
|
|
93
|
-
native picker, zsh prompt, Codex pane, notification sidebar, and usage HUD
|
|
94
|
-
visible in the relevant frames.
|
|
95
|
-
|
|
96
|
-
Set `PROJMUX_RECORD_KEEP_TMP=1` when you need to inspect intermediate MP4s,
|
|
97
|
-
Ghostty logs, or palette files under `/tmp/projmux-readme-record-*`.
|