@mu-crew/mu 3.2.0 → 3.3.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.
Files changed (71) hide show
  1. package/AGENTS.md +208 -599
  2. package/README.md +125 -329
  3. package/dist/cli.js +108 -78
  4. package/dist/cli.js.map +1 -1
  5. package/dist/extension/mu-pi.js +421 -56
  6. package/dist/extension/mu-pi.js.map +1 -1
  7. package/dist/index.d.ts +36 -10
  8. package/dist/index.js +89 -67
  9. package/dist/index.js.map +1 -1
  10. package/docs/ARCHITECTURE.md +176 -1072
  11. package/docs/ROADMAP.md +88 -169
  12. package/docs/VISION.md +205 -415
  13. package/docs/VOCABULARY.md +204 -466
  14. package/docs/architecture/control-socket.md +133 -0
  15. package/docs/architecture/dag.md +113 -0
  16. package/docs/architecture/mux.md +162 -0
  17. package/docs/architecture/ops-log.md +140 -0
  18. package/docs/architecture/sdk.md +185 -0
  19. package/docs/architecture/sync.md +129 -0
  20. package/docs/architecture/tui.md +146 -0
  21. package/docs/guide/README.md +30 -0
  22. package/docs/guide/backends.md +61 -0
  23. package/docs/guide/cleanup.md +74 -0
  24. package/docs/guide/delegate.md +87 -0
  25. package/docs/guide/dispatch.md +144 -0
  26. package/docs/guide/getting-started.md +180 -0
  27. package/docs/guide/recovery.md +135 -0
  28. package/docs/guide/remote.md +74 -0
  29. package/docs/guide/sql.md +76 -0
  30. package/docs/guide/stop-a-worker.md +64 -0
  31. package/docs/guide/sync.md +78 -0
  32. package/docs/guide/tui.md +98 -0
  33. package/docs/guide/upgrade.md +76 -0
  34. package/docs/history/CHANGELOG-pre-3.md +4866 -0
  35. package/docs/reference/env.md +87 -0
  36. package/docs/reference/naming.md +82 -0
  37. package/docs/specs/2026-09-28-agent-state-from-murmur.md +1 -1
  38. package/docs/specs/2026-09-29-task-substates.md +1 -1
  39. package/docs/specs/2026-10-03-keep-driving-nudge.md +142 -0
  40. package/package.json +2 -1
  41. package/prompts/mu-refute.md +8 -0
  42. package/prompts/mu-research.md +8 -0
  43. package/prompts/mu-review.md +8 -0
  44. package/prompts/mu-rules-audit.md +8 -0
  45. package/prompts/mu-tournament.md +9 -0
  46. package/prompts/ultrathink.md +9 -0
  47. package/skills/mu/SKILL.md +126 -255
  48. package/skills/mu/recipes/adversarial-review.md +83 -0
  49. package/skills/mu/recipes/brief.md +53 -0
  50. package/skills/mu/recipes/codemode-driver.md +54 -0
  51. package/skills/mu/recipes/deep-research.md +52 -0
  52. package/skills/mu/recipes/fan-out.md +36 -0
  53. package/skills/mu/recipes/hypothesis-panel.md +40 -0
  54. package/skills/mu/recipes/long-run.md +20 -0
  55. package/skills/mu/recipes/loop-until-done.md +38 -0
  56. package/skills/mu/recipes/orchestrator-loop.md +87 -0
  57. package/skills/mu/recipes/plan.md +54 -0
  58. package/skills/mu/recipes/recovery.md +26 -0
  59. package/skills/mu/recipes/refute.md +49 -0
  60. package/skills/mu/recipes/remote-workers.md +292 -0
  61. package/skills/mu/recipes/review-panel.md +57 -0
  62. package/skills/mu/recipes/rules-audit.md +70 -0
  63. package/skills/mu/recipes/tournament.md +37 -0
  64. package/skills/mu/recipes/triage.md +38 -0
  65. package/skills/mu/recipes/ultrathink.md +73 -0
  66. package/skills/mu/recipes/watcher.md +16 -0
  67. package/skills/mu/recipes/waves.md +19 -0
  68. package/skills/mu/recipes/worker.md +24 -0
  69. package/docs/HANDOVER.md +0 -486
  70. package/docs/USAGE_GUIDE.md +0 -2738
  71. package/skills/mu/REMOTE_WORKERS.md +0 -617
@@ -0,0 +1,87 @@
1
+ # How to delegate a one-off task
2
+
3
+ ## Delegate from pi
4
+
5
+ `mu link pi` installs the `mu_delegate` and `mu_delegate_cancel` tools
6
+ in every pi session. Ask pi in plain words:
7
+
8
+ - "Delegate a review of src/x.ts to a helper."
9
+ - "Have three helpers investigate A, B, and C."
10
+
11
+ pi calls `mu_delegate`. It spawns a pi agent in the reserved `scratch`
12
+ workstream and returns at once with the delegate's name and attach
13
+ command. The answer arrives later as a follow-up message; do not poll.
14
+ Delegates called in one turn run in parallel.
15
+
16
+ | Option | Meaning |
17
+ | ------ | ------- |
18
+ | `task` (required) | All the context. The delegate starts empty. |
19
+ | `label` | Names the delegate: `review` gives `delegate-review`. |
20
+ | `brief` | Ad hoc persona or ground rules, sent first. Not enforced. |
21
+ | `cwd` | Start directory. Default: the caller's. Must exist. |
22
+ | `timeout` | Seconds to wait for the answer (default 3600). After it, the answer does not come back; the follow-up gives the `mu agent wait` command. |
23
+ | `workspace` | Own VCS checkout, for delegates that edit files. The follow-up names its path. It isolates repository edits only. |
24
+ | `cli` | Key for `$MU_<CLI>_COMMAND` (default `pi`), e.g. a cheaper model. |
25
+ | `keep` | Keep the pane after it finishes, to talk to it again. |
26
+
27
+ - Watch or steer: run the attach command.
28
+ - Stop: `mu_delegate_cancel`, or `mu agent abort <name> -w scratch`.
29
+ - The pane closes after a clean finish; died or timed-out panes stay
30
+ as evidence.
31
+ - pi's footer shows how many delegates this session is waiting on.
32
+ - Each delegate costs a pane and a pi process.
33
+
34
+ `MU_DELEGATE=0` hides the tool ([env vars](../reference/env.md)).
35
+
36
+ ## Delegate without pi
37
+
38
+ From a script or other shell, run what the tool runs:
39
+
40
+ ```bash
41
+ mu agent spawn helper-1 -w scratch
42
+ mu agent send helper-1 -w scratch --fresh 'Investigate why foo.spec.ts fails. Report the cause.'
43
+ mu agent wait helper-1 -w scratch --json
44
+ ```
45
+
46
+ Use `--fresh`: a plain send to a reused agent carries the previous
47
+ task's context.
48
+
49
+ `mu agent wait` fires when the agent leaves busy (including to
50
+ `needs_input`), never on an already idle agent. For pi, the `--json`
51
+ row carries:
52
+
53
+ - `outcome`: `done`, `empty`, `died`, `timeout`, or `pending`.
54
+ - `lastText`: the final message, capped at 64 KiB.
55
+
56
+ Exit codes: `0` met, `5` timeout, `6` pane died. Non-pi agents have no
57
+ `lastText`; read the pane with `mu agent read helper-1 -w scratch -n 80`.
58
+
59
+ ## Keep a helper
60
+
61
+ Pass `keep: true`, or spawn a named agent in `scratch`. It is created
62
+ on first spawn, needs no tasks, and cannot be `init`ed.
63
+
64
+ ```bash
65
+ mu agent spawn helper -w scratch
66
+ mu agent send helper -w scratch 'Watch CI on PR 1234 and tell me when it is green'
67
+ mu agent read helper -w scratch -n 50
68
+ mu agent close helper -w scratch
69
+ ```
70
+
71
+ A watcher's chat context does not survive compaction. Log each tick
72
+ under your own `--kind`; read the latest entry on the next:
73
+
74
+ ```bash
75
+ mu log -w scratch --kind pr-state 'pr=1234 sha=abc ci=red -> spawned fixer-1'
76
+ mu log -w scratch --kind pr-state -n 1 --json
77
+ ```
78
+
79
+ Act only on change. `--since <seq>` replays entries a dead watcher
80
+ missed.
81
+
82
+ ## When to stop delegating
83
+
84
+ Dependencies, several agents, or review need a real workstream: see
85
+ [Getting started](getting-started.md) and
86
+ [How to dispatch work](dispatch.md). There, `mu task wait` keys on the
87
+ task and has `--on-stall`.
@@ -0,0 +1,144 @@
1
+ # How to dispatch work to a worker
2
+
3
+ This guide assumes you finished [Getting started](getting-started.md).
4
+ The agent-facing loop and its traps are in
5
+ [recipes/orchestrator-loop.md](../../skills/mu/recipes/orchestrator-loop.md). For several workers in
6
+ one repo, see [waves](../../skills/mu/recipes/waves.md); for runs that
7
+ last hours, see [long runs](../../skills/mu/recipes/long-run.md).
8
+
9
+ ## Claim before you send
10
+
11
+ Always claim the task for the worker before the first send, even for a
12
+ one-shot reviewer:
13
+
14
+ ```bash
15
+ mu task claim build -w auth --for worker-1
16
+ ```
17
+
18
+ `mu task wait` watches tasks, and the reaper returns a claimed task to
19
+ `OPEN` when its pane dies. An unclaimed task gets neither. If no task
20
+ exists, create one with `mu task add --note '<brief>'`.
21
+
22
+ - `--for` takes a worker name or a qualified `<workstream>/<name>`.
23
+ The worker stays in its own workstream. Only the ownership crosses.
24
+ - Inside a worker's pane, bare `mu task claim <id>` uses the pane
25
+ title as the worker name.
26
+ - To do the task yourself, use `mu task claim <id> --self`.
27
+
28
+ ## Pick the send mode
29
+
30
+ For a pi agent, `mu agent send` goes through the agent's control
31
+ socket. Pick the mode by what the agent is doing:
32
+
33
+ | Situation | Command |
34
+ | --------- | ------- |
35
+ | New task, any state | `mu agent send worker-1 --fresh '<brief>'` |
36
+ | Busy, and you want to interrupt the current run | `mu agent send worker-1 --steer '<text>'` |
37
+ | Answering a question, or adding to the same task | `mu agent send worker-1 '<text>'` |
38
+
39
+ - `--fresh` starts a new pi session and sends the prompt into it as
40
+ one operation. It refuses with exit 4 while pi is busy. Run
41
+ `mu agent abort` first, or pass `--force` to drop the running turn.
42
+ - Never send `/new` and then the prompt as two sends to pi. The prompt
43
+ can land during the reset and vanish.
44
+ - A plain send to a busy agent queues as a follow-up.
45
+ - `/new`, `/reload` and `/compact [instructions]` run inside pi through
46
+ the socket and report pi's answer (for example `Nothing to compact`).
47
+ They refuse with exit 4 while pi is busy; `--force` overrides. Any
48
+ other slash command exits 2; add `--via mux` to type it into the pane.
49
+ - If the socket does not answer, the send fails with exit 1 and
50
+ pastes nothing. `--via mux` pastes into the pane on purpose.
51
+
52
+ After a claim, spawn, or wait, the `Next:` block prints the right send.
53
+
54
+ ### Non-pi agents
55
+
56
+ Agents other than pi have no control socket, so mu pastes the text
57
+ into the pane. To start a new session, send `/new` (codex: `/clear`),
58
+ then the prompt. If mu prints `warning: ... was NOT submitted`, the
59
+ agent has not seen the text. Read the pane before you wait. On a slow
60
+ tmux link, raise `MU_SEND_DELAY_MS` (default 500 ms).
61
+
62
+ ## Write the brief
63
+
64
+ Put the full brief in a task note, so it survives context compaction
65
+ and the next agent can read it. Send a short prompt that points at it:
66
+
67
+ ```bash
68
+ mu task note build -w auth 'FILES: src/auth/\nVERIFY: npm test\nSCOPE: no schema changes'
69
+ mu agent send worker-1 -w auth --fresh 'Work on build. Read: mu task notes build -w auth'
70
+ ```
71
+
72
+ End the brief with the exact final action, for example:
73
+
74
+ ```text
75
+ ⚠️ FINAL ACTION
76
+ git commit -am '...' THEN
77
+ mu task close build -w auth --evidence '...'
78
+ ```
79
+
80
+ Single-quote prompts that contain `$` or backticks. To see only what the worker wrote after the claim, run
81
+ `mu task notes build -w auth --since-claim`.
82
+
83
+ ## Give each worker a workspace
84
+
85
+ `mu agent spawn --workspace` creates a jj, sl, or git worktree for the
86
+ agent (`cp -a` outside a repo). You cherry-pick from it.
87
+
88
+ Refresh the workspace between tasks. The rebase keeps the agent's pi
89
+ context:
90
+
91
+ ```bash
92
+ mu workspace refresh worker-1 -w auth
93
+ ```
94
+
95
+ It rebases onto the remote's main (`origin/HEAD`); without a remote,
96
+ pass `--from main`. It refuses on a dirty tree. On a conflict it exits 5
97
+ with a `cd` hint. To throw the workspace away instead, run
98
+ `mu workspace free worker-1 -w auth`.
99
+
100
+ Claim and send warn when the worker's workspace is 10 or more commits
101
+ behind main. `--strict-staleness` makes that a refusal (exit 4).
102
+
103
+ ## Wait for the first task to close
104
+
105
+ Wait on every in-flight task and handle the first one that closes:
106
+
107
+ ```bash
108
+ mu task wait auth/build auth/docs --first --on-stall exit --json
109
+ ```
110
+
111
+ - `--first` prints the closed ref and fills `firing` in `--json`.
112
+ `--any` leaves `firing` null even on success.
113
+ - `nextSteps[0]` is the cherry-pick command for the worker's new
114
+ commits. If the worker closed without committing, it says so.
115
+ - Exit codes: `0` met, `5` timeout, `6` the owner's pane died,
116
+ `7` the owner sat in `needs_input` for `--stuck-after` seconds
117
+ (default 300).
118
+
119
+ Exit 7 has several causes: the worker finished but did not close, it
120
+ asked a question, or it hit a prompt. In each case, run
121
+ `mu agent read <owner>` first.
122
+
123
+ Pipeline the work: merge one task, run your tests on the merged tree,
124
+ then dispatch the next task. Waiting for a whole wave hides partial
125
+ progress.
126
+
127
+ ## Close and park tasks
128
+
129
+ ```bash
130
+ mu task close spike -w auth --as wontfix --why "superseded by v2"
131
+ mu task close umbrella -w auth --if-ready
132
+ mu task park polish -w auth --why "after the release"
133
+ mu task release build -w auth
134
+ ```
135
+
136
+ - Closed substates other than `done` need `--why`. Every `CLOSED`
137
+ substate satisfies a blocker.
138
+ - `--if-ready` closes only when every blocker is closed. Otherwise it
139
+ lists the open blockers and exits 0.
140
+ - A parked task leaves the ready set, and its dependents keep waiting.
141
+ - `release` clears the owner and returns `IN_PROGRESS` to `OPEN`.
142
+
143
+ To wait on something outside the repo, such as an upstream release,
144
+ block on a placeholder task and close it when the thing lands.
@@ -0,0 +1,180 @@
1
+ # Getting started
2
+
3
+ In this tutorial we install mu, plan two tasks where one blocks the
4
+ other, hand the first task to a pi worker, and merge its commit. It
5
+ takes about ten minutes.
6
+
7
+ You need Node.js, the pi coding agent, tmux 3.0
8
+ or later, and a git repository to work in. Run every command from
9
+ inside a tmux session, in the root of that repository.
10
+
11
+ ## Install mu and link pi
12
+
13
+ First, install mu and connect it to pi:
14
+
15
+ ```bash
16
+ npm i -g @mu-crew/mu
17
+ mu link pi
18
+ mu doctor
19
+ ```
20
+
21
+ `mu link pi` installs the mu pi extension and the mu skill. In the
22
+ output of `mu doctor`, the extension, skill, and `ctl` rows say `ok`.
23
+ If pi was already running, restart it so it loads the extension.
24
+
25
+ ## Create a workstream
26
+
27
+ A workstream is one project: one tmux session, its agents, and its
28
+ task graph.
29
+
30
+ ```bash
31
+ mu workstream init auth
32
+ ```
33
+
34
+ ```
35
+ Created workstream auth (mux session mu-auth)
36
+ Next:
37
+ Attach the session : tmux attach -t mu-auth
38
+ ...
39
+ ```
40
+
41
+ Every verb ends with a `Next:` block of follow-up commands. We use
42
+ them as we go.
43
+
44
+ ## Plan two tasks
45
+
46
+ Now add two tasks. Each needs an impact (1–100) and an effort in
47
+ days. `--blocked-by` makes `build` wait for `design`:
48
+
49
+ ```bash
50
+ mu task add design -w auth -t "Design the auth module" -i 80 -e 2
51
+ mu task add build -w auth -t "Build the auth module" -i 80 -e 5 --blocked-by design
52
+ mu task next -w auth
53
+ ```
54
+
55
+ ```
56
+ ┌────────┬────────┬────────────────────────┬────────┬────────┬──────┬───────┐
57
+ │ name │ status │ title │ impact │ effort │ ROI │ owner │
58
+ ├────────┼────────┼────────────────────────┼────────┼────────┼──────┼───────┤
59
+ │ design │ OPEN │ Design the auth module │ 80 │ 2 │ 40.0 │ — │
60
+ └────────┴────────┴────────────────────────┴────────┴────────┴──────┴───────┘
61
+ ```
62
+
63
+ Only `design` is ready. `build` appears when `design` closes.
64
+
65
+ ## Spawn a worker
66
+
67
+ Spawn a pi agent with its own git worktree:
68
+
69
+ ```bash
70
+ mu agent spawn worker-1 -w auth --workspace
71
+ ```
72
+
73
+ ```
74
+ Spawned worker-1 (pi) in window worker-1 of mu-auth, pane %15 with auto-workspace
75
+ workspace: ~/.local/state/mu/workspaces/auth/worker-1 (git)
76
+ ```
77
+
78
+ The worker runs in a new window of the `mu-auth` session. To watch
79
+ it, run `tmux attach -t mu-auth`. Detach with `Ctrl+b d`.
80
+
81
+ ## Claim the task for the worker
82
+
83
+ Assign the task before you send any text. The claim is what
84
+ `mu task wait` watches.
85
+
86
+ ```bash
87
+ mu task note design -w auth 'SCOPE: write docs/auth.md with the token design'
88
+ mu task claim design -w auth --for worker-1
89
+ ```
90
+
91
+ ```
92
+ Claimed design for worker-1 (OPEN → IN_PROGRESS)
93
+ ```
94
+
95
+ ## Send the task
96
+
97
+ `--fresh` starts a new pi session and sends the prompt into it in
98
+ one step:
99
+
100
+ ```bash
101
+ mu agent send worker-1 -w auth --fresh 'Work on task design. Read: mu task notes design -w auth.
102
+ When done: git commit -am "Design auth", then mu task close design -w auth --evidence "<what you verified>"'
103
+ ```
104
+
105
+ The worker reads its notes, does the work, commits in its worktree,
106
+ and closes the task.
107
+
108
+ ## Wait for the task to close
109
+
110
+ ```bash
111
+ mu task wait design -w auth --first --on-stall exit
112
+ ```
113
+
114
+ ```
115
+ auth/design
116
+ any-of 1 reached CLOSED in 41094ms
117
+ Next:
118
+ Cherry-pick worker-1's commit onto your branch : git cherry-pick 26278f1...
119
+ Refresh worker-1's workspace onto current main : mu workspace refresh worker-1 -w auth
120
+ ```
121
+
122
+ The exit code tells you what happened:
123
+
124
+ | Exit | Meaning | Next move |
125
+ | ---- | ------- | --------- |
126
+ | `0` | the task closed | merge the work |
127
+ | `5` | `--timeout` expired (default 600 s) | wait again |
128
+ | `6` | the worker's pane died and the task went back to `OPEN` | spawn and claim again |
129
+ | `7` | the worker sat in `needs_input` for 5 minutes | `mu agent read worker-1 -w auth`, then answer it |
130
+
131
+ Without `--on-stall exit`, a stalled worker only prints a warning and
132
+ the wait keeps running.
133
+
134
+ ## Merge the commit
135
+
136
+ Run the cherry-pick command from the `Next:` block, then run your
137
+ tests on the result:
138
+
139
+ ```bash
140
+ git cherry-pick 26278f1
141
+ ```
142
+
143
+ Before the next task, rebase the worker's worktree onto the new main.
144
+ The worker keeps its pi context:
145
+
146
+ ```bash
147
+ mu workspace refresh worker-1 -w auth
148
+ ```
149
+
150
+ The default target is the remote's main branch (`origin/HEAD`). In a
151
+ repository without a remote, name the branch: `--from main`.
152
+
153
+ ## Check the graph
154
+
155
+ ```bash
156
+ mu task next -w auth
157
+ ```
158
+
159
+ `build` is ready now. You can claim it for `worker-1` and repeat the
160
+ claim, send, wait, and merge steps.
161
+
162
+ ## Close the worker
163
+
164
+ When you are done, free the worktree and close the agent:
165
+
166
+ ```bash
167
+ mu workspace free worker-1 -w auth
168
+ mu agent close worker-1 -w auth
169
+ ```
170
+
171
+ `mu agent close` refuses while the worktree has commits or edits that
172
+ mu has not freed. That protects work you have not merged.
173
+
174
+ ## Next steps
175
+
176
+ - [Dispatch work to a worker](dispatch.md) covers more than one
177
+ worker and the `--fresh`, `--steer`, and plain send choices.
178
+ - [Use the TUI dashboard](tui.md): run bare `mu` to see every
179
+ workstream at once.
180
+ - [Clean up](cleanup.md) when the workstream is finished.
@@ -0,0 +1,135 @@
1
+ # How to recover from a broken state
2
+
3
+ Start with `mu doctor`. Each row that is not `ok` prints the command
4
+ that fixes it. mu reports and never cleans up for you, because an
5
+ orphan directory can hold the only copy of uncommitted work. Agents
6
+ read the same rules in
7
+ [recipes/recovery.md](../../skills/mu/recipes/recovery.md).
8
+
9
+ ```bash
10
+ mu doctor # exit 0 healthy, 5 on drift
11
+ mu doctor --deep # rebuild the ops log and diff every field
12
+ mu doctor --disk # add per-workspace byte usage
13
+ ```
14
+
15
+ ## An agent's pane died
16
+
17
+ Run `mu agent list` or `mu state`. Each run reconciles the registry
18
+ with the multiplexer:
19
+
20
+ - An agent row whose pane is gone is a ghost. mu deletes the row, and
21
+ its `IN_PROGRESS` task returns to `OPEN`. A `mu task wait` on that
22
+ task exits 6.
23
+ - A pane in the session that runs an agent CLI but has no row is an
24
+ orphan. mu lists it with an adopt hint and does not adopt it.
25
+
26
+ To register an orphan pane, or a pi you started by hand:
27
+
28
+ ```bash
29
+ mu agent adopt %15 -w auth
30
+ mu agent adopt %15 -w auth --name investigator
31
+ ```
32
+
33
+ The pane title becomes the agent name. The pane must be in the
34
+ `mu-<workstream>` session. An adopted pi has no control socket until
35
+ you restart it with the `MU_CTL_SOCK` path that `adopt` prints.
36
+
37
+ ## A pi agent shows `ctl missing` or `ctl refused`
38
+
39
+ mu reaches pi agents only through the control socket, and never falls
40
+ back to pasting.
41
+
42
+ | State | Means | Fix |
43
+ | ----- | ----- | --- |
44
+ | `ctl missing` | no socket: the extension is not loaded | run `mu link pi`, then respawn the agent |
45
+ | `ctl refused` | the socket exists but does not answer | respawn the agent; for a remote agent, check the ssh forward |
46
+ | `extension X older than installed Y` | pi loaded an older mu build | type `/reload` in the pane, or respawn |
47
+
48
+ To send `/reload` without attaching:
49
+
50
+ ```bash
51
+ mu agent send worker-1 -w auth '/reload' --via mux
52
+ ```
53
+
54
+ `/reload` keeps the pi session. A `send --fresh` or `abort` against an
55
+ outdated extension fails with exit 4 and prints the same two fixes.
56
+
57
+ ## A new pi agent is stuck at `needs_input`
58
+
59
+ pi asks whether to trust a project folder on first start. Run
60
+ `/trust` in the pane once, or spawn with
61
+ `--command 'pi --approve'`. `--approve` trusts every directory,
62
+ including workspace forks, so use it only on your own code.
63
+
64
+ ## You closed your terminal
65
+
66
+ The tmux session keeps running. Reattach with `tmux attach -t mu-auth`.
67
+ Every `mu` command is a short process that reads the DB, so nothing
68
+ needs restarting.
69
+
70
+ ## You ran the wrong command
71
+
72
+ Every action is one group of ops. Find it, preview the inverse, then
73
+ apply:
74
+
75
+ ```bash
76
+ mu undo # list recent groups
77
+ mu undo 6380dd3d # preview
78
+ mu undo 6380dd3d --yes # apply
79
+ ```
80
+
81
+ - Any unique prefix of a group id works.
82
+ - The undo is its own group, so undoing it again is redo.
83
+ - If later work changed the same fields, undo exits 4 and names the
84
+ conflict. `--force --yes` overrides and discards the newer work.
85
+ - Undo restores rows only. Killed panes and freed workspace
86
+ directories do not come back.
87
+
88
+ ## `mu doctor` reports drift
89
+
90
+ Drift means the ops log and the live tables disagree. `--deep` names
91
+ the table, key, and field. Do not rebuild by reflex: if capture missed
92
+ a write, the live table holds real work that a rebuild would discard.
93
+
94
+ ```bash
95
+ mu db backup /tmp/mu-drift-evidence.db # 1. keep the evidence
96
+ mu rebuild /tmp/mu-rebuilt.db # 2. replay the log into a new file
97
+ MU_DB_PATH=/tmp/mu-rebuilt.db mu sql "SELECT local_id, title FROM tasks" # 3. compare
98
+ ```
99
+
100
+ Decide which side is right, then report the drift as a bug with the
101
+ named field. `mu rebuild` never writes in place. It prints the swap
102
+ command.
103
+
104
+ ## The `disk` section of `mu doctor` warns
105
+
106
+ | Row | Means |
107
+ | --- | ----- |
108
+ | `ws-rows` | a workspace row whose directory is gone; the next send fails in the VCS |
109
+ | `ws-dirs` | a workspace directory with no row; it blocks the next `--workspace` spawn with that name |
110
+ | `ws-empty` | a workstream directory with no checkouts |
111
+ | `db-copies` | stray `mu.db*` files that nothing reads |
112
+ | `exports` | output left by the removed export verb |
113
+ | `locks` | lock directories older than one hour, from a spawn or flush that died |
114
+
115
+ To list workspace orphans with cleanup commands, run
116
+ `mu workspace orphans -w auth`. Remove a git-backed orphan with
117
+ `git worktree remove --force <path>` from the project root.
118
+
119
+ ## Rename a workstream
120
+
121
+ There is no rename verb. Every child table cascades on the name:
122
+
123
+ ```bash
124
+ mu sql "UPDATE workstreams SET name='auth-refactor' WHERE name='auth-refator'"
125
+ tmux rename-session -t mu-auth-refator mu-auth-refactor
126
+ ```
127
+
128
+ Names start with a lowercase letter, use letters, digits, `_`, or
129
+ `-`, are at most 32 characters, and do not start with `mu-`.
130
+
131
+ ## Report a bug
132
+
133
+ Include the exact command, its full output, the `environment` block of
134
+ `mu doctor`, and your platform. To reproduce without your real data,
135
+ set `MU_DB_PATH=/tmp/mu-debug.db` and `MU_SYNC_DIR=` (empty).
@@ -0,0 +1,74 @@
1
+ # How to run a worker on another machine
2
+
3
+ The pane is local and the pi process is remote. mu runs no ssh
4
+ itself. `mu agent remote-env` prints the ssh pieces, and you put them
5
+ in the spawn command. The full recipe, with recording, collecting,
6
+ and the traps, is in
7
+ [skills/mu/recipes/remote-workers.md](../../skills/mu/recipes/remote-workers.md).
8
+ Read it before your first remote spawn.
9
+
10
+ ## Prepare the host
11
+
12
+ On the remote host:
13
+
14
+ 1. Install mu and run `mu link pi`, so the remote pi loads the mu
15
+ extension.
16
+ 2. Allow unix-socket forwards in the host's sshd:
17
+ `AllowStreamLocalForwarding yes`.
18
+ 3. Create the worker's checkout yourself. `--workspace` works only
19
+ for local agents:
20
+
21
+ ```bash
22
+ ssh dev 'git -C ~/repo worktree add ~/ws/worker-1'
23
+ ```
24
+
25
+ Use one orchestrator DB on your machine. Do not run a second mu on the
26
+ host for the same work: task ownership points into your local
27
+ `agents` table.
28
+
29
+ ## Spawn the agent
30
+
31
+ ```bash
32
+ eval "$(mu agent remote-env worker-1 -w auth --shell)" # sets MU_SSH_ARGS, MU_REMOTE_ENV
33
+ mu agent spawn worker-1 -w auth --command \
34
+ "ssh $MU_SSH_ARGS dev -t 'cd ~/ws/worker-1 && $MU_REMOTE_ENV \$SHELL -ilc \"pi --approve\"'"
35
+ ```
36
+
37
+ What each part does:
38
+
39
+ - `MU_SSH_ARGS` forwards the remote pi's control socket to the local
40
+ path mu connects to. It includes `-o ControlMaster=no -o
41
+ ControlPath=none`, because a multiplexed ssh connection never binds
42
+ the local end of the forward.
43
+ - `MU_REMOTE_ENV` sets the agent's identity inside the remote shell.
44
+ tmux `-e` variables do not cross the ssh hop.
45
+ - `$SHELL -ilc` starts pi in an interactive login shell, so the
46
+ remote `~/.zshrc` or `~/.bashrc` loads PATH and provider keys.
47
+ Without it, ssh's non-interactive shell skips them and pi can die at
48
+ startup.
49
+ - `pi --approve` skips pi's project-trust prompt. It trusts whatever
50
+ directory the pane starts in, so use it only on your own code.
51
+
52
+ If the spawn reports `ctl refused`, check `AllowStreamLocalForwarding`
53
+ on the host.
54
+
55
+ ## Drive it like a local agent
56
+
57
+ Claim, `mu agent send --fresh`, `mu agent wait`, and `mu agent abort`
58
+ all go through the forwarded socket and behave as they do locally:
59
+
60
+ ```bash
61
+ mu task note build -w auth 'REMOTE: dev:~/ws/worker-1'
62
+ mu task claim build -w auth --for worker-1
63
+ mu agent send worker-1 -w auth --fresh 'Work on build. Read: mu task notes build -w auth'
64
+ ```
65
+
66
+ The `REMOTE: <host>:<path>` note line is how `mu state` lists remote
67
+ workers. Collect the work by fetching from the remote checkout:
68
+
69
+ ```bash
70
+ git fetch "ssh://dev/~/ws/worker-1" HEAD && git cherry-pick FETCH_HEAD
71
+ ```
72
+
73
+ `mu agent kick` does not reach a remote process. Use `mu agent abort`,
74
+ or close the pane.
@@ -0,0 +1,76 @@
1
+ # How to query and script mu
2
+
3
+ Use typed verbs with `--json` first. Use `mu sql` for ad-hoc joins,
4
+ reports, and repairs that no verb covers.
5
+
6
+ ## Script with `--json`
7
+
8
+ Every verb takes `--json`.
9
+
10
+ - Collection reads print `{"items": [...], "count": N}`.
11
+ - Single objects, such as `mu task show`, print an object with named
12
+ fields.
13
+ - `mu sql --json` prints a bare array of rows.
14
+ - `mu log --tail --json` prints one JSON object per line.
15
+ - Errors go to stderr as `{error, message, nextSteps, exitCode}`.
16
+
17
+ ```bash
18
+ mu state -w auth --json
19
+ mu task list -w auth --json | jq '.count'
20
+ ```
21
+
22
+ Exit codes: `2` usage error, `3` not found, `4` conflict, `5`
23
+ timeout or a multiplexer, VCS, or drift failure, `6` reaped pane,
24
+ `7` stall.
25
+
26
+ ## Read the schema
27
+
28
+ The schema has 11 tables and 3 views (`ready`, `blocked`, `goals`).
29
+ Four tables travel between machines: `workstreams`, `tasks`,
30
+ `task_edges`, and `task_notes`. List them all:
31
+
32
+ ```bash
33
+ mu sql "SELECT type, name FROM sqlite_master WHERE type IN ('table','view') ORDER BY type, name"
34
+ ```
35
+
36
+ Task ids (`local_id`) are unique per workstream only. Join
37
+ `workstreams` in every query, or you hit a same-named task elsewhere.
38
+ Edges and notes reference `tasks.id`, not `local_id`.
39
+
40
+ ## Run common queries
41
+
42
+ Blocked tasks and the goals view, which replaced removed verbs:
43
+
44
+ ```bash
45
+ mu sql "SELECT b.local_id, b.title FROM blocked b JOIN workstreams w ON w.id = b.workstream_id WHERE w.name = 'auth'"
46
+ mu sql "SELECT g.local_id, g.title FROM goals g JOIN workstreams w ON w.id = g.workstream_id WHERE w.name = 'auth'"
47
+ ```
48
+
49
+ Search task titles:
50
+
51
+ ```bash
52
+ mu sql "SELECT t.local_id, t.status, t.title FROM tasks t JOIN workstreams w ON w.id = t.workstream_id
53
+ WHERE w.name = 'auth' AND LOWER(t.title) LIKE '%token%'"
54
+ ```
55
+
56
+ Every task that blocks `launch`, directly or not:
57
+
58
+ ```bash
59
+ mu sql "WITH RECURSIVE prereqs(id) AS (
60
+ SELECT t.id FROM tasks t JOIN workstreams w ON w.id = t.workstream_id
61
+ WHERE t.local_id = 'launch' AND w.name = 'auth'
62
+ UNION
63
+ SELECT e.from_task_id FROM task_edges e JOIN prereqs ON e.to_task_id = prereqs.id
64
+ )
65
+ SELECT t.local_id, t.title, t.status FROM prereqs JOIN tasks t ON t.id = prereqs.id"
66
+ ```
67
+
68
+ `mu sql` runs writes too and prints the number of rows changed. Writes
69
+ are captured as ops, so `mu undo` can revert them.
70
+
71
+ ## Pass list flags
72
+
73
+ A flag with `<value...>` in its help takes repeats, commas, or both:
74
+ `--blocked-by a,b` equals `--blocked-by a --blocked-by b`. An empty
75
+ fragment from a stray comma is dropped. A blank fragment such as
76
+ `" "` is a usage error.