Experimental software. APIs, schemas, and behaviors change without notice. Use at your own risk. Contributions welcome β expect rough edges.
β οΈ Dispatch surface is currently broken. Recent Claude Code harness changes regressed theclaude -psubprocess invocation path used byrsry_dispatchand the reconciler's hub-to-spoke sync (see rosary-a53b91 + rosary-403a1a). The bead/task-tracking surface (CLI + MCP) is unaffected β see "Use rosary as a task tracker only" below if that's all you need. The architectural fix is a tmux-per-agent spawn substrate (rosary-75555d, pre-scoped into 6 children); contributions welcome.
Autonomous work orchestrator for AI agents across multiple code repos. Local-first, open source.
Rosary structures work as beads β small, trackable units stored in each repo via Dolt. A reconciliation loop scans for ready beads, dispatches AI agents (Claude, Gemini) to execute them in isolated workspaces, verifies the results, and syncs status to Linear for human review.
The human reviews 5-10 feature PRs a day. The agents handle the atoms.
graph LR
A[Scan repos] --> B[Triage & prioritize]
B --> C[Dispatch to agent]
C --> D[Agent works in<br/>isolated workspace]
D --> E{Verify}
E -->|pass| F[Close bead]
E -->|fail| G[Retry with backoff]
E -->|deadletter| H[Flag for human]
G --> C
stateDiagram-v2
[*] --> open
open --> dispatched: agent assigned
dispatched --> verifying: agent completes
verifying --> done: checks pass
verifying --> open: retry
verifying --> blocked: deadlettered
blocked --> open: human /resume
Work items live in each repo as beads β an AI-native issue tracker backed by Dolt (version-controlled SQL). Rosary reads and writes beads directly over MySQL, no CLI shelling.
Beads are organized into threads (ordered progressions of related work) and decades (ADR-level groupings) via the BDR harmony lattice.
# Beads are managed via rosary's MCP tools or CLI:
rsry bead create "Fix auth bug" --priority 1 --issue-type bug --files src/auth.rs
rsry bead list
rsry bead search "auth"
rsry bead close rsry-abc123 # requires a verifiable test command in the description
rsry bead close rsry-abc123 --force # override (legacy / non-impl beads)# Transcript β BeadSpecs (Session provenance)
rsry capture --from-session sessions/2026-04-29.md --commit
# Source file β BeadSpecs (Code provenance, optionally scoped to a symbol)
rsry capture --from-code rosary src/bead.rs --symbol BeadSpec --commit
# Markdown ADR β beads + Rust stubs for design review
rsry decompose docs/adr/0009-feature.md --stub-output .task build # requires Task (taskfile.dev)
task test
# Register repos to watch
rsry enable ~/code/my-app
rsry enable ~/code/my-lib
# See what's ready
rsry status
# Dry run β see what would be dispatched
rsry run --once --dry-run
# Real run β dispatch agents, verify, close
rsry run --once --concurrency 3
# Continuous loop
rsry runUse
task build/task testinstead of rawcargoβ the Taskfile setsPKG_CONFIG_PATHfor the fuse-t dependency via ley-line.
The dispatch + reconciler surface is currently broken (see banner above). The bead/task surface is fully functional today β rsry bead * CLI subcommands, the MCP server (rsry serve --transport stdio), and the Linear sync all work independently of the broken dispatch path.
If you just want issue tracking β backed by Dolt, queryable via MCP, optionally synced to Linear β you can use rosary today as a pure task tracker. Two install paths:
macOS (full install β codesigns binary + sets up an HTTP MCP launchd service):
task build
task install # macOS-specific: codesigns + launchd; binary lands at ~/.local/bin/rsryLinux / Windows / any platform (build + copy; skips the macOS-only codesign + launchd steps):
cargo build --release
mkdir -p ~/.local/bin && cp target/release/rsry ~/.local/bin/rsry # or any directory on $PATHThen on any platform:
# Register your repos for tracking (no dispatch loop will run)
rsry enable ~/code/my-app
# Create / search / update / close beads via CLI
rsry bead create "Refactor auth module" --priority 1 --type task --files src/auth.rs
rsry bead list
rsry bead search "auth"
rsry bead close rsry-abc123 --force # `--force` skips the test-command verification
# Or wire rosary as an MCP server in your AI client (Claude Code, etc.)
rsry serve --transport stdio # exposes 33 bead/thread/decade tools
# Optionally sync to Linear for human review (read+write, bidirectional)
rsry sync # one-shot
rsry serve --transport http --port 8383 # also receives Linear webhooksThe dispatch loop (rsry run) is the only piece that doesn't work today. Everything else is stable.
Future: an explicit --no-default-features --features task-tracker-only build that compiles the dispatch + reconciler modules out entirely (for a smaller cross-platform binary) is tracked under rosary-ef101c β until that lands, the full binary works fine on any platform; the dispatch code is just dormant.
Rosary exposes 33 tools as MCP. Any AI agent or human with an MCP client can scan beads, dispatch work, manage threads, and track progress.
# Add to Claude Code (one-time)
claude mcp add -s user rsry -- rsry serve --transport stdio
# Or run as HTTP server
rsry serve --transport http --port 838331 tools across six categories:
| Category | Tools |
|---|---|
| Beads | rsry_bead_create, rsry_bead_update, rsry_bead_search, rsry_bead_close, rsry_bead_link, rsry_bead_import |
| Comments | rsry_bead_comment, rsry_bead_comment_list, rsry_bead_comment_update, rsry_bead_comment_delete (audit-trail preserved; hard-delete CLI-only) |
| Status | rsry_status, rsry_list_beads, rsry_scan, rsry_active |
| Dispatch | rsry_dispatch, rsry_run_once, rsry_decompose, rsry_pipeline_upsert, rsry_pipeline_query, rsry_dispatch_record, rsry_dispatch_history |
| Workspaces | rsry_workspace_create, rsry_workspace_checkpoint, rsry_workspace_cleanup, rsry_workspace_merge |
| Hierarchy | rsry_decade_list, rsry_thread_list, rsry_thread_assign, rsry_thread_reparent |
| Repos | rsry_repo_register, rsry_repo_list |
See docs/CONFIGURATION.md for the full reference.
# ~/.rsry/config.toml
[[repo]]
name = "my-app"
path = "~/code/my-app"
[[repo]]
name = "my-lib"
path = "~/code/my-lib"
[linear]
team = "ENG"
[backend]
provider = "dolt"
path = "~/.rsry/dolt/rosary"
[compute]
backend = "local" # or "sprites" for remote containersAgents run in isolated workspaces (jj preferred, git worktree fallback). The compute backend is pluggable:
| Provider | What | Config |
|---|---|---|
local |
Host subprocess (default) | none |
sprites |
sprites.dev containers | SPRITES_TOKEN env var |
Bidirectional sync β beads are source of truth, Linear is the UI. Threaded beads sync as sub-issues.
rsry sync --dry-run # preview
rsry sync # push + pull + reconcileWebhooks for real-time updates: rsry serve --transport http exposes:
/webhookβ Linear bead status sync/webhook/githubβ GitHub merge events advance the linked bead and unblock dependents
rsry sync --github # mirror bead context (id, title, status, file scopes) to PR commentsThe merge webhook closes the bead and unblocks its dependents when the linked PR lands.
Notes live under notes/<scope>/ encrypted with age. Each scope has a .recipients file listing the public keys allowed to decrypt. Different machines see different scopes naturally because they hold different unwrap keys.
# Re-encrypt every note in `notes/work/` for an updated recipient list
rsry notes rotate --scope work --add-recipient age1abc...Refuses to rotate to an empty recipient list (would brick the scope). Atomic writes β partial failures don't corrupt files.
Plugins extend rosary along a kind axis declared in ~/.rsry/plugins/*.toml or <repo>/.rosary/plugins/*.toml:
| Kind | Purpose |
|---|---|
hook |
Pipeline hook (default) β runs at pipeline.triage / verify / close |
mcp |
Outbound MCP server β rosary connects as a client (planned) |
dispatch |
Alternative AgentProvider (e.g. local model, sprites) |
state_sink |
Mirrors bead state to an external system (planned) |
Verify-tier plugins can return a coverage: f64. When a bead has doc_coverage_min in its success criteria, rosary fails the gate if the plugin reports coverage below the threshold (e.g. assay for doc-coverage delta).
# File P3 chore beads for stale markdownβcode refs reported by `assay.scan` plugins
rsry scan --assayAfter an agent completes, rosary runs tiered checks:
- Did it commit something?
- Does it compile?
- Do tests pass?
- Does the linter approve?
- Is the diff a reasonable size?
Failed checks trigger retry with backoff. After 5 failures or 3 regressions, the bead is deadlettered for human attention.
Rosary manages its own development. It scans its own repo, dispatches agents to fix its own bugs, and verifies the results. The plumbing works β proving it at scale is ongoing.
See docs/ARCHITECTURE.md for the full technical picture, docs/CONFIGURATION.md for config reference, and docs/glossary.md for terminology (beads, decades, threads, triage, etc.).
task build # debug build with fuse-t support
task test # run tests
task lint # fmt + clippy
task all # fmt + check + lint + testPre-commit hooks enforce cargo fmt and cargo clippy on every commit.
Build prereqs:
- Rust toolchain (
rustup) andcargo - The
capnpschema compiler (brew install capnp/apt-get install capnproto) βbuild.rsinvokes it to generate Rust bindings fromschemas/cloister.capnp.
task image produces a distroless OCI image tagged rosary:0.2.0 β the
exact tag cloister's cluster.capnp pins for the rosary bundle. The
image's default CMD matches cluster.capnp's launch args
(mcp --ipc-socket /run/cloister-uds/rosary.sock).
task image # krust musl cross-compile + docker COPY
task image:smoke # verify the binary runs inside the distroless imageThe pipeline is two steps:
- krust + cargo-zigbuild cross-compiles
rsrytoaarch64-unknown-linux-musl(target/krust/.../release/rsry, ~19MB static). image.Dockerfiledrops that binary ontogcr.io/distroless/static-debian12:nonroot(no shell, no package manager, nonroot uid 65532) β a singleCOPY, no Rust toolchain in the container.
Pattern adopted from ley-line-open after its melange/apko path stalled
on Apple Silicon (precedent: ley-line-open-2b255c). The melange.yaml
and apko.yaml files are retained for reference; task apk still wires
them but is no longer the recommended path.