# 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. `http://localhost:10003` | | **agentception** | `~/ecosystem/agentception` | Multi-agent orchestration. `http://localhost:1337` | 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 / cat / impact / deps before reading files directly. - 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 hub` — targeting staging vs local By default `muse hub` targets the hub configured for the repo (usually `http://localhost:10003`). 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 / unstage | `muse code add ` / `muse code reset ` | | Commit | `muse commit -m "message"` | | Commit with provenance | `muse commit -m "msg" --agent-id --model-id --sign` | | History | `muse log --json` | | Inspect commit | `muse show --json` | | Branches | `muse branch --json` | | Create / switch | `muse checkout -b ` / `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 ` | | Stash / pop | `muse stash [-m "msg"]` / `muse stash 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"` --- ## 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. ### Standard cycle ```bash # Start muse -C ~/ecosystem/ checkout dev muse -C ~/ecosystem/ checkout -b task/my-thing # Work muse code add . muse commit -m "feat: ..." # 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 ``` --- ## 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 http://localhost:10003 muse auth register --hub http://localhost:10003 --handle muse auth whoami muse auth logout --hub http://localhost:10003 # decommission / key rotation ``` 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` and `MUSE_AGENT_HANDLE` env vars. `get_signing_identity()` in `muse/cli/config.py` checks `MUSE_AGENT_KEY` before `~/.muse/identity.toml`. --- ## 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` | | Show content | `muse agent-config show [--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?** | Old reflex | Muse command | |-----------|-------------| | `rg "FunctionName"` to find a declaration | `muse code grep "FunctionName" --json` | | Read file to find one function | `muse code cat "file.py::FunctionName" --json` | | `muse code cat "file.py"` (no `::`) | ❌ always errors — use `muse code symbols --file file.py` | | Understand a file's structure | `muse code symbols --file path/to/file.py --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` | ### Three questions, three commands — do not confuse them - **`muse code grep "X"`** — find symbols whose **name** matches X (declarations) - **`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** (dependency graph) ### Pre-task ritual ```bash muse code symbols --file path/to/file.py --json # understand structure muse code cat "file.py::Symbol" --json # read one symbol muse code impact "file.py::Symbol" --json # map blast radius before touching anything muse code breakage --json # structural safety check ``` --- ## 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 | |----------------------|--------------|----------| | `untracked` | `added` | `muse status` | | `sha` / `hash` / `id` | `commit_id` | everywhere | | `msg` / `commit_message` | `message` | `muse log`, `muse show` | | `date` / `timestamp` / `time` | `committed_at` | `muse log`, `muse show` | | `parent` | `parent_commit_id` | `muse log`, `muse show` | | `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` | ### 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 show` | | `muse hub update-repo` | `muse hub repo update` | | `muse hub create-issue` | `muse hub issue create` | | `muse hub list-issues` | `muse hub issue list` | | `muse hub close-issue` | `muse hub issue update --status closed` | | `muse hub create-proposal` | `muse hub proposal create` | | `muse hub merge-proposal` | `muse hub proposal merge` | | `muse hub list-proposals` | `muse hub proposal list` | | `muse hub add-label` | `muse hub label create` | | `muse hub add-collaborator` | `muse hub collaborator add` | Always check `muse hub --help` when unsure — the subcommand tree is the canonical reference, not any git/gh mental model.