Experimental software. APIs, schemas, and behaviors change without notice. Use at your own risk. Contributions welcome β expect rough edges.
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 (a local SQLite beads.db, or a per-repo Dolt server where concurrent access is needed). A reconciliation loop scans for ready beads, dispatches AI agents (Claude, Codex, 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. Rosary reads and writes beads in-process via its own stores: over the MySQL wire to a per-repo Dolt server when .beads/dolt/ exists, otherwise directly against a local SQLite beads.db. The bd CLI is not required or invoked either way (see ADR-0014).
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 close condition (acceptance_criteria / test command)
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 check # canonical local/CI verification gate
# 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 checkinstead of rawcargoβ the Taskfile is the verification contract and setsPKG_CONFIG_PATHfor the fuse-t dependency via ley-line.
You don't have to run the dispatch loop to get value. The bead surface stands on
its own β rsry bead * CLI subcommands, the MCP server (rsry serve --transport stdio), and Linear sync all work whether or not rsry run is going.
If you just want issue tracking β backed by Dolt, queryable via MCP, optionally
synced to Linear β install the binary and skip straight to rsry enable +
rsry bead. 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 (you can start the dispatch loop later)
rsry enable ~/code/my-app
# Create / search / update / close beads via CLI
rsry bead create "Refactor auth module" --priority 1 --issue-type task --files src/auth.rs
rsry bead list
rsry bead search "auth"
rsry bead close rsry-abc123 --force # `--force` skips the close-condition gate
# Or wire rosary as an MCP server in your AI client (Claude Code, etc.)
rsry serve --transport stdio # exposes 40 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 webhooksFuture: 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 dispatch modules are always compiled in, and you simply choose whether to run the loop.
Rosary exposes 40 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 838340 tools across eight 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, rsry_bead_history |
| Dispatch | rsry_dispatch, rsry_run_once, rsry_decompose, rsry_pipeline_upsert, rsry_pipeline_query, rsry_dispatch_record, rsry_dispatch_history, rsry_agent_run_event_record, rsry_agent_run_events, rsry_agent_session_addresses, rsry_agent_session_message_record |
| Review | rsry_review, rsry_ticket_load |
| Workspaces | rsry_workspace_create, rsry_workspace_checkpoint, rsry_workspace_cleanup, rsry_workspace_merge |
| Hierarchy | rsry_decade_list, rsry_decade_create, rsry_thread_list, rsry_thread_create, 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 (and reference a bead)?
- Does it compile?
- Do tests pass?
- Does an adversarial review pass?
- Is the diff a reasonable size?
- Is the bead's close condition satisfied?
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 compile # fast cargo check
task lint # fmt + clippy + semgrep
task test # run tests
task smells # mache structural-smell ratchet (vs docs/smell-baseline.json)
task check # canonical gate: contract + rules + compile + lint + test + smells
task ci # CI alias for task checkCI delegates to task check; keep Taskfile targets as the source of truth instead of duplicating raw cargo commands in workflows or agent instructions.
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:build # cargo-zigbuild musl cross-compile + docker build (native arch, loadable)
task image:smoke # verify the binary runs inside the distroless image
task image:release # multi-arch build + push + cosign sign (CI hooks into this; see below)Image tasks live in .taskfiles/image.yml, included under the image:
namespace. The pipeline is two steps:
cargo-zigbuildcross-compilesrsryto<arch>-unknown-linux-musl(target/<triple>/release/rsry, ~19MB static), staged atdist/<arch>/rsry. zig handles the musl C cross-compile (leyline-fs FUSE bindings included) that stalled the apko/melange path on Apple Silicon β and cross-builds both arches on one machine with no emulation.image.Dockerfiledrops that binary ontogcr.io/distroless/static-debian12:nonroot(no shell, no package manager, nonroot uid 65532), selecting the arch by buildxTARGETARCH.
CI (.github/workflows/release.yml) publishes on a tag by calling the same
task image:release β no image command lives in CI that the Taskfile doesn't
own. The retained melange.yaml / apko.yaml / task apk are a reference
artifact of the abandoned apko path, not the recommended one.