muse bridge — CI Authentication & Usage
Overview
muse bridge provides bidirectional Git interoperability for Muse repositories.
This document covers CI setup, environment variables, and usage patterns for
automated mirror workflows.
Environment Variables
| Variable | Purpose |
|---|---|
MUSE_AGENT_KEY |
PEM-encoded Ed25519 private key (agent identity) |
MUSE_AGENT_HANDLE |
Registered Muse agent handle |
GIT_AUTHOR_EMAIL |
Override git commit author email for exports |
GIT_AUTHOR_NAME |
Override git commit author name |
GIT_COMMITTER_EMAIL |
Override git committer email |
GIT_COMMITTER_NAME |
Override git committer name |
.muse/git-bridge.toml — Bridge State File
Bridge state is persisted in .muse/git-bridge.toml. It records the last
successful import and export sync points. Add this file to .museignore to
keep per-developer state out of the Muse object store:
# .museignore
.muse/git-bridge.toml
Structure
[last_import]
git_sha = "abc123..." # 40-char SHA-1 of last imported git commit
git_ref = "main" # git branch imported
muse_commit_id = "sha256:..." # Muse commit ID created by import
imported_at = "2026-04-14T10:00:00Z"
[last_export]
muse_commit_id = "sha256:..." # Muse commit ID that was exported
git_ref = "muse-mirror" # git branch written to
git_sha = "def456..." # git commit SHA created by export
exported_at = "2026-04-14T09:55:00Z"
Subcommand Reference
muse bridge git-import
Import git commits into a Muse repository:
muse bridge git-import /path/to/git-repo \
--branch main \
--incremental \
--attribution-map /path/to/authors.json \
--sign \
--json
muse bridge git-export
Export a Muse snapshot into a git working tree:
muse bridge git-export \
--git-dir /path/to/git-mirror \
--git-branch muse-mirror \
--git-remote origin \
--no-push \
--json
muse bridge git-status
Show bridge state and drift counts:
muse bridge git-status --git-dir /path/to/git-repo --json
Output:
{
"last_import": {"git_sha": "...", "git_ref": "main", ...},
"last_export": {"muse_commit_id": "sha256:...", "git_ref": "muse-mirror", ...},
"drift": {
"git_commits_since_import": 3,
"muse_commits_since_export": 1
}
}
--watch mode
Poll Muse HEAD every N seconds and auto-export on new commits:
muse bridge git-export \
--git-dir /path/to/git-mirror \
--git-branch muse-mirror \
--no-push \
--watch 30 \
--json
Each poll emits a NDJSON event:
{"event": "poll", "muse_commit_id": "sha256:...", "changed": false}
{"event": "exported", "muse_commit_id": "sha256:...", "git_sha": "abc..."}
GitHub Actions Example
name: Mirror to Git
on:
push:
branches: [main]
jobs:
mirror:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install muse
run: pip install muse-vcs
- name: Export to git mirror
env:
MUSE_AGENT_KEY: ${{ secrets.MUSE_AGENT_KEY }}
MUSE_AGENT_HANDLE: ${{ secrets.MUSE_AGENT_HANDLE }}
run: |
muse bridge git-export \
--git-dir /tmp/git-mirror \
--git-branch muse-mirror \
--git-remote origin \
--no-push \
--json
CircleCI Example
version: 2.1
jobs:
mirror-to-git:
docker:
- image: cimg/python:3.12
steps:
- checkout
- run:
name: Install muse
command: pip install muse-vcs
- run:
name: Export Muse snapshot to git mirror
command: |
muse bridge git-export \
--git-dir /tmp/git-mirror \
--git-branch muse-mirror \
--git-remote origin \
--no-push \
--json
environment:
MUSE_AGENT_KEY: << pipeline.parameters.muse_agent_key >>
MUSE_AGENT_HANDLE: muse-ci-bot
workflows:
mirror:
jobs:
- mirror-to-git:
filters:
branches:
only: [main]
Attribution Map
When importing git commits, map git author emails to Muse handles:
{
"[email protected]": "alice",
"[email protected]": "bob",
"[email protected]": "ci-bot"
}
Unmapped emails receive a synthetic handle: git-import/<sha256[:8]>.
Pass the map file with --attribution-map:
muse bridge git-import /path/to/git-repo \
--attribution-map /path/to/authors.json \
--sign \
--json
Security Notes
- All subprocess calls use argument lists —
shell=Trueis never used. --git-branchis validated against a safe-character regex before any subprocess call. Characters;,&,|,`,$,(,), spaces, and control chars are rejected.- Git SHA-1 values are validated (40 lowercase hex chars) before being passed to
git cat-file. Invalid SHAs raiseValueErrorrather than reaching the subprocess. - Attribution handles are stripped of ASCII control characters on load.
- Bridge state is written atomically (temp-file + rename) with a module-level lock.
muse_commit_idvalues are validated for thesha256:prefix at the persistence boundary — bare hex strings are never stored.