gabriel / muse public
_muse
415 lines 15.9 KB
45033f17 feat: CLI polish — diff model, log colours, commit summary, push fix Gabriel Cardona <gabriel@tellurstori.com> 1d ago
1 #compdef muse
2 # Zsh completion for the Muse CLI.
3 #
4 # Installation (pick one):
5 # 1. Symlink into a directory already on $fpath:
6 # ln -sf /path/to/muse/completions/_muse ~/.zsh/completions/_muse
7 # 2. Oh-My-Zsh users — copy or symlink into the custom completions dir:
8 # ln -sf /path/to/muse/completions/_muse \
9 # ~/.oh-my-zsh/completions/_muse
10 # 3. Add the completions directory directly to $fpath in ~/.zshrc:
11 # fpath=(/path/to/muse/completions $fpath)
12 # autoload -Uz compinit && compinit
13 #
14 # After installing, reload completions:
15 # exec zsh OR autoload -Uz compinit && compinit -u
16
17 # ---------------------------------------------------------------------------
18 # Helpers
19 # ---------------------------------------------------------------------------
20
21 # Emit branch names from the nearest Muse repo, or nothing if not in one.
22 _muse_branches() {
23 local -a branches
24 if muse plumbing show-ref &>/dev/null; then
25 branches=(${(f)"$(muse plumbing show-ref 2>/dev/null \
26 | python3 -c \
27 'import sys,json; d=json.load(sys.stdin); [print(r["ref"].replace("refs/heads/","")) for r in d["refs"]]' \
28 2>/dev/null)"})
29 _describe 'branches' branches
30 fi
31 }
32
33 # Emit remote names from the Muse config.
34 _muse_remotes() {
35 local -a remotes
36 local cfg
37 cfg="$(muse remote 2>/dev/null | awk '{print $1}')"
38 if [[ -n $cfg ]]; then
39 remotes=(${(f)cfg})
40 _describe 'remotes' remotes
41 else
42 # Always offer the built-in special remotes.
43 _values 'remote' 'origin' 'local'
44 fi
45 }
46
47 # ---------------------------------------------------------------------------
48 # Command lists (kept in sync with muse/cli/app.py)
49 # ---------------------------------------------------------------------------
50
51 local -a _muse_top_cmds=(
52 'plumbing:Tier 1 machine-readable plumbing commands'
53 'init:Initialise a new Muse repository'
54 'status:Show working-tree drift against HEAD'
55 'log:Display commit history'
56 'commit:Record the current state as a new version'
57 'diff:Compare working tree against HEAD or two commits'
58 'show:Inspect a commit'
59 'branch:List, create, or delete branches'
60 'checkout:Switch branches or restore from a commit'
61 'merge:Three-way merge a branch into HEAD'
62 'reset:Move HEAD to a prior commit'
63 'revert:Undo a prior commit'
64 'cherry-pick:Apply a specific commit on top of HEAD'
65 'stash:Shelve uncommitted changes'
66 'tag:Attach and query semantic tags'
67 'push:Upload commits and objects to a remote'
68 'pull:Fetch from a remote and merge'
69 'fetch:Download commits from a remote'
70 'clone:Create a local copy of a remote repository'
71 'remote:Manage remote connections'
72 'auth:Identity management'
73 'hub:MuseHub fabric connection'
74 'config:Local repository configuration'
75 'domains:Domain plugin dashboard'
76 'attributes:Display .museattributes rules'
77 'annotate:Attach CRDT annotations to a commit'
78 'blame:Show per-line commit provenance'
79 'reflog:History of HEAD and branch-ref movements'
80 'rerere:Reuse recorded conflict resolutions'
81 'gc:Remove unreachable objects'
82 'archive:Export a historical snapshot'
83 'bisect:Binary search commit history'
84 'worktree:Manage multiple branch checkouts'
85 'workspace:Compose multiple Muse repositories'
86 'rebase:Replay commits onto a new base'
87 'clean:Remove untracked files'
88 'describe:Label a commit by its nearest tag'
89 'shortlog:Summarise history by author or agent'
90 'verify:Check repository integrity'
91 'snapshot:Explicit snapshot management'
92 'bundle:Pack commits into a portable bundle'
93 'content-grep:Search tracked file content'
94 'whoami:Show current identity'
95 'check:Run domain invariant checks'
96 'cat:Print a single tracked symbol'
97 'midi:MIDI domain semantic commands'
98 'code:Code domain semantic commands'
99 'coord:Multi-agent coordination commands'
100 )
101
102 local -a _muse_plumbing_cmds=(
103 'hash-object:SHA-256 a file and optionally store it'
104 'cat-object:Emit raw bytes of a stored object'
105 'rev-parse:Resolve branch or HEAD to a commit ID'
106 'ls-files:List tracked files and object IDs'
107 'read-commit:Emit full commit JSON'
108 'read-snapshot:Emit full snapshot JSON'
109 'commit-tree:Create a commit from an explicit snapshot ID'
110 'update-ref:Move a branch HEAD to a specific commit'
111 'commit-graph:Emit the commit DAG as JSON'
112 'pack-objects:Build a PackBundle to stdout'
113 'unpack-objects:Read a PackBundle from stdin'
114 'ls-remote:List remote branch heads'
115 'merge-base:Find the lowest common ancestor of two commits'
116 'snapshot-diff:Diff two snapshot manifests'
117 'domain-info:Inspect the active domain plugin'
118 'show-ref:List all refs and their commit IDs'
119 'check-ignore:Test paths against .museignore rules'
120 'check-attr:Query merge-strategy attributes for paths'
121 'verify-object:Re-hash stored objects to detect corruption'
122 'symbolic-ref:Read or write HEAD symbolic reference'
123 'for-each-ref:Iterate all refs with rich commit metadata'
124 'name-rev:Map commit IDs to descriptive names'
125 'check-ref-format:Validate branch or ref names'
126 'verify-pack:Verify the integrity of a PackBundle'
127 )
128
129 local -a _muse_midi_cmds=(
130 'notes:List notes in a MIDI track'
131 'note-log:Show note-level history'
132 'note-blame:Show per-note commit provenance'
133 'harmony:Analyse harmonic content'
134 'piano-roll:Render a piano-roll view'
135 'note-hotspots:Find most-changed note regions'
136 'velocity-profile:Plot velocity distribution'
137 'transpose:Shift pitches by semitones'
138 'mix:Merge MIDI tracks'
139 'query:Query note events'
140 'check:Run MIDI domain checks'
141 'rhythm:Analyse rhythmic patterns'
142 'scale:Detect active scales'
143 'contour:Analyse melodic contour'
144 'density:Compute note density over time'
145 'tension:Compute harmonic tension'
146 'cadence:Detect cadence points'
147 'motif:Find recurring motifs'
148 'voice-leading:Analyse voice-leading quality'
149 'instrumentation:List instrumentation per track'
150 'tempo:Display tempo map'
151 'compare:Compare two MIDI commits'
152 'quantize:Snap notes to a rhythmic grid'
153 'humanize:Add expressive timing variation'
154 'invert:Invert intervals around an axis'
155 'retrograde:Reverse note sequence'
156 'arpeggiate:Spread chords into arpeggios'
157 'normalize:Normalise velocity levels'
158 'shard:Split a MIDI file into shards'
159 'agent-map:Show which agents modified which notes'
160 'find-phrase:Search for a melodic phrase'
161 )
162
163 local -a _muse_code_cmds=(
164 'cat:Print a symbol'\''s source'
165 'symbols:List symbols in the snapshot'
166 'symbol-log:Show per-symbol commit history'
167 'detect-refactor:Detect renames and extractions'
168 'grep:Search symbol names and bodies'
169 'blame:Show per-symbol commit provenance'
170 'hotspots:Find most-changed symbols'
171 'stable:Find stable (rarely changed) symbols'
172 'coupling:Show frequently co-changed symbol pairs'
173 'compare:Compare two code commits'
174 'languages:List languages in the snapshot'
175 'patch:Apply a delta patch to symbols'
176 'query:Query the symbol graph'
177 'query-history:Query across commit history'
178 'deps:Show dependency graph'
179 'find-symbol:Search for a symbol by name'
180 'impact:Estimate change impact'
181 'dead:Find unreachable symbols'
182 'coverage:Show test coverage mapping'
183 'lineage:Trace a symbol'\''s ancestry'
184 'api-surface:Enumerate public API symbols'
185 'codemap:Render the module dependency map'
186 'clones:Detect duplicate code'
187 'checkout-symbol:Restore a symbol to a prior version'
188 'semantic-cherry-pick:Apply a symbol-level change'
189 'index:Rebuild the symbol index'
190 'breakage:Detect breaking changes'
191 'invariants:Run symbol invariant checks'
192 'add:Stage files for commit'
193 'reset:Unstage files'
194 'code-check:Run code-domain checks'
195 'code-query:Run a structured code query'
196 )
197
198 local -a _muse_coord_cmds=(
199 'reserve:Reserve a symbol for exclusive editing'
200 'intent:Declare editing intent'
201 'forecast:Forecast merge conflicts'
202 'plan-merge:Plan a coordinated merge'
203 'shard:Partition work across agents'
204 'reconcile:Reconcile diverged agent branches'
205 )
206
207 # ---------------------------------------------------------------------------
208 # Main dispatcher
209 # ---------------------------------------------------------------------------
210
211 _muse() {
212 local curcontext="$curcontext" state line
213 typeset -A opt_args
214
215 _arguments -C \
216 '(-h --help)'{-h,--help}'[Show help]' \
217 '(-V --version)'{-V,--version}'[Show version]' \
218 '1: :->command' \
219 '*:: :->args' \
220 && return 0
221
222 case $state in
223 command)
224 _describe 'muse commands' _muse_top_cmds
225 ;;
226
227 args)
228 case $words[1] in
229
230 # --- sub-namespaces -----------------------------------------
231 plumbing)
232 _arguments '1: :->sub' '*:: :->plumbing_args'
233 case $state in
234 sub) _describe 'plumbing commands' _muse_plumbing_cmds ;;
235 esac
236 ;;
237
238 midi)
239 _arguments '1: :->sub'
240 case $state in
241 sub) _describe 'midi commands' _muse_midi_cmds ;;
242 esac
243 ;;
244
245 code)
246 _arguments '1: :->sub' '*:: :->code_args'
247 case $state in
248 sub) _describe 'code commands' _muse_code_cmds ;;
249 code_args)
250 case $words[1] in
251 add|reset) _files ;;
252 esac
253 ;;
254 esac
255 ;;
256
257 coord)
258 _arguments '1: :->sub'
259 case $state in
260 sub) _describe 'coord commands' _muse_coord_cmds ;;
261 esac
262 ;;
263
264 # --- branch-aware commands -----------------------------------
265 checkout)
266 _arguments \
267 '(-b --branch)'{-b,--branch}'[Create new branch]:branch:_muse_branches' \
268 '(-f --force)'{-f,--force}'[Force checkout]' \
269 '1: :_muse_branches'
270 ;;
271
272 merge)
273 _arguments \
274 '--no-commit[Do not auto-commit after merge]' \
275 '--squash[Squash into a single commit]' \
276 '--strategy[Merge strategy]:strategy:(ours theirs union)' \
277 '1: :_muse_branches'
278 ;;
279
280 branch)
281 _arguments \
282 '(-d --delete)'{-d,--delete}'[Delete a branch]:branch:_muse_branches' \
283 '(-D --force-delete)'{-D,--force-delete}'[Force-delete a branch]:branch:_muse_branches' \
284 '(-m --move)'{-m,--move}'[Rename a branch]:branch:_muse_branches' \
285 '1:: :_muse_branches'
286 ;;
287
288 cherry-pick)
289 _arguments \
290 '(-n --no-commit)'{-n,--no-commit}'[Stage without committing]' \
291 '1: :_muse_branches'
292 ;;
293
294 rebase)
295 _arguments \
296 '--onto[New base branch]:branch:_muse_branches' \
297 '1: :_muse_branches'
298 ;;
299
300 # --- remote-aware commands -----------------------------------
301 push)
302 _arguments \
303 '(-b --branch)'{-b,--branch}'[Branch to push]:branch:_muse_branches' \
304 '(-u --set-upstream)'{-u,--set-upstream}'[Set upstream tracking]' \
305 '--force[Force push even if remote diverged]' \
306 '1:: :_muse_remotes' \
307 '2:: :_muse_branches'
308 ;;
309
310 pull)
311 _arguments \
312 '(-b --branch)'{-b,--branch}'[Branch to pull into]:branch:_muse_branches' \
313 '--rebase[Rebase instead of merge]' \
314 '--no-commit[Do not auto-commit after merge]' \
315 '1:: :_muse_remotes' \
316 '2:: :_muse_branches'
317 ;;
318
319 fetch)
320 _arguments \
321 '(-b --branch)'{-b,--branch}'[Specific branch to fetch]:branch:_muse_branches' \
322 '--all[Fetch from all configured remotes]' \
323 '1:: :_muse_remotes'
324 ;;
325
326 clone)
327 _arguments \
328 '(-b --branch)'{-b,--branch}'[Branch to check out after clone]:branch' \
329 '--name[Override repo directory name]:name' \
330 '1: :_urls'
331 ;;
332
333 # --- simple flag commands ------------------------------------
334 commit)
335 _arguments \
336 '(-m --message)'{-m,--message}'[Commit message]:message' \
337 '--allow-empty[Allow a commit with no changes]' \
338 '--sign[Sign the commit]' \
339 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)'
340 ;;
341
342 status)
343 _arguments \
344 '(-s --short)'{-s,--short}'[Condensed output]' \
345 '--porcelain[Machine-readable output]' \
346 '(-b --branch)'{-b,--branch}'[Show branch only]' \
347 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)'
348 ;;
349
350 log)
351 _arguments \
352 '(-n --max-count)'{-n,--max-count}'[Limit number of commits]:count' \
353 '--oneline[Compact one-line output]' \
354 '--graph[Show commit graph]' \
355 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)'
356 ;;
357
358 diff)
359 _arguments \
360 '--stat[Show diffstat summary]' \
361 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)' \
362 '1:: :_muse_branches' \
363 '2:: :_muse_branches'
364 ;;
365
366 show)
367 _arguments \
368 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)' \
369 '1:: :_muse_branches'
370 ;;
371
372 reset)
373 _arguments \
374 '--hard[Discard working tree changes]' \
375 '--soft[Keep working tree changes staged]' \
376 '1:: :_muse_branches'
377 ;;
378
379 tag)
380 _arguments \
381 '(-d --delete)'{-d,--delete}'[Delete a tag]' \
382 '(-l --list)'{-l,--list}'[List tags]' \
383 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)'
384 ;;
385
386 stash)
387 _arguments \
388 '1:: :(push pop list drop show apply)'
389 ;;
390
391 remote)
392 _arguments \
393 '1:: :(add remove list rename set-url show)'
394 ;;
395
396 auth)
397 _arguments \
398 '1:: :(login logout whoami)'
399 ;;
400
401 hub)
402 _arguments \
403 '1:: :(connect disconnect status ping)'
404 ;;
405
406 config)
407 _arguments \
408 '1:: :(show get set edit)'
409 ;;
410 esac
411 ;;
412 esac
413 }
414
415 _muse "$@"