many agents on one repository · one total order from a single-writer sequencer · merge conflicts as first-class values
Quick start · Install · Run a node · How it works · Documentation · Why
Every change is a signed operation on an append-only log, ordered by one
writer thread. A race gets a compare-and-swap rejection, not a lost write.
A merge conflict is a committed value. Plain git clone, fetch and
push work: the sequencer is a pre-receive hook.
Needs only git. Everything comes from the node serving this
repository. The last command prints your own node URL:
curl -fsSL https://choirs.dev/download/install.sh | sh
choir hostchoir host mints the repository root, a 0600 credential, a trusted key
and a config file, then installs the daemon under launchd or systemd.
Two demos, no install beyond a toolchain:
git clone https://choirs.dev/choir/choir.git
cd choir
demo/run.sh # the same twenty agents on git alone and on choir, side by side, about a minute
cargo run -p choir-demo # narrated walkthrough of every layerdemo/run.sh builds into its own target dir and plays against a live
loopback node with plain git and curl; demo/README.md
says what each beat shows and what the numbers mean.
From the node, with rustup. One clone URL, no account and no forge:
cargo install --git https://choirs.dev/choir/choir.git choir-cli choir-nodechoir-cli is choir and choir-mcp; choir-node is the daemon and
choir-ssh, only if you run one. All land in $CARGO_HOME/bin
(~/.cargo/bin by default).
Prebuilt, macOS and Linux, x86-64 and arm64, no toolchain. Served by the node, which also renders the installer, so the script and every archive it fetches come from the one host you typed:
curl -fsSL https://choirs.dev/download/install.sh | shThat is choir, choir-mcp, choir-node and choir-ssh, 3.5 MiB of
download. For the client alone, pass it a name:
curl -fsSL https://choirs.dev/download/install.sh | sh -s -- choir-cliEach archive is checked against the SHA256 published beside it.
https://choirs.dev/download/ lists
what is there, and the installer is plain text: read it first. When
~/.cargo/bin is not on your PATH, it adds one line to your shell's
startup file so new terminals find choir, and prints the export for
the terminal you ran it in.
The archives are built by CI, not by the node, and the digests prove the transfer rather than the build. Releases are also on GitHub if you would rather take them from there.
Nothing is on a package registry.
Subprocesses. git and curl always; openssl and ssh-keygen
where used; mergiraf for structured merges. Workspaces use APFS
clonefile on macOS, btrfs snapshots on Linux.
One port, 8417 by default, serves git smart-HTTP and the platform API.
choir host # nothing to running node, supervised, prints the URL
choir repo create me/thing.git # a sequenced repository
choir repo url me/thing.git # the clone URL and the git config to go with it
choir node status # health, the commit serving, sequencer positionchoir host --domain example.com issues a Let's Encrypt certificate.
choir host --foreground execs the daemon instead of installing a service
unit. A non-loopback bind requires TLS.
choir invite prints one link; choir join '<link>' mints the key, stores
the token, points git at it and clones each repository the invite names.
Important
Pass --acl-file before issuing a second credential; until then every
credential reaches every repository. See
Authorization.
choir backup take <dir> copies the log, node fingerprint, policy files
and one git bundle per repository, and verifies the copy; choir backup schedule <dir> does it hourly; choir backup restore <dir> <root> proves
it. None carries a secret. choir node upgrade --from <node> puts newer
binaries in place, restarts, and reads the stamp back. choir repo follower add names a remote every landing is pushed to.
A seed is a live copy of another node's log: it verifies every page
before keeping it, serves reads under its own ACL, signs a statement
about what it saw, and answers every write with 421 not_home naming
the home. choir seed <home-url> runs one, in two runs: the first prints
what the home registers, the second takes the credential it issued.
seeds = <url> beside node = in .choir/config makes choir doctor
check each for a fork. Run a seed.
Every flag and policy file: Running a node.
A change is a signed operation on a hash-chained log. One writer thread per repository decides the order. Refs, reviews and workspaces are folds over that log.
- Two agents push the same ref. The later one gets a compare-and-swap rejection naming the winning head. Integrate and retry.
- A merge cannot be resolved. The conflict is committed as a value.
- Proof.
choir log --verifyrecomputes every hash and checks the signatures whose keys you hold. - Not included. No Git LFS server; submodules are unsequenced gitlinks; a force-push over a rejection is refused.
Layer map: Architecture.
Authentication is passed as flags: choir --auth-file ~/.choir/auth --auth-user choir <command>
| Command | What it does |
|---|---|
choir host |
take this machine from nothing to a running node and print its… |
choir key |
mint a key and print the line the operator registers |
choir join |
redeem an invite link and set this machine up: actor key at… |
choir workspace |
provision a CoW workspace |
choir propose |
create a change, push its commits and request review, with no… |
choir reviews |
your pending review queue |
choir verdict |
answer a review you were assigned |
choir state |
list what you owe and what you are waiting on |
choir log |
read log entries from a cursor |
Full surface, every command and every endpoint: docs/using/cli.md.
Exit codes: 0 accepted, 1 rejected with its JSON error body,
2 usage. choir doctor explains a failure.
Full index: docs/README.md.
| You want | Read |
|---|---|
| Why | Why choir exists |
| How the pieces fit | Architecture |
| To run a node | Running a node |
| To get a change reviewed and landed | The contribution workflow |
| Every command and endpoint | The CLI and HTTP API |
| To wire up a coding agent | templates/ · AGENTS.md |
| Something is broken | Troubleshooting · ERRORS.md |
Build the book:
cargo install mdbook --locked
choir docs --opencargo build --release -p choir-node -p choir-cli
cargo test --workspace # hermetic: no network, no servicesFull release gate:
./gateFails closed. Edit-loop lanes: ./gate touched (changed crates),
./gate quick (compiles nothing), ./gate fast (skips timing-gated
stages).
Caution
Keep .cargo/config.toml. Every build needs its LIBSQLITE3_FLAGS, and
the failure it prevents does not name itself.
Important
Research prototype. DECISIONS.md is the register behind every
design choice; the invariants in CONTRIBUTING.md
are one-way doors.
The code is public; write access is not. Fork and open a pull request.
A hosted node is separate and invite-only. Running your own needs nothing from anybody.
Keys, tokens and PEM files: ~/.choir/ at mode 0600, the daemon key at
<repo-root>/.choir/node.key. Never commit them.
CONTRIBUTING.md: gate lanes, invariants, house
conventions. Security reports: SECURITY.md, never a
public issue.
MIT (LICENSE-MIT) or Apache-2.0
(LICENSE-APACHE). Mergiraf, an optional subprocess, is
GPLv3 and executed rather than linked. Attributions: NOTICE.