An issue tracker for coding agents working across Git worktrees, clones, and
machines. beadroll provides the bead command: a shared tracker with exclusive
task claims, dependency tracking, and Beads JSONL import and export.
- Every worktree and clone of a repository uses the same tracker.
- Claims are confirmed by the remote, so two agents cannot hold the same task.
- Tracker data lives outside your checkout and syncs through a dedicated Git ref. Your code branches stay free of tracker commits.
- One Rust binary uses your existing Git remote and credentials. No server, daemon, or database to set up.
Install · Quick start · For agents · Migration guide · Contributing
Requirements: Linux or macOS, git 2.40+, and rustup. beadroll builds from source. From a new checkout:
git clone https://github.com/bpcakes/beadroll.git
cd beadroll
cargo install --locked --force --path crates/beadroll --root ~/.local
export PATH="$HOME/.local/bin:$PATH"
bead --versionRun the install command from the repository root so rustup picks up
rust-toolchain.toml and installs Rust 1.99.0. The binary
goes in ~/.local/bin; keep that directory on your PATH. To upgrade, pull
the latest source and run the install command again.
Install directly from Git without a checkout
rustup toolchain install 1.99.0 --profile minimal
cargo +1.99.0 install --locked --force --config net.git-fetch-with-cli=true \
--git https://github.com/bpcakes/beadroll.git beadroll --root ~/.localThe explicit toolchain is required because cargo install --git does not
read the repository's toolchain file. Add ~/.local/bin to your PATH as above.
In a Git repository whose origin you can push to, initialize a tracker once:
cd your-project
bead init --prefix app
bead prime
bead create "Fix the rate limiter after a restart" -t bug -p 1init publishes the tracker to refs/beads/journal on origin. It writes
no files in your checkout and makes no commits on your code branches. The
origin URL identifies the tracker across worktrees, clones, and machines.
Use the issue ID printed by create in place of app-zs43 below:
bead ready
bead claim app-zs43
bead comments add app-zs43 "The counter resets before the first tick."
# Make and verify the fix, then record the outcome.
bead close app-zs43 -r "The counter now survives a restart."
bead show app-zs43A confirmed claim belongs to its owner until release, close, or takeover.
Other agents cannot claim it, and bead ready excludes it while held.
On another machine, run these commands in any clone of the same repository:
bead sync
bead readyWrites publish automatically. With --offline, or when the remote does not
answer, changes remain local and bead reports what is unpublished. Run
bead sync to publish them and fetch other machines' work. Reads such as
ready, show, and list use local state and never contact the network;
sync first when you need the latest changes.
| Task | Command |
|---|---|
| Find available work | bead ready, or bead ready EPIC for an epic's subtree |
| Inspect an issue and its history | bead show ID, bead log ID |
| List or search issues | bead list, bead search "query" |
| See who is working on what | bead claims |
| Hand back unfinished work | bead release ID |
| Create a child task | bead create "Title" --parent ID |
| Inspect blockers | bead blocked, bead dep tree ID |
| Review activity across local trackers | bead recap |
| Inspect the store and remote | bead info |
Run bead for the command overview and bead help COMMAND for usage and
options. Add --json for machine-readable output.
bead recap works from any directory and reads all local trackers without
syncing. The first recap shows the last 24 hours. Terminal output marks
activity as seen; pipes, files, and --json only read it unless you pass
--advance.
Add the workflow to your repository's agent instructions:
bead onboard >> AGENTS.mdUse CLAUDE.md instead if that is where your agent reads instructions. Fill
in the project specifics at the end of the generated block. Each agent then
starts a session with bead prime, which reports its identity, held issues,
workflow, and error codes.
bead detects Claude Code and Codex session identities from their environments. A claim belongs to the agent thread that made it. To continue your own work in a new session:
bead takeover ID -r "same task, new session"Use --actor NAME or BEAD_ACTOR for an explicit identity. Verify who owns a
task before taking it over; claims never expire automatically.
For automation, use --json and inspect structured error codes such as
ALREADY_CLAIMED. If a write succeeds but bead cannot count unpublished
events, the result stays on stdout and a warning goes to stderr. With
--json, the warning is a separate JSON document. Do not repeat a successful
write because of that warning; follow its repair instructions. See the
command guarantees for error and recovery details.
beadroll reads and writes Beads JSONL, including issue IDs, parent-child keys, dependencies, comments, labels, statuses, and timestamps. Preview an import, then apply it:
bead init --import .beads/issues.jsonl --dry-run
bead init --import .beads/issues.jsonlAfter migration, use bead for tracker changes. The old .beads/ directory
is no longer read or updated automatically. Export when a Beads reader such
as bv needs a copy:
bead export -o issues.jsonlImported in_progress issues have no owner until someone claims them.
beadroll's claims have no Beads equivalent and are not exported. The
migration guide covers preparation, validation, and moving back.
Compatibility checks cover import, export, ready, and blocked against
br 0.5.7 on 48 real trackers, plus reading exports with bv. Upstream bd
has not been tested. Imports containing memory records (_type: memory)
are rejected. Commands and features not implemented include stats, count,
epic status, graph, saved queries, templates, external-project
dependencies, and bv-style ranking.
Each machine appends events to its own journal under
~/.local/state/beadroll/<workspace>/. Worktrees and clones on that machine
share the store. Sync exchanges journals through refs/beads/journal on the
coordination remote, which defaults to origin. Events record what their
writer had seen, allowing every machine to reconstruct the same issue state.
Claims use a conditional update of the remote ref. A claim is exclusive only after the remote accepts it; an offline or unanswered claim is provisional. Publishing is serialized on that ref, so heavy contention and network latency can delay writes.
The stored and published format is frozen at version 1, with additive changes only. Machines can upgrade in any order. Older versions preserve and report events they cannot apply until upgraded. The guarantees describe recovery after interrupted writes, lost acknowledgements, and damaged stores, along with measured performance and known limits.
| Concurrent changes | Result after sync |
|---|---|
| Edit different fields | Both edits are kept. |
| Edit the same field | Both values are kept under conflicts; the newer one is shown. A later write that has seen both settles the conflict. |
| Set different statuses | The conflict also prevents readiness, claims, and unblocking other issues until settled. |
| Add comments | All comments are kept. |
| Add and remove a label or dependency | A removal affects only additions its writer had seen. |
| Create children of the same parent | A colliding child key is renumbered, for example app-x.1 to app-x.2, and sync reports it. |
| Add dependencies that form a blocking cycle | Dependencies are kept and reported by bead dep cycles; affected issues are not ready. |
An edit made after seeing another is not a conflict, regardless of clock differences. Child keys can change after concurrent creation; a key copied into a commit message before sync may then refer to another issue.
Most repositories need no configuration. bead derives the workspace from the
origin URL; SSH and HTTPS URLs for the same host and repository resolve to
the same workspace. A repository with neither a remote nor a .beadroll.json
gets a machine-local tracker that cannot sync.
For a different coordination remote, create a tracked configuration:
bead init --tracked --remote NAME_OR_URLCommit the generated .beadroll.json on the default branch so other
checkouts can find it. bead uses your checkout's Git transport settings,
including credential helpers and SSH configuration. See
configuration and
moving a repository for details.
All environment variables are optional:
| Variable | Purpose / default |
|---|---|
BEAD_HOME |
Store root; must be absolute after ~ expansion. Default: ~/.local/state/beadroll. |
BEAD_WORKSPACE |
Override the derived workspace ID and its check; see the repository move guide above. |
BEAD_REMOTE |
Coordination remote for this call: a remote name, URL, or path. |
BEAD_AGENT, BEAD_THREAD, BEAD_ACTOR |
Override detected identity. --actor takes precedence. |
CLAUDE_CODE_SESSION_ID, CLAUDECODE, CODEX_THREAD_ID, CODEX_SESSION_ID |
Agent harness and session detection. |
BEAD_NET_TIMEOUT |
Fetch or push timeout in seconds, including decimals. Default: 45. |
BEAD_ROTATE_BYTES |
Journal segment rotation size. Default: 262,144 bytes. |
BEAD_REPACK_LOOSE, BEAD_REPACK_PACKS |
Repack thresholds for loose objects and packs. Defaults: 1,000 and 40. |
NO_COLOR, CLICOLOR, CLICOLOR_FORCE, TERM |
Terminal color; see the command-line reference. |
COLUMNS |
Text wrapping width; otherwise the terminal width, capped at 100. |
Invalid numeric settings produce a CONFIG error, even for --version.
Variables used by tests and infrastructure scripts are listed in
CONTRIBUTING.md.
Anyone who can read the coordination repository can read its tracker. On a public repository, issue text and history are public too.
Published events contain issue data, an opaque machine ID, the agent type and
thread or explicit actor name, a timestamp, and the branch and commit where
the command ran. Set "where": false in .beadroll.json to omit the branch
and commit from future events. Hostnames used as machine aliases stay local;
remote URL credentials are removed before storage or display.
- Migration guide: move a Beads tracker to beadroll or export it back.
- Guarantees: behavior, recovery, configuration, and known limits.
- Design and review guide: architecture, format, and design decisions.
- Review findings: findings and their resolutions.
- Changelog: changes by version.
To report a problem, open an issue
with the command you ran, its --json output, bead info --json, and your
Git version. Check the output for private information before posting it.
See CONTRIBUTING.md for development setup, crate boundaries, and test requirements. From the checkout root:
cargo build --package beadroll
./check.shThe build produces target/debug/bead. The baseline requires cargo-nextest
and Python 3 in addition to the install prerequisites. Tests use temporary
stores; for manual experiments, set BEAD_HOME to a scratch directory and
work in a disposable repository to keep real trackers untouched.
Licensed under either the Apache License, Version 2.0 or the MIT license, at your option. Contributions use the same terms unless stated otherwise.