# Muse Ecosystem — Agent Guide > Drop `@path/to/this/file` into any `CLAUDE.md` or agent system prompt for full ecosystem context. --- ## Three Repos, One Platform | Repo | Path | What it is | |------|------|------------| | **muse** | `~/ecosystem/muse` | VCS engine and CLI | | **musehub** | `~/ecosystem/musehub` | Remote server — pushes, issues, MCP tooling. `https://localhost:1337` | | **agentception** | `~/ecosystem/agentception` | Multi-agent orchestration. `http://localhost:10003` | All three live under `~/ecosystem/` as a `muse workspace`. When you change a muse CLI command, agentception callers may need updating. When you change a musehub API shape, agentception readers may need updating. --- ## No git. No GitHub. Ever. - Never run `git`, `gh`, or any git subcommand. - Never reference GitHub, GitHub Actions, or GitHub URLs. - **Muse and MuseHub are the only VCS tools.** - If you find a `git` or `gh` call anywhere — delete it in the same commit. No comment, no fallback. Delete it. --- ## Sub-Agents Must Use Muse Too Sub-agents start with no ecosystem knowledge. Include this in every sub-agent prompt: ``` IMPORTANT — this project uses Muse (not git) for version control. - Never run git, gh, or any git subcommand. - Repo paths: ~/ecosystem/muse, ~/ecosystem/musehub, ~/ecosystem/agentception - Use muse code grep / symbols / cat / impact / deps / hotspots / gravity / entangle before reading files directly. Every command accepts --json / -j. - Use muse -C ~/ecosystem/ when CWD differs from the target repo. ``` --- ## Muse Commands Every command accepts `--json`. Always use `--json` for structured reads. ### `-C` — cross-repo targeting ```bash muse -C ~/ecosystem/muse muse -C ~/ecosystem/musehub muse -C ~/ecosystem/agentception ``` `-C` does `os.chdir()` before dispatch — file paths resolve against the target repo root. Never omit it when your CWD is a different repo: ### `muse hub` — always needs repo context `muse hub` commands require a configured hub connection. Running them without `-C` (or from a repo without a remote) fails with "No hub connected." Always target a repo that has the hub wired up: ```bash # ❌ Wrong — no hub context muse hub repo list --json # ✅ Correct muse -C ~/ecosystem/musehub hub repo list --json ``` ```bash # ❌ Wrong — path resolves against CWD (wrong repo) muse code add musehub/services/musehub_wire.py # ✅ Correct muse -C ~/ecosystem/musehub code add musehub/services/musehub_wire.py muse -C ~/ecosystem/musehub commit -m "..." ``` ### `muse push` — check remotes exist before pushing Before pushing to a repo for the first time, verify remotes are configured: ```bash muse -C ~/ecosystem/ remote --json ``` If the named remote is not found, the error now lists what is configured: ``` ❌ Remote 'local' is not configured. Configured remotes: (none) Add one with: muse remote add local ``` No follow-up `muse remote --json` call needed — the answer is in the error. ### `muse push` — uses remote names, not `--hub` `--hub ` is **only valid on `muse hub` subcommands**. `muse push` always takes a named remote. Never mix the two patterns: ```bash # ❌ Wrong — --hub is not a push flag muse -C ~/ecosystem/maestro push --hub https://staging.musehub.ai local main # ✅ Correct — use the remote name muse -C ~/ecosystem/maestro push staging main muse -C ~/ecosystem/maestro push local main ``` To see which remotes are configured and their URLs: ```bash muse -C ~/ecosystem/ remote --json ``` `muse push` now also accepts `--hub ` as a convenience: it resolves the URL to its configured remote name automatically, so the wrong pattern is corrected rather than crashing. ### `muse hub` — targeting staging vs local By default `muse hub` targets the hub configured for the repo (usually `https://localhost:1337`). To target staging, pass `--hub https://staging.musehub.ai`: ```bash # local (default) muse -C ~/ecosystem/musehub hub repo list --json # staging muse -C ~/ecosystem/musehub hub repo list --hub https://staging.musehub.ai --json ``` ### `muse hub repo list` — exact flags `hub repo list` lists repos for the **authenticated user** only. It has NO `--owner` flag. Valid flags: `--limit N`, `--cursor CURSOR`, `--hub URL`, `--json`. Filter by owner or name in Python after fetching: ```bash muse -C ~/ecosystem/musehub hub repo list --limit 100 --json \ | python3 -c "import sys,json; [print(r['slug']) for r in json.load(sys.stdin)['repos'] if r['owner']=='gabriel']" ``` ### Never pipe `2>&1` into a JSON parser `2>&1 |` redirects stderr into the pipe. If the muse command fails, the error text lands in stdin and Python raises `JSONDecodeError: Expecting value` — hiding the real error. ```bash # ❌ Wrong — error text swallowed as fake JSON muse hub repo list --owner gabriel --json 2>&1 | python3 -c "json.load(sys.stdin)..." # ✅ Correct — check exit code first, or let stderr print to terminal muse -C ~/ecosystem/musehub hub repo list --json \ | python3 -c "import sys,json; [print(r['name']) for r in json.load(sys.stdin)['repos']]" ``` ### Core commands | Task | Command | |------|---------| | Status | `muse status --json` | | Diff working tree | `muse diff` | | Diff staged | `muse diff --staged` | | Stage additions/modifications | `muse code add ` / `muse code add .` | | Unstage | `muse code reset ` | | Remove file (disk + stage deletion) | `muse rm ` | | Untrack file (keep on disk) | `muse rm --cached ` | | Commit (agent — standard) | `muse commit -m "msg" --agent-id --model-id --sign` | | Commit (human — manual only) | `muse commit -m "message"` | | History | `muse log --json` | | Inspect commit | `muse read --json` | | Inspect commit + full manifest | `muse read --json --manifest` | | Branches | `muse branch --json` | | Create / switch | `muse checkout -b [--intent "..." --resumable]` / `muse checkout ` | | Delete branch | `muse branch -d ` | | Merge | `muse merge ` | | Dry-run merge | `muse merge --dry-run --json` | | Push | `muse push local dev` | | Pull | `muse pull ` | | Shelf / pop | `muse shelf save [-m "msg"]` / `muse shelf pop` | | Workspace status | `muse workspace status --json` | | Tag | `muse tag add "label" []` | | Release | `muse release add ` | ### `muse content-grep` — regex gotchas Uses Python `re` (ERE). Metacharacters `( ) . [ * + ? { } ^ $` must be escaped for literal matches: ```bash muse content-grep "session\.add\(obj_row\)" # ✅ escaped muse content-grep "session.add(obj_row)" # ❌ fails — ( opens a group ``` OR syntax: `muse content-grep "TODO|FIXME"` ### `muse content-grep` — JSON output shape ```python { "results": [ { "path": "src/main.py", # ← "path" — matches all other muse commands "object_id": "sha256:...", "match_count": 2, "matches": [ { "line_number": 42, "line": "matched line text", # ← "line", not "text" "context_before": [], "context_after": [] } ] } ] } ``` Iteration idiom: ```python for r in data["results"]: for m in r["matches"]: print(r["path"], m["line_number"], m["line"]) ``` --- ## Branch Flow ``` main ← production; tagged releases; never direct-pushed ↑ dev ← integration; latest deliverable state ↑ ↑ ↑ feat/* task/* bugfix/* ← short-lived; one atomic task; hours not days hotfix/* ← from main; merges into main AND dev experiment/* ← exploratory; time-boxed; promoted or deleted ``` **Never work directly on `dev` or `main`.** Branch first, always. ### Branch semantic flags Every agent branch should carry intent and resumability metadata. `--intent` and `--resumable` are accepted by both `muse checkout -b` (create + switch atomically) and `muse branch` (create or annotate only): ```bash # Create, annotate, and switch in one command — the canonical agent pattern muse -C ~/ecosystem/ checkout -b task/my-thing \ --intent "implement OAuth token rotation" \ --resumable # Annotate an existing branch (no switch) muse -C ~/ecosystem/ branch task/my-thing \ --intent "implement OAuth token rotation" \ --resumable # Discover all resumable branches (handoff discovery) muse -C ~/ecosystem/ branch --resumable --json # JSON listing always includes intent, resumable, created_by on every entry muse -C ~/ecosystem/ branch --json # → [{"name": "task/my-thing", "intent": "...", "resumable": true, "created_by": "claude-code", ...}] ``` **Why**: `--intent` lets any agent reading `branch --json` understand what each branch is for without inspecting commit history. `--resumable` marks branches as safe for another agent to pick up — use it for any task that may be interrupted. ### Standard cycle ```bash # Start — create, annotate, and switch in one command muse -C ~/ecosystem/ checkout dev muse -C ~/ecosystem/ checkout -b task/my-thing \ --intent "describe what this task does" \ --resumable # Work — always commit with full agent provenance muse code add . # stages new + modified + deleted tracked files muse commit -m "feat: ..." --agent-id claude-code --model-id claude-sonnet-4-6 --sign # Merge back muse -C ~/ecosystem/ checkout dev muse -C ~/ecosystem/ merge task/my-thing muse -C ~/ecosystem/ branch -d task/my-thing muse -C ~/ecosystem/ push local dev # When dev is ready for main muse -C ~/ecosystem/ checkout main muse -C ~/ecosystem/ merge dev muse -C ~/ecosystem/ push local main muse -C ~/ecosystem/ push local dev muse -C ~/ecosystem/ checkout dev ``` --- ## Harmony — Resolution Intelligence Harmony is Muse's conflict-resolution memory system — a three-tier intelligence layer: ``` Tier 1 — Policy declarative rule fires automatically on pattern match Tier 2 — Exact replay blob fingerprint matches a saved resolution Tier 3 — Semantic domain plugin similarity score ≥ threshold Tier 4 — Escalate create hub issue; flag for human or specialist agent ``` ### How Harmony learns The learning loop is automatic when `--harmony-autoupdate` is on (the default): ``` muse merge ← harmony auto-applies any saved resolutions conflicts that have no resolution → patterns recorded (future merges will try to replay them) # Resolve conflicts manually, then: muse commit -m "merge: ..." ← harmony records the outcome as a human-verified resolution (confidence=1.0) for every conflict path ``` ### Idiomatic harmony workflow ```bash # 1. Merge — harmony tries to auto-resolve using saved resolutions muse merge feature-x --json # ✔ [harmony] auto-resolved: config.py::MAX_CONNECTIONS ← replayed # CONFLICT: src/server.py::timeout ← new, no prior resolution # 2. Inspect what harmony knows muse harmony patterns --json # all saved conflict patterns muse harmony resolutions --json # all saved resolutions muse harmony audit --json # full tamper-evident action log # 3. Resolve remaining conflicts manually muse checkout --ours src/server.py # or --theirs, or edit manually muse code add src/server.py # 4. Commit — harmony automatically records the resolution muse commit -m "merge: resolve timeout conflict" \ --agent-id claude-code --model-id claude-sonnet-4-6 --sign # ✅ harmony: recorded resolution for 'src/server.py::timeout' # 5. Next time the same conflict recurs → auto-resolved without human input muse merge feature-y --json # ✔ [harmony] auto-resolved: src/server.py::timeout ``` ### Harmony storage layout ``` .muse/harmony/ patterns/ / pattern.json ← ConflictPattern (blob + semantic fingerprint) resolutions/ .json ← Resolution (outcome_blob, confidence, strategy) policies/ .json ← declarative Policy rules audit/ -.json ← append-only tamper-evident log escalations/ .json ← Tier 4 escalation records ``` ### Harmony CLI reference | Task | Command | |------|---------| | List all patterns | `muse harmony patterns --json` | | List resolutions for a pattern | `muse harmony resolutions --pattern-id --json` | | Show best resolution | `muse harmony best --pattern-id --json` | | Add a policy | `muse harmony policy-add --id --action prefer-ours --path-pattern "*.mid"` | | List policies | `muse harmony policies --json` | | View audit log | `muse harmony audit --json` | | Run the engine on a conflict | `muse harmony engine --json` | | GC stale unresolved patterns | `muse harmony gc --age-days 90 --json` | | Clear all patterns | `muse harmony clear --json` | | View escalations | `muse harmony escalations --json` | ### Pattern fingerprinting Two fingerprints identify each conflict: - **Blob fingerprint** — `SHA-256(sorted(ours_id, theirs_id))`. Exact-replay only; different content never matches. - **Semantic fingerprint** — provided by a `HarmonyPlugin` implementation. Enables cross-content replay: two conflicts with different blob IDs but the same semantic shape (e.g. the same musical phrase at different tempo) share one pattern and replay the same resolution. When a `HarmonyPlugin` is active and returns `semantic_fp != blob_fp`, the `pattern_id` is keyed on `semantic_fp` alone — enabling cross-content replay. Without a plugin, `semantic_fp == blob_fp` and the system degenerates to exact replay with full provenance. ### Key behaviours to remember - **Idempotent learning**: calling `record_resolutions` twice with the same `outcome_blob` produces exactly one resolution — no duplicates. - **Symbol-path aware**: conflict paths like `config.py::MAX_CONNECTIONS` are handled correctly — file portion used for manifest lookups, full address stored in the pattern. - **Original conflict paths preserved**: `checkout --ours/--theirs` clears `conflict_paths` in MERGE_STATE, but `original_conflict_paths` is preserved through all writes so `commit` always has the full list to learn from. - **Path traversal guard**: `auto_apply` resolves `..` before any filesystem access — tampered MERGE_STATE cannot escape the repo root. - **Human-verified wins**: `best_resolution` ranks by `(human_verified, confidence, applied_count)` descending — a human-verified resolution always beats an unverified one regardless of confidence score. --- ## Bundle — Off-Network Transfer Bundles are self-contained msgpack files carrying commits, snapshots, and objects. Use them to transfer repo slices over SSH, USB, or email — no network connection required. ### Agent decision chain Always follow this sequence before applying a bundle: ```bash # 1. What's in it? muse bundle inspect bundle.muse --json # → total_commits, branches map, per-commit message + agent_id # 2. Is it clean? muse bundle verify bundle.muse -q # → exit 0 = clean; exit 1 = corrupt; no output in -q mode # 3. What's new relative to my local repo? muse bundle diff bundle.muse --json # → new_commits, known_commits, refs_to_advance # 4. Apply safely (verify before any write) muse bundle unbundle bundle.muse --verify --json # → verified=true in JSON if integrity passed before writes ``` Skip step 4 if `new_commits == 0` — the repo is already up-to-date. Abort if step 2 exits 1 — the bundle is corrupt. ### Create ```bash muse bundle create repo.bundle --json # all of HEAD muse bundle create out.bundle feat/audio --json # specific branch muse bundle create out.bundle HEAD --have --json # incremental ``` ### Subcommand reference | Subcommand | Needs repo? | Purpose | |------------|-------------|---------| | `inspect` | No | Show commits + branch heads — no writes | | `verify` | No | Hash-check every object — no writes | | `list-heads` | No | Print branch → commit_id map | | `diff` | Yes | Show commits not yet in local repo | | `unbundle` | Yes | Apply bundle; `--verify` guards writes | | `create` | Yes | Pack commits into a bundle file | --- ## Deploy (MuseHub) Docker + ECR + AWS SSM. Always staging first. ```bash bash ~/ecosystem/musehub/deploy/push.sh staging bash ~/ecosystem/musehub/deploy/push.sh prod bash ~/ecosystem/musehub/deploy/push.sh staging prod # both in sequence IMAGE_TAG= bash ~/ecosystem/musehub/deploy/push.sh staging # rollback ``` Full details: `musehub/docs/infrastructure.md`. --- ## Auth — MSign (Ed25519) No passwords, no JWTs. Ed25519 key pairs. Keys in `~/.muse/identity.toml`. ```bash muse auth keygen --hub https://localhost:1337 muse auth register --hub https://localhost:1337 --handle muse auth whoami muse auth logout --hub https://localhost:1337 # decommission / key rotation ``` ### Mnemonic backup — critical `keygen` stores the BIP-39 mnemonic in the OS keychain and **never prints it to the terminal** (scrollback is not safe). Back it up immediately after keygen by piping from the keychain directly to your password manager — the mnemonic never touches the terminal display: ```bash # macOS — copies to clipboard; paste into 1Password / Bitwarden immediately security find-generic-password -s muse -a mnemonic -w | pbcopy # Linux secret-tool lookup service muse account mnemonic | xclip -selection clipboard ``` Losing the mnemonic means permanent loss of all derived keys. The keychain entry uses service=`muse`, account=`mnemonic`. ### Key rotation ```bash # Generate a fresh mnemonic and rotate to a new key (IRREVERSIBLE) muse auth keygen --hub https://localhost:1337 --force --destroy-mnemonic # Then back up the new mnemonic immediately (see above) ``` Push returns 404 ("Repository not found on remote")? The repo doesn't exist on MuseHub yet — create it via the API, then retry `muse push local`. Agentception injects keys into spawned agents via `MUSE_AGENT_KEY_FD` (pipe fd carrying 64-byte sub-seed) and `MUSE_AGENT_HANDLE` env vars. `get_signing_identity()` reads `MUSE_AGENT_KEY_FD` first, derives the Ed25519 key via SLIP-0010, then falls back to `~/.muse/identity.toml`. --- ## Cryptographic Value Codec — `muse.core.types` Every cryptographic value is **always canonically prefixed** — never a bare hex string or bare base64 blob. The prefix embeds the algorithm so the value is self-describing across storage, wire, and log output. ### Wire format ``` sha256:<64-hex> — content-addressed object / commit / snapshot ID ed25519: — Ed25519 signature or public key (no padding) mldsa65: — future post-quantum signature (reserved) ``` ### Utility functions (all in `muse.core.types`) | Need | Function | Returns | |------|----------|---------| | Object ID → `(algo, hex_str)` | `split_id(id)` | `("sha256", "<64-hex>")` | | Signature string → `(algo, b64_str)` | `split_sig(value)` | `("ed25519", "")` | | Public key string → `(algo, b64_str)` | `split_pubkey(value)` | `("ed25519", "")` | | Signature string → `(algo, raw_bytes)` | `decode_sig(value)` | `("ed25519", b"...")` | | Public key string → `(algo, raw_bytes)` | `decode_pubkey(value)` | `("ed25519", b"...")` | | Raw bytes → prefixed sig string | `encode_sig(algo, raw)` | `"ed25519:"` | | Raw bytes → prefixed pubkey string | `encode_pubkey(algo, raw)` | `"ed25519:"` | | Just the algo name | `sig_algo(value)` | `"ed25519"` or `""` | ### Rules - **Never strip prefixes manually** — no `removeprefix("ed25519:")`, no `[10:]`, no `partition(":")` inline. Use `split_sig` / `split_pubkey` / `split_id`. - **Never store or transmit bare bytes** — always encode with `encode_sig` / `encode_pubkey` before serialisation. - **`split_sig` vs `decode_sig`**: use `split_sig` when you need the base64 string (e.g. to pass to another API, embed in JSON, or validate format); use `decode_sig` only when you need raw bytes for cryptographic operations. - **`split_sig` vs `split_pubkey`**: semantically distinct — never pass a signature where a public key is expected. --- ## Agent Config One canonical source per level. IDE adapter files are derived outputs — never edit them by hand. ``` /.muse/agent.md — repo-specific rules /.muse/agent.md — shared rules inherited by all members ``` ### First-time setup ```bash # At the workspace root (if inside a workspace) muse -C ~/ecosystem agent-config init # At each member repo muse -C ~/ecosystem/ agent-config init # Choose which adapters you need (persists to .muse/config.toml) muse -C ~/ecosystem/ agent-config set --adapters claude,codex # Generate adapter files muse -C ~/ecosystem/ agent-config sync ``` ### Keeping adapters in sync After editing `.muse/agent.md`: ```bash muse agent-config sync --force # regenerate from updated source muse agent-config status # verify all adapters are in sync ``` ### Adapter files generated | Adapter | File | Style | |---------|------|-------| | `claude` | `CLAUDE.md` | `@include` reference | | `codex` | `AGENTS.md` | embedded content | | `cursor` | `.cursorrules` | embedded content | | `windsurf` | `.windsurfrules` | embedded content | Claude's adapter uses `@path` include syntax — it stays minimal and Claude resolves the content at read time. All others embed the full content inline. Inside a workspace, Claude's `CLAUDE.md` includes both levels: ``` @../.muse/agent.md ← workspace rules @.muse/agent.md ← repo-specific rules ``` ### Commands | Task | Command | |------|---------| | Create agent.md | `muse agent-config init [--force]` | | Generate adapters | `muse agent-config sync [--force] [--adapters a,b]` | | Set default adapters | `muse agent-config set --adapters claude,codex` | | Read content | `muse agent-config read [--scope repo\|workspace\|merged]` | | Check sync state | `muse agent-config status [--json]` | --- ## No Legacy. No Deprecated. No Exceptions. - **Delete on sight.** Dead code, deprecated shapes, backward-compat shims — delete in the same commit. - **No fallback paths.** The current shape is the only shape. - **No `# deprecated` annotations.** Delete it, don't annotate it. - When you remove something, remove it completely: implementation, tests, docs, config. --- ## Code Intelligence — Replace Your Reflexes **Before you grep or read a file, ask: which `muse code` command answers this?** ### Layered intel — three altitudes, one repo ``` Micro (symbol-level) grep · symbols · cat · find-symbol · symbol-log Meso (file-level) deps · impact · coverage · breakage Macro (repo-level) gravity · hotspots · entangle · dead · detect-refactor · velocity ``` Start at the altitude that matches the question. Never reach for a file read when a Micro command answers it. Never reach for Micro when a Macro command gives you the full picture in one call. ### Reflex replacement table | Old reflex | Muse command | |-----------|-------------| | `git ls-files` / `ls` / `find .` — list tracked files | `muse ls-files --json` | | `git ls-files src/` — list tracked files under a path | `muse ls-files --path-prefix src/ --json` | | `rg "FunctionName"` to find a declaration | `muse code grep "FunctionName" --json` | | Read raw file bytes | `muse cat file.py --json` | | Read file to find one function | `muse code cat "file.py::FunctionName" --json` | | `muse code cat "file.py"` (no `::`) | ❌ always errors — use `muse cat file.py` (file-level) or `muse code symbols --file file.py` (symbol list) | | Understand a file's structure | `muse code symbols --file path/to/file.py --json` | | Find a symbol across all branches | `muse code find-symbol "Name" --json` | | Map scope before a refactor | `muse code impact "file.py::Symbol" --json` | | Find all callers of a function | `muse code impact "file.py::Symbol" --json` | | Understand imports | `muse code deps "path/to/file.py" --json` | | Update one function body | `muse code patch "file.py::Symbol" --body /tmp/new.py` | | Dead-code hunt | `muse code dead --high-confidence-only --json` | | Check refactor safety | `muse code breakage --json` | | Run tests for what changed | `muse code test --json` | | Find the most unstable symbols | `muse code hotspots --json` | | Rank symbols by downstream blast radius | `muse code gravity --json` | | Find files that always change together | `muse code entangle --json` | | Detect latent refactor opportunities | `muse code detect-refactor --json` | | Measure test coverage at symbol level | `muse code semantic-test-coverage --json` | | Summarise repo activity over time | `muse code velocity --json` | | How much of a symbol's original code survives? | `muse code age --json` | | When was a symbol last fundamentally rewritten? | `muse code age --explain file.py::Fn --json` | | Generate an agent keypair | `muse agent keygen --json` | | List registered agents | `muse agent list --json` | | Register an agent identity | `muse agent register --handle --json` | | Create agent.md config | `muse agent-config init [--force] --json` | | Generate adapter files | `muse agent-config sync [--force] --json` | | Read merged agent config | `muse agent-config read --scope merged --json` | | Check adapter sync state | `muse agent-config status --json` | | Add inline annotation to a symbol | `muse annotate "file.py::Fn" --note "..." --json` | | List all annotations | `muse annotate list --json` | | Show API surface (public symbols) | `muse api-surface --json` | | API surface diff between refs | `muse api-surface --from v1.0 --to HEAD --json` | | Apply a unified diff .patch file | `muse apply my.patch --json` | | Apply a Muse .mpatch file | `muse apply-patch patch.mpatch --json` | | Export snapshot as tar.gz / zip | `muse archive --json` | | List .museattributes merge rules | `muse attributes list --json` | | Resolve strategy for a path | `muse attributes check src/foo.py --json` | | Validate .museattributes file | `muse attributes validate --json` | | Generate Ed25519 keypair | `muse auth keygen --hub --json` | | Register key with hub | `muse auth register --hub --handle --json` | | Show current identity | `muse auth whoami --json` | | Remove stored credentials | `muse auth logout --json` | | Recover key from mnemonic | `muse auth recover --hub --json` | | Rotate key to next HD index | `muse auth rotate --hub --json` | | Show full HD identity details | `muse auth show --json` | | Start a regression bisect | `muse bisect start --bad HEAD --good v1.0.0 --json` | | Automate bisect with a test command | `muse bisect run "pytest -x" --json` | | Mark current commit bad/good/skip | `muse bisect bad --json` / `muse bisect good --json` | | Show bisect session state | `muse bisect status --json` | | End bisect session | `muse bisect reset --json` | | Blame a symbol's change history | `muse blame "file.py::Symbol" --json` | | Rank symbols by blast-risk score | `muse code blast-risk --json` | | List / create / delete branches | `muse branch --json` / `muse branch -b feat/x --json` / `muse branch -d feat/x --json` | | Detect working-tree structural breakage | `muse code breakage --json` | | Create a portable bundle | `muse bundle create repo.bundle --json` | | Inspect bundle contents | `muse bundle inspect repo.bundle --json` | | Verify bundle integrity | `muse bundle verify repo.bundle --json` | | Show new commits in bundle | `muse bundle diff repo.bundle --json` | | Apply a bundle | `muse bundle unbundle repo.bundle --verify --json` | | List bundle branch heads | `muse bundle list-heads repo.bundle --json` | | Print one symbol's source | `muse code cat "file.py::Symbol" --json` | | Print all symbols in a file | `muse code cat "file.py" --all --json` | | Read a raw object by ID | `muse cat-object sha256: --json` | | Run domain invariant checks | `muse check --json` / `muse check --base HEAD~1 --json` | | Query merge-strategy attributes | `muse check-attr tracks/drums.mid --json` | | Test paths against ignore rules | `muse check-ignore build/ --json` | | Validate branch names | `muse check-ref-format feat/my-thing --json` | | Switch / create branch | `muse checkout dev --json` / `muse checkout -b task/x --intent "..." --resumable --json` | | Restore a symbol from history | `muse checkout-symbol "file.py::Fn" --commit HEAD~5 --json` | | Cherry-pick a commit | `muse cherry-pick --json` | | Remove untracked files | `muse clean --dry-run --json` / `muse clean --force --json` | | Clone a remote repository | `muse clone --json` | | Find duplicate symbols | `muse code clones --json` | | Enforce code invariant rules | `muse code check --json` | | Query commit history by predicate | `muse code query "symbol == 'X'" --json` | | Stage files for commit | `muse code add . --json` / `muse code reset --json` | | Repo semantic topology map | `muse code codemap --json` | | Create a commit | `muse commit -m "feat: X" --agent-id claude-code --model-id claude-sonnet-4-6 --sign --json` | | Walk commit DAG | `muse commit-graph --tip dev --stop-at main --json` | | Create commit from snapshot ID | `muse commit-tree sha256: -m "msg" --json` | | Symbol-level diff between refs | `muse code compare HEAD~10 HEAD --json` | | Read / get / set config | `muse config read --json` / `muse config get user.handle --json` / `muse config set user.type agent --json` | | List merge conflicts | `muse conflicts --json` | | Search file content | `muse content-grep "TODO\|FIXME" --json` | | Validate smart contract invariants | `muse contract check --json` / `muse contract list --json` | | GC expired coordination records | `muse coord gc --json` | | Recommend merge order / conflict hotspots | `muse coord reconcile --json` | | Release a reservation (mark done) | `muse coord release --run-id agent-42 --json` | | Release all reservations for a run | `muse coord release --all-for-run agent-42 --run-id agent-42 --json` | | Sync coordination state from remote | `muse coord sync --json` | | Enqueue a work item for agents | `muse coord enqueue "title" --run-id orch --json` | | Claim the next pending task | `muse coord claim --run-id agent-1 --json` / `muse coord claim --queue hotfix --run-id agent-1 --json` | | Mark a task completed | `muse coord complete --run-id agent-1 --json` | | Mark a task failed | `muse coord fail-task --run-id agent-1 --error "msg" --json` | | Cancel a pending or claimed task | `muse coord cancel-task --run-id orch --json` | | List tasks with filtering | `muse coord tasks --json` / `muse coord tasks --status pending --json` | | Line-level blame for any text file | `muse blame README.md --json` / `muse blame src/main.py --range 10-20 --json` | | Print raw file content | `muse cat file.py --json` / `muse cat file.py --at HEAD~5 --json` | | Count objects in the object store | `muse count-objects --json` / `muse count-objects --unreachable --json` | | Find co-changing file pairs | `muse code coupling --json` / `muse code coupling --file src/billing.py --json` | | Measure symbol-level test coverage | `muse code coverage --json` / `muse code coverage --symbol "file.py::Fn" --json` | | Inspect coordination DAG | `muse coord dag --json` / `muse coord dag --active-only --json` | | Find dead code candidates | `muse code dead --high-confidence-only --json` | | Show import / call graph | `muse code deps src/billing.py --json` / `muse code deps "file.py::Fn" --transitive --json` | | Label commit by nearest tag | `muse describe --json` / `muse describe --exact-match --json` | | Detect semantic refactoring events | `muse code detect-refactor --json` / `muse code detect-refactor --from v1.0.0 --to v2.0.0 --json` | | Show working-tree diff | `muse diff --json` / `muse diff --staged --json` / `muse diff HEAD~3 HEAD --json` | | Render / gate symbol documentation | `muse docs --json` / `muse docs --ci --json` / `muse docs --diff v1 v2 --json` | | Inspect active domain plugin | `muse domain-info --json` / `muse domain-info --all-domains --json` | | List registered domain plugins | `muse domains --json` | | Find entangled symbol pairs | `muse code entangle --json` / `muse code entangle --min-rate 0.8 --json` | | Download commits from a remote | `muse fetch local --json` / `muse fetch --all --json` | | Search all branches for a symbol | `muse code find-symbol --name validate_amount --json` / `muse code find-symbol --hash a3f2c9 --json` | | Iterate all branch refs | `muse for-each-ref --format json` / `muse for-each-ref --pattern "feat/*" --format json` | | Predict merge conflicts | `muse coord forecast --format json` / `muse coord forecast --branch feat/x --format json` | | Export commit as patch file | `muse format-patch --json` / `muse format-patch HEAD~3 --json` | | GC unreachable objects | `muse gc --json` / `muse gc --dry-run --json` / `muse gc --full --json` | | Compute structural gravity scores | `muse code gravity --json` / `muse code gravity --explain "file.py::Fn" --json` | | Search symbols by name | `muse code grep "validate" --json` / `muse code grep "compute.*" --regex --json` | | Manage harmony conflict patterns | `muse harmony patterns --format json` / `muse harmony audit --format json` | | Hash file or stdin content | `muse hash-object file.py --format json` / `echo x \| muse hash-object --stdin --format json` | | Refresh coordination heartbeat | `muse coord heartbeat --run-id agent-42 --format json` | | Show symbol churn leaderboard | `muse code hotspots --json` / `muse code hotspots --top 20 --json` | | Map blast radius for a symbol | `muse code impact "file.py::Symbol" --json` / `muse code impact "file.py::Fn" --reverse --json` | | Initialise a new Muse repository | `muse init --json` / `muse init --domain audio --json` | | Check architectural invariants | `muse code invariants --json` / `muse code invariants --strict --json` | | Show language breakdown by commit | `muse languages --json` / `muse languages HEAD~5 HEAD --json` | | Trace symbol lineage across commits | `muse code lineage "file.py::Symbol" --json` | | List active coordination sessions | `muse coord list --json` / `muse coord list --active-only --json` | | Walk commit history | `muse log --json` / `muse log -n 20 --branch feat/x --json` | | Inspect ref movement history | `muse reflog --json` / `muse reflog --branch dev --json` | | List all refs with a reflog | `muse reflog --all --json` | | List tracked files in snapshot | `muse ls-files --json` / `muse ls-files --path-prefix src/ --json` | | List branch heads on a remote | `muse ls-remote --json` / `muse ls-remote local --json` | | Inspect snapshot tree structure | `muse ls-tree --json` / `muse ls-tree -r HEAD --json` | | Run scheduled store maintenance | `muse maintenance run --all --json` / `muse maintenance status --json` | | Merge a branch into current | `muse merge feat/x --format json` / `muse merge feat/x --dry-run --format json` | | Find common ancestor of two commits | `muse merge-base dev feat/x --json` / `muse merge-base HEAD sha256: --json` | | Three-way merge without touching workdir | `muse merge-tree dev feat/x --json` / `muse merge-tree dev feat/x --write-objects --json` | | Rewrite commit DAG to v2 ID formula (+ optional re-sign) | `muse code migrate --dry-run --json` / `muse code migrate --sign --json` / `muse code migrate --force-resign --json` | | Rename a tracked file | `muse mv src/old.py src/new.py --json` / `muse mv src/old.py src/new.py --dry-run --json` | | Map commit IDs to branch-relative names | `muse name-rev sha256: --json` | | Render a symbol's life story | `muse code narrative "file.py::Symbol" --json` | | Build a pack bundle (dry-run) | `muse pack-objects HEAD --dry-run --json` | | Surgical symbol replacement | `muse code patch "file.py::Symbol" --body /tmp/new.py --json` | | Compute patch fingerprint | `muse patch-id --json` / `muse patch-id HEAD~3 --json` | | Dry-run plan a merge (conflict prediction) | `muse plan-merge feat/x --json` | | Predict merge risk between branches | `muse predict feat/x dev --json` | | GC dangling objects | `muse prune --json` / `muse prune --dry-run --json` | | Fetch from a remote | `muse pull local dev --json` | | Push branch to remote | `muse push local dev --json` | | Query commit history with predicates | `muse query "author == 'gabriel'" --json` | | Query symbol change history | `muse query-history "file.py::Fn" --json` | | Show diffs between two commit ranges | `muse range-diff main..feat/a main..feat/b --json` | | Inspect HEAD commit | `muse read --json` | | Inspect HEAD commit + full file list | `muse read --json --manifest` | | Inspect a specific commit | `muse read sha256: --json` | | Read a commit record by ID | `muse read-commit sha256: --json` | | Read a snapshot manifest | `muse read-snapshot sha256: --json` | | Replay commits onto a new base | `muse rebase main --json` / `muse rebase --squash main --json` | | Preview rebase commits | `muse rebase --dry-run main --json` | | Resume a paused rebase | `muse rebase --continue --json` / `muse rebase --abort --json` | | Inspect in-progress rebase | `muse rebase --status --json` | | Create a local release | `muse release add v1.2.0 --json` / `muse release add v1.3.0-beta.1 --channel beta --draft --json` | | List releases | `muse release list --json` / `muse release list --channel stable --json` | | Read a single release | `muse release read v1.2.0 --json` | | Infer next version from commit graph | `muse release suggest --json` / `muse release suggest --base v1.1.0 --json` | | Push a release to remote | `muse release push v1.2.0 --json` / `muse release push v1.2.0 --dry-run --json` | | Delete a release label | `muse release delete v1.2.0 --yes --json` / `muse release delete v1.2.0 --dry-run --json` | | List configured remotes | `muse remote --json` | | Add a remote | `muse remote add origin https://musehub.ai/user/repo --json` | | Get a remote's URL | `muse remote get-url origin --json` | | Update a remote's URL | `muse remote set-url origin https://... --json` | | Rename a remote | `muse remote rename origin upstream --json` | | Remove a remote | `muse remote remove origin --json` | | Check remote reachability | `muse remote status origin --json` | | AST-level symbol rename | `muse code rename billing.py::compute_total compute_invoice_total --json --yes` | | Preview rename without writing | `muse code rename billing.py::compute_total new_name --dry-run --json` | | Rename only the definition | `muse code rename billing.py::compute_total new_name --scope definition --json --yes` | | Reserve symbol addresses (advisory) | `muse coord reserve "billing.py::compute_total" --run-id agent-42 --json` | | Reserve with operation and TTL | `muse coord reserve "auth.py::validate" --run-id agent-42 --op modify --ttl 7200 --json` | | Reserve with dependency ordering | `muse coord reserve "billing.py::Fn" --run-id agent-B --depends-on --json` | | Soft reset (branch pointer only) | `muse reset HEAD~1 --json` | | Hard reset (branch + working tree) | `muse reset HEAD~1 --hard --json` | | Preview reset without writing | `muse reset HEAD~3 --dry-run --json` | | Restore working-tree file from HEAD | `muse restore a.py --json` | | Unstage a file (reset stage to HEAD) | `muse restore --staged a.py --json` | | Full restore: stage + working tree | `muse restore --staged --worktree a.py --json` | | Restore from an arbitrary ref | `muse restore --source HEAD~3 a.py b.py --json` | | Stream filtered commit IDs | `muse rev-list HEAD --json` / `muse rev-list -n 10 HEAD --json` | | Count commits in a range | `muse rev-list --count main..feat --json` | | Filter by author or date | `muse rev-list --author alice --after 2026-01-01 HEAD --json` | | Resolve ref to full commit ID | `muse rev-parse HEAD --json` / `muse rev-parse main --json` | | Get current branch name | `muse rev-parse --abbrev-ref HEAD --json` | | Revert a commit (creates new commit) | `muse revert HEAD --json` | | Revert to working tree only (no commit) | `muse revert HEAD --no-commit --json` | | Preview revert without writing | `muse revert HEAD --dry-run --json` | | Remove file from tracking + disk | `muse rm song.txt --json` | | Untrack file (keep on disk) | `muse rm --cached compiled/app.css --json` | | Recursive untrack of directory | `muse rm -r --cached build/ --json` | | Cherry-pick a symbol from a commit | `muse code semantic-cherry-pick "src/billing.py::compute_total" --from abc123 --json` | | Cherry-pick multiple symbols | `muse code semantic-cherry-pick "src/auth.py::validate_token" "src/auth.py::refresh_token" --from feat --json` | | Preview semantic cherry-pick | `muse code semantic-cherry-pick "src/core.py::Fn" --from HEAD~5 --dry-run --json` | | Static symbol-level test coverage | `muse code semantic-test-coverage --json` | | Coverage for one file | `muse code semantic-test-coverage --file billing.py --json` | | Show only uncovered symbols | `muse code semantic-test-coverage --uncovered-only --json` | | CI coverage gate | `muse code semantic-test-coverage --min-coverage 80 --json` | | Partition codebase into work zones | `muse coord shard --agents 4 --json` | | Shard for a specific language | `muse coord shard --agents 4 --language Python --json` | | Shard at a historical commit | `muse coord shard --agents 8 --commit HEAD~10 --json` | | Save working-tree checkpoint | `muse shelf save --json` / `muse shelf save name --intent-type handoff -m "desc" --json` | | List all shelf entries | `muse shelf list --json` / `muse shelf list --resumable --json` | | Inspect a shelf entry | `muse shelf read --json` / `muse shelf read name --json` | | Preview what a shelf apply would change | `muse shelf diff --json` / `muse shelf diff name --json` | | Restore shelf entry (keep entry) | `muse shelf apply --json` / `muse shelf apply name --json` | | Restore shelf entry and remove it | `muse shelf pop --json` / `muse shelf pop name --json` | | Discard a shelf entry | `muse shelf drop --json` / `muse shelf drop name --json` | | Commit summary by author | `muse shortlog --json` / `muse shortlog --numbered --json` | | Commit summary by agent | `muse shortlog --group-by agent --json` | | Commit summary by model | `muse shortlog --group-by model --numbered --json` | | List all branch refs | `muse show-ref --json` / `muse show-ref --pattern 'refs/heads/task/*' --json` | | Check if a ref exists | `muse show-ref --verify refs/heads/feat/my-task --json` | | Show HEAD ref | `muse show-ref --head --json` | | Count all branches | `muse show-ref --count --json` | | Produce an MSign Authorization header | `muse sign header --method POST --path /owner/repo/push --hub URL --json` | | Verify an MSign header | `muse sign verify --header 'MSign ...' --method POST --url URL --public-key-b64 KEY --json` | | Sign and execute an HTTP request | `muse sign request --method POST --url URL --body-file payload.json --json` | | Sign an MPay micropayment | `muse sign payment --from alice --to bob --amount 1000000 --nonce HEX --json` | | Capture working-tree checkpoint | `muse snapshot create --json` / `muse snapshot create -m "before refactor" --json` | | List all snapshots | `muse snapshot list --json` / `muse snapshot list -n 5 --json` | | Inspect a snapshot manifest | `muse snapshot read sha256:abc123 --json` | | Export snapshot as archive | `muse snapshot export sha256:abc123 --json` / `muse snapshot export sha256:abc123 -f zip -o out.zip --json` | | Diff two snapshots | `muse snapshot-diff main dev --json` / `muse snapshot-diff sha256:abc sha256:def --json` | | Diff — only added files | `muse snapshot-diff main dev --only added --json` | | Diff — scope to subdirectory | `muse snapshot-diff main dev --path-prefix src/ --json` | | Attach a tag to a commit | `muse tag add emotion:joyful --json` / `muse tag add section:chorus HEAD --json` | | List all tags | `muse tag list --json` / `muse tag list --match 'emotion:*' --json` | | Remove a tag | `muse tag remove emotion:joyful --json` | | List all symbols in a file | `muse code symbols --file src/utils.py --json` | | List symbols by kind | `muse code symbols --kind function --json` | | Read HEAD symbolic ref | `muse symbolic-ref HEAD --json` | | Point HEAD at a branch | `muse symbolic-ref HEAD --set main --json` | | Track a symbol's full lifecycle | `muse code symbol-log "file.py::Fn" --json` | | Symbol log since a tag | `muse code symbol-log "file.py::Fn" --from v1.0.0 --json` | | Switch to existing branch | `muse switch feat --json` | | Create and switch (with intent) | `muse switch -c task/x --intent "implement X" --resumable --json` | | Return to previous branch | `muse switch - --json` | | Working-tree status | `muse status --json` / `muse status --exit-code --json` | | Branch + upstream info only | `muse status --branch --json` | | Find most stable (unchanged) symbols | `muse code stable --json` / `muse code stable --top 20 --json` | | Stable symbols since a release | `muse code stable --since v2.0.0 --json` | | Enable sparse-checkout (cone mode) | `muse sparse-checkout init --json` | | Enable sparse-checkout (glob mode) | `muse sparse-checkout init --no-cone --json` | | Replace active pattern list | `muse sparse-checkout set 'src/' 'tests/' --json` | | Append patterns to sparse config | `muse sparse-checkout add 'docs/' --json` | | List active patterns | `muse sparse-checkout list --json` | | Count matching vs. excluded files | `muse sparse-checkout stats --json` | | Disable sparse-checkout | `muse sparse-checkout disable --json` | | Type-health report for HEAD | `muse code type --json` | | Trace Any-annotation blast radius | `muse code type --any-blast-radius billing.py::compute --json` | | Type coverage trend over commits | `muse code type --drift --json` | | Rank untyped symbols by typing ROI | `muse code type --migration-targets --top 10 --json` | | Type-signature diff since a ref | `muse code type --diff HEAD~5 --json` | | Run tests for changed files | `muse code test --json` | | Run one test file | `python3 -m pytest tests/test_foo.py -q --tb=short` | | List trusted paths | `muse trust list --json` | | Add a trusted path | `muse trust add /path/to/repo --json` | | Remove a trusted path | `muse trust remove /path/to/repo --json` | | List trusted hub fingerprints | `muse trust hub-list --json` | | Reset a hub fingerprint | `muse trust hub-reset hostname --json` | | Unpack a MPack from stdin | `muse unpack-objects --json` | | Move a branch HEAD (low-level) | `muse update-ref main sha256: --json` | | Compare-and-swap branch update | `muse update-ref main sha256: --old-value sha256: --json` | | Symbol growth rate by module | `muse code velocity --json` | | Whole-repo integrity check | `muse verify --json` / `muse verify --no-objects --json` | | Verify Ed25519 commit signatures | `muse verify-commit HEAD --json` | | Verify stored object integrity | `muse verify-object --all --json` | | Verify a MPack | `muse verify-pack --file bundle.muse --json` | | Verify tag signatures | `muse verify-tag v1.0 --json` | | Stream coordination events | `muse coord watch --json` / `muse coord watch --once --json` | | Add workspace member | `muse workspace add core https://musehub.ai/acme/core --json` | | List workspace members | `muse workspace list --json` | | Workspace member status | `muse workspace status --json` | | Remove workspace member | `muse workspace remove core --json` | | Sync workspace members | `muse workspace sync --workers 8 --json` | | List worktrees | `muse worktree list --json` | | Create linked worktree | `muse worktree add feat-x feat/x --json` | | Worktree status | `muse worktree status feat-x --json` | | Remove a worktree | `muse worktree remove feat-x --json` | | Prune stale worktree records | `muse worktree prune --json` | | Repair worktree paths | `muse worktree repair --json` | | Rebuild code intelligence indexes | `muse code index rebuild --json` | | Index rebuild dry-run | `muse code index rebuild --dry-run --json` | | Index status | `muse code index status --json` | | Purge indexes | `muse code index purge --json` | ### Trigger phrases → commands When you find yourself thinking this… run this instead. | Thought | Command | |---------|---------| | "Let me read the whole file to understand it" | `muse code symbols --file f.py --json` → then `muse code cat "f.py::X" --json` for the symbol you need | | "Where is this function defined?" | `muse code grep "FunctionName" --json` | | "I wonder which branch has the latest version" | `muse code find-symbol "Name" --json` | | "What would break if I change this?" | `muse code impact "file.py::Symbol" --json` | | "What does this file import?" | `muse code deps "file.py" --json` | | "Which functions change most often?" | `muse code hotspots --top 10 --json` | | "What is the most dangerous symbol to touch?" | `muse code gravity --top 1 --json` | | "Are these two files suspiciously coupled?" | `muse code entangle --json` | | "Is there dead code I can delete?" | `muse code dead --high-confidence-only --json` | | "What tests cover this symbol?" | `muse code semantic-test-coverage --json` | | "Is it safe to commit?" | `muse code breakage --json && muse code test --json` | ### Eight questions, eight commands — do not confuse them - **`muse code grep "X"`** — find symbols whose **name** matches X (declarations only) - **`muse code find-symbol "X"`** — same, but searches **across all branches** (multi-branch discovery) - **`muse code impact "file.py::X"`** — find everything that **calls or imports** X (blast radius) - **`muse code deps "file.py"`** — find what **file.py imports** (outbound dependency graph) - **`muse code hotspots`** — find symbols that **change most often** (churn leaderboard) - **`muse code gravity`** — find symbols with the **largest downstream blast radius** (change risk) - **`muse code entangle`** — find **file pairs** that always change together (hidden coupling) - **`muse code dead`** — find symbols that are **never called** (safe to delete) ### Task-typed rituals **Before modifying a symbol** ```bash muse code grep "SymbolName" --json # confirm declaration location muse code cat "file.py::Symbol" --json # read the current body muse code impact "file.py::Symbol" --json # map blast radius muse code semantic-test-coverage --json # what tests already cover it? ``` **Before a refactor** ```bash muse code gravity --top 20 --json # which symbols carry the most risk? muse code hotspots --top 20 --json # which symbols are most volatile? muse code entangle --json # which files move together? muse code deps "file.py" --json # outbound dependency map muse code breakage --json # current structural health ``` **Before deleting a symbol or file** ```bash muse code impact "file.py::Symbol" --json # blast radius — anything still calls it? muse code dead --high-confidence-only --json # confirm dead-code classification ``` **Before merging / releasing** ```bash muse code breakage --json # structural safety gate muse code test --json # tests for what changed muse code hotspots --top 5 --json # flag high-churn symbols for review ``` ### `muse read --json` — what the output contains `muse read --json` gives commit metadata and a file-level diff (`files_added`, `files_modified`, `files_removed`). It does **not** include the full snapshot manifest by default. To get the complete path → object_id map for every tracked file at that commit, add `--manifest`: ```bash muse read --json --manifest # HEAD muse read --json --manifest # any commit or branch tip ``` The `manifest` key is absent unless `--manifest` is given — default JSON stays compact. ### `muse cat` vs `muse code cat` — two different commands | Command | Level | Use for | |---------|-------|---------| | `muse cat file.py --json` | File-level | Raw file bytes — any domain | | `muse code cat "file.py::Symbol" --json` | Symbol-level | One function/class body | | `muse code cat "file.py" --all --json` | Symbol-level | All symbols in a file | `muse cat` accepts `--at ` for historical reads. `muse code cat` accepts `--at` too. --- ## Gitism Glossary Every wrong pattern on the left is burned into agent training data from Git. ### JSON key names | Git term / wrong key | Muse JSON key | Location | |----------------------|--------------|----------| | `sha` / `hash` / `id` | `commit_id` | everywhere | | `msg` / `commit_message` | `message` | `muse log`, `muse read` | | `date` / `timestamp` / `time` | `committed_at` | `muse log`, `muse read` | | `parent` | `parent_commit_id` | `muse log`, `muse read` | | `entries` / `log` / `data` | `commits` | `muse log` | | `active` / `checked_out` | `current` | `muse branch` | | `branch_name` | `name` | `muse branch` list entries | | `index` as integer | string keys `"1"`, `"2"` | `muse code impact` `blast_radius` | | `callers` / `caller_list` | `blast_radius["1"]` | `muse code impact` | | `coverage` | `coverage_pct` | `muse code semantic-test-coverage` | | `churn` | `changes` | `muse code hotspots` | | `score` / `risk_score` | `gravity_pct` | `muse code gravity` | | `files` (combined) | `added` + `modified` + `deleted` | `muse diff`, `muse status` | | `muse log` top-level | `{ "truncated": bool, "commits": [...] }` | `muse log --json` | | `muse branch` top-level | a list — no wrapper key | `muse branch --json` | | `muse hub repo list` top-level | `{ "total": N, "next_cursor": null, "repos": [...] }` | `muse hub repo list --json` | | `blast_radius` key type | strings `"1"` `"2"` — not integers | `muse code impact` | ### Deletion muscle memory — `git rm` → `muse rm` Git has two patterns for staging a file deletion. Both have exact Muse equivalents: | Git reflex | Muse equivalent | Effect | |-----------|----------------|--------| | `git rm ` | `muse rm ` | delete from disk **and** stage deletion | | `git rm --cached ` | `muse rm --cached ` | stage deletion only (keep on disk) | | `git rm -r ` | `muse rm -r ` | recursive — required for directories | | `git add ` | `muse code add ` | stage deletion of already-deleted file | | `git add -u` | `muse code add -u` | stage all tracked changes incl. deletions | | `git add .` | `muse code add .` | stage all tracked changes incl. deletions | The wrong reflex that burns agents: reaching for `muse code add --deleted` (flag doesn't exist) or `muse code reset ` (that **unstages** — the opposite of what you want). **Rule**: deleting a file in a task? Use `muse rm ` — it does the `rm` and stages the deletion in one step. `muse code add ` also works if the file is already gone from disk, but `muse rm` is clearer intent. ### `muse status --json` — always the same shape The schema is **identical** regardless of domain or staging state. Every key is always present — no `dict.get` guards needed. ```json { "branch": "dev", "head_commit": "sha256:abc…", "upstream": null, "ahead": null, "behind": null, "clean": true, "dirty": false, "total_changes": 0, "untracked_count": 0, "added": [], "modified": [], "deleted": [], "renamed": {}, "staged": {"added": [], "modified": [], "deleted": []}, "unstaged": {"added": [], "modified": [], "deleted": []}, "untracked": [], "conflict_paths": [], "merge_in_progress": false, "merge_from": null, "conflict_count": 0, "checkout_interrupted": false, "checkout_target": null } ``` Key rules: - `added` / `modified` / `deleted` — flat union of staged + unstaged. Primary interface for "what changed". - `staged` / `unstaged` — `{added, modified, deleted}` sub-objects for staging detail. `null` for domains with no staging concept (non-code domains). - `untracked` — files on disk not tracked by Muse. Non-empty list makes `clean=false`. - `untracked_count` — `len(untracked)`. Use this when you need to distinguish "only untracked files" (`total_changes == 0` and `untracked_count > 0`) from "tracked changes" (`total_changes > 0`). Do not check `dirty` alone for this. - `total_changes` — counts only tracked-file changes (`len(added) + len(modified) + len(deleted) + len(renamed)`). It is **not** a count of all dirtiness — `total_changes == 0` with `dirty == true` means only untracked files are present. - `clean` — `true` only when no staged changes, no unstaged changes, **and no untracked files**. Matches git: "untracked files present" is not a clean working tree. - `dirty` — always `not clean`. Git muscle-memory traps for `muse status --json`: | Git reflex | What Muse actually has | |-----------|------------------------| | `data["index"]` or `data["worktree"]` (git status --porcelain=v2) | `data["staged"]` / `data["unstaged"]` | | `"untracked" in data` as a flag | `data["untracked"]` is always a list | | `data["staged"]` is a path→object map | `data["staged"]` is `{added, modified, deleted}` lists | | `dirty` means only tracked-content changes | `dirty` is also `true` when untracked files exist | ### Hub command shape — noun then verb, not verb-noun Git flattens everything to `git ` or `gh -`. Muse uses `muse hub `. The wrong reflex produces commands that don't exist. | Wrong reflex (git/gh pattern) | Correct Muse command | |-------------------------------|----------------------| | `muse hub delete-repo` | `muse hub repo delete` | | `muse hub create-repo` | `muse hub repo create` | | `muse hub list-repos` | `muse hub repo list` | | `muse hub show-repo` | `muse hub repo read` | | `muse hub get-repo` | `muse hub repo read` | | `muse hub update-repo` | `muse hub repo update` | | `muse hub transfer-repo` | `muse hub repo transfer-ownership` | | `muse hub create-issue` | `muse hub issue create` | | `muse hub list-issues` | `muse hub issue list` | | `muse hub show-issue` | `muse hub issue read` | | `muse hub get-issue` | `muse hub issue read` | | `muse hub close-issue` | `muse hub issue update --status closed` | | `muse hub reopen-issue` | `muse hub issue update --status open` | | `muse hub comment-issue` | `muse hub issue comment --body "..."` | | `muse hub assign-issue` | `muse hub issue assign --assignee ` | | `muse hub label-issue` | `muse hub issue label --set