gabriel / muse public
agent-guide.md markdown
383 lines 13.7 KB
Raw
sha256:53386fd8a81ed8223bf9274bfbc201141ea13cfe6bc6dfb154aace6a787d2276 use idiomatic and modern switch syntax instead of checkout Human 35 days ago

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/<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 # 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

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.

File History 6 commits
sha256:53386fd8a81ed8223bf9274bfbc201141ea13cfe6bc6dfb154aace6a787d2276 use idiomatic and modern switch syntax instead of checkout Human 35 days ago
sha256:a2741505cee973e52080a1999023399faee8796d008a03592d071a5b55179684 update agent-guide.md to mention checking out target branch… Human 35 days ago
sha256:be65ef1b8ae474deaa9c5fe9bde8114f4a32b29b8c26484cb2179a14070499b7 minor docs updates. `^` syntax replaced w/ `..` Human 35 days ago
sha256:3db35e858ee12a4777e7fdaa3e5b29b7b34749d5a17368647c6576b635ec770b update agent.md to include Safe Merge Protocol Human 35 days ago
sha256:b5ec4e4a3a73cae0cd08224f32090f2a4836afa0a804cb3231e70c42a3e89295 fix adapter for agent config Human patch 42 days ago
sha256:99f8eb388d9a9c353e68b9a4e5bebe1b4240a8f511e6f0928e58c0e95153e103 feat: branch --prune-config, fix hub repo delete docstrings… Sonnet 4.6 minor 43 days ago