Muse Ecosystem — Agent Guide
Drop
@path/to/this/fileinto anyCLAUDE.mdor 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
gitorghcall 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/<repo> <command> when CWD differs from the target repo.
Muse Commands
Every command accepts --json. Always use --json for structured reads.
-C — cross-repo targeting
muse -C ~/ecosystem/muse <command>
muse -C ~/ecosystem/musehub <command>
muse -C ~/ecosystem/agentception <command>
-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:
# ❌ Wrong — no hub context
muse hub repo list --json
# ✅ Correct
muse -C ~/ecosystem/musehub hub repo list --json
# ❌ 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:
# 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:
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.
# ❌ 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 <file> / muse code reset <file> |
| Commit | muse commit -m "message" |
| Commit with provenance | muse commit -m "msg" --agent-id <id> --model-id <id> --sign |
| History | muse log --json |
| Inspect commit | muse show --json |
| Branches | muse branch --json |
| Create / switch | muse checkout -b <name> / muse checkout <branch> |
| Delete branch | muse branch -d <name> |
| Merge | muse merge <branch> |
| Dry-run merge | muse merge --dry-run <branch> --json |
| Push | muse push local dev |
| Pull | muse pull <remote> <branch> |
| Stash / pop | muse stash [-m "msg"] / muse stash pop |
| Workspace status | muse workspace status --json |
| Tag | muse tag add "label" [<ref>] |
| Release | muse release add <semver> |
muse content-grep — regex gotchas
Uses Python re (ERE). Metacharacters ( ) . [ * + ? { } ^ $ must be escaped for literal matches:
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
# Start
muse -C ~/ecosystem/<repo> checkout dev
muse -C ~/ecosystem/<repo> checkout -b task/my-thing
# Work
muse code add .
muse commit -m "feat: ..."
# Merge back
muse -C ~/ecosystem/<repo> checkout dev
muse -C ~/ecosystem/<repo> merge task/my-thing
muse -C ~/ecosystem/<repo> branch -d task/my-thing
muse -C ~/ecosystem/<repo> push local dev
# When dev is ready for main
muse -C ~/ecosystem/<repo> checkout main
muse -C ~/ecosystem/<repo> merge dev
muse -C ~/ecosystem/<repo> push local main
muse -C ~/ecosystem/<repo> push local dev
muse -C ~/ecosystem/<repo> checkout dev
Deploy (MuseHub)
Docker + ECR + AWS SSM. Always staging first.
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=<prev-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.
muse auth keygen --hub http://localhost:10003
muse auth register --hub http://localhost:10003 --handle <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.
<repo>/.muse/agent.md — repo-specific rules
<workspace>/.muse/agent.md — shared rules inherited by all members
First-time setup
# At the workspace root (if inside a workspace)
muse -C ~/ecosystem agent-config init
# At each member repo
muse -C ~/ecosystem/<repo> agent-config init
# Choose which adapters you need (persists to .muse/config.toml)
muse -C ~/ecosystem/<repo> agent-config set --adapters claude,codex
# Generate adapter files
muse -C ~/ecosystem/<repo> agent-config sync
Keeping adapters in sync
After editing .muse/agent.md:
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
# deprecatedannotations. 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
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 <verb> or gh <verb>-<noun>. Muse uses
muse hub <noun> <verb>. 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 <n> --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 <noun> --help when unsure — the subcommand tree is
the canonical reference, not any git/gh mental model.