docs/GIT_INTEGRATION.md
For: AI agents and developers managing bd git workflows
bd integrates with git for worktree support and protected branch workflows. The Dolt backend handles all data storage and versioning natively.
Beads has comprehensive Git worktree compatibility with shared database architecture.
Git worktrees share the same .git directory and .beads database:
.beads/dolt/ database in the main repositoryDatabase Discovery:
BEADS_DIR, worktree fallback, and shared main-repo .beadsbd where as the authoritative check; local ./.beads may be absent in pure worktree or redirected setupsGit Operations:
Note: Beads data is stored in Dolt under refs/dolt/data, separate from standard Git refs. This means beads does not commit to any Git branch, so protected branch workflows are not affected.
Sync with remotes using Dolt's native push/pull:
bd dolt push # Push changes to Dolt remote
bd dolt pull # Pull changes from Dolt remote
# Agents work normally - no changes needed!
bd create "Fix authentication" -t bug -p 1
bd update bd-a1b2 --claim
bd close bd-a1b2 "Fixed"
# Check what's changed
bd dolt show
# Option 1: Create pull request
git push origin beads-sync
# Then create PR on GitHub/GitLab
# Option 2: Direct merge (if allowed)
git merge beads-sync
main branchesSee PROTECTED_BRANCHES.md for complete setup guide, troubleshooting, and examples.
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.
All core beads functionality works without git hooks:
| Feature | Hooks Required? | Notes |
|---|---|---|
bd create, bd update, bd close | No | Core CRUD uses Dolt directly |
bd ready, bd list, bd show | No | Read-only queries |
bd dolt push / bd dolt pull | No | Dolt-native sync, independent of git |
bd onboard, bd doctor | No | Diagnostics and onboarding |
| Agent identity trailers | Yes | prepare-commit-msg hook adds Executed-By: to commits |
| Hook chaining | Yes | Preserves existing pre-commit, post-merge hooks |
To skip hooks entirely during init:
bd init --skip-hooks
The AGENTS.md file generated by bd init provides AI agent instructions (including "Landing the Plane" push/pull workflow). If you manage your own agent instructions or don't want beads to modify tracked files:
bd init --skip-agents # Skip AGENTS.md and Claude settings generation
bd init --stealth # Full invisible mode (also skips hooks + agents)
Colocated repos (jj git init --colocate): Git hooks work normally. Beads installs simplified hooks (no staging logic).
Pure jj repos (no git): Since jj doesn't have native hooks yet, set up push aliases:
# ~/.config/jj/config.toml
[aliases]
push = ["util", "exec", "--", "sh", "-c", "bd dolt commit && bd dolt push && jj git push \"$@\"", ""]
Configure jj to use beads' merge driver for .beads/issues.jsonl:
# ~/.config/jj/config.toml
[merge-tools.beads-merge]
program = "bd"
merge-args = ["merge", "$output", "$base", "$left", "$right"]
merge-conflict-exit-codes = [1]
Then resolve with: jj resolve --tool=beads-merge .beads/issues.jsonl
bd detects and integrates with these external git hook managers:
.husky/ directory scripts.pre-commit-config.yamlWhen an external hook manager is detected, bd hooks install uses --chain to preserve existing hooks.
Add bd hooks to your hk.pkl:
hooks {
["pre-commit"] {
steps {
["bd-pre-commit"] {
check = "bd hooks run pre-commit"
}
}
}
["post-merge"] {
steps {
["bd-post-merge"] {
check = "bd hooks run post-merge"
}
}
}
["pre-push"] {
steps {
["bd-pre-push"] {
check = "bd hooks run pre-push \"$@\""
}
}
}
}
# Install hooks
bd hooks install --beads
pre-commit hook:
post-merge hook:
The beads hook shim wraps bd hooks run with an OS-level timeout to prevent hooks from hanging git operations indefinitely. The default timeout is 300 seconds (5 minutes), which accommodates repos with chained pre-commit pipelines (e.g., eslint, prettier, TypeScript compilation).
If your chained hooks need more time, override the timeout with the BEADS_HOOK_TIMEOUT environment variable:
# Set a longer timeout (in seconds)
export BEADS_HOOK_TIMEOUT=600 # 10 minutes
# Or set it per-invocation
BEADS_HOOK_TIMEOUT=600 git commit -m "..."
When the timeout is reached, beads prints a warning and allows the git operation to proceed (the commit/push is not blocked).
cmd/bd/hooks.go)The installHooks() function:
.git/hooks/ directoryos.MkdirAll() if needed.backup extension (unless --force flag used)--shared flag (installs to .beads-hooks/ instead)Critical for worktree support: The getGitDir() helper uses git rev-parse --git-dir to resolve the actual git directory:
// Returns ".git" in normal repos
// Returns "/path/to/shared/.git" in git worktrees
gitDir, err := getGitDir()
In normal repositories, .git is a directory containing the git internals.
In git worktrees, .git is a file containing gitdir: /path/to/actual/git/dir.
cmd/bd/init.go)The detectExistingHooks() function scans for existing hooks and classifies them:
┌──────────────┐ ┌─────────────────┐
│ OSS Contrib │─────▶│ Planning Repo │
│ (Fork) │ │ (.beads/dolt/) │
└──────────────┘ └─────────────────┘
│
│ PR
▼
┌─────────────────┐
│ Upstream Repo │
│ (no .beads/) │
└─────────────────┘
Best for:
Setup:
bd init --contributor # Interactive wizard
┌──────────────┐
│ Team Member │────┐
│ (main) │ │
└──────────────┘ │
▼
┌──────────────┐ ┌─────────────────┐
│ Team Member │─▶│ Shared Repo │
│ (main) │ │ (beads-sync) │
└──────────────┘ └─────────────────┘
Best for:
Setup:
bd init --team # Interactive wizard
See MULTI_REPO_MIGRATION.md for complete guide.
# Dolt database (not tracked in git)
.beads/dolt/
The Dolt database directory (.beads/dolt/) should be gitignored, not tracked via LFS or regular git.
bd includes a built-in merge driver for resolving conflicts in .beads/issues.jsonl files. This replaces the standalone beads-merge binary that was previously maintained in a separate repository.
⚠️ Deprecated: The standalone
beads-mergebinary (previously hosted atgithub.com/neongreen/mono) is no longer maintained and may be incompatible with current versions of bd. Usebd mergeinstead.
The built-in bd merge command provides the same functionality:
bd merge <output> <base> <left> <right>
See also: Branchless Workflows for a complete guide.
For Jujutsu users, add to ~/.config/jj/config.toml:
[merge-tools.beads-merge]
program = "bd"
merge-args = ["merge", "$output", "$base", "$left", "$right"]
merge-conflict-exit-codes = [1]
Then resolve conflicts with:
jj resolve --tool=beads-merge .beads/issues.jsonl
This configures Jujutsu to invoke bd merge as its merge tool, restricted to .beads/issues.jsonl (since it only handles beads data conflicts, not general file conflicts).