@mu-crew/mu 3.13.3 → 4.1.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/AGENTS.md +73 -35
- package/README.md +71 -57
- package/dist/chunk-4ULY3ZKO.js +4482 -0
- package/dist/chunk-4ULY3ZKO.js.map +1 -0
- package/dist/chunk-7M634JMD.js +375 -0
- package/dist/chunk-7M634JMD.js.map +1 -0
- package/dist/{chunk-3BARPJLY.js → chunk-PZ5GOCWH.js} +16 -2
- package/dist/chunk-PZ5GOCWH.js.map +1 -0
- package/dist/chunk-SS7NQSSZ.js +3660 -0
- package/dist/chunk-SS7NQSSZ.js.map +1 -0
- package/dist/chunk-UCZPJX7K.js +14253 -0
- package/dist/chunk-UCZPJX7K.js.map +1 -0
- package/dist/{cli-CKOMHBXV.js → cli-TV3N47AZ.js} +7317 -4593
- package/dist/cli-TV3N47AZ.js.map +1 -0
- package/dist/cli.js +2 -3
- package/dist/cli.js.map +1 -1
- package/dist/errors-GRONKWFS.js +65 -0
- package/dist/extension/mu-pi.js +1632 -837
- package/dist/extension/mu-pi.js.map +1 -1
- package/dist/index.d.ts +4067 -2561
- package/dist/index.js +614 -297
- package/dist/index.js.map +1 -1
- package/dist/tui-FUBQ326D.js +1848 -0
- package/dist/tui-FUBQ326D.js.map +1 -0
- package/docs/ARCHITECTURE.md +118 -66
- package/docs/VOCABULARY.md +113 -49
- package/docs/guide/README.md +3 -3
- package/docs/guide/backends.md +8 -4
- package/docs/guide/cleanup.md +69 -33
- package/docs/guide/delegate.md +149 -66
- package/docs/guide/dispatch.md +148 -53
- package/docs/guide/getting-started.md +37 -44
- package/docs/guide/other-agent-clis.md +102 -0
- package/docs/guide/recovery.md +31 -50
- package/docs/guide/remote.md +122 -45
- package/docs/guide/sql.md +104 -24
- package/docs/guide/stop-a-worker.md +30 -37
- package/docs/guide/sync.md +11 -3
- package/docs/guide/upgrade.md +93 -43
- package/docs/reference/env.md +24 -32
- package/docs/reference/naming.md +14 -7
- package/docs/reference/surface-contract.md +153 -0
- package/package.json +33 -11
- package/prompts/mu-debug.md +3 -1
- package/prompts/mu-refute.md +2 -1
- package/prompts/mu-research.md +3 -1
- package/prompts/mu-review.md +2 -1
- package/prompts/mu-rules-audit.md +5 -4
- package/prompts/mu-sweep.md +2 -1
- package/prompts/mu-tournament.md +4 -2
- package/prompts/mu-until.md +3 -1
- package/prompts/ultrathink.md +1 -1
- package/skills/mu/SKILL.md +60 -291
- package/skills/mu/recipes/adversarial-review.md +12 -103
- package/skills/mu/recipes/brief.md +14 -61
- package/skills/mu/recipes/course-correct.md +23 -0
- package/skills/mu/recipes/findings.md +17 -111
- package/skills/mu/recipes/models.md +17 -92
- package/skills/mu/recipes/move.md +14 -0
- package/skills/mu/recipes/orchestrator-loop.md +20 -119
- package/skills/mu/recipes/recovery.md +8 -29
- package/skills/mu/recipes/remote-workers.md +17 -318
- package/skills/mu/recipes/tasks-or-calls.md +15 -78
- package/skills/mu/recipes/test-health.md +19 -77
- package/skills/mu/recipes/worker.md +17 -24
- package/dist/chunk-45KQLMEL.js +0 -2908
- package/dist/chunk-45KQLMEL.js.map +0 -1
- package/dist/chunk-G434JKV2.js +0 -641
- package/dist/chunk-G434JKV2.js.map +0 -1
- package/dist/chunk-KUGUFBWH.js +0 -12527
- package/dist/chunk-KUGUFBWH.js.map +0 -1
- package/dist/chunk-QITLNZEM.js +0 -87
- package/dist/chunk-QITLNZEM.js.map +0 -1
- package/dist/chunk-VIEYQMQA.js +0 -393
- package/dist/chunk-VIEYQMQA.js.map +0 -1
- package/dist/chunk-WI6AWCMK.js +0 -19
- package/dist/chunk-WI6AWCMK.js.map +0 -1
- package/dist/cli-CKOMHBXV.js.map +0 -1
- package/dist/devtools-LS4ZEPWM.js +0 -3772
- package/dist/devtools-LS4ZEPWM.js.map +0 -1
- package/dist/tui-LFJ5P4Y2.js +0 -40956
- package/dist/tui-LFJ5P4Y2.js.map +0 -1
- package/dist/tui-sync-worker.js +0 -17
- package/dist/tui-sync-worker.js.map +0 -1
- package/dist/yank-XDOONQSL.js +0 -13
- package/dist/yank-XDOONQSL.js.map +0 -1
- package/docs/ROADMAP.md +0 -123
- package/docs/VISION.md +0 -298
- package/docs/architecture/control-socket.md +0 -142
- package/docs/architecture/dag.md +0 -117
- package/docs/architecture/mux.md +0 -167
- package/docs/architecture/ops-log.md +0 -160
- package/docs/architecture/sdk.md +0 -187
- package/docs/architecture/sync.md +0 -159
- package/docs/architecture/tui.md +0 -165
- package/docs/guide/tui.md +0 -98
- package/docs/history/CHANGELOG-pre-3.md +0 -4866
- package/docs/img/tui-dashboard.png +0 -0
- package/docs/specs/2026-09-28-agent-state-from-murmur.md +0 -333
- package/docs/specs/2026-09-29-task-substates.md +0 -247
- package/docs/specs/2026-10-03-keep-driving-nudge.md +0 -163
- package/docs/specs/2026-10-21-fast-and-slow-gates.md +0 -229
- package/skills/mu/recipes/backlog-triage.md +0 -45
- package/skills/mu/recipes/codemode-driver.md +0 -118
- package/skills/mu/recipes/deep-research.md +0 -69
- package/skills/mu/recipes/drift-audit.md +0 -75
- package/skills/mu/recipes/fan-out.md +0 -42
- package/skills/mu/recipes/hypothesis-panel.md +0 -48
- package/skills/mu/recipes/long-run.md +0 -32
- package/skills/mu/recipes/loop-until-done.md +0 -45
- package/skills/mu/recipes/plan.md +0 -67
- package/skills/mu/recipes/refute.md +0 -55
- package/skills/mu/recipes/review-panel.md +0 -65
- package/skills/mu/recipes/rules-audit.md +0 -89
- package/skills/mu/recipes/tournament.md +0 -44
- package/skills/mu/recipes/ultrathink.md +0 -86
- package/skills/mu/recipes/watcher.md +0 -28
- package/skills/mu/recipes/waves.md +0 -21
- /package/dist/{chunk-3BARPJLY.js.map → errors-GRONKWFS.js.map} +0 -0
package/docs/guide/sql.md
CHANGED
|
@@ -1,36 +1,62 @@
|
|
|
1
1
|
# How to query and script mu
|
|
2
2
|
|
|
3
|
-
Use typed verbs with `--json` first. Use `mu sql` for
|
|
4
|
-
|
|
3
|
+
Use typed verbs with `--json` first. Use `mu db query` (alias `mu sql`) for
|
|
4
|
+
ad-hoc joins and reports that no verb covers; a repair needs `--write`.
|
|
5
5
|
|
|
6
6
|
## Script with `--json`
|
|
7
7
|
|
|
8
8
|
Every verb takes `--json`.
|
|
9
9
|
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
- Every verb prints ONE document on stdout: `{"ok": true, "data": ..., "next": null}`.
|
|
11
|
+
- Collection reads put `{"items": [...], "count": N}` in `data`. The task
|
|
12
|
+
reads (`task list/next/owned-by/show/tree`, `me tasks`) cap the result at 4 KB:
|
|
13
|
+
`more` counts what is left and `retrieve` is the same command with `--all`
|
|
14
|
+
(`--full` on `owned-by`, whose `--all` means every workstream), which prints
|
|
15
|
+
everything whole. Task items use the SQL column names (`id` is the `local_id`,
|
|
16
|
+
`effort_days`, `workstream_id`, `owner_id`; `owner` only while
|
|
17
|
+
IN_PROGRESS), never `name`/`effortDays`/`roi`. `task add --json` returns its
|
|
18
|
+
`task` (and `tasks`) in the same shape.
|
|
19
|
+
- Single objects, such as `mu task show`, put an object with named
|
|
20
|
+
fields in `data`.
|
|
21
|
+
- `mu db query` and `mu sql` print this document by default (`--table` gives
|
|
22
|
+
the human table). A read puts `{items, count, more}` in `data`, the same
|
|
23
|
+
shape as task lists, with your row keys untouched. It stops at 4 KB of final
|
|
24
|
+
output, cells never cut: `more` counts the rows left out and `retrieve` is the
|
|
25
|
+
same query with `--all`, which prints every row whole. One row bigger than the
|
|
26
|
+
cap gives zero `items`, `more: 1` and `retrieve`. A write prints
|
|
27
|
+
`{changes, lastInsertRowid}` (a script `{statements, multiStatement}`); an
|
|
28
|
+
`UPDATE ... RETURNING` prints its rows whole, with no `retrieve`, since running
|
|
29
|
+
it again would write again. Errors are the failure document on stdout, with or
|
|
30
|
+
without `--json`.
|
|
31
|
+
- `mu state` and bare `mu me` print the document by default too (no `--json` needed); a read over 4 KB is cut and names `mu state ... --full`.
|
|
32
|
+
- `mu log --tail` (no `--json` needed) is the exception: one raw JSON object per line, keyed by the `ops` column names.
|
|
33
|
+
- A failure is `{"ok": false, "error", "message", "next", "exit"}` on
|
|
34
|
+
**stdout** (plus, for usage errors, `usage`, at most 3 lines), with
|
|
35
|
+
the same non-zero exit code. `2>/dev/null` loses nothing.
|
|
16
36
|
|
|
17
37
|
```bash
|
|
18
|
-
mu state -w auth
|
|
19
|
-
mu task list -w auth --json | jq '.count'
|
|
38
|
+
mu state -w auth
|
|
39
|
+
mu task list -w auth --json | jq '.data.count'
|
|
40
|
+
mu task show t1 -w auth --json | jq 'if .ok then .data.task else .message end'
|
|
20
41
|
```
|
|
21
42
|
|
|
22
|
-
Exit codes: `
|
|
23
|
-
|
|
24
|
-
|
|
43
|
+
Exit codes: `1` any other failure (a spawn that failed, an unreachable
|
|
44
|
+
control socket, a send whose delivery is unknown), `2` usage error, `3` not found, `4` conflict, `5`
|
|
45
|
+
an abort or interrupt that timed out (pi still busy), a locked DB, or a multiplexer, VCS, drift, or `mu doctor`
|
|
46
|
+
FAIL-row failure, `6` a watched owner died, `7` stall, `130`/`143`
|
|
47
|
+
SIGINT/SIGTERM during a wait. A wait that hits its cap
|
|
48
|
+
(`mu wait`, `mu task wait`, `mu agent wait`) is `0` with `timedOut: true`, not `5`.
|
|
25
49
|
|
|
26
50
|
## Read the schema
|
|
27
51
|
|
|
28
|
-
The schema has
|
|
52
|
+
The schema (version 13) has 26 tables and 4 views (`ready`, `blocked`,
|
|
53
|
+
`blockers`, `goals`). Views skip torn-down workstreams. `blockers` has one
|
|
54
|
+
row per open edge: `task_local_id` is held up by `blocker_local_id`.
|
|
29
55
|
Four tables travel between machines: `workstreams`, `tasks`,
|
|
30
56
|
`task_edges`, and `task_notes`. List them all:
|
|
31
57
|
|
|
32
58
|
```bash
|
|
33
|
-
mu
|
|
59
|
+
mu db query "SELECT type, name FROM sqlite_master WHERE type IN ('table','view') ORDER BY type, name"
|
|
34
60
|
```
|
|
35
61
|
|
|
36
62
|
Task ids (`local_id`) are unique per workstream only. Join
|
|
@@ -42,21 +68,21 @@ Edges and notes reference `tasks.id`, not `local_id`.
|
|
|
42
68
|
Blocked tasks and the goals view, which replaced removed verbs:
|
|
43
69
|
|
|
44
70
|
```bash
|
|
45
|
-
mu
|
|
46
|
-
mu
|
|
71
|
+
mu db query "SELECT b.local_id, b.title FROM blocked b JOIN workstreams w ON w.id = b.workstream_id WHERE w.name = 'auth'"
|
|
72
|
+
mu db query "SELECT g.local_id, g.title FROM goals g JOIN workstreams w ON w.id = g.workstream_id WHERE w.name = 'auth'"
|
|
47
73
|
```
|
|
48
74
|
|
|
49
75
|
Search task titles:
|
|
50
76
|
|
|
51
77
|
```bash
|
|
52
|
-
mu
|
|
78
|
+
mu db query "SELECT t.local_id, t.status, t.title FROM tasks t JOIN workstreams w ON w.id = t.workstream_id
|
|
53
79
|
WHERE w.name = 'auth' AND LOWER(t.title) LIKE '%token%'"
|
|
54
80
|
```
|
|
55
81
|
|
|
56
82
|
Every task that blocks `launch`, directly or not:
|
|
57
83
|
|
|
58
84
|
```bash
|
|
59
|
-
mu
|
|
85
|
+
mu db query "WITH RECURSIVE prereqs(id) AS (
|
|
60
86
|
SELECT t.id FROM tasks t JOIN workstreams w ON w.id = t.workstream_id
|
|
61
87
|
WHERE t.local_id = 'launch' AND w.name = 'auth'
|
|
62
88
|
UNION
|
|
@@ -65,15 +91,69 @@ mu sql "WITH RECURSIVE prereqs(id) AS (
|
|
|
65
91
|
SELECT t.local_id, t.title, t.status FROM prereqs JOIN tasks t ON t.id = prereqs.id"
|
|
66
92
|
```
|
|
67
93
|
|
|
68
|
-
`mu
|
|
69
|
-
|
|
70
|
-
|
|
94
|
+
`mu db query` syncs like every other verb (when `MU_SYNC_DIR` is set): it
|
|
95
|
+
ingests peer ops before the query and flushes its own writes after, even
|
|
96
|
+
when the statement fails. It reads by default: a statement SQLite reports as
|
|
97
|
+
not read-only (`INSERT`, `UPDATE`, `DELETE`, `REPLACE`, `WITH ... INSERT`,
|
|
98
|
+
anything with `RETURNING`) is refused in one line, exit 2, until you add
|
|
99
|
+
`--write`. A write prints the number of rows changed. Writes
|
|
100
|
+
are captured as ops under one `sql.write` group per call, so `mu log --group`
|
|
101
|
+
shows the whole call. `--confirm-rows N` counts rows removed by
|
|
71
102
|
`ON DELETE CASCADE` too: deleting a task with one edge counts 2.
|
|
72
103
|
|
|
73
|
-
|
|
104
|
+
With `-w <ws>` (a spawned worker defaults to its own), the views `ready`,
|
|
105
|
+
`blocked` and `blockers` cover that workstream only, with the same columns;
|
|
106
|
+
`main.ready` is still the global one. The scope is the connection's own
|
|
107
|
+
(`TEMP` views), so nothing is left in the file.
|
|
108
|
+
|
|
109
|
+
`no such column: x` answers in one line with the closest columns and the real
|
|
110
|
+
columns of every table the query names; the SQL is never rewritten.
|
|
111
|
+
|
|
112
|
+
The whole call runs in one transaction that mu opens, so `BEGIN`,
|
|
113
|
+
`COMMIT`, `END`, `ROLLBACK`, `SAVEPOINT` and `RELEASE` are refused, each
|
|
114
|
+
statement checked by SQLite itself (a table or column named `begin` or
|
|
115
|
+
`end` is fine, a leading `;` hides nothing); a failed statement rolls the call
|
|
116
|
+
back. An `INSERT` that names an `id` of 0 or below is refused too (omit it), and
|
|
117
|
+
so is an `UPDATE` of `id` (or `rowid`) on `workstreams`, `tasks`, `task_notes`
|
|
118
|
+
and `task_edges`: ids are set once. Notes are append-only: an `UPDATE` of a
|
|
119
|
+
note's `author`, `content`, `created_at` or `kind` is refused (add a new
|
|
120
|
+
note), and so is an `UPDATE` of an edge's `created_at`. A rebuild or peer
|
|
121
|
+
would replay either as a different row than the one you edited.
|
|
122
|
+
|
|
123
|
+
What it will not touch: mu's capture bookkeeping, the schema and the
|
|
124
|
+
connection. The rule is a policy, so nothing has to be detected:
|
|
125
|
+
|
|
126
|
+
- No `CREATE`, `DROP` or `ALTER` of any kind, `TEMP` tables, views and
|
|
127
|
+
triggers included, and no `ANALYZE` or `REINDEX`. A trigger that outlives
|
|
128
|
+
one statement can fire inside mu's own bookkeeping.
|
|
129
|
+
- No `ATTACH` or `DETACH`: the verb works on this one DB. Another mu DB
|
|
130
|
+
(a backup, a peer) is not for it to write.
|
|
131
|
+
- `PRAGMA` only as a read: `table_info`, `table_xinfo`, `table_list`,
|
|
132
|
+
`index_list`, `index_info`, `index_xinfo`, `foreign_key_list`,
|
|
133
|
+
`foreign_key_check`, `integrity_check`, `quick_check`, and a bare
|
|
134
|
+
`user_version`, `foreign_keys`, `busy_timeout` or `database_list`.
|
|
135
|
+
Anything else is refused before it runs.
|
|
136
|
+
- No write to `op_ctx`, `op_dying`, `ops`, `schema_version`, `machine_identity`,
|
|
137
|
+
`sqlite_sequence` (the AUTOINCREMENT counters; inserts still advance them) or
|
|
138
|
+
`sync_peers` (sync watermarks: `mu sync --repair <peer>` re-reads a peer).
|
|
139
|
+
|
|
140
|
+
SQLite itself decides what a statement does (its `EXPLAIN` listing, trigger
|
|
141
|
+
bodies included), never the text, so a table named `begin` is fine and a
|
|
142
|
+
leading `;` hides nothing.
|
|
143
|
+
|
|
144
|
+
Need DDL? `mu db backup`, edit the copy with `sqlite3` yourself, and leave the
|
|
145
|
+
live DB to mu's verbs. `mu db forget` shrinks it.
|
|
146
|
+
|
|
147
|
+
`mu db --shell [-w <ws>]` opens the `sqlite3` CLI on the same file,
|
|
148
|
+
read-only and in safe mode, with the same scoped views. Plain `sqlite3`
|
|
149
|
+
starts with `foreign_keys=0` and no capture context: use it to look, never to write.
|
|
150
|
+
|
|
151
|
+
The whole-file commands stay under `mu db`: `backup`, `compact`, `forget`.
|
|
152
|
+
|
|
153
|
+
`mu db query` refuses to change a natural-key column (`workstreams.name`,
|
|
74
154
|
`tasks.workstream_id`, `tasks.local_id`, a note's task, or an edge's
|
|
75
155
|
endpoints). The ops log files every change under that key, so changing
|
|
76
|
-
it would desync sync
|
|
156
|
+
it would desync sync and `mu doctor`. Add a new row instead.
|
|
77
157
|
|
|
78
158
|
## Pass list flags
|
|
79
159
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# How to stop a worker
|
|
2
2
|
|
|
3
|
-
Use the gentlest step that works, in this order: abort,
|
|
3
|
+
Use the gentlest step that works, in this order: abort, close.
|
|
4
4
|
|
|
5
5
|
## Abort the turn (pi agents)
|
|
6
6
|
|
|
@@ -14,53 +14,46 @@ keeps the session and its context. It works for remote agents too.
|
|
|
14
14
|
|
|
15
15
|
- An idle agent is left alone (exit 0).
|
|
16
16
|
- Exit 5 means pi was still busy after `--timeout` (default 30 s).
|
|
17
|
-
|
|
17
|
+
Close the agent.
|
|
18
18
|
- A follow-up queued before the abort does not run. pi puts it back
|
|
19
19
|
into the pane's editor, unsent. Send it again if you still want it.
|
|
20
20
|
|
|
21
21
|
To give the agent new work after the abort, send with `--fresh`. See
|
|
22
22
|
[Dispatch work to a worker](dispatch.md#pick-the-send-mode).
|
|
23
23
|
|
|
24
|
-
## Kick the foreground process
|
|
25
|
-
|
|
26
|
-
Use `mu agent kick` when abort failed, when the agent is not pi, or
|
|
27
|
-
when pi's socket is gone:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
mu agent kick worker-1 -w auth # SIGINT
|
|
31
|
-
mu agent kick worker-1 -w auth --signal SIGTERM
|
|
32
|
-
mu agent kick worker-1 -w auth --signal SIGKILL
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
mu finds the foreground process group on the pane's TTY and signals
|
|
36
|
-
it. This is the fix for a worker stuck on an unbounded `find /` or a
|
|
37
|
-
busy-wait loop. Typing Ctrl-C into the pane does not work, because
|
|
38
|
-
the agent CLI catches it as input.
|
|
39
|
-
|
|
40
|
-
- Kick refuses with `NoForegroundProcessError` when the foreground
|
|
41
|
-
process is the agent CLI itself. Close the agent instead.
|
|
42
|
-
- Kick works on local panes only. On herdr it works on Linux only.
|
|
43
|
-
|
|
44
|
-
To prevent the problem, scope worker prompts to the workspace. Do not
|
|
45
|
-
ask for filesystem-wide `find` or `grep -r /`.
|
|
46
|
-
|
|
47
24
|
## Close the agent
|
|
48
25
|
|
|
49
26
|
```bash
|
|
50
|
-
mu agent close worker-1 -w auth
|
|
27
|
+
mu agent close worker-1 -w auth # preview: writes and kills nothing, prints rev=<n>
|
|
28
|
+
mu agent close worker-1 -w auth --if <n> # apply that preview
|
|
51
29
|
```
|
|
52
30
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
31
|
+
Bare close only previews: it names the pane, the tasks the agent owns
|
|
32
|
+
(an `IN_PROGRESS` one goes back to `OPEN`), the worktree's state and
|
|
33
|
+
the `--if` command that applies it. Pass `--if <n>` to close. It
|
|
34
|
+
refuses (exit 4, nothing killed) when the agent changed since the
|
|
35
|
+
preview: a task claimed or released, a respawn under the same name.
|
|
36
|
+
Another `mu` closing or spawning the same name makes it exit 4 too
|
|
37
|
+
(`AgentLockBusyError`; nothing was done, retry). If the agent was
|
|
38
|
+
replaced while the close was running, the replacement is left alone
|
|
39
|
+
(`AgentReplacedError`).
|
|
40
|
+
|
|
41
|
+
Close kills the pane and deletes the agent row. It is also the step
|
|
42
|
+
for a non-pi agent, which has no socket to abort through. To prevent a
|
|
43
|
+
worker stuck on an unbounded `find /` or a busy-wait loop, scope worker
|
|
44
|
+
prompts to the worktree. Do not ask for filesystem-wide `find` or
|
|
45
|
+
`grep -r /`. A clean worktree is removed with it, and unmerged commits
|
|
46
|
+
are kept on a new branch `mu/<workstream>/<agent>-<sha>` that the close
|
|
47
|
+
prints. If the worktree has uncommitted edits, close refuses with exit 4
|
|
48
|
+
before it kills the pane, and the preview offers no apply command. Then
|
|
49
|
+
do one of these:
|
|
50
|
+
|
|
51
|
+
- Commit the edits in the worktree (`git -C <cwd> add -A && git -C <cwd>
|
|
52
|
+
commit`), then preview and close again.
|
|
53
|
+
- Preview with `--discard` (`mu agent close worker-1 -w auth --discard`),
|
|
54
|
+
then apply it with `--if <n>` to drop the edits in one step. You lose
|
|
55
|
+
them, and no branch is made.
|
|
63
56
|
|
|
64
57
|
If the worker owned a task, its pane is gone, so the reaper returns
|
|
65
|
-
the task to `OPEN` on the next reconcile. A `mu
|
|
58
|
+
the task to `OPEN` on the next reconcile. A `mu wait` on that task
|
|
66
59
|
exits 6.
|
package/docs/guide/sync.md
CHANGED
|
@@ -18,12 +18,20 @@ mu task add auth_fix -w app -t "Fix the auth redirect" -i 80 -e 2
|
|
|
18
18
|
mu task close auth_fix -w app --evidence "shipped in #412"
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
## Keep 3.x out of the sync folder
|
|
22
|
+
|
|
23
|
+
4.0 writes v2 segments, which 3.x warns about on every command. So 4.0
|
|
24
|
+
refuses a `MU_SYNC_DIR` where any segment opens with a v1 line (exit 4,
|
|
25
|
+
nothing read or written): `MU_SYNC_DIR holds 3.x segments; give mu 4
|
|
26
|
+
its own dir`. Point it at a new folder.
|
|
27
|
+
|
|
21
28
|
## Keep the DB out of the sync folder
|
|
22
29
|
|
|
23
30
|
Never put `MU_DB_PATH` inside `MU_SYNC_DIR`. A live SQLite DB is three
|
|
24
31
|
files (`mu.db`, `-wal`, `-shm`). A file syncer copies them out of
|
|
25
32
|
order and can bring back a stale `-wal`, which corrupts the DB with no
|
|
26
|
-
error. `mu
|
|
33
|
+
error. Every `mu` verb refuses to run (exit 4, before it opens or
|
|
34
|
+
writes anything) when the DB path is inside `MU_SYNC_DIR`.
|
|
27
35
|
|
|
28
36
|
Also keep the DB off NFS, SMB, and sshfs. `mu doctor` warns in the
|
|
29
37
|
`db-filesystem` row.
|
|
@@ -60,7 +68,7 @@ it, and `behind`: lines you hold but have not applied. A non-zero
|
|
|
60
68
|
|
|
61
69
|
```bash
|
|
62
70
|
mu sync --repair c8ec # re-read a peer's file from the start
|
|
63
|
-
mu sync --from /mnt/devserver/.local/state/mu/mu.db # read a peer's DB directly
|
|
71
|
+
mu sync --from /mnt/devserver/.local/state/mu-next/mu.db # read a peer's DB directly
|
|
64
72
|
MU_SYNC_DIR=/media/usb-stick mu state # one-off folder
|
|
65
73
|
```
|
|
66
74
|
|
|
@@ -68,7 +76,7 @@ Ingest is idempotent, so `--repair` is safe at any time.
|
|
|
68
76
|
|
|
69
77
|
## Know what travels
|
|
70
78
|
|
|
71
|
-
Workstreams, tasks, edges, and notes travel. Agents and
|
|
79
|
+
Workstreams, tasks, edges, and notes travel. Agents and worktrees
|
|
72
80
|
stay on their machine, because a pane id and a local path mean nothing
|
|
73
81
|
elsewhere. So task ownership does not sync: a task claimed on the
|
|
74
82
|
devserver shows no owner on your laptop.
|
package/docs/guide/upgrade.md
CHANGED
|
@@ -1,25 +1,43 @@
|
|
|
1
1
|
# How to upgrade mu
|
|
2
2
|
|
|
3
|
+
Coming from 3.x? Read [Upgrade from 3.x to 4.0](#upgrade-from-3x-to-40)
|
|
4
|
+
first: `npm i -g @mu-crew/mu@latest` replaces your 3.x `mu`.
|
|
5
|
+
|
|
3
6
|
## Upgrade the package
|
|
4
7
|
|
|
5
8
|
```bash
|
|
6
9
|
npm i -g @mu-crew/mu@latest
|
|
7
|
-
|
|
10
|
+
pi update --extensions # only if the package is already registered in pi
|
|
8
11
|
mu doctor
|
|
9
12
|
```
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
pi loads mu as a package: one extension, one skill, and the recipe
|
|
15
|
+
prompts, all from the declared `pi` manifest. There is no relink step.
|
|
16
|
+
|
|
17
|
+
### Coming from the old `link pi` install
|
|
18
|
+
|
|
19
|
+
Before the package, the old `link pi` verb wrote a shim at
|
|
20
|
+
`~/.pi/agent/extensions/mu.ts` and a skill link at
|
|
21
|
+
`~/.agents/skills/mu`. `pi update` registers nothing for that install,
|
|
22
|
+
and a shim left in place loads a second copy of the extension next to
|
|
23
|
+
the package. In this order:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm i -g @mu-crew/mu@latest
|
|
27
|
+
pi install npm:@mu-crew/mu # once: registers the package
|
|
28
|
+
mu pi migrate # report only
|
|
29
|
+
mu pi migrate --apply # move mu-owned files aside; nothing is deleted
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Then restart pi agents or send them `/reload`.
|
|
16
33
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
Only a file mu can prove it generated is moved, into a `disabled/`
|
|
35
|
+
folder pi does not read: a file byte for byte equal to the shim `link pi` generated (only its
|
|
36
|
+
generated import URL may differ), or a skill
|
|
37
|
+
link into this install's `skills/mu` (or a skill copy identical to a
|
|
38
|
+
released one). Anything else (your own `mu.ts`, an edited copy, a link
|
|
39
|
+
to somewhere else, even one named `mu`) is reported with its path and
|
|
40
|
+
left for you. `MU_PI_HOME` changes the home directory both start from.
|
|
23
41
|
|
|
24
42
|
For agents other than pi, see [README § Install](../../README.md#install).
|
|
25
43
|
|
|
@@ -29,46 +47,78 @@ A running pi keeps the extension it loaded at start. After an upgrade,
|
|
|
29
47
|
send `/reload` to each agent, or respawn the agent. From a shell:
|
|
30
48
|
|
|
31
49
|
```bash
|
|
32
|
-
mu agent send worker-1 -w auth '/reload'
|
|
33
|
-
mu agent send worker-1 -w auth '/reload' --via mux # older extension
|
|
50
|
+
mu agent send worker-1 -w auth '/reload' # extension serves op command; older: respawn
|
|
34
51
|
```
|
|
35
52
|
|
|
36
53
|
Until then, the `ctl` row of `mu doctor` warns
|
|
37
54
|
`extension X older than installed Y` or `extension lacks ops`. Ops the old extension lacks,
|
|
38
55
|
such as `send --fresh`, fail with exit 4.
|
|
39
56
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
An agent started before the pi package was installed has no control
|
|
58
|
+
socket, so a send to it fails with `ctl missing`. Restart it.
|
|
59
|
+
|
|
60
|
+
## Upgrade from 3.x to 4.0
|
|
61
|
+
|
|
62
|
+
4.0 is a breaking release with its own DB. It does not import a 3.x DB,
|
|
63
|
+
and nothing converts one. 3.x keeps its state in `~/.local/state/mu`
|
|
64
|
+
(`$XDG_STATE_HOME/mu`); 4.0 keeps its state in `~/.local/state/mu-next`
|
|
65
|
+
(`$XDG_STATE_HOME/mu-next`), a name kept so the two never share a DB,
|
|
66
|
+
socket or worktree. The release notes list every breaking change:
|
|
67
|
+
[CHANGELOG](../../CHANGELOG.md).
|
|
68
|
+
|
|
69
|
+
There is no flag day. Each machine switches when its human decides:
|
|
70
|
+
|
|
71
|
+
1. Close the 3.x agents you no longer need (`mu agent close`); 4.0 cannot
|
|
72
|
+
see them.
|
|
73
|
+
2. If you still need the old DB, [keep 3.x runnable](#keep-3x-runnable)
|
|
74
|
+
before you install: `npm i -g @mu-crew/mu@latest` replaces the `mu` on
|
|
75
|
+
your `PATH`.
|
|
76
|
+
3. Install 4.0 as above (`npm i -g @mu-crew/mu@latest`, `pi install`,
|
|
77
|
+
`mu pi migrate --apply`). `mu --version` should print `4.x`.
|
|
78
|
+
4. Give 4.0 its own sync folder, or none. Sync stays off until you set
|
|
79
|
+
`MU_SYNC_DIR`. If any segment in the folder opens with a 3.x (v1)
|
|
80
|
+
line, every 4.0 verb exits 4 with `MU_SYNC_DIR holds 3.x segments;
|
|
81
|
+
give mu 4 its own dir` before it reads or writes anything. Unset
|
|
82
|
+
or change `MU_SYNC_DIR` in a shell that also runs 3.x.
|
|
83
|
+
5. Move workstreams one at a time, from the machine that holds each one,
|
|
84
|
+
with the [Move recipe](../../skills/mu/recipes/move.md). Only open
|
|
85
|
+
tasks move; owners, agents and history stay in the 3.x DB, an archive.
|
|
86
|
+
The recipe's one 3.x write is the last step: it parks each moved task
|
|
87
|
+
with `--why "moved to 4.0"`, so nobody works it twice.
|
|
88
|
+
|
|
89
|
+
Rollback: `pi remove npm:@mu-crew/mu`, `npm i -g @mu-crew/mu@3`, then
|
|
90
|
+
3.x's `link pi` to relink its shim. Nothing needs converting. For each
|
|
91
|
+
moved workstream, run `mu task unpark <id> -w <ws>` on 3.x per task. Work
|
|
92
|
+
done in 4.0 since the move stays in 4.0's DB.
|
|
93
|
+
|
|
94
|
+
## Keep 3.x runnable
|
|
95
|
+
|
|
96
|
+
`npm i -g @mu-crew/mu@latest` replaces the `mu` on your `PATH`, so the
|
|
97
|
+
Move recipe needs 3.x from somewhere else. Install it into its own
|
|
98
|
+
prefix, or run it once with npx:
|
|
46
99
|
|
|
47
|
-
|
|
100
|
+
```bash
|
|
101
|
+
npm i --prefix ~/.local/share/mu3 @mu-crew/mu@3.13.3
|
|
102
|
+
~/.local/share/mu3/node_modules/.bin/mu --version # 3.13.3
|
|
48
103
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
alone. `scripts/migrate.ts` converts a v7, v8, v9, or v10 DB into a new
|
|
52
|
-
v11 file. It never writes in place.
|
|
104
|
+
npx -y @mu-crew/mu@3.13.3 --version # no install; slower to start
|
|
105
|
+
```
|
|
53
106
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
107
|
+
Use that path, or the `npx` command, as `<mu3>` in the recipe. 3.x reads its own state dir, so
|
|
108
|
+
it finds the old DB with no flags. Use it to read the archive and to park
|
|
109
|
+
moved tasks, not for new work: `mu pi migrate --apply` moved aside the
|
|
110
|
+
shim 3.x's pi agents load. A harness that runs `mu` through your shell rc
|
|
111
|
+
may pick the wrong one; see
|
|
112
|
+
[Pin the mu the harness runs](other-agent-clis.md#pin-the-mu-the-harness-runs).
|
|
57
113
|
|
|
58
|
-
|
|
59
|
-
git clone --branch "v$(mu --version)" https://github.com/mu-crew/mu && cd mu && npm install
|
|
60
|
-
DB=${MU_DB_PATH:-$HOME/.local/state/mu/mu.db}
|
|
61
|
-
BACKUP="$HOME/mu-old-backup-$(date +%Y%m%d-%H%M%S).db"
|
|
62
|
-
sqlite3 "$DB" ".backup '$BACKUP'"
|
|
63
|
-
npx tsx scripts/migrate.ts "$BACKUP" --out "${DB}.v11"
|
|
64
|
-
MU_DB_PATH="${DB}.v11" mu doctor --deep
|
|
65
|
-
mv "$DB" "${DB}.old-kept" && mv "${DB}.v11" "$DB"
|
|
66
|
-
mu doctor
|
|
67
|
-
```
|
|
114
|
+
## Old DBs
|
|
68
115
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
116
|
+
A v13 DB missing a later addition is completed on its first open, in one
|
|
117
|
+
transaction: it either completes or leaves the file as it was. mu
|
|
118
|
+
refuses a DB older than v13 with `SchemaTooOldError`, and a newer one
|
|
119
|
+
with `SchemaTooNewError`. Both exit 4 and leave the file alone, so
|
|
120
|
+
pointing 4.0 at a 3.x DB (`MU_DB_PATH`) is safe. Back up an old DB and
|
|
121
|
+
move it aside.
|
|
72
122
|
|
|
73
123
|
## Run mu from a checkout
|
|
74
124
|
|
|
@@ -78,5 +128,5 @@ alias mu="node $PWD/dist/cli.js"
|
|
|
78
128
|
```
|
|
79
129
|
|
|
80
130
|
Or run `npm install -g .` in the checkout. Its `prepare` script builds
|
|
81
|
-
first.
|
|
82
|
-
checkout
|
|
131
|
+
first. To load the checkout as the pi package instead of the installed
|
|
132
|
+
one, run `pi install /path/to/checkout`.
|
package/docs/reference/env.md
CHANGED
|
@@ -10,11 +10,10 @@ milliseconds; `0` disables a wait unless noted.
|
|
|
10
10
|
| Name | Effect | Default |
|
|
11
11
|
| --- | --- | --- |
|
|
12
12
|
| `MU_DB_PATH` | SQLite file path. Wins over the state dir. | `<state-dir>/mu.db` |
|
|
13
|
-
| `MU_STATE_DIR` | State directory. Also holds `compile-cache/` (V8 code cache for the CLI; `NODE_DISABLE_COMPILE_CACHE=1` turns it off). | `$XDG_STATE_HOME/mu` |
|
|
14
|
-
| `XDG_STATE_HOME` | XDG state base; mu appends `mu
|
|
13
|
+
| `MU_STATE_DIR` | State directory. Also holds `compile-cache/` (V8 code cache for the CLI; `NODE_DISABLE_COMPILE_CACHE=1` turns it off). | `$XDG_STATE_HOME/mu-next` |
|
|
14
|
+
| `XDG_STATE_HOME` | XDG state base; mu appends `mu-next/` (3.x owns `mu/`, so the two builds never share a DB). An empty or relative value is ignored. | `~/.local/state` |
|
|
15
15
|
| `XDG_CACHE_HOME` | XDG cache base; mu appends `mu/`. Holds only disposable copies. An empty or relative value is ignored. | `~/.cache` |
|
|
16
|
-
| `
|
|
17
|
-
| `MU_SYNC_DIR` | Folder holding one segment per machine. This is the whole sync setup; there is no peer list. | unset: sync off |
|
|
16
|
+
| `MU_SYNC_DIR` | Folder holding one segment per machine. This is the whole sync setup; there is no peer list. 4.0 refuses (exit 4, nothing read or written) a folder holding a segment that opens with a v1 line, i.e. a 3.x peer: give it its own folder. | unset: sync off |
|
|
18
17
|
|
|
19
18
|
## Multiplexer
|
|
20
19
|
|
|
@@ -22,12 +21,11 @@ milliseconds; `0` disables a wait unless noted.
|
|
|
22
21
|
| --- | --- | --- |
|
|
23
22
|
| `MU_MUX` | Force `tmux` or `herdr`, skipping mux detection. An unknown value fails the invocation. | detected |
|
|
24
23
|
| `HERDR_ENV` | Read only. `1` (set by herdr in its panes) selects herdr; outranks `$TMUX`. | |
|
|
25
|
-
| `TMUX`, `TMUX_PANE` | Read only. Either one (set by tmux in its panes) selects tmux. `$TMUX` gates reading the current session name,
|
|
24
|
+
| `TMUX`, `TMUX_PANE` | Read only. Either one (set by tmux in its panes) selects tmux. `$TMUX` gates reading the current session name, used only as the suggestion in the missing-`-w` error: it never routes a verb. `mu me` / `mu state --me` never read `$TMUX_PANE` (identity is the injected `MU_AGENT_NAME` or `PI_SESSION_ID`); only `mu task list --mine` and a few older self-readers still fall back to it when no `MU_AGENT_NAME` is injected. | |
|
|
26
25
|
| `HERDR_WORKSPACE_ID` | Read only. Set by herdr in its panes; pane listing with no target reads this workspace first. | |
|
|
27
|
-
| `HERDR_PANE_ID` | Read only. Set by herdr in its panes
|
|
28
|
-
| `MU_TMUX_SOCKET` |
|
|
26
|
+
| `HERDR_PANE_ID` | Read only. Set by herdr in its panes. | |
|
|
27
|
+
| `MU_TMUX_SOCKET` | Run every tmux call on a private server (`-L <name>`) with `-f /dev/null`, so `~/.tmux.conf` is not loaded. The test suite uses it, and so can you to keep a crew off your own tmux server (a demo, a smoke test). Attach lines mu prints then carry `-L <name>`, and the dashboard's `a` nests a client on purpose when you are inside another tmux. tmux only. | unset: tmux's default server |
|
|
29
28
|
| `MU_HERDR_SESSION` | Named herdr server (`--session <name>`). herdr only. Tests must set it to a non-default name. | herdr default session |
|
|
30
|
-
| `MU_BANNER_QUIET` | `1` disables mu's pane border and banner decorations. tmux only. | unset |
|
|
31
29
|
|
|
32
30
|
## Spawn
|
|
33
31
|
|
|
@@ -37,16 +35,7 @@ milliseconds; `0` disables a wait unless noted.
|
|
|
37
35
|
| `MU_SPAWN_CTL_MS` | Budget for the control-socket handshake with a new pi agent, polled every 250ms. On timeout spawn still exits 0, reports `ctl: missing` or `ctl: refused`, and warns. `--no-ctl` skips it per spawn. | `30000` |
|
|
38
36
|
| `MU_SPAWN_LIVENESS_MS` | tmux only. Wait this long, then check the pane is alive and its scrollback has no startup error (auth failure, `command not found`). Failure rolls back the row and throws `AgentDiedOnSpawnError` or `AgentSpawnStartupError`. A pi agent skips the wait: the pane is checked on each ctl handshake tick and scanned when it ends. | `1500` |
|
|
39
37
|
| `MU_SPAWN_LOCK_TIMEOUT_MS` | How long a spawn waits for the per-workstream spawn lock. | `15000` |
|
|
40
|
-
|
|
41
|
-
## Send and state (tmux path)
|
|
42
|
-
|
|
43
|
-
These apply to the tmux paste path only. For when that path runs, see
|
|
44
|
-
[No silent fallback](../architecture/control-socket.md#no-silent-fallback).
|
|
45
|
-
|
|
46
|
-
| Name | Effect | Default |
|
|
47
|
-
| --- | --- | --- |
|
|
48
|
-
| `MU_SEND_READINESS_MS` | Before pasting, wait out a pane's modal or re-init; after Enter, confirm it landed. `0` sends fire-and-forget. A busy pane is not waited on. | `15000` |
|
|
49
|
-
| `MU_SEND_DELAY_MS` | Delay between the bracketed paste and Enter. | `500` |
|
|
38
|
+
| `MU_AGENT_LOCK_TIMEOUT_MS` | How long `agent close` and `--worktree` staging wait for the per-agent lock before exit 4 (`AgentLockBusyError`, nothing done). | `15000` |
|
|
50
39
|
|
|
51
40
|
## Agents and timing
|
|
52
41
|
|
|
@@ -60,36 +49,39 @@ These apply to the tmux paste path only. For when that path runs, see
|
|
|
60
49
|
| Name | Value |
|
|
61
50
|
| --- | --- |
|
|
62
51
|
| `MU_AGENT_NAME` | The agent's name; first rung of actor identity. |
|
|
63
|
-
| `MU_WORKSTREAM` | The agent's workstream. With `MU_MANAGED_AGENT=1` it
|
|
52
|
+
| `MU_WORKSTREAM` | The agent's workstream. With `MU_MANAGED_AGENT=1` it is the scope of every verb that has no `-w` (no tmux lookup); without it, ignored. `MU_SESSION` is not read: a verb with no `-w` and no injected scope fails with `no workstream: pass -w <name>`. |
|
|
64
53
|
| `MU_CTL_SOCK` | The agent's control socket path, derived from state dir, workstream, and agent. The mu pi extension serves it. |
|
|
65
54
|
| `MU_MANAGED_AGENT` | `1`. Hides `mu_delegate` inside agents, so a helper cannot spawn helpers. |
|
|
55
|
+
| `MU_DB_PATH`, `MU_STATE_DIR` | The absolute DB path and state dir the spawn used, so the worker's `mu` reads the same DB from any cwd. Local agents only. |
|
|
56
|
+
| `PI_CODING_AGENT_SESSION_DIR` | `<DB dir>/delegate-sessions/<workstream>/<task>`, set when `mu agent spawn --task <id> --send` (what `mu_delegate` and `mu next --refute` run) starts a pi agent for a `delegate`-kind task, so delegate sessions stay out of the caller's pi `/resume` list. Not set by a plain `mu agent spawn`. Local agents only. |
|
|
57
|
+
| `SSH_AUTH_SOCK` | The caller's, when it is a socket (a detached tmux session would otherwise hand the pane a stale one). Local agents only. |
|
|
58
|
+
| `MU_REMOTE` | `1`, only for an agent spawned with `--host`. Tells its pi extension there is no mu DB on that host: it skips the close nudge (you close the task) and the settle wait. |
|
|
66
59
|
|
|
67
|
-
`
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
A `--host` agent gets exactly `MU_MANAGED_AGENT`, `MU_AGENT_NAME`,
|
|
61
|
+
`MU_WORKSTREAM`, `MU_CTL_SOCK` (the host-side path) and `MU_REMOTE`, written
|
|
62
|
+
into its profile's shell template (`{env}`). It never gets `MU_DB_PATH`,
|
|
63
|
+
`MU_STATE_DIR` or `MU_SYNC_DIR`; its local pane gets none of the vars above.
|
|
70
64
|
|
|
71
|
-
## pi
|
|
65
|
+
## pi package and `mu pi migrate`
|
|
72
66
|
|
|
73
67
|
| Name | Effect | Default |
|
|
74
68
|
| --- | --- | --- |
|
|
75
69
|
| `MU_DELEGATE` | `0` hides the `mu_delegate` tool. `mu doctor` reports it. | unset: shown |
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
70
|
+
| `MU_DELEGATE_TRACE` | `1` appends one JSON line per delegate wake send and pi lifecycle event to `<cache dir>/delegate-trace.log`. For debugging a lost wake. | unset: off |
|
|
71
|
+
| `MU_DELEGATE_MAX` | Most delegates one pi session runs at once. Further calls queue, up to four times this; past that a call is recorded as `refused` and reissued with `mu_delegate_reissue` in its session. A positive integer. | `16` |
|
|
72
|
+
| `MU_NUDGE` | `0` turns off the two nudges: the keep-driving settle wait (every completed settle of an orchestrator runs `mu wait` for the work it owns and continues the turn on an event) and the close nudge (one reminder when a mu-spawned pi worker ends a turn still owning an IN_PROGRESS task). A pi nested in an agent's pane (it found `MU_CTL_SOCK` served by another pi) gets neither; a pi without UI (`pi -p`, json mode) gets no close nudge. `mu doctor` reports it. | unset: on |
|
|
73
|
+
| `MU_PI_HOME` | Root under which `mu pi migrate` looks for the old `.pi/` shim and `.agents/` skill link. | `$HOME` |
|
|
74
|
+
| `PI_SESSION_ID` | Read only. The pi session's id: the caller identity `pi:<id>` of `mu_delegate` calls, a bare `mu wait`, `mu me` and `mu next --refute` when no managed agent is injected. | |
|
|
79
75
|
| `PI_CODING_AGENT_DIR` | Read only. pi's agent dir, checked for a linked murmur extension. | `~/.pi/agent` |
|
|
80
|
-
| `MU_EXTENSION_ENTRY` | Test only. Built extension the `mu link pi` shim imports. | `dist/extension/mu-pi.js` |
|
|
81
76
|
|
|
82
|
-
## Output
|
|
77
|
+
## Output
|
|
83
78
|
|
|
84
79
|
| Name | Effect | Default |
|
|
85
80
|
| --- | --- | --- |
|
|
86
81
|
| `NO_COLOR` | Any value turns colour off; wins over everything. | unset |
|
|
87
82
|
| `MU_FORCE_COLOR` | Truthy forces colour on. `""`, `0`, and `false` opt out. Checked before `FORCE_COLOR`. | unset |
|
|
88
|
-
| `MU_NO_TUI` | `1` makes bare `mu` print help instead of opening the TUI. | unset |
|
|
89
|
-
| `MU_TUI_DEBUG_MOUSE` | `1` logs mouse hit-tests to stderr. | unset |
|
|
90
|
-
| `NODE_ENV` | Unset: the TUI loads React's production build. Set it (e.g. `development`) to get React's dev build and warnings. | unset |
|
|
91
83
|
|
|
92
84
|
## Tests
|
|
93
85
|
|
|
94
|
-
`VITEST` or `NODE_ENV=test` makes `openDb()` refuse the real default DB.
|
|
86
|
+
`VITEST` or `NODE_ENV=test` makes `openDb()` refuse the real default DB. The dashboard sets `NODE_ENV=production` for itself when it is unset, to get React's production build.
|
|
95
87
|
`test/_setup.ts` clears inherited `MU_*` vars except `MU_TMUX_SOCKET`.
|