Developer Docs Getting Started
PHASE 00

Getting Started

Install the Muse CLI, generate an Ed25519 identity, create your first repository, and run the core commit → branch → merge → push workflow. Covers new repos and migration from an existing Git history. No prior knowledge of Muse required.

What is Muse

Muse is a content-addressed, domain-agnostic version control engine with humans, agents, and orgs as first-class citizens. Give it any state space — source code, MIDI tracks, genomic sequences, financial models — and it gives you content-addressed history, branching, three-way merge, time-travel, typed diffs, conflict resolution, semantic versioning, and cryptographic commit provenance. The domain plugin protocol is six methods.

The current implementation is Python. A Rust port of the core engine is planned; the on-disk format and wire protocol are stable and will be a drop-in swap.

Prerequisites

The installer requires Python 3.14 or later.

bash check your Python version
python3 --version
Python 3.14.4

If you need to install Python 3.14, the canonical options are python.org, uv (uv python install 3.14), or your OS package manager. The installer probes python3.14 first, then python3 — if the right version is on your PATH under either name, it will be found.

The only other system dependency is curl. No system-level pip required — the installer creates a fresh venv and uses that venv's own pip. No other build tools needed — the sdist is downloaded directly from the MuseHub instance, not from PyPI.

Install

bash
curl -fsSL http://staging.musehub.ai/install.sh | sh

To uninstall, run the companion script — it removes the venv and symlink without touching your identity store or local repos:

bash
curl -fsSL http://staging.musehub.ai/uninstall.sh | sh

Before running either script, inspect it — view install.sh in your browser or pipe to less first:

bash
curl -fsSL http://staging.musehub.ai/install.sh | less

The installer does exactly four things:

  1. Probes your PATH for Python 3.14+ and exits with a clear error if absent.
  2. Creates a dedicated venv at ~/.local/share/muse/venv.
  3. Downloads the muse sdist from the MuseHub instance and installs it into that venv via pip. No PyPI involved.
  4. Symlinks ~/.local/share/muse/venv/bin/muse~/.local/bin/muse.

The venv is isolated — installing or upgrading muse cannot touch your system Python or any other project. Running the installer a second time is safe: it recreates the venv in place.

PATH setup

The binary lands at ~/.local/bin/muse. If ~/.local/bin is not already on your PATH, add it. Where you add it depends on your shell:

bash ~/.bashrc or ~/.zshrc
export PATH="$HOME/.local/bin:$PATH"

After editing your shell config, reload it (source ~/.zshrc) or open a new terminal. The installer always prints a reminder to verify ~/.local/bin is on your PATH before exiting.

Verify

bash
muse --version
muse 0.2.0rc9

Troubleshooting

SymptomFix
muse: command not found ~/.local/bin is not on your PATH. Add export PATH="$HOME/.local/bin:$PATH" to your ~/.zshrc or ~/.bashrc, then run source ~/.zshrc or open a new terminal.
Error: Muse requires Python 3.14 or later. The installer found only an older Python. Install 3.14 from python.org or via uv python install 3.14. The installer probes python3.14 then python3 — make sure the right binary is on your PATH under one of those names.
curl: (22) The requested URL returned error: 404 during install The sdist for this version hasn't been published to the hub yet. Check http://staging.musehub.ai/releases to see available versions, or contact the hub operator.
curl: (22) … error: 522 You used http:// instead of https://. The install command requires a secure connection: curl -fsSL http://staging.musehub.ai/install.sh | sh
Hub unreachable or TLS errors Verify the hub is up: curl -I http://staging.musehub.ai/healthz. For a self-hosted local hub, ensure the TLS certificate is trusted — see the local dev setup guide.

Uninstall

The uninstall script removes the venv and the symlink. Your identity store (~/.muse/) and all local repositories are never touched.

bash
curl -fsSL http://staging.musehub.ai/uninstall.sh | sh

# Only if you are decommissioning this machine entirely
rm -rf ~/.muse

Cryptographic identity

Muse has no passwords, no API tokens, and no JWTs. Every request to a MuseHub instance is authenticated via a signed Ed25519 challenge-response. The server stores only your public key.

Your private key is never written to disk in any form. It is derived on-the-fly from a BIP-39 mnemonic stored in your OS keychain (macOS Keychain, Linux Secret Service) using SLIP-0010 HD key derivation. Each hub gets a key derived at a distinct HD path — so a key compromise on one hub does not affect others, and key rotation is a derivation index increment.

Generate a key pair

bash
muse auth keygen --hub http://staging.musehub.ai
✅  24-word BIP-39 mnemonic generated and stored in your OS keychain.
   Back it up now — pipe directly to your password manager so it
   never appears in your terminal scrollback:

   macOS:  security find-generic-password -s muse -a mnemonic -w | pbcopy
   Linux:  secret-tool lookup service muse account mnemonic | xclip -selection clipboard

✅ Ed25519 keypair generated
   Public key (b64url): <base64url>
   Fingerprint (SHA-256): sha256:220897cdf3a...
   HD path: m/1075233755'/1660078172'/0'/0'/0'/0'
   Mnemonic: 24 words (english)

   Next step: muse auth register --hub http://staging.musehub.ai --handle <your-handle>

This generates a fresh BIP-39 mnemonic (if you don't have one yet), stores it in the OS keychain, derives the Ed25519 key pair at m/1075233755'/1660078172'/0'/0'/0'/0', and writes the public key fingerprint to ~/.muse/identity.toml. The private key is never logged or printed.

Back up your mnemonic immediately after keygen. Losing it means permanent loss of all derived keys — there is no recovery without the mnemonic. The mnemonic never appears in terminal output (scrollback is not safe). Copy it directly from the keychain to your password manager:
bash macOS
# Copies mnemonic to clipboard — paste into 1Password / Bitwarden immediately
security find-generic-password -s muse -a mnemonic -w | pbcopy
bash Linux
secret-tool lookup service muse account mnemonic | xclip -selection clipboard

Register with a hub

bash
muse auth register --hub http://staging.musehub.ai --handle your-handle
✅ Registered as 'your-handle' on https://staging.musehub.ai
   Identity ID: ident_...
   Auth method: ed25519 (key fingerprint: sha256:220897c…)
   HD path: m/1075233755'/1660078172'/0'/0'/0'/0'
   Identity stored in: ~/.muse/identity.toml

Registration is a signed challenge-response: the hub issues a random 32-byte challenge, you sign it with your private key, and the hub verifies the signature against the public key you submitted. No password, no session token — the private key never leaves your machine. After registration your handle is your identity on that instance: it appears in commit records, repo slugs, and issue assignments.

Verify your identity

bash
muse auth whoami
bash human output
    Hub:         staging.musehub.ai
    Type:        human
    Handle:      your-handle
    Fingerprint: sha256:220897cdf3a8b4e5f1d2c6a7b9e0f3d4a5c8b2e7f1a0d3c6b9e2f5a8c1d4e7f0
    Key:         keychain
    HD path:     m/1075233755'/1660078172'/0'/0'/0'/0'

The HD path is the SLIP-0010 derivation path for this identity — the exact node in your key tree for this hub. It tells you where in the hierarchy this key sits, which matters for key rotation and multi-hub setups. Use --json for the full structured output:

json muse auth whoami --json
{
  "hub":          "staging.musehub.ai",
  "type":         "human",
  "handle":       "your-handle",
  "fingerprint":  "sha256:<64-hex>",
  "key_set":      true,
  "capabilities": [],
  "hd_path":      "m/1075233755'/1660078172'/0'/0'/0'/0'"
}

The identity file at ~/.muse/identity.toml holds one section per hub hostname. Multiple hubs, multiple handles — all derived from the same mnemonic at distinct HD paths.

Logout and key rotation

muse auth logout removes the local identity entry for a hub — it does not invalidate anything server-side because MSign is stateless (no sessions). Use it when decommissioning a machine or rotating a key.

bash
# Remove local key entry for one hub
muse auth logout --hub http://staging.musehub.ai

# Generate a new mnemonic and rotate to a new key (irreversible)
muse auth keygen --hub http://staging.musehub.ai --force --destroy-mnemonic

Create a repo

muse init initialises a new Muse repository in the current directory. It creates a .muse/ subdirectory containing the object store, refs, and config. It does not touch any existing files.

bash
mkdir my-project && cd my-project
muse init
✅ Initialized Muse repository in /home/you/my-project/.muse/

The default domain is code. The domain determines which plugin handles diffs, merges, and semantic commands — it is stored in .muse/repo.json and cannot be changed after init.

bash .muse/repo.json
{
  "repo_id":        "sha256:<64-hex>",
  "domain":         "code",
  "schema_version": 1,
  "created_at":     "2026-04-30T12:00:00Z",
  "bare":           false,
  "muse_version":   "<semver>"
}

Connect to a hub

Connecting registers the hub URL in the repo's config. This is required before pushing — it is what authorises the repo to authenticate with that hub instance.

bash
muse hub connect http://staging.musehub.ai

Add a remote

A remote is a named pointer to a push/pull URL. The name is arbitrary — you choose it. A repo can have as many remotes as you want.

Separately, as a developer you typically have multiple deployment environments. The convention in this ecosystem is to name remotes after the environment they point to: local, staging, prod. That way muse push staging dev reads unambiguously — remote name and environment are the same thing.

bash
# Create the repo on the hub first
muse hub repo create --name my-project --json

# Add a remote for each environment you push to
muse remote add local   https://localhost:1337/your-handle/my-project
muse remote add staging https://staging.musehub.ai/your-handle/my-project
If muse push returns 404 ("Repository not found on remote"), the repo does not yet exist on the hub. Create it with muse hub repo create --name <name> first, then retry.

Core workflow

The core loop is: stage → commit → branch → merge → push. The commands map directly from Git, with two key differences: staging uses muse code add (not git add), and agent commits carry provenance fields.

Stage and commit

bash
# Check what's changed
muse status

# Stage everything (new files, modifications, and deletions of tracked files)
muse code add .

# Stage specific paths
muse code add src/api.py tests/test_api.py

# Remove a file from disk and stage the deletion
muse rm src/legacy.py

# Review staged changes before committing
muse diff --staged

Two commit forms — human and agent. The absence of provenance flags is itself a structural signal that a human committed directly:

bash
# Human commit
muse commit -m "feat: add rate limiting"
[main sha256:3f8a1c2d] feat: add rate limiting
 2 files changed (2 modified)
bash
# Agent commit — full provenance chain (agent_id + model_id + Ed25519 signature)
muse commit -m "feat: add rate limiting" \
  --agent-id claude-code \
  --model-id claude-sonnet-4-6 \
  --sign
[main sha256:9e21b8f4] feat: add rate limiting
 2 files changed (2 modified)
 ✔ signed with ed25519:Kx7mP2...

--sign embeds an Ed25519 signature and the signer's public key directly in the CommitRecord. Any party with the public key can verify the commit was produced by the agent holding the matching private key, which itself traces back to the signer's HD wallet seed.

Branch and merge

Work on a feature branch — never commit directly to dev or main. Branch names carry optional --intent and --resumable metadata. --intent is free text describing what the branch is for; --resumable marks it as safe for another agent to pick up mid-flight. Both are readable from muse branch --json.

bash standard branch cycle
# Start from dev
muse checkout dev
muse checkout -b feat/rate-limiting \
  --intent "implement token bucket rate limiter" \
  --resumable

# ... work, stage, commit ...

# Merge back into dev
muse checkout dev
muse merge feat/rate-limiting
muse branch -d feat/rate-limiting

Merge is three-way: Muse finds the lowest common ancestor of the two branch tips, runs the domain plugin's merge(), and auto-resolves conflicts using Harmony (the conflict-resolution memory system) if prior resolutions exist. Unresolved conflicts are written to the working tree for manual resolution, exactly as in Git.

Push

muse push takes a remote name and a branch name. It sends only the objects the remote doesn't already have, computed by walking the commit graph from the branch tip back to the last shared ancestor.

bash
muse push staging dev
Pushing dev → staging/dev …
  uploading objects: 3/3
✅ Pushed 2 commit(s), 3 object(s) to staging/dev (sha256:9e21b8f4)
bash
# Push main as well
muse push staging main

# See all configured remotes
muse remote --json

Branch topology

BranchRoleRule
mainProductionTagged releases only; never direct-pushed
devIntegrationLatest deliverable state; always green
feat/*FeatureFrom dev; one atomic task; hours, not days
task/*Agent taskSame as feat/*; carries --intent and --resumable
bugfix/*Bug fixFrom dev; merges back into dev
hotfix/*Hot fixFrom main; merges into both main and dev

Git interoperability

muse bridge is the bidirectional Git interoperability layer. It imports Git commit history into Muse and exports Muse snapshots back to Git — so you can move to Muse incrementally, maintain a Git mirror for tooling that requires it, or keep both in sync indefinitely.

Import from Git

muse bridge git-import walks a Git repo's DAG and writes equivalent Muse commits and snapshots. Author names, emails, and timestamps are preserved verbatim. The Git repo is never modified.

bash
# Import main from a git repo into the current Muse repo
muse bridge git-import /path/to/git-repo --branch main

# Incremental — only import commits since the last run
muse bridge git-import /path/to/git-repo --branch main --incremental

# Sign imported commits with your Ed25519 key
muse bridge git-import /path/to/git-repo --branch main --sign --json

Git author emails are mapped to Muse handles via an optional attribution map. Unmapped emails get a synthetic handle (git-import/<sha[:8]>).

json authors.json
{
  "[email protected]": "alice",
  "[email protected]":   "bob"
}
bash
muse bridge git-import /path/to/git-repo \
  --branch main \
  --attribution-map authors.json \
  --incremental \
  --sign \
  --json

Export back to Git

muse bridge git-export writes the current Muse snapshot into a Git working tree. Use this to maintain a Git mirror — for CI systems, code review tools, or anything else that only speaks Git.

bash
muse bridge git-export \
  --git-dir /path/to/git-mirror \
  --git-branch muse-mirror \
  --no-push \
  --json

Check sync state

muse bridge git-status shows the last import and export sync points and how many commits of drift have accumulated on each side.

json muse bridge git-status --json
{
  "last_import": {
    "git_sha":       "abc123...",
    "git_ref":       "main",
    "muse_commit_id": "sha256:..."
  },
  "last_export": {
    "muse_commit_id": "sha256:...",
    "git_ref":       "muse-mirror",
    "git_sha":       "def456..."
  },
  "drift": {
    "git_commits_since_import":  3,
    "muse_commits_since_export": 1
  }
}
Bridge state is persisted in .muse/git-bridge.toml. Add it to .museignore to keep per-developer sync state out of the Muse object store. Imported commits that predate your Muse adoption won't carry Ed25519 signatures — all commits made natively in Muse going forward will.

What's next

The remaining sections cover the platform in depth:

SectionWhat it covers
01 — Foundations The complete object model: object store, CommitRecord schema, SnapshotManifest, branch DAG, serialization (msgpack), on-disk layout, push/pull wire flow.
02 — Cryptographic Identity HD key derivation in depth, MSign request signing, the human→agent→org trust chain, quorum authorization, and MPay micropayments.
03 — Domain Protocol How to implement a domain plugin: the six required methods, typed delta algebra, address-keyed Map merge, CRDT extension. Build Muse support for any state space.
04 — Code Intelligence Symbol graph, blast radius analysis, gravity scores, hotspots, entanglement, dead-code detection, and the semantic test coverage model.
05 — Harmony Four-tier conflict resolution: policy rules, exact blob replay, semantic similarity matching, and hub-escalated human review.
06 — Agent Coordination Work queues, claim/complete lifecycle, symbol reservations, codebase sharding for parallel agent swarms, and merge forecasting.
07 — MCP Tooling The Model Context Protocol server: tools, resources, elicitation flows, and SSE streaming for real-time agent feedback.
08 — Shelves Working-tree checkpoints: intent types, resumability metadata, domain state capture, and agent handoff patterns.
09 — Wire Protocol MsgPack-over-HTTP streaming: push frame layout, ACK/NAK negotiation, fetch protocol, and presigned large-object transfer.
10 — MuseHub API Reference Full REST API: MSign authentication, all endpoints, rate limits, webhook events, and pagination.
11 — Identity Profiles Three-archetype profile system: Spectral Sigil, provenance badges, attestations, MPay ledger, and agent genealogy.
12 — Mist Domain Content-addressed, forkable, embeddable artifact shares: URL schema, artifact types, the Mist CLI, REST API surface, and the security model.