# 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. List remaining conflicts muse conflicts --json # → [{path: "src/server.py::timeout", kind: "symbol"}] # 4. Read the conflicted file — understand BOTH sides before touching anything # Conflict markers show three versions: # <<<<<<< ours [modified] ← what your branch has # (ours content) # ||||||| base ← common ancestor (what both started from) # (base content) # ======= theirs [modified] ← what the incoming branch has # (theirs content) # >>>>>>> end conflict # # Understand WHY each side changed what it did. # Never blindly pick --ours or --theirs — that silently discards real work. # 5. Manually edit the file to produce the correct merged result # (incorporate the intent of BOTH sides, not just one) # 6. Mark resolved — this stages the file and clears it from the conflict list muse resolve src/server.py::timeout --json # or to resolve all at once: muse resolve --all --json # 7. 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' # 8. Next time the same conflict recurs → auto-resolved without human input muse merge feature-y --json # ✔ [harmony] auto-resolved: src/server.py::timeout ``` ### ⚠️ Never blindly pick --ours or --theirs `muse checkout --ours ` and `muse checkout --theirs ` exist for when you have verified that one side is entirely correct and the other is entirely wrong. In practice this is rare. Using them without reading both sides discards real work. **The safe pattern for every conflict:** 1. `muse conflicts --json` — see what needs resolving 2. Read the file — understand `<<<<<<< ours`, `||||||| base`, `>>>>>>> theirs` 3. Edit the file manually to produce the correct result 4. `muse resolve ` — mark resolved (stages automatically) 5. `muse commit` — complete the merge **Only use `--ours` / `--theirs` when:** - You have read both sides and confirmed one is entirely superseded - You are deliberately reverting one branch's changes to a specific file - The conflict is in generated/derived content that should always come from one side ### 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 # Once — globally, across every repo on this machine (like ~/.gitconfig). # Survives branch switches and merges. Never needs to be repeated. muse agent-config set --global --adapters claude # At the workspace root (if inside a workspace) muse -C ~/ecosystem agent-config init # At each member repo muse -C ~/ecosystem/ agent-config init # Generate adapter files (uses the global config set above) muse -C ~/ecosystem/ agent-config sync ``` `--global` writes to `~/.muse/config.toml`. Without `--global`, the setting goes into the repo's `.muse/config.toml` and only applies to that repo. The repo-level setting takes priority over the global setting when both exist. ### 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 ``` `sync` requires adapter configuration (global or repo-level). It exits with an error if neither source has an `[agent-config]` section — no silent "generate everything" fallback. ### 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]` | | Set adapters globally (once) | `muse agent-config set --global --adapters claude` | | Set adapters for this repo only | `muse agent-config set --adapters claude,codex` | | Generate adapters | `muse agent-config sync [--force] [--adapters a,b]` | | 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` | | Set adapters globally (once, all repos) | `muse agent-config set --global --adapters claude --json` | | Set adapters for this repo | `muse agent-config set --adapters claude,codex --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