gabriel / muse public
README.md markdown
375 lines 10.4 KB
9ef121d1 feat: add Oh My ZSH plugin for Muse (all six phases) Gabriel Cardona <gabriel@tellurstori.com> 3d ago
1 # Muse — Oh My ZSH Plugin
2
3 Domain-aware, agent-native ZSH integration for [Muse](https://github.com/gabrielchua/muse) — version control for multidimensional state.
4
5 Unlike the Git plugin which treats every repo identically, this plugin **knows what kind of state you are versioning** — MIDI, code, genomics, spatial data — and surfaces domain-specific information at every layer: the prompt, the completions, the workflow functions, and the agent session system.
6
7 ---
8
9 ## Installation
10
11 **One-liner** (run from the muse repo root):
12
13 ```zsh
14 bash tools/install-omzsh-plugin.sh
15 ```
16
17 Then add `muse` to your `plugins` array in `~/.zshrc`:
18
19 ```zsh
20 plugins=(git muse) # add 'muse' alongside your existing plugins
21 ```
22
23 Reload:
24
25 ```zsh
26 source ~/.zshrc
27 ```
28
29 The install script creates symlinks from `~/.oh-my-zsh/custom/plugins/muse/` back into the repo, so the plugin stays up to date as you pull new Muse releases.
30
31 ---
32
33 ## Prompt Setup
34
35 ### Oh My ZSH (default theme)
36
37 Add `$(muse_prompt_info)` to your `$PROMPT` in `~/.zshrc`:
38
39 ```zsh
40 PROMPT='%~ $(muse_prompt_info) %# '
41 RPROMPT='$(muse_rprompt_info)'
42 ```
43
44 ### Powerlevel10k
45
46 Add `muse_vcs` to your prompt element arrays in `~/.p10k.zsh`:
47
48 ```zsh
49 POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(… muse_vcs …)
50 # or
51 POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(… muse_vcs muse_rprompt …)
52 ```
53
54 The plugin provides both `prompt_muse_vcs()` (async) and `instant_prompt_muse_vcs()` (instant prompt) so your prompt is never blank during p10k's async refresh.
55
56 ### What the prompt looks like
57
58 | State | Prompt |
59 |---|---|
60 | Clean, midi domain | `♪ midi:main ✓` |
61 | Dirty (3 changed paths) | `♪ midi:main ✗ 3Δ` |
62 | Mid-merge (2 conflicts) | `♪ midi:main ⚡ ← feature/exp (2 conflicts)` |
63 | Detached HEAD | `♪ midi:(detached:a1b2c3d4)` |
64 | Agent session active | `♪ midi:main ✗ 3Δ [🤖 claude-4.6-sonnet]` |
65 | `MUSE_AGENT_MODE=1` | `[midi\|main\|dirty:3\|no-merge]` |
66 | `MUSE_AGENT_MODE=1` + merge | `[midi\|main\|dirty:3\|merging:feature/exp:2]` |
67
68 The right-prompt segment shows the SemVer bump of the HEAD commit:
69
70 | SemVer | Right prompt |
71 |---|---|
72 | major | `[MAJOR]` (red) |
73 | minor | `[MINOR]` (yellow) |
74 | patch | `[PATCH]` (green) |
75
76 Domain icons are user-overridable:
77
78 ```zsh
79 MUSE_DOMAIN_ICONS[midi]="♩" # change just the midi icon
80 MUSE_DOMAIN_ICONS[genomics]="🔬" # add a new domain before it exists in core
81 ```
82
83 ---
84
85 ## Configuration
86
87 Set these in `~/.zshrc` **before** `plugins=(… muse …)`:
88
89 | Variable | Default | Effect |
90 |---|---|---|
91 | `MUSE_PROMPT_SHOW_DOMAIN` | `1` | Include domain name in prompt |
92 | `MUSE_PROMPT_SHOW_OPS` | `1` | Include dirty-path count (the `3Δ` indicator) |
93 | `MUSE_PROMPT_ICONS` | `1` | Use emoji icons; set to `0` for ASCII fallback |
94 | `MUSE_AGENT_MODE` | `0` | Machine-parseable mode (see Agent Mode below) |
95 | `MUSE_DIRTY_TIMEOUT` | `1` | Seconds before dirty check gives up (shows `?`) |
96 | `MUSE_SESSION_LOG_DIR` | `~/.muse/sessions` | Where session `.jsonl` logs are written |
97 | `MUSE_BIND_KEYS` | `1` | Bind `Ctrl+B` / `ESC-M` / `ESC-H` shortcuts |
98 | `MUSE_POST_COMMIT_CMD` | _(empty)_ | Shell command run after each `muse commit` |
99 | `MUSE_POST_CHECKOUT_CMD` | _(empty)_ | Shell command run after each `muse checkout` |
100 | `MUSE_POST_MERGE_CMD` | _(empty)_ | Shell command run after a clean `muse merge` |
101
102 **Example** — desktop notification on commit:
103
104 ```zsh
105 MUSE_POST_COMMIT_CMD='osascript -e "display notification \"Committed!\" with title \"Muse\""'
106 ```
107
108 ---
109
110 ## Aliases
111
112 All aliases use the `m` prefix to avoid collisions with system commands.
113
114 ### Core VCS
115
116 | Alias | Expands to |
117 |---|---|
118 | `mst` | `muse status` |
119 | `msts` | `muse status --short` |
120 | `mstp` | `muse status --porcelain` |
121 | `mcm` | `muse commit -m` |
122 | `mco` | `muse checkout` |
123 | `mlg` | `muse log` |
124 | `mlgo` | `muse log --oneline` |
125 | `mlgg` | `muse log --graph` |
126 | `mlggs` | `muse log --graph --oneline` |
127 | `mdf` | `muse diff` |
128 | `mdfst` | `muse diff --stat` |
129 | `mdfp` | `muse diff --patch` |
130 | `mbr` | `muse branch` |
131 | `mbrv` | `muse branch -v` |
132 | `msh` | `muse show` |
133 | `mbl` | `muse blame` |
134 | `mrl` | `muse reflog` |
135 | `mtg` | `muse tag` |
136
137 ### Stash
138
139 | Alias | Expands to |
140 |---|---|
141 | `msta` | `muse stash` |
142 | `mstap` | `muse stash pop` |
143 | `mstal` | `muse stash list` |
144 | `mstad` | `muse stash drop` |
145
146 ### Remotes
147
148 | Alias | Expands to |
149 |---|---|
150 | `mfh` | `muse fetch` |
151 | `mpull` | `muse pull` |
152 | `mpush` | `muse push` |
153 | `mrm` | `muse remote` |
154 | `mclone` | `muse clone` |
155
156 ### Domain & plumbing shortcuts
157
158 | Alias | Expands to |
159 |---|---|
160 | `mmidi` | `muse midi` |
161 | `mcode` | `muse code` |
162 | `mcoord` | `muse coord` |
163 | `mplumb` | `muse plumbing` |
164 | `mcfg` | `muse config` |
165 | `mhub` | `muse hub` |
166
167 ---
168
169 ## Workflow Functions
170
171 ### Branch management
172
173 ```zsh
174 muse-new-feat drums-pattern # creates and switches to feat/drums-pattern
175 muse-new-fix bad-velocity # creates and switches to fix/bad-velocity
176 muse-new-refactor engine-core # creates and switches to refactor/engine-core
177 ```
178
179 ### Commits
180
181 ```zsh
182 muse-wip # commit with auto-timestamp "[WIP] 2026-03-20T14:30:00Z"
183 muse-quick-commit # interactive guided commit (domain-aware metadata prompts)
184 muse-agent-commit "msg" # commit with agent session identity auto-injected
185 ```
186
187 ### Sync & merge
188
189 ```zsh
190 muse-sync # fetch + pull + status
191 muse-safe-merge feature/x # merge with conflict list + editor launch on failure
192 ```
193
194 ### Health & provenance
195
196 ```zsh
197 muse-health # repo health summary (dirty, merge, stashes, remotes)
198 muse-who-last # show HEAD commit author (human or agent + model)
199 muse-agent-blame 20 # show authorship breakdown for last 20 commits
200 muse-overview # domain-specific live state overview
201 ```
202
203 ---
204
205 ## Keybindings
206
207 | Key | Action |
208 |---|---|
209 | `Ctrl+B` | Open branch picker (fzf) |
210 | `ESC-M` | Open commit browser (fzf) |
211 | `ESC-H` | Show repo health summary |
212
213 Set `MUSE_BIND_KEYS=0` in `.zshrc` to disable all keybindings.
214
215 ---
216
217 ## Tab Completion
218
219 The plugin registers `_muse` as the completion function for the `muse` command.
220 Completions are provided for:
221
222 - All ~50 top-level commands with descriptions
223 - Branch names (`checkout`, `merge`, `branch -d`, …)
224 - Tag names (`tag create`, `tag -d`, …)
225 - Remote names (`push`, `pull`, `fetch`, `remote`, …)
226 - Short SHAs (`show`, `diff`, `reset`, `revert`, `cherry-pick`, …)
227 - Config key paths (`config get`, `config set`)
228 - All `plumbing` subcommands (12)
229 - All `midi` subcommands (25) with MIDI-specific descriptions
230 - All `code` subcommands (28) with code-analysis descriptions
231 - All `coord` subcommands (6)
232 - Common flags per command (`log`, `diff`, `commit`, `status`, …)
233
234 Branch, tag, and remote lookups read directly from `.muse/` — no subprocess.
235 File-argument completions (`midi notes <tab>`) use `muse plumbing ls-files`.
236
237 ---
238
239 ## Visual Tools (fzf optional)
240
241 Install [fzf](https://github.com/junegunn/fzf) to unlock the interactive tools:
242
243 ```zsh
244 muse-commit-browser # fzf over commit log; ↵=checkout, ctrl-d=diff, ctrl-y=copy SHA
245 muse-branch-picker # fzf over branch list; ↵=checkout, ctrl-d=delete
246 muse-stash-browser # fzf over stash list; ↵=pop, ctrl-d=drop
247 ```
248
249 Install [bat](https://github.com/sharkdp/bat) or [delta](https://github.com/dandavison/delta) for syntax-highlighted diff output:
250
251 ```zsh
252 muse-diff-preview # muse diff with bat/delta highlighting
253 muse-diff-preview feature/x # diff against a branch
254 ```
255
256 Graph and timeline visualisations work without fzf:
257
258 ```zsh
259 muse-graph # colorised commit graph (domain-themed, SemVer badges)
260 muse-timeline 30 # visual vertical timeline of last 30 commits
261 ```
262
263 ---
264
265 ## Agent Mode
266
267 Muse is built for AI agents as first-class authors. The plugin reflects this throughout.
268
269 ### Machine-readable prompt
270
271 ```zsh
272 export MUSE_AGENT_MODE=1
273 ```
274
275 Prompt becomes: `[midi|main|dirty:3|no-merge|agent:coding-assistant]`
276
277 All workflow functions emit JSON instead of human text. `$MUSE_CONTEXT_JSON` is emitted to stderr before every prompt so an orchestrating process can read it.
278
279 ### `$MUSE_CONTEXT_JSON`
280
281 Always set when inside a muse repo. Updated before every prompt. Format:
282
283 ```json
284 {
285 "schema_version": 1,
286 "domain": "midi",
287 "branch": "main",
288 "repo_root": "/path/to/project",
289 "dirty": true,
290 "dirty_count": 3,
291 "merging": false,
292 "merge_branch": null,
293 "conflict_count": 0,
294 "user_type": "human",
295 "agent_id": null,
296 "model_id": null,
297 "semver": "minor"
298 }
299 ```
300
301 Agents can read this without running any subcommands:
302
303 ```zsh
304 echo $MUSE_CONTEXT_JSON | python3 -m json.tool
305 ```
306
307 ### `muse-context`
308
309 Human-readable, TOML, or JSON context block designed for AI context injection:
310
311 ```zsh
312 muse-context # human-readable block
313 muse-context --json # pretty-printed JSON
314 muse-context --toml # TOML
315 muse-context --oneline # single-line summary: "midi:main dirty:3 commit:a1b2c3d4"
316 ```
317
318 ### Agent session management
319
320 ```zsh
321 # Begin a session — sets identity vars, starts JSONL audit log
322 muse-agent-session claude-4.6-sonnet coding-assistant
323
324 # Every muse commit in this shell now auto-injects agent_id + model_id
325 muse-agent-commit "Refactor velocity normalisation"
326 # equivalent to: muse commit -m "…" --agent-id coding-assistant --model-id claude-4.6-sonnet
327
328 # End the session
329 muse-agent-end
330 ```
331
332 ### Session logs
333
334 Every `muse` command run during an agent session is logged to a `.jsonl` file:
335
336 ```json
337 {"t":"2026-03-20T14:23:11Z","cmd":"muse commit -m refactor","cwd":"/proj","domain":"midi","branch":"feat/x","pid":1234}
338 {"t":"2026-03-20T14:23:11Z","event":"cmd_end","exit":0,"elapsed_ms":312}
339 ```
340
341 List and replay sessions:
342
343 ```zsh
344 muse-sessions # list recent sessions
345 muse-sessions ~/.muse/sessions/... # replay a session log
346 ```
347
348 ---
349
350 ## Dependencies
351
352 | Tool | Required | Purpose |
353 |---|---|---|
354 | `python3` | Yes | JSON/TOML parsing (always available — Muse requires it) |
355 | `fzf` | Optional | Interactive branch picker, commit browser, stash browser |
356 | `bat` | Optional | Syntax-highlighted diff preview |
357 | `delta` | Optional | Enhanced diff pager |
358 | ZSH 5.0+ | Yes | Associative arrays, `autoload -Uz`, `EPOCHSECONDS` |
359
360 ---
361
362 ## Starship users
363
364 Add a custom command to `~/.config/starship.toml`:
365
366 ```toml
367 [custom.muse]
368 command = "muse-context --oneline 2>/dev/null"
369 when = "test -d .muse || git rev-parse --git-dir 2>/dev/null | grep -q .muse"
370 shell = ["zsh", "-c"]
371 format = "[$output]($style) "
372 style = "bold magenta"
373 ```
374
375 This gives you the one-line context (`midi:main dirty:3 commit:a1b2c3d4`) in any Starship prompt.