@martintrojer/mu 0.3.1
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 +343 -0
- package/README.md +189 -0
- package/dist/cli.js +11260 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3130 -0
- package/dist/index.js +6312 -0
- package/dist/index.js.map +1 -0
- package/docs/ARCHITECTURE.md +481 -0
- package/docs/ROADMAP.md +542 -0
- package/docs/USAGE_GUIDE.md +1631 -0
- package/docs/VISION.md +440 -0
- package/docs/VOCABULARY.md +349 -0
- package/package.json +76 -0
- package/skills/mu/SKILL.md +523 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# Repo guide for AI coding agents
|
|
2
|
+
|
|
3
|
+
You're an AI coding agent working on the `mu` repo, which builds
|
|
4
|
+
**mu** — a CLI that manages a persistent crew of AI agents in tmux
|
|
5
|
+
panes coordinated through a built-in task DAG.
|
|
6
|
+
|
|
7
|
+
This file is your orientation. Read the linked docs before you
|
|
8
|
+
write code. Follow the conventions below.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Read these first (in this order)
|
|
13
|
+
|
|
14
|
+
1. **[docs/USAGE_GUIDE.md](docs/USAGE_GUIDE.md)** — what mu does
|
|
15
|
+
from a user's perspective. ~10 minutes.
|
|
16
|
+
2. **[CHANGELOG.md](CHANGELOG.md)** — the v0.1.0 release entry.
|
|
17
|
+
Single source of truth for the verb list, schema, env vars.
|
|
18
|
+
3. **[docs/VISION.md](docs/VISION.md)** — the load-bearing pillars.
|
|
19
|
+
The design principles you must not violate.
|
|
20
|
+
4. **[docs/ROADMAP.md](docs/ROADMAP.md)** — what's next, with
|
|
21
|
+
promotion criteria. **Read the "Anti-feature pledges" section
|
|
22
|
+
before adding any new dep, abstraction, or surface.**
|
|
23
|
+
5. **[docs/VOCABULARY.md](docs/VOCABULARY.md)** — canonical terms.
|
|
24
|
+
**Source of truth for every word** in code, docs, and error
|
|
25
|
+
messages. If you use a term not defined there, fix the docs first.
|
|
26
|
+
6. **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** — module layout,
|
|
27
|
+
reconciliation algorithm, key seams.
|
|
28
|
+
|
|
29
|
+
Design rationale for rejected and unbuilt features (DSL, snapshots,
|
|
30
|
+
task_artifacts, ...) is now folded into
|
|
31
|
+
[docs/ROADMAP.md](docs/ROADMAP.md) per item, alongside its
|
|
32
|
+
promotion criteria.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Repo layout
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
mu/
|
|
40
|
+
├── README.md # human-user entry point
|
|
41
|
+
├── AGENTS.md # this file
|
|
42
|
+
├── CHANGELOG.md # release notes
|
|
43
|
+
├── docs/ # everything else
|
|
44
|
+
│ ├── USAGE_GUIDE.md
|
|
45
|
+
│ ├── ROADMAP.md # what's next; promotion criteria
|
|
46
|
+
│ ├── VISION.md
|
|
47
|
+
│ ├── VOCABULARY.md
|
|
48
|
+
│ └── ARCHITECTURE.md
|
|
49
|
+
├── src/ # all source (root files: SDK + shared infra; one
|
|
50
|
+
│ # level of subdirs OK for cohesive clusters — see
|
|
51
|
+
│ # `src/cli/`, `src/agents/`, `src/tasks/` below)
|
|
52
|
+
│ ├── db.ts # SQLite schema + openDb (single CREATE-IF-NOT-EXISTS block)
|
|
53
|
+
│ ├── tmux.ts # tmux wrapper, send protocol, pane validation
|
|
54
|
+
│ ├── detect.ts # pi-only status detector
|
|
55
|
+
│ ├── reconcile.ts # ghost prune + status detect + orphan surface
|
|
56
|
+
│ ├── agents.ts # CRUD + send/read/list/close/free + liveness + reaper hub (re-exports src/agents/*)
|
|
57
|
+
│ ├── agents/ # cohesive cluster of agent-lifecycle internals
|
|
58
|
+
│ │ ├── spawn.ts # spawnAgent + resolveCliCommand / awaitSpawnLiveness / pane create-or-reuse / prestage / rollback
|
|
59
|
+
│ │ ├── adopt.ts # adoptAgent: register an existing tmux pane as a managed agent
|
|
60
|
+
│ │ └── errors.ts # typed agent error classes (AgentNotFoundError, AgentDiedOnSpawnError, …)
|
|
61
|
+
│ ├── tasks.ts # task SDK hub (re-exports src/tasks/* + edit/edges/queries verbs)
|
|
62
|
+
│ ├── tasks/ # cohesive cluster of task-graph internals
|
|
63
|
+
│ │ ├── status.ts # TaskStatus enum + helpers (single source of truth for statuses)
|
|
64
|
+
│ │ ├── claim.ts # claim/release + resolveActorIdentity (atomic CAS)
|
|
65
|
+
│ │ ├── lifecycle.ts # setTaskStatus / closeTask / openTask / rejectTask / deferTask + cascade
|
|
66
|
+
│ │ ├── wait.ts # waitForTasks: block until tasks reach a target status
|
|
67
|
+
│ │ └── errors.ts # typed task error classes (TaskAlreadyOwnedError, CycleError, …)
|
|
68
|
+
│ ├── tracks.ts # parallel-tracks union-find with diamond merge
|
|
69
|
+
│ ├── workstream.ts # ensureWorkstream / list / summarize / destroy / export
|
|
70
|
+
│ ├── archives.ts # cross-workstream archive buckets (create / add / remove / restore)
|
|
71
|
+
│ ├── exporting.ts # unified bucket renderer (workstream + archive export)
|
|
72
|
+
│ ├── importing.ts # inverse of exporting.ts: parse a v0.3 bucket dir → live DB rows
|
|
73
|
+
│ ├── logs.ts # agent_logs SDK (append, list, latestSeq, emitEvent)
|
|
74
|
+
│ ├── vcs.ts # VcsBackend interface + jj/sl/git/none impls
|
|
75
|
+
│ ├── workspace.ts # per-agent VCS workspaces (CRUD over vcs_workspaces)
|
|
76
|
+
│ ├── snapshots.ts # whole-DB snapshots (VACUUM INTO) + auto-capture hook
|
|
77
|
+
│ ├── output.ts # NextStep type + printNextSteps / errorNextSteps
|
|
78
|
+
│ ├── cli.ts # commander wiring (buildProgram); re-exports format/handle for back-compat
|
|
79
|
+
│ ├── cli/ # one file per verb-namespace; thin wrappers over the SDK
|
|
80
|
+
│ │ ├── workstream.ts # workstream init / list / destroy / export
|
|
81
|
+
│ │ ├── agents.ts # agent spawn / send / read / list / show / close / free / adopt / attach
|
|
82
|
+
│ │ ├── tasks.ts # `mu task` hub (re-exports wireTaskCommands / cmdMyNext / cmdMyTasks / unescapeNoteText)
|
|
83
|
+
│ │ ├── tasks/ # sub-cluster of the `mu task` namespace
|
|
84
|
+
│ │ │ ├── queries.ts # list / next / owned-by + cmdMyTasks / cmdMyNext (back `mu me tasks` / `mu me next`)
|
|
85
|
+
│ │ │ ├── lifecycle.ts # close / open / reject / defer + cascade preview
|
|
86
|
+
│ │ │ ├── edit.ts # add / show / notes / note / update + helpers
|
|
87
|
+
│ │ │ ├── edges.ts # block / unblock / reparent / delete
|
|
88
|
+
│ │ │ ├── claim.ts # claim / release / wait
|
|
89
|
+
│ │ │ ├── tree.ts # tree rendering
|
|
90
|
+
│ │ │ └── wire.ts # Commander glue
|
|
91
|
+
│ │ ├── workspace.ts # workspace create / list / free / path / orphans
|
|
92
|
+
│ │ ├── log.ts # log read / write / tail
|
|
93
|
+
│ │ ├── archive.ts # archive create / list / show / add / remove / delete
|
|
94
|
+
│ │ ├── state.ts # `mu state` (canonical state card) + bare `mu` (mission control / hud render mode)
|
|
95
|
+
│ │ ├── snapshot.ts # undo / snapshot list / snapshot show
|
|
96
|
+
│ │ ├── sql.ts # sql escape hatch
|
|
97
|
+
│ │ ├── doctor.ts # doctor diagnostic
|
|
98
|
+
│ │ ├── format.ts # pure rendering helpers (table renderers, status colourers, truncate/relTime)
|
|
99
|
+
│ │ └── handle.ts # typed-error → exit-code map + handle() wrapper
|
|
100
|
+
│ └── index.ts # SDK entrypoint (re-exports)
|
|
101
|
+
├── test/ # 60 files / 57 *.test.ts / ~996 it()/test() calls; many use real tmux/git/jj/sl
|
|
102
|
+
├── skills/mu/SKILL.md # what the LLM running inside an agent pane sees
|
|
103
|
+
├── package.json # bin: { mu: ./dist/cli.js }, type: module
|
|
104
|
+
├── tsconfig.json # strict + noUncheckedIndexedAccess + verbatimModuleSyntax
|
|
105
|
+
├── tsup.config.ts # bundles src/ → dist/ (cli + index entries)
|
|
106
|
+
├── biome.json # lint + format
|
|
107
|
+
└── vitest.config.ts # tests
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Working conventions
|
|
113
|
+
|
|
114
|
+
### Build / test / lint
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npm install
|
|
118
|
+
npm run build # tsup → dist/
|
|
119
|
+
npm run typecheck # tsc --noEmit
|
|
120
|
+
npm run lint # biome check src test
|
|
121
|
+
npm run test # vitest run
|
|
122
|
+
npm run test:watch # vitest in watch mode
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
All four must pass before any commit. Tests include real-tmux
|
|
126
|
+
integration tests that need `$TMUX` set. If you're not in tmux,
|
|
127
|
+
those tests skip themselves; CI runs inside tmux.
|
|
128
|
+
|
|
129
|
+
### Commits
|
|
130
|
+
|
|
131
|
+
- Conventional but not strict: prefix with the scope when helpful
|
|
132
|
+
(e.g. `R4 + R9: ...`, `schema: ...`). One logical change per
|
|
133
|
+
commit.
|
|
134
|
+
- Body explains **what changed and why**, not just what. Reference
|
|
135
|
+
the [VISION.md](docs/VISION.md) pillar / [ROADMAP.md](docs/ROADMAP.md)
|
|
136
|
+
item / promotion criterion that motivated the change.
|
|
137
|
+
- Always verify typecheck + lint + tests + build clean before
|
|
138
|
+
committing. Commit messages should say so explicitly.
|
|
139
|
+
|
|
140
|
+
### Code style
|
|
141
|
+
|
|
142
|
+
- TypeScript, strict mode. `noUncheckedIndexedAccess` is on — don't
|
|
143
|
+
trust array indices to be defined; use early returns.
|
|
144
|
+
- ESM only (`"type": "module"`). NodeNext module resolution.
|
|
145
|
+
- No `any`. Use `unknown` and narrow.
|
|
146
|
+
- No non-null assertions (`!`). Use early returns or `if (!x) throw`.
|
|
147
|
+
- Errors are typed classes (e.g. `AgentNotFoundError`,
|
|
148
|
+
`TaskAlreadyOwnedError`, `CycleError`, `TmuxError`,
|
|
149
|
+
`AgentDiedOnSpawnError`) so the CLI's `handle()` wrapper can map
|
|
150
|
+
them to specific exit codes.
|
|
151
|
+
- Imports stay sorted (Biome's `organizeImports` enforces this).
|
|
152
|
+
- Run `npx biome check --write src test` to auto-fix sort + format.
|
|
153
|
+
**Do not** run `--write --unsafe`; it has rewritten `delete
|
|
154
|
+
process.env.X` to `process.env.X = undefined` for us, which
|
|
155
|
+
silently produces the literal string `"undefined"`. The codebase
|
|
156
|
+
pattern for env deletion is `const key = "FOO"; delete
|
|
157
|
+
process.env[key];` (computed-key form).
|
|
158
|
+
- Hard cap: 1500 LOC per file. Refactor signal at 800.
|
|
159
|
+
- **Layout: flat at the root; one level of subdirs is allowed when a
|
|
160
|
+
cluster of files is naturally cohesive** (e.g. `src/cli/` for the
|
|
161
|
+
thin commander wrappers, one file per verb-namespace). The original
|
|
162
|
+
flat-only rule was authored when `src/` had ~12 files; past ~20 the
|
|
163
|
+
flat layout starts hurting (Finder/IDE listing becomes noise; `ls
|
|
164
|
+
src/` no longer reads as architecture). Each subdir cluster needs:
|
|
165
|
+
(1) a clear theme (every file does the same kind of thing),
|
|
166
|
+
(2) imports go from cluster-files → root-files (no upward imports),
|
|
167
|
+
(3) ARCHITECTURE.md's module table has a row covering it.
|
|
168
|
+
|
|
169
|
+
### Tests
|
|
170
|
+
|
|
171
|
+
- Unit tests: real SQLite (in-temp-dir), mocked tmux executor via
|
|
172
|
+
`setTmuxExecutor()`. Fast, deterministic.
|
|
173
|
+
- Integration tests: real tmux server. File suffix
|
|
174
|
+
`.integration.test.ts` (e.g. `tmux.integration.test.ts`). Skipped
|
|
175
|
+
when `$TMUX` is unset. These tests typically opt out of the spawn
|
|
176
|
+
liveness check via `process.env.MU_SPAWN_LIVENESS_MS = "0"` in
|
|
177
|
+
`beforeEach` since the long-running sh subprocesses they spawn are
|
|
178
|
+
intentionally alive.
|
|
179
|
+
- Each test gets its own temp DB and (for integration) a unique
|
|
180
|
+
tmux session like `mu-test-<pid>-<ts>-<rand>` to avoid colliding
|
|
181
|
+
with the user's panes or with parallel test runs.
|
|
182
|
+
- The acceptance test in `test/acceptance.test.ts` is the
|
|
183
|
+
"everything works" gate. Keep it passing.
|
|
184
|
+
|
|
185
|
+
### When you change behaviour, update VOCABULARY first
|
|
186
|
+
|
|
187
|
+
Vocabulary is canonical. If you introduce a new concept, name, or
|
|
188
|
+
verb, **add it to docs/VOCABULARY.md before the code lands**. If
|
|
189
|
+
you rename something, update VOCABULARY.md in the same commit. The
|
|
190
|
+
"term not defined here, fix the docs" rule is enforced by code
|
|
191
|
+
review.
|
|
192
|
+
|
|
193
|
+
### Deferred features — don't smuggle them in
|
|
194
|
+
|
|
195
|
+
[docs/ROADMAP.md](docs/ROADMAP.md) lists what's next, by version,
|
|
196
|
+
with **promotion criteria**:
|
|
197
|
+
|
|
198
|
+
> 1. A real user hits the missing feature in real workflows ≥2
|
|
199
|
+
> times.
|
|
200
|
+
> 2. The current substrate makes the addition straightforward (no
|
|
201
|
+
> major pillar refactor).
|
|
202
|
+
> 3. The addition fits in <300 LOC or has a clear smaller subset.
|
|
203
|
+
|
|
204
|
+
If you find yourself adding something not on the roadmap and not
|
|
205
|
+
meeting these criteria, **stop**. Add an entry to
|
|
206
|
+
[docs/ROADMAP.md](docs/ROADMAP.md) (or open an issue) and move on.
|
|
207
|
+
|
|
208
|
+
The "anti-feature pledges" in ROADMAP.md are firm:
|
|
209
|
+
|
|
210
|
+
- No config file
|
|
211
|
+
- No daemon
|
|
212
|
+
- No anticipatory abstractions (no traits with zero implementors)
|
|
213
|
+
- No wrappers around wrappers
|
|
214
|
+
- No codegen
|
|
215
|
+
- An agent template/discovery system requires explicit promotion
|
|
216
|
+
- No render layer beyond `cli-table3` + `picocolors`
|
|
217
|
+
- Don't bundle pi (it's a peer dep)
|
|
218
|
+
|
|
219
|
+
### When in doubt: be small
|
|
220
|
+
|
|
221
|
+
The README, ROADMAP, and VISION docs all hammer this. Pi-subagents
|
|
222
|
+
philosophy: ship the smallest thing that works, then layer on as
|
|
223
|
+
real friction proves itself.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Common tasks
|
|
228
|
+
|
|
229
|
+
### "Add a new CLI verb"
|
|
230
|
+
|
|
231
|
+
1. Find or write the programmatic function in `src/agents.ts`,
|
|
232
|
+
`src/tasks.ts`, `src/workstream.ts`, etc. Test it with mocked
|
|
233
|
+
tmux. Return a typed result object (`{ changed: boolean,
|
|
234
|
+
previousStatus, ... }`) so callers can log lifecycle
|
|
235
|
+
transitions.
|
|
236
|
+
2. Wire the verb in `src/cli.ts` using `commander`. Use
|
|
237
|
+
`handle(...)` so typed errors map to exit codes. If the verb
|
|
238
|
+
takes `--workstream`, use `command.optsWithGlobals()` (via
|
|
239
|
+
`this`) so the top-level option doesn't swallow it (commander
|
|
240
|
+
gotcha).
|
|
241
|
+
3. Update [docs/USAGE_GUIDE.md](docs/USAGE_GUIDE.md) with the new
|
|
242
|
+
verb in the right section.
|
|
243
|
+
4. Update [docs/VOCABULARY.md](docs/VOCABULARY.md) operations
|
|
244
|
+
table.
|
|
245
|
+
5. Update [skills/mu/SKILL.md](skills/mu/SKILL.md) verb list.
|
|
246
|
+
6. Update [CHANGELOG.md](CHANGELOG.md) under the upcoming version.
|
|
247
|
+
7. If this verb promotes a `mu sql` workaround, remove the
|
|
248
|
+
workaround entry from `docs/USAGE_GUIDE.md` "What's NOT in 0.1.0"
|
|
249
|
+
table.
|
|
250
|
+
8. Smoke-test: `MU_DB_PATH=/tmp/mu-smoke.db node dist/cli.js <verb>
|
|
251
|
+
...` to verify it works against real tmux.
|
|
252
|
+
|
|
253
|
+
### "Update the schema"
|
|
254
|
+
|
|
255
|
+
1. 0.1.0 has no migration layer. Schema lives in `src/db.ts` as a
|
|
256
|
+
single CREATE-IF-NOT-EXISTS block. The first non-additive
|
|
257
|
+
change should land alongside a `schema_version` table.
|
|
258
|
+
2. Update tests that exercise the schema (`test/db.test.ts`).
|
|
259
|
+
3. Update [CHANGELOG.md](CHANGELOG.md) §"Schema" snapshot.
|
|
260
|
+
|
|
261
|
+
### "Add a new tmux operation"
|
|
262
|
+
|
|
263
|
+
All tmux invocations go through `src/tmux.ts` `tmux(args)`. **No
|
|
264
|
+
raw `execa("tmux", …)` anywhere else.** The wrapper produces typed
|
|
265
|
+
`TmuxError` and the test suite mocks via `setTmuxExecutor`.
|
|
266
|
+
|
|
267
|
+
For send-style operations: use the canonical bracketed-paste
|
|
268
|
+
sequence already in `src/tmux.ts` `sendToPane`. Naive `tmux
|
|
269
|
+
send-keys "<text>"` is broken — characters like `/`, `?`, `f` get
|
|
270
|
+
interpreted by the agent's TUI.
|
|
271
|
+
|
|
272
|
+
### "Fix a flaky integration test"
|
|
273
|
+
|
|
274
|
+
Integration tests against real tmux can be slow because tmux/sh
|
|
275
|
+
processes need time to settle. Use:
|
|
276
|
+
|
|
277
|
+
- Unique session names (`mu-test-<pid>-<ts>-<random>`) so parallel
|
|
278
|
+
runs never collide.
|
|
279
|
+
- Polling loops (50ms × 10 attempts) when waiting for state to
|
|
280
|
+
propagate, not fixed sleeps.
|
|
281
|
+
- `try { ... } catch {}` cleanup in `afterEach` for tmux session
|
|
282
|
+
kills and DB closes — a failure mid-test should never block the
|
|
283
|
+
next.
|
|
284
|
+
- `setSleepForTests(async () => {})` in unit tests so the real
|
|
285
|
+
`MU_SEND_DELAY_MS` doesn't slow them.
|
|
286
|
+
- `process.env.MU_SPAWN_LIVENESS_MS = "0"` in integration-test
|
|
287
|
+
`beforeEach` to skip the 1500ms post-spawn check (the unit-test
|
|
288
|
+
suite covers it).
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## What NOT to do
|
|
293
|
+
|
|
294
|
+
- **Don't add a config file.** mu is CLI flags + env vars.
|
|
295
|
+
- **Don't add a daemon, watcher, or background process.** Every
|
|
296
|
+
invocation is short-lived.
|
|
297
|
+
- **Don't add abstractions for hypothetical future flexibility.**
|
|
298
|
+
A prior internal LLM-runtime had a `RunContext` trait with zero
|
|
299
|
+
implementors — that's the cautionary tale. Two real impls today,
|
|
300
|
+
or use a concrete type.
|
|
301
|
+
- **Don't grow stream wrappers around stream wrappers.**
|
|
302
|
+
Stream-of-streams wrappers (`TextStream` / `TextState` /
|
|
303
|
+
`StreamResult`) we've seen before are the cautionary tale.
|
|
304
|
+
- **Don't generate JS strings as a "typed protocol."** A prior
|
|
305
|
+
internal agent-protocol layer regretted `await
|
|
306
|
+
spawnCliAgent(...)` strings.
|
|
307
|
+
- **Don't put state-snapshot/handle layering on top of SQLite.**
|
|
308
|
+
SQLite is the canonical state. Read it directly; don't introduce
|
|
309
|
+
a `MuStateHandle` facade.
|
|
310
|
+
- **Don't add a template/discovery system for agent roles** until
|
|
311
|
+
pattern promotion criteria are met.
|
|
312
|
+
- **Don't bundle pi.** It's a peer dep, optional.
|
|
313
|
+
- **Don't write to files outside `~/.local/state/mu/` or the
|
|
314
|
+
project repo** without documenting why.
|
|
315
|
+
- **Don't promote a roadmap item to "shipped"** unless its
|
|
316
|
+
promotion criteria in [docs/ROADMAP.md](docs/ROADMAP.md) are met.
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## When you're done
|
|
321
|
+
|
|
322
|
+
Before opening a PR or marking a task complete:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
npm run typecheck && npm run lint && npm run test && npm run build
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
All four green. The acceptance test (`test/acceptance.test.ts`)
|
|
329
|
+
must pass — it's the "end-to-end works" gate.
|
|
330
|
+
|
|
331
|
+
Checklist for any non-trivial change:
|
|
332
|
+
|
|
333
|
+
- [ ] If you added a typed verb, the corresponding `mu sql`
|
|
334
|
+
workaround row was removed from `docs/USAGE_GUIDE.md`.
|
|
335
|
+
- [ ] If you added vocabulary, `docs/VOCABULARY.md` has the new
|
|
336
|
+
entry.
|
|
337
|
+
- [ ] If you changed an architectural seam,
|
|
338
|
+
`docs/ARCHITECTURE.md` is updated.
|
|
339
|
+
- [ ] [CHANGELOG.md](CHANGELOG.md) has an entry under the upcoming
|
|
340
|
+
version.
|
|
341
|
+
|
|
342
|
+
That's it. Be small, be typed, follow the conventions, ship clean
|
|
343
|
+
green builds.
|
package/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# mu
|
|
2
|
+
|
|
3
|
+
**A small, opinionated control plane for a crew of AI coding agents
|
|
4
|
+
working in parallel.** One tmux session, a typed task DAG, isolated
|
|
5
|
+
VCS workspaces per agent, an audit log — and a hard refusal to
|
|
6
|
+
grow into another bloated agent framework.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
mu workstream init auth-refactor
|
|
10
|
+
mu task add --title "Design auth" --impact 80 --effort-days 2
|
|
11
|
+
mu task add --title "Build auth" --impact 80 --effort-days 5 --blocks design_auth
|
|
12
|
+
mu task add --title "Review auth" --impact 60 --effort-days 1 --blocks build_auth
|
|
13
|
+
|
|
14
|
+
mu agent spawn worker-1 --workspace
|
|
15
|
+
mu agent spawn reviewer-1 --workspace --role read-only
|
|
16
|
+
mu agent send worker-1 "Pick up the next ready task and design the auth module."
|
|
17
|
+
|
|
18
|
+
tmux a -t mu-auth-refactor # watch the whole crew live
|
|
19
|
+
mu # mission control: ready tasks, parallel tracks, agent status
|
|
20
|
+
mu log --tail # subscribe to every state change
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The crew is real (tmux panes you can attach to), the work graph is
|
|
24
|
+
real (SQLite + a parallel-tracks algorithm with diamond-merge), the
|
|
25
|
+
workspaces are real (jj workspace / sl share / git worktree), and
|
|
26
|
+
**mu does not get in your model's way.**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## What mu is
|
|
31
|
+
|
|
32
|
+
- **Parallelism that doesn't trip over itself.** Per-agent VCS
|
|
33
|
+
workspaces (jj/sl/git auto-detected; `cp -a` for non-VCS); a real
|
|
34
|
+
task DAG with **deterministic parallel-track detection +
|
|
35
|
+
diamond-merge** so two agents are never assigned tasks that share
|
|
36
|
+
a prerequisite.
|
|
37
|
+
- **Get out of the model's way.** Mu coordinates agents; it does
|
|
38
|
+
not reason about them. No model selection, no thinking-effort
|
|
39
|
+
knobs, no system-prompt templating, no tool routing. `--cli <key>`
|
|
40
|
+
uppercases to `$MU_<KEY>_COMMAND` — your shell rc owns the
|
|
41
|
+
mapping. Swap your whole stack in one line.
|
|
42
|
+
- **A deliberate refusal to over-engineer.** One CLI. One SQLite
|
|
43
|
+
file. ~60 typed verbs. No daemon, no config file, no plugin
|
|
44
|
+
runtime, no DSL, no codegen, no web UI, no chat integration, no
|
|
45
|
+
hosted service. Each missing piece is an
|
|
46
|
+
**[anti-feature pledge](docs/ROADMAP.md#anti-feature-pledges-still-in-force-reinforced-by-an-internal-critique)**,
|
|
47
|
+
not an oversight.
|
|
48
|
+
|
|
49
|
+
## What mu is NOT
|
|
50
|
+
|
|
51
|
+
- **Not a build tool.** mu doesn't compile, test, or deploy
|
|
52
|
+
anything.
|
|
53
|
+
- **Not a chat protocol.** Agents communicate via the work graph
|
|
54
|
+
and the activity log, never agent-to-agent messaging.
|
|
55
|
+
- **Not a verifier.** `task close --evidence "tests pass"` records
|
|
56
|
+
the claim; mu doesn't run the tests.
|
|
57
|
+
- **Not a replacement for [pi-subagents](https://github.com/nicobailon/pi-subagents).**
|
|
58
|
+
Different problem (persistent crew vs one-shot focused
|
|
59
|
+
delegation). Install both.
|
|
60
|
+
- **Not a hosted service.** Local-first SQLite.
|
|
61
|
+
- **DB-undoable, not tmux-undoable.** Every destructive verb
|
|
62
|
+
auto-captures a whole-DB snapshot first; `mu undo --yes` restores
|
|
63
|
+
the DB. Killed panes and freed workspace dirs are NOT replayed.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## When mu earns its overhead
|
|
68
|
+
|
|
69
|
+
**Use mu for** — multi-phase investigations; tasks worth gating
|
|
70
|
+
with review; parallel read-only/audit work alongside a heavier
|
|
71
|
+
task; implementation + reviewer splits with isolated workspaces;
|
|
72
|
+
anything where "what was decided and why" needs to outlive a
|
|
73
|
+
single agent's scrollback.
|
|
74
|
+
|
|
75
|
+
**Don't use mu for** — tiny direct edits; quick local inspection;
|
|
76
|
+
single-context work where no durable coordination is needed. The
|
|
77
|
+
orchestrator's first decision is whether to reach for mu at all.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# 1. The CLI.
|
|
85
|
+
npm install -g @martintrojer/mu
|
|
86
|
+
mu --version
|
|
87
|
+
|
|
88
|
+
# 2. The skill (teaches your coding agent how to drive mu).
|
|
89
|
+
npx skills add martintrojer/mu # auto-detects pi / claude-code / codex / etc.
|
|
90
|
+
# Add -g to install globally (~/.<agent>/skills/), -y to skip prompts.
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Requirements:**
|
|
94
|
+
- Node 20, 22, or 23 (LTS recommended; see `.nvmrc`). Node 24+ is
|
|
95
|
+
currently blocked by a `better-sqlite3` native-build incompatibility.
|
|
96
|
+
- tmux ≥ 3.0 (`mu doctor` checks)
|
|
97
|
+
- pi (the agent CLI mu orchestrates)
|
|
98
|
+
- For `--workspace`: jj, sl, or git on PATH (or `--backend none`)
|
|
99
|
+
|
|
100
|
+
**Update:** `npm install -g @martintrojer/mu@latest` for the CLI;
|
|
101
|
+
`npx skills update mu` for the skill.
|
|
102
|
+
|
|
103
|
+
**Install from source** (hacking on mu itself):
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
git clone https://github.com/martintrojer/mu
|
|
107
|
+
cd mu
|
|
108
|
+
npm install -g . # `prepare` script auto-builds; `mu` lands on $PATH
|
|
109
|
+
npx skills add ./skills/mu # local-path source format
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
More install patterns (alias-to-dist for fastest dev iteration) in
|
|
113
|
+
[docs/USAGE_GUIDE.md § 1 Setup](docs/USAGE_GUIDE.md#1-setup).
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Quick start
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Make sure you're inside tmux.
|
|
121
|
+
tmux
|
|
122
|
+
|
|
123
|
+
# Initialize the workstream (creates tmux session mu-auth-refactor)
|
|
124
|
+
mu workstream init auth-refactor
|
|
125
|
+
|
|
126
|
+
# Plan the work as a DAG. IDs auto-derive from titles.
|
|
127
|
+
mu task add --title "Design auth module" --impact 80 --effort-days 2
|
|
128
|
+
mu task add --title "Build auth" --impact 80 --effort-days 5 --blocks design_auth_module
|
|
129
|
+
mu task add --title "Review auth" --impact 60 --effort-days 1 --blocks build_auth
|
|
130
|
+
|
|
131
|
+
# Spawn a crew with isolated workspaces.
|
|
132
|
+
mu agent spawn worker-1 --workspace
|
|
133
|
+
mu agent spawn reviewer-1 --workspace --role read-only
|
|
134
|
+
|
|
135
|
+
# Mission control: parallel tracks, ready tasks, agent status.
|
|
136
|
+
mu
|
|
137
|
+
|
|
138
|
+
# Inside an agent's pane, the agent claims and closes tasks
|
|
139
|
+
# without ever knowing its own name (mu reads $TMUX_PANE).
|
|
140
|
+
mu task claim design_auth_module
|
|
141
|
+
mu task note design_auth_module "DECISION: JWT, 24h expiry, refresh via cookie"
|
|
142
|
+
mu task close design_auth_module --evidence "design doc reviewed by reviewer-1"
|
|
143
|
+
|
|
144
|
+
# Subscribe to events instead of polling.
|
|
145
|
+
mu log --tail
|
|
146
|
+
|
|
147
|
+
# Cleanup (auto-snapshots + auto-exports the conversation first).
|
|
148
|
+
mu workstream destroy --yes
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Full tour: [docs/USAGE_GUIDE.md](docs/USAGE_GUIDE.md).
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## vs `pi-subagents`
|
|
156
|
+
|
|
157
|
+
| | [`pi-subagents`](https://github.com/nicobailon/pi-subagents) | `mu` |
|
|
158
|
+
| ------------------------ | -------------------------------------------------------- | ---- |
|
|
159
|
+
| Best for | "Send this focused task to a specialist, return a result" | "Stand up a crew of agents I can keep talking to and watch live" |
|
|
160
|
+
| Lifetime | one-shot per task | long-lived by default |
|
|
161
|
+
| Substrate | `pi` subprocess + result files | tmux panes running pi sessions |
|
|
162
|
+
| Built-in task graph | no | yes: parallel-tracks union-find with diamond-merge |
|
|
163
|
+
| Drivable from outside pi | no (extension-only) | yes (`mu` is a real CLI) |
|
|
164
|
+
|
|
165
|
+
The two play well together. A pi session can install both.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Documentation
|
|
170
|
+
|
|
171
|
+
- **[docs/USAGE_GUIDE.md](docs/USAGE_GUIDE.md)** — practical tour
|
|
172
|
+
of every verb. **Start here.**
|
|
173
|
+
- **[skills/mu/SKILL.md](skills/mu/SKILL.md)** — what an LLM
|
|
174
|
+
running inside an agent pane sees: the in-pane working loop,
|
|
175
|
+
subscribe-vs-poll pattern.
|
|
176
|
+
- **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** — module map,
|
|
177
|
+
reconciliation algorithm, schema seam (surrogate INTEGER PKs +
|
|
178
|
+
the SDK boundary discipline).
|
|
179
|
+
- **[docs/VOCABULARY.md](docs/VOCABULARY.md)** — canonical terms;
|
|
180
|
+
source of truth for every word in code, docs, error messages.
|
|
181
|
+
- **[docs/VISION.md](docs/VISION.md)** — the load-bearing pillars
|
|
182
|
+
+ the prior-runtime retrospective.
|
|
183
|
+
- **[docs/ROADMAP.md](docs/ROADMAP.md)** — what's next + the
|
|
184
|
+
anti-feature pledges + explicitly-rejected ideas.
|
|
185
|
+
- **[CHANGELOG.md](CHANGELOG.md)** — release notes.
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT.
|