@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
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# Vocabulary
|
|
2
|
+
|
|
3
|
+
Canonical terms for mu. **Use these exact words in code, docs, error
|
|
4
|
+
messages, and the LLM-facing skill.** When two words could mean the
|
|
5
|
+
same thing, the one in this doc wins.
|
|
6
|
+
|
|
7
|
+
This document is the source of truth. If another doc uses a term not
|
|
8
|
+
defined here, fix the doc. If you need a new term, add it here first.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## TL;DR — canonical terms
|
|
13
|
+
|
|
14
|
+
| Use this | For… | Don't use |
|
|
15
|
+
| --------------------- | ------------------------------------------------------------------------ | -------------------------------------------------- |
|
|
16
|
+
| **workstream** | The unit of organization. One workstream = one tmux session = one DB partition | "project", "session" (ambiguous), "context" |
|
|
17
|
+
| **tmux session** | The literal tmux session a workstream lives in | "session" alone (ambiguous) |
|
|
18
|
+
| **window** | A tmux window (tmux's tabs); identified by `window_name` | "tab" (except as the frontmatter field name) |
|
|
19
|
+
| **pane** | A tmux pane (one shell view inside a window); identified by **stable pane id** like `%15` | "terminal", "shell" |
|
|
20
|
+
| **pane title** | The string set on a pane via `select-pane -T`. **Equals the agent's name.** Read by the claim protocol. | "pane name" |
|
|
21
|
+
| **window name** | The tmux window's name. **Equals the agent's `tab:` value** (groups one or more agents). | "tab name" (in code; `tab:` only in frontmatter) |
|
|
22
|
+
| **agent** | A named worker running in a pane; identity = pane title; row in `agents` table | "subagent" (reserved for pi-subagents), "worker" (only the specific role) |
|
|
23
|
+
| **worker** | An **agent** in its role-as-task-claimer. Synonym for the registered side of identity — a row in `agents`, owns tasks via the FK. | (when ambiguous, prefer **agent**) |
|
|
24
|
+
| **actor** | The party that *caused* a state change. May or may not be a registered worker. Recorded in `agent_logs.source` for every event. The orchestrator running mu from a top-level shell is an actor but not a worker. | "caller", "author" (only on notes) |
|
|
25
|
+
| **crew** | *Informal* collective noun for the agents in a workstream | (no API surface; prose only) |
|
|
26
|
+
| **task** | A node in the DAG. Has mandatory `impact` and `effort_days`. Status one of `OPEN`, `IN_PROGRESS`, `CLOSED`, `REJECTED`, `DEFERRED` (see **task status** below). | "issue", "ticket", "item" |
|
|
27
|
+
| **task status** | One of 5 states. **OPEN** = ready to be claimed; **IN_PROGRESS** = claimed and active; **CLOSED** = work completed (the only state that satisfies a `--blocked-by` edge); **REJECTED** = terminal 'won't do' (out of scope, duplicate, wontfix); **DEFERRED** = parked, may revisit. REJECTED and DEFERRED both still BLOCK downstream by design — only CLOSED unblocks. | "state" |
|
|
28
|
+
| **reject** | Verb: stamp a task `REJECTED`. Refuses if open dependents would be stranded; pass `--cascade` to apply to the whole sub-tree. | "wontfix", "close as wontfix" |
|
|
29
|
+
| **defer** | Verb: stamp a task `DEFERRED`. Same stranded-dependent guard as reject. Reopen with `mu task open`. | "park", "snooze", "backlog" |
|
|
30
|
+
| **task DAG** / **graph** | The directed acyclic graph of tasks. Cloned from a prior internal task-graph crate. | "task list", "todo", "tree" (it's a DAG, not a tree) |
|
|
31
|
+
| **edge** | A `blocks` relationship between two tasks. The single edge type. `A blocks B` = A must close before B can start. | "dependency" (use only in prose) |
|
|
32
|
+
| **track** | An independent subtree of the DAG identified by parallel-track detection | "branch", "lane" |
|
|
33
|
+
| **diamond merge** | When two tracks share a prerequisite, parallel-track detection collapses them into one track to prevent two agents from colliding on the shared dependency. | "join", "converge" |
|
|
34
|
+
| **ready** | An OPEN task with no unresolved blockers. Exposed as the `ready` SQL view. | "unblocked", "available" |
|
|
35
|
+
| **goals** | Tasks with no outgoing blocks-edges (graph endpoints). Exposed as the `goals` SQL view. | "leaves", "targets" |
|
|
36
|
+
| **sort key** | Argument to `mu task list / next / ready --sort <key>`. One of `roi` (impact / effort_days, default for `next` / `ready`), `recency` (`updated_at` DESC — "what did I touch most recently"), `age` (`created_at` ASC — "what's gone stale"), `id` (`local_id` ASC, default for `task list`). The two time-based keys also render an `updated`/`created` relative-time column in the table view. | "order by", "sort by" |
|
|
37
|
+
| **subtree** / **scope** | The set of tasks reachable from a root via blocks-edges | "subgraph" (only for technical descriptions) |
|
|
38
|
+
| **note** | An append-only piece of context attached to a task | "comment" (reserved for VCS), "log" (reserved for `agent_logs`) |
|
|
39
|
+
| **log entry** | A row in `agent_logs` (broadcast channel) | "message" (overloaded), "event" (overloaded) |
|
|
40
|
+
| **claim** | Verb: set `tasks.owner` to an agent. Atomic CAS. | "assign" (use only in prose), "lock" |
|
|
41
|
+
| **owner** | The **worker** name in `tasks.owner`. Set by claim. NULL when the task is unowned OR was claimed via `--self` (anonymous, attributed via `agent_logs.source` instead). | "claimer", "assignee" |
|
|
42
|
+
| **anonymous claim** | A claim made via `--self` where the **actor** isn't a registered **worker**. `tasks.owner` stays NULL; the actor is recorded in `agent_logs.source` for the auto-emitted `task claim` event. The orchestrator-doing-direct-work pattern. | "self-claim" (in code; "anonymous claim" in prose), "unowned claim" |
|
|
43
|
+
| **release** | Verb: clear `tasks.owner` | "unclaim", "unassign" |
|
|
44
|
+
| **free** | Verb: mark an agent's `status = 'free'` (idle, available) | "park", "idle" (verb) |
|
|
45
|
+
| **status** | Persisted enum on `agents` (busy/needs_input/free/...) | "state" (use only "lifecycle state") |
|
|
46
|
+
| **lifecycle state** | A position in the agent state machine | "state" alone, "phase" |
|
|
47
|
+
| **role** | `full-access` or `read-only` capability flag | "permission" (avoid), "tier" |
|
|
48
|
+
| **persistent** | Agent that stays alive across tasks | "long-lived" (only in prose) |
|
|
49
|
+
| **one-shot** | Agent that exists for a single task and then terminates | "ephemeral", "transient" |
|
|
50
|
+
| **workspace** | A VCS-isolated checkout (jj workspace / sl worktree / git worktree / cp) | "branch" (it has one but isn't one), "checkout" (only for `none` backend) |
|
|
51
|
+
| **workspace orphan** | A directory under `<state-dir>/workspaces/<workstream>/` with no row in `vcs_workspaces`. Blocks subsequent `--workspace` spawns. Surfaced by `mu workspace orphans -w X` and `mu state -w X`. | "stray dir", "leftover workspace" |
|
|
52
|
+
| **stale workspace** | A workspace whose `parent_ref` is N commits behind the project's default branch HEAD (per the workspace's local refs cache). Rendered as a color-coded `behind` column (green ≤2, yellow 3–9, red ≥10) in `mu workspace list` and `mu state`; ≥10 triggers a one-line warn in `mu state`. Pure observation — mu never auto-fetches. | "out of date", "drifting" |
|
|
53
|
+
| **refresh** | `mu workspace refresh <agent>` — rebase the agent's workspace onto a fresh base (default = backend's tracked main; `--from <ref>` overrides) WITHOUT touching the agent or pane. Refuses on dirty WC; surfaces conflicts as exit 5 with a resolve-in-place hint. The `none` backend errors (no VCS to rebase). | "recycle", "reset" (overloaded) |
|
|
54
|
+
| **backend** | Implementation of `AgentBackend` or `VcsBackend` | "driver", "provider" |
|
|
55
|
+
| **detector** | Per-CLI pattern matcher for busy/permission/ready. Today mu has one (`detectPiStatus` in `src/detect.ts`); covers vanilla pi + any TUI wrapper that uses Braille spinner glyphs. Other CLIs spawned via `--cli <other>` may misclassify; trust scrollback over the emoji. | "matcher", "parser" |
|
|
56
|
+
| **snapshot** | A whole-DB backup (`<state-dir>/snapshots/<id>.db`) auto-captured before each destructive verb (workstream destroy, agent close, task close/reject/defer/release/delete, workspace free). Indexed by the `snapshots` table; restore via `mu undo`. | "checkpoint", "backup" |
|
|
57
|
+
| **prune** | Verb: bulk-drop rows from the snapshots collection per a policy (`mu snapshot prune` with `--keep-last`, `--older-than <D>d`, `--stale-version`, `--all`, or the bare GC-policy form). Sibling of the auto-GC that runs on every capture; the explicit verb is for the dogfood case where the auto-GC's count + age caps need an operator-driven supplement (e.g. "drop every snapshot whose schema_version is now stale"). Surgical single-row removal is `mu snapshot delete <id>`. | "reap", "sweep" (overloaded by workstream-destroy --empty) |
|
|
58
|
+
| **export** | A directory of plain markdown files produced by `mu workstream export` (one `.md` per task + `INDEX.md` + `README.md` + `manifest.json`). Survives `mu workstream destroy` (auto-run pre-destroy to `<state-dir>/exports/<ws>-<ts>/` unless `--no-export`). Idempotent: re-export against the same dir rewrites only changed files; deleted tasks are preserved with a banner. Markdown-only by design — no HTML/PDF, no embedded VCS. The inverse is **import** (markdown only; never `.db`). | "dump", "snapshot" (snapshot is the binary `.db`) |
|
|
59
|
+
| **import** | The inverse of **export**: `mu workstream import <bucket-dir>` walks a v0.3 bucket directory and rebuilds every source-ws subdir as live tasks + edges + notes in the DB. Markdown-only by design (cross-machine `.db` is `mu undo` + snapshots). Per-source-ws transactional; refuses to merge silently into an existing workstream (use `--workstream <name>` for single-source rename, or destroy the existing one first). Owners reset to NULL on import (agents aren't restored); the original owner name survives in the markdown frontmatter. | "rehydrate", "restore" (restore = `mu undo`) |
|
|
60
|
+
| **archive** | An operator-named bucket of preserved task graphs (rows in `archives` + `archived_tasks` + `archived_edges` + `archived_notes` + `archived_events`). Cross-workstream and additive: one archive may accumulate snapshots from many workstreams under the same label. Outlives every source workstream; `archived_tasks.source_workstream` is intentionally TEXT (not an FK) so destroyed-workstream attribution survives. Distinct from a **snapshot** (binary whole-DB backup for `mu undo`) and an **export** (markdown files on disk). | "backup", "vault" |
|
|
61
|
+
| **archived task** | A row in `archived_tasks`: a snapshot of a `tasks` row at archive time. Pins `status`, `impact`, `effort_days`, `owner_name`, and the original `created_at`/`updated_at` for retrospect ordering. The `(archive_id, source_workstream, original_local_id)` composite UNIQUE makes `mu archive add` idempotent at the (archive, workstream) granularity. | "closed task" (status-orthogonal) |
|
|
62
|
+
| **archive label** | The operator-facing TEXT name of an **archive**. Globally unique across the machine (NOT per-workstream — archives outlive workstreams). Shape: `/^[a-z][a-z0-9_-]{0,63}$/` (wider than workstream names because labels often encode workstream + date + purpose, e.g. `auth-2026-q1`). | "archive name" (in code; `label` only) |
|
|
63
|
+
| **qualified ref** | An entity-arg form `<workstream>/<name>` that targets a specific workstream's task / agent / workspace without `-w`. Bare `<name>` still resolves via the standard chain (`-w` / `$MU_SESSION` / current tmux session). Mixing a qualified ref with a non-matching `-w` is rejected (`UsageError`). When a bare name appears AND no workstream resolves AND ≥2 workstreams contain that name, mu raises `NameAmbiguousError` (exit 4) listing every candidate as a qualified-form one-paste fix. | "fully-qualified id" (in prose), "prefixed name" |
|
|
64
|
+
| **doctor** | The diagnostic command + report | "health check", "diagnose" |
|
|
65
|
+
| **CLI** | The `mu` command-line binary | "tool" (overloaded), "binary" (only when relevant) |
|
|
66
|
+
| **extension** | The pi extension shipped in the same package | "plugin" |
|
|
67
|
+
| **skill** | The bundled SKILL.md that teaches the LLM | "system prompt", "instruction" |
|
|
68
|
+
| **DB** / **registry** | `~/.local/state/mu/mu.db` and its tables | "store", "database" (full word OK in prose) |
|
|
69
|
+
| **substrate** | An external system mu depends on (tmux, jj, sl, git, sqlite) | "dependency" (means npm dep), "service" |
|
|
70
|
+
| **operation** | A canonical mu verb (e.g. `mu task add`). Each verb is a thin CLI wrapper over a typed function in `src/*.ts` — the SDK and the CLI share one surface. | "command" (overloaded), "action" |
|
|
71
|
+
| **reconcile** | Verb: re-derive registry rows from substrate reality (tmux). Always runs in `mu agent list` and `mu doctor`. | "sync", "refresh" |
|
|
72
|
+
| **adopt** | Verb: register an existing tmux pane as a managed **agent**. The inverse of `mu agent list`'s 'orphan' state. Pane must be in the workstream's tmux session. | "import", "absorb" |
|
|
73
|
+
| **pi-subagents** | A different package by Nico Bailon for in-pi focused delegation. Mu and pi-subagents are complementary, not competing. | conflating with mu |
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## The topology, with terms labeled
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
workstream (one mu instance, one DB partition)
|
|
81
|
+
──────────
|
|
82
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
83
|
+
│ tmux session: mu-auth-refactor │
|
|
84
|
+
│ ─────────── │
|
|
85
|
+
│ │
|
|
86
|
+
│ ┌──────────────────────────┐ ┌──────────────────────────────┐ │
|
|
87
|
+
│ │ window: Backend │ │ window: Review │ │
|
|
88
|
+
│ │ ───── │ │ ───── │ │
|
|
89
|
+
│ │ ┌──────────┐ ┌────────┐│ │ ┌────────────────────────┐ │ │
|
|
90
|
+
│ │ │ worker-1 │ │worker-2││ │ │ reviewer-1 │ │ │
|
|
91
|
+
│ │ │ pane │ │ pane ││ │ │ pane │ │ │
|
|
92
|
+
│ │ │ (pi) │ │ (pi) ││ │ │ (pi, role=read-only) │ │ │
|
|
93
|
+
│ │ │ agent │ │ agent ││ │ │ agent │ │ │
|
|
94
|
+
│ │ └──────────┘ └────────┘│ │ └────────────────────────┘ │ │
|
|
95
|
+
│ └──────────────────────────┘ └──────────────────────────────┘ │
|
|
96
|
+
│ │
|
|
97
|
+
│ the crew = { worker-1, worker-2, reviewer-1 } (informal) │
|
|
98
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
99
|
+
|
|
100
|
+
partitioned by session_id in ~/.local/state/mu/mu.db
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Identity convention:** the agent's name == the tmux **pane title**
|
|
104
|
+
(set by `select-pane -T <name>` on spawn). The window name comes from
|
|
105
|
+
the `tab:` frontmatter field and may group multiple agents in one
|
|
106
|
+
window.
|
|
107
|
+
|
|
108
|
+
This is what makes the claim protocol zero-config: an agent runs
|
|
109
|
+
`mu task claim foo` and mu reads `tmux display-message -p '#{pane_title}'`
|
|
110
|
+
to know who's claiming. **Read pane title (`#{pane_title}`), not
|
|
111
|
+
window name (`#W`)** — they are different when several agents share a
|
|
112
|
+
window.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Status, lifecycle, and the verbs that touch them
|
|
117
|
+
|
|
118
|
+
### Agent status enum (persisted in `agents.status`)
|
|
119
|
+
|
|
120
|
+
| Value | Icon | Meaning |
|
|
121
|
+
| ----------------- | ---- | --------------------------------------------------- |
|
|
122
|
+
| `spawning` | ⏳ | Pane created, agent process booting |
|
|
123
|
+
| `busy` | ⚙️ | Actively working (detector saw busy marker) |
|
|
124
|
+
| `needs_input` | 💤 | Idle prompt visible, waiting for input |
|
|
125
|
+
| `needs_permission`| 🔐 | Permission prompt visible (e.g., "Allow once") |
|
|
126
|
+
| `free` | ✓ | Marked available by user (`mu agent free`) |
|
|
127
|
+
| `managed` | 🤝 | Under external orchestration; mu observes only |
|
|
128
|
+
| `unreachable` | ❓ | Transport down, status uncertain |
|
|
129
|
+
| `terminated` | ✕ | Process gone, awaiting reaping |
|
|
130
|
+
|
|
131
|
+
**Source of truth:** the substrate (tmux + detector). The DB is a
|
|
132
|
+
cache; `mu agent list` reconciles on every call.
|
|
133
|
+
|
|
134
|
+
### The four "stop talking to this agent" verbs — keep them straight
|
|
135
|
+
|
|
136
|
+
| Verb | Effect |
|
|
137
|
+
| --------------------- | --------------------------------------------------------------------------- |
|
|
138
|
+
| `mu agent free alice` | Sets `alice.status = 'free'`. Agent stays alive. Means "I'm done with you for now; you're available." |
|
|
139
|
+
| `mu release feature_a`| Clears `tasks.owner` for `feature_a`. The agent who claimed it is unaffected. |
|
|
140
|
+
| `mu agent close alice` | Terminates alice's pane and removes from registry. Destructive. |
|
|
141
|
+
| `mu detach alice` | (Future) Tmux-detaches alice's pane without killing the process. Not in v1. |
|
|
142
|
+
|
|
143
|
+
**Don't conflate `free` and `release`.** Free is about the *agent*;
|
|
144
|
+
release is about the *task*.
|
|
145
|
+
|
|
146
|
+
### Verbs that move tasks through the lifecycle
|
|
147
|
+
|
|
148
|
+
| Verb | Effect |
|
|
149
|
+
| ------------------------------------- | ----------------------------------------------------- |
|
|
150
|
+
| `mu task add <id> ...` | Creates a new OPEN task |
|
|
151
|
+
| `mu task close/open/reject/defer <id>` | Lifecycle transition |
|
|
152
|
+
| `mu task claim <task> [--for <agent>]` | Atomic: sets `owner`, flips status to `IN_PROGRESS` |
|
|
153
|
+
| `mu release <task>` | Clears `owner`. Auto-flips `IN_PROGRESS` → `OPEN` (so the task re-enters the ready set); other statuses preserved. `--reopen` forces `OPEN` from `CLOSED`/`REJECTED`/`DEFERRED` |
|
|
154
|
+
| `mu task note <task> "..."` | Appends to `task_notes`. Never edits prior notes. |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Mode of address — who is "you" in each surface?
|
|
159
|
+
|
|
160
|
+
When the docs/code say "you", it must be unambiguous which actor.
|
|
161
|
+
|
|
162
|
+
| Surface | "you" means |
|
|
163
|
+
| -------------------- | ---------------------------------------------------- |
|
|
164
|
+
| README.md | The human user installing/running mu |
|
|
165
|
+
| VISION.md | The human user |
|
|
166
|
+
| ARCHITECTURE.md | A developer working on mu's source |
|
|
167
|
+
| AGENTS.md (root) | An AI coding agent working on this repo |
|
|
168
|
+
| ROADMAP.md | A developer implementing one of the listed items |
|
|
169
|
+
| **SKILL.md** | **The LLM running inside an agent's pane** |
|
|
170
|
+
| Agent prompt bodies | The LLM running as that specific agent |
|
|
171
|
+
| `mu doctor` output | The human user running the diagnostic |
|
|
172
|
+
| Error messages | The caller (CLI user, script, or pi tool invocation) |
|
|
173
|
+
|
|
174
|
+
Avoid second-person across these surfaces unless the audience is
|
|
175
|
+
unambiguous.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Reserved / avoided terms
|
|
180
|
+
|
|
181
|
+
These words show up in adjacent ecosystems and would confuse mu users.
|
|
182
|
+
Don't use them in mu code or docs:
|
|
183
|
+
|
|
184
|
+
| Avoided word | Why | Use instead |
|
|
185
|
+
| ---------------- | ---------------------------------------------------------------- | ---------------------------------------------------- |
|
|
186
|
+
| "subagent" | Pi-subagents owns this term in our ecosystem | "agent" (mu's unit) or quote `pi-subagents` explicitly |
|
|
187
|
+
| "session" | Pi has its own "session"; tmux has "session"; ambiguous alone | "workstream" (mu's unit) or "tmux session" (literal) |
|
|
188
|
+
| "project" | Means a `.pi/` project root; conflict with mu's organizational unit | "workstream" |
|
|
189
|
+
| "context" | Overloaded (LLM context, project context, fork context) | Be specific: "task context", "forked context", etc. |
|
|
190
|
+
| "tab" | Tmux has windows, not tabs. Pi-subagents and dg use "tab" as a frontmatter field; we keep that field for compatibility but use "window" everywhere else | "window" (in prose); only `tab:` in frontmatter |
|
|
191
|
+
| "thread" | OS threads + chat threads + git threads; bad word | Be specific |
|
|
192
|
+
| "message" | Overloaded (LLM message, log message, send-keys input) | "log entry" (for `agent_logs`), "send" (for input to a pane) |
|
|
193
|
+
| "config" | Already means the global mu config; don't reuse | Specific: "settings", "frontmatter", "options" |
|
|
194
|
+
| "manager" | Vague; everything could be a manager | The specific noun (e.g., "the registry", "the eval engine") |
|
|
195
|
+
| "service" | Implies long-running daemon; mu has none | Be specific |
|
|
196
|
+
| "plugin" | Pi has extensions, not plugins | "extension" |
|
|
197
|
+
| "instance" | Vague; could be agent / workstream / process | The specific thing |
|
|
198
|
+
| "broker" | Implies pub-sub middleware; we don't have one | "log entry" or be specific |
|
|
199
|
+
| "checkpoint" | Implies recoverable savepoints in the work; we have snapshots, which back up the DB | "snapshot" |
|
|
200
|
+
| "agent type" | "Type" implies a class hierarchy; mu has no class system | "agent role" (scout/reviewer/etc.) |
|
|
201
|
+
| "agent definition" / "agent template" / "agent role doc" | mu has no template/definition concept. Spawn flags + the orchestrator's prompt are the only "definition" | Just describe the spawn invocation directly |
|
|
202
|
+
| "worker" | "worker" is the name of one specific built-in agent | "agent" (general); "the worker" only when referring to that specific agent |
|
|
203
|
+
| "claimer" | Awkward; we have "owner" already | "owner" |
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Operations reference
|
|
208
|
+
|
|
209
|
+
The complete verb list lives in two places, both authoritative:
|
|
210
|
+
|
|
211
|
+
- **`mu --help`** and **`mu <verb> --help`** — the canonical CLI
|
|
212
|
+
reference. If anything below ever disagrees with `--help`, trust
|
|
213
|
+
`--help`.
|
|
214
|
+
- **[skills/mu/SKILL.md](../skills/mu/SKILL.md) § "CLI — complete
|
|
215
|
+
verb list"** — the LLM-facing one-pager with every verb, its
|
|
216
|
+
arguments, and a one-line description.
|
|
217
|
+
|
|
218
|
+
For worked examples of each verb, see
|
|
219
|
+
[USAGE_GUIDE.md](USAGE_GUIDE.md).
|
|
220
|
+
|
|
221
|
+
This document is a *vocabulary* doc; it doesn't try to be a verb
|
|
222
|
+
reference too.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Naming conventions
|
|
227
|
+
|
|
228
|
+
### IDs
|
|
229
|
+
|
|
230
|
+
- **Agent name**: lowercase, `[a-z][a-z0-9_-]*`, ≤32 chars. Used as
|
|
231
|
+
tmux window name verbatim. Unique within a workstream.
|
|
232
|
+
- **Task local_id**: same shape and rules. Unique within the DB.
|
|
233
|
+
- **Workstream name**: same shape; tmux session is `mu-<name>`.
|
|
234
|
+
- **Tab name (frontmatter `tab:`)**: human-friendly,
|
|
235
|
+
`[A-Za-z][A-Za-z0-9 _-]*`, ≤32 chars. Used as tmux window name when
|
|
236
|
+
multiple agents share the window.
|
|
237
|
+
|
|
238
|
+
### Agent names: prefer `<role>-<n>`, not human names
|
|
239
|
+
|
|
240
|
+
Agents are workers with **roles**, not people. Pick names that
|
|
241
|
+
describe the role, with a numeric suffix when there are multiples:
|
|
242
|
+
|
|
243
|
+
Good: `worker-1`, `worker-2`, `reviewer-1`, `scout-1`, `auditor-1`,
|
|
244
|
+
`oracle-1`, `planner-1`
|
|
245
|
+
|
|
246
|
+
Avoid: `alice`, `bob`, `carol`, `revv`, `mallory`, `peon`, ...
|
|
247
|
+
|
|
248
|
+
Why: anthropomorphic (or status-loaded) names confuse the model
|
|
249
|
+
when reading commands ("alice claims design" sounds like a person;
|
|
250
|
+
"worker-1 claims design" is obviously a generic worker taking a
|
|
251
|
+
task). Role-based names also make `mu agent list` and tmux's window
|
|
252
|
+
list legible at a glance — you can see "three workers and a
|
|
253
|
+
reviewer" instead of decoding name salad.
|
|
254
|
+
|
|
255
|
+
The roles align with pi-subagents' role taxonomy:
|
|
256
|
+
|
|
257
|
+
`worker` long-lived implementer; the default
|
|
258
|
+
`reviewer` reads diffs/code; usually `--role read-only`
|
|
259
|
+
`scout` fast recon; one-shot, returns context
|
|
260
|
+
`oracle` second opinion before action
|
|
261
|
+
`auditor` long-lived watcher; `--role read-only`
|
|
262
|
+
`planner` designs implementation plans
|
|
263
|
+
|
|
264
|
+
If you have multiple agents in the same role, suffix with `-1`,
|
|
265
|
+
`-2`, ... (`worker-1`, `worker-2`).
|
|
266
|
+
|
|
267
|
+
This is a convention, not enforcement. mu's regex accepts any
|
|
268
|
+
`[a-z][a-z0-9_-]{0,31}` string. Test fixtures often use `alice`/`bob`
|
|
269
|
+
as placeholder names — that's fine for tests; just don't propagate
|
|
270
|
+
it to user-facing examples or actual workstreams.
|
|
271
|
+
|
|
272
|
+
### File paths
|
|
273
|
+
|
|
274
|
+
XDG-Base-Directory-Spec compliant. The state directory resolves as:
|
|
275
|
+
|
|
276
|
+
`MU_STATE_DIR` > `$XDG_STATE_HOME/mu` > `~/.local/state/mu`
|
|
277
|
+
|
|
278
|
+
- `<state-dir>/mu.db` — the canonical SQLite database (shared across
|
|
279
|
+
all workstreams; partitioned by `workstream` columns)
|
|
280
|
+
- `<state-dir>/workstreams/<workstream>/` — per-workstream artifact
|
|
281
|
+
directory (created lazily); reserved for tracing logs / forensic
|
|
282
|
+
pane captures.
|
|
283
|
+
- `<state-dir>/workspaces/<workstream>/<agent>/` — per-agent VCS
|
|
284
|
+
workspace (created by `mu agent spawn --workspace` or
|
|
285
|
+
`mu workspace create`). Orphan dirs (no row in `vcs_workspaces`)
|
|
286
|
+
surfaced by `mu workspace orphans -w <workstream>` and
|
|
287
|
+
`mu state -w <workstream>`.
|
|
288
|
+
- `<state-dir>/snapshots/<id>.db` — whole-DB snapshots auto-captured
|
|
289
|
+
before destructive verbs (introduced in schema v4; carried forward).
|
|
290
|
+
Indexed by the `snapshots`
|
|
291
|
+
table; restore via `mu undo` (inspect via `mu snapshot list` /
|
|
292
|
+
`mu snapshot show <id>`). Default colocation: snapshots live
|
|
293
|
+
next to the live DB, so per-test isolation works without env
|
|
294
|
+
gymnastics.
|
|
295
|
+
- mu does NOT consult any agent-template directory. If pi-subagents
|
|
296
|
+
is installed, its `~/.pi/agent/agents/` and `.pi/agents/` paths
|
|
297
|
+
are pi-subagents' concern — not mu's.
|
|
298
|
+
|
|
299
|
+
### Env vars (mu state location)
|
|
300
|
+
|
|
301
|
+
| Name | Effect | Precedence |
|
|
302
|
+
| ----------------- | ------------------------------------------------------------ | ---------- |
|
|
303
|
+
| `MU_DB_PATH` | Override the SQLite file path directly | wins over all |
|
|
304
|
+
| `MU_STATE_DIR` | Override the state directory | beats `XDG_STATE_HOME` |
|
|
305
|
+
| `XDG_STATE_HOME` | Standard XDG base-directory state path; `mu/` appended | default fallback chain |
|
|
306
|
+
| `MU_SESSION` | Override active workstream name (when not auto-detectable) | n/a |
|
|
307
|
+
|
|
308
|
+
### Env vars passed to spawned children
|
|
309
|
+
|
|
310
|
+
| Name | Value |
|
|
311
|
+
| ---------------------------- | ---------------------------------------------------- |
|
|
312
|
+
| `MU_SESSION_ID` | Workstream identifier |
|
|
313
|
+
| `MU_AGENT_NAME` | This agent's name |
|
|
314
|
+
| `MU_PARENT_PANE` | Tmux pane ID of the spawning process |
|
|
315
|
+
| `MU_DB_PATH` / `MU_STATE_DIR` | Inherited from parent unless overridden |
|
|
316
|
+
| `XDG_STATE_HOME` | Inherited; mu uses `<XDG_STATE_HOME>/mu` by default |
|
|
317
|
+
| `MU_SEND_DELAY_MS` | Delay between bracketed paste and Enter (default `500`) |
|
|
318
|
+
| `MU_TMUX_SOCKET` | Override tmux socket (`-L <name>`); default uses `$TMUX` |
|
|
319
|
+
| `MU_<UPPER_CLI>_COMMAND` | Override the executable launched for `--cli <cli>` (e.g. `MU_PI_COMMAND=pi-alt` makes `--cli pi` exec `pi-alt`). Accepts multi-word strings (`MU_PI_COMMAND="pi-alt --some-flag"`); tmux exec's via a shell. Reconcile also treats the resolved binary as agent-worthy when surfacing orphan panes. |
|
|
320
|
+
| `MU_SPAWN_LIVENESS_MS` | After spawn, wait this many ms then verify the pane is still alive. Default 1500. Set to 0 to disable (useful in CI). On detected death, the DB row is rolled back and `AgentDiedOnSpawnError` is thrown with the captured scrollback. |
|
|
321
|
+
|
|
322
|
+
These mirror pi-subagents' `PI_SUBAGENT_*` env vars in spirit but live
|
|
323
|
+
in a separate namespace so the two can coexist in one pi session.
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Type of "session"
|
|
328
|
+
|
|
329
|
+
Because "session" is overloaded, here are the four senses we encounter
|
|
330
|
+
and the disambiguated terms:
|
|
331
|
+
|
|
332
|
+
| Generic word | mu term used in docs/code | What it actually is |
|
|
333
|
+
| ------------ | ------------------------------------- | ------------------------------------------------ |
|
|
334
|
+
| session | **workstream** | mu's unit of organization |
|
|
335
|
+
| session | **tmux session** | The tmux process group `mu-<workstream>` |
|
|
336
|
+
| session | **pi session** | The thing pi calls a session (its conversation) |
|
|
337
|
+
| session | **agent session** (avoid in code) | Colloquial for "an agent's run/lifetime"; prefer "lifetime" or "the work alice has done" |
|
|
338
|
+
|
|
339
|
+
When writing code, say `workstream_id` not `session_id` in any new
|
|
340
|
+
column or variable name. The existing `agents.session_id` column name
|
|
341
|
+
is grandfathered for SQL-schema-stability reasons but should be
|
|
342
|
+
documented as "workstream id" in column comments.
|
|
343
|
+
|
|
344
|
+
<!-- The alphabetical glossary that used to live here was removed:
|
|
345
|
+
it duplicated the canonical-terms table at the top of this file,
|
|
346
|
+
drifted out of sync, and carried entries for rejected features
|
|
347
|
+
(capability, agent-frontmatter `persistent: false`, the JS DSL,
|
|
348
|
+
the `defineOperation` registry). The table is the single source.
|
|
349
|
+
For deeper background, follow the links the table rows carry. -->
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@martintrojer/mu",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "A persistent, observable crew of pi agents running in one tmux session per workstream, coordinated through a built-in task DAG.",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Martin Trojer <martin.trojer@gmail.com>",
|
|
11
|
+
"homepage": "https://github.com/martintrojer/mu",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/martintrojer/mu.git"
|
|
15
|
+
},
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/martintrojer/mu/issues"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"tmux",
|
|
21
|
+
"agents",
|
|
22
|
+
"ai",
|
|
23
|
+
"orchestration",
|
|
24
|
+
"task-graph",
|
|
25
|
+
"pi-coding-agent",
|
|
26
|
+
"pi-package"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20 <24"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"bin": {
|
|
40
|
+
"mu": "./dist/cli.js"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"skills",
|
|
45
|
+
"docs",
|
|
46
|
+
"README.md",
|
|
47
|
+
"AGENTS.md"
|
|
48
|
+
],
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsup",
|
|
51
|
+
"dev": "tsup --watch",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"test:watch": "vitest",
|
|
54
|
+
"lint": "biome check src test",
|
|
55
|
+
"lint:fix": "biome check --write src test",
|
|
56
|
+
"format": "biome format --write src test",
|
|
57
|
+
"typecheck": "tsc --noEmit",
|
|
58
|
+
"prepare": "npm run build"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"better-sqlite3": "^11.8.0",
|
|
62
|
+
"cli-table3": "^0.6.5",
|
|
63
|
+
"commander": "^14.0.0",
|
|
64
|
+
"execa": "^9.5.2",
|
|
65
|
+
"picocolors": "^1.1.1",
|
|
66
|
+
"zod": "^3.24.1"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@biomejs/biome": "^1.9.4",
|
|
70
|
+
"@types/better-sqlite3": "^7.6.12",
|
|
71
|
+
"@types/node": "^22.10.7",
|
|
72
|
+
"tsup": "^8.3.5",
|
|
73
|
+
"typescript": "^5.7.3",
|
|
74
|
+
"vitest": "^2.1.8"
|
|
75
|
+
}
|
|
76
|
+
}
|