Skip to main content
How beads integrates with git.

Overview

Beads uses git for:
  • Project hosting - Your code repository also hosts beads configuration
  • Hooks - Auto-sync on git operations
Data storage and sync are handled by Dolt (a version-controlled SQL database) — see Sync Concepts for how issue data moves between machines.

File Structure

bd init writes .beads/.gitignore to keep the database directory and runtime files out of git — no manual gitignore rules are needed. Never track the database directory (.beads/embeddeddolt/ or .beads/dolt/) in git or via Git LFS.

Git Hooks

Installation

bd init installs hooks by default (skip with bd init --skip-hooks). To install or refresh them manually:
Installed hooks are thin shims that call bd hooks run <hook-name>. Upgrading bd automatically updates the delegated behavior inside that command; the shim’s generated shell policy remains installed content and changes only when the hook is installed or refreshed: The shims use section markers to coexist with existing hooks — content outside the markers is preserved across installs and upgrades. Install variants:
Hook installation is worktree-aware: bd resolves the shared git directory, so installing from a linked worktree works.

Status

Uninstall

External Hook Managers

bd detects these external git hook managers and checks whether their config calls bd hooks run:
  • lefthook — YAML/TOML/JSON config
  • husky.husky/ directory scripts
  • pre-commit.pre-commit-config.yaml
  • prek — Rust-based pre-commit alternative (same config)
  • hk — fast hook manager using Pkl config
  • overcommit — Ruby-based (detection only)
  • yorkie — detection only
  • simple-git-hooks — lightweight JS (detection only)
bd doctor reports whether a detected manager is integrated with bd, and bd doctor --fix reinstalls the hooks with --chain so the manager’s existing hooks keep running. For config-driven managers, add bd steps directly. Example hk.pkl:

Hook Timeout

The hook shim applies a soft deadline to bd hooks run when a compatible helper is available. It uses timeout or gtimeout only after a successful GNU coreutils identity probe, avoiding the incompatible timeout.exe that native Windows can place on PATH. GNU timeout sends TERM at the configured deadline. On POSIX hosts, the Perl fallback uses SIGALRM on the direct bd process at the deadline. Git for Windows Perl does not guarantee that alarm across exec, so GNU coreutils is the preferred deadline backend there. The default deadline is 300 seconds (5 minutes), which accommodates chained pre-commit pipelines (eslint, prettier, TypeScript compilation). Override it with the BEADS_HOOK_TIMEOUT environment variable:
The value must be a positive whole number of seconds. Invalid values and zero produce a warning and use the 300-second default. These are soft process deadlines, not process-tree containment: TERM-resistant work or descendants can outlive them. If neither GNU timeout nor Perl is available, the hook warns and runs directly without a deadline; that last-resort path can hang until the hook itself returns. After upgrading from a release whose generated hooks used a name-only timeout check, run bd hooks install once to refresh already-installed canonical hook sections. Automatic generated-policy adoption is tracked separately. When the timeout is reached, beads prints a warning and lets the git operation proceed — the commit or push is not blocked.

Conflict Resolution

Dolt handles merge conflicts at the database level using its built-in merge capabilities. When conflicts arise during sync, Dolt identifies conflicting rows and allows resolution through SQL.

Protected Branches

Dolt stores data under refs/dolt/data, separate from Git refs. This means beads data does not conflict with protected Git branches, and no separate beads-sync branch or protected-branch exception is needed. On new projects with a Git origin, bd init configures that origin as the Dolt remote automatically. See Protected Branches for the full workflow, including legacy beads-sync cleanup.

Git Worktrees

Beads works in Git worktrees without extra setup. Linked worktrees discover the repository’s .beads workspace and sync issue data through Dolt:
All worktrees share the repository’s .beads workspace: discovery follows BEADS_DIR if set, then the main repository’s .beads, preventing database duplication across worktrees. Use bd where as the authoritative check for which workspace is active — a local ./.beads may legitimately be absent in a worktree. Embedded mode (the default) serves one writer at a time; for concurrent writers across worktrees, use server mode. See Git Worktrees for the full guide. Older beads versions documented a sync.branch workflow that created hidden Git worktrees. That workflow has been removed; current sync uses Dolt remotes.

Branch Workflows

Feature Branch

Fork Workflow

The contributor wizard keeps issue data in a separate planning repository, leaving the upstream repo without any .beads/. Best for open source contributors, solo developers, and private task tracking on public repos. bd init auto-detects forks and offers to configure .git/info/exclude (--setup-exclude) so beads files stay local. Set the role without prompting via --role contributor or --role maintainer (the default in non-interactive mode).

Team Workflow

Best for teams on protected branches and review-before-merge policies. See Multi-Repo Migration for multi-repo patterns.

Duplicate Detection

After merging branches:

Branchless Workflows (Jujutsu / jj)

Beads works with branchless VCS tools like Jujutsu (jj). Since beads data is stored in Dolt (not git branches), there is no dependency on the “current branch” concept.

What Works Without Hooks

All core beads functionality works without git hooks: To skip hooks entirely during init:

What Works Without AGENTS.md

The AGENTS.md file generated by bd init provides AI agent instructions. If you manage your own agent instructions or don’t want beads to modify tracked files:

Jujutsu Setup

Colocated repos (jj git init --colocate): Git hooks work normally. Beads installs simplified hooks (pre-commit and post-merge only, no staging logic). Pure jj repos (no git): Since jj doesn’t have native hooks yet, set up push aliases:
Then use jj push instead of jj git push.

Best Practices

  1. Install hooks - bd hooks install
  2. Push regularly - bd dolt push at session end
  3. Pull before work - bd dolt pull to get latest issues
  4. Use normal Git worktrees - no sync branch is required