docs/WORKTREES.md
Enhanced Git worktree compatibility for Beads issue tracking
Beads now provides enhanced Git worktree support with a shared database architecture. All worktrees in a repository share the same .beads database located in the main repository, enabling seamless issue tracking across multiple working directories.
Note: While comprehensively implemented and tested internally, this feature may benefit from real-world usage feedback to identify any remaining edge cases.
Important: Beads automatically creates git worktrees internally for its sync-branch feature. This is different from user-created worktrees for parallel development.
Note: The sync-branch feature has been removed. Dolt now stores data under refs/dolt/data, separate from standard Git refs, so a separate branch is no longer needed. The information below applies only to older versions of beads.
When a sync branch was configured (via bd config set sync.branch <name>), beads needed to commit issue updates to that branch without switching your working directory away from your current branch.
Solution: Beads creates a lightweight worktree that:
.beads/ directory (sparse checkout).git/beads-worktrees/<sync-branch>/your-project/
├── .git/
│ ├── beads-worktrees/ # Beads-created worktrees live here
│ │ └── beads-sync/ # Default sync branch worktree
│ │ └── .beads/
│ │ └── dolt/ # Dolt database
│ └── worktrees/ # Standard git worktrees directory
├── .beads/ # Your working copy
│ └── dolt/ # Local Dolt database
└── src/ # Your code (untouched by sync)
If you see worktrees pointing to main and can't switch branches normally, this is likely because:
mainSymptoms:
$ git checkout main
fatal: 'main' is already checked out at '/path/to/.git/beads-worktrees/beads-sync'
Quick Fix:
# Remove the beads worktree
rm -rf .git/beads-worktrees
# Prune stale worktree references
git worktree prune
# Also remove any stray worktrees in .git/worktrees (older versions)
rm -rf .git/worktrees/beads-*
git worktree prune
If you don't want beads to use a separate sync branch:
# Unset the sync branch configuration
bd config set sync.branch ""
# Clean up existing worktrees
rm -rf .git/beads-worktrees
git worktree prune
# See current sync branch setting
bd config get sync.branch
# Check if worktrees exist
ls -la .git/beads-worktrees/ 2>/dev/null || echo "No beads worktrees"
ls -la .git/worktrees/ 2>/dev/null || echo "No standard worktrees"
# List all git worktrees
git worktree list
For complete sync-branch documentation, see PROTECTED_BRANCHES.md.
Main Repository
├── .git/ # Shared git directory
├── .beads/ # Shared database (main repo)
│ ├── dolt/ # Dolt database directory
│ └── config.yaml # Configuration
├── feature-branch/ # Worktree 1
│ └── (code files only)
└── bugfix-branch/ # Worktree 2
└── (code files only)
Key points:
.beads directory in main repobd automatically detects when you're in a git worktree:
Default behavior (no sync-branch configured):
With sync-branch configured:
beads-sync)# Configure sync-branch once (in main repo or any worktree)
bd config set sync-branch beads-sync
# Now server mode works safely in all worktrees
cd feature-worktree
bd create "Implement feature X" -t feature -p 1
bd update bd-a1b2 --claim
bd ready # Auto-syncs to beads-sync branch
# Without sync-branch, worktrees use embedded mode automatically
cd feature-worktree
bd create "Implement feature X" -t feature -p 1
bd ready # Uses embedded mode automatically
bd dolt push # Manual sync when needed
bd intelligently finds the correct database:
.beads directory first.beads contains actual project filesPre-commit hooks adapt to worktree context:
# In main repo: Runs beads checks normally
# In worktree: Safely handles shared database context
# Hook detects context and handles appropriately
Worktree-aware sync operations:
git rev-parse --show-toplevel for main repo.git (file) and .git/ (directory)# Create main worktree
git worktree add main-repo
# Create feature worktree
git worktree add feature-worktree
# Initialize beads in main repo
cd main-repo
bd init
# Worktrees automatically share the database
cd ../feature-worktree
bd ready # Works immediately - sees same issues
# Main development
cd main-repo
bd create "Epic: User authentication" -t epic -p 1
# Returns: bd-a3f8e9
# Feature branch worktree
git worktree add auth-feature
cd auth-feature
bd create "Design login UI" -p 1
# Auto-assigned: bd-a3f8e9.1 (child of epic)
# Bugfix worktree
git worktree add auth-bugfix
cd auth-bugfix
bd create "Fix password validation" -t bug -p 0
# Auto-assigned: bd-f14c3
Symptoms:
$ git checkout main
fatal: 'main' is already checked out at '/path/to/.git/beads-worktrees/beads-sync'
Cause: Beads created a worktree for its sync branch feature, and that worktree has your target branch checked out. Git doesn't allow the same branch to be checked out in multiple worktrees.
Solution:
# Remove beads worktrees
rm -rf .git/beads-worktrees
rm -rf .git/worktrees/beads-*
# Clean up git's worktree registry
git worktree prune
# Now you can checkout the branch
git checkout main
Prevention: If you use trunk-based development and don't need a separate sync branch, disable it:
bd config set sync.branch ""
Symptoms: You notice .git/beads-worktrees/ or entries in .git/worktrees/ that you didn't create.
Cause: Older versions of beads created worktrees for the sync-branch feature (configured via bd config set sync.branch). This feature has been removed.
Solution: See Beads-Created Worktrees section above for details on what these are and how to remove them if unwanted.
Symptoms: Changes appear on unexpected branch in git history
Note: This issue should no longer occur with the worktree safety feature. Worktrees use embedded mode automatically unless sync-branch is configured.
Solution (if still occurring):
# Configure sync-branch (recommended)
bd config set sync-branch beads-sync
Symptoms: bd: database not found error
Solutions:
# Ensure main repo has .beads directory
cd main-repo
ls -la .beads/
# Re-run bd init if needed
bd init
# Check worktree can access main repo
cd ../worktree-name
bd info # Should show database path in main repo
Symptoms: Warning about multiple .beads directories
Solution:
# bd shows warning with database locations
# Typically, the closest database (in main repo) is correct
# Remove extra .beads directories if they're not needed
Symptoms: Pre-commit hook errors about staging files outside working tree
Solution: This is now automatically handled. The hook detects worktree context and adapts its behavior. No manual intervention needed.
# Force specific database location
export BEADS_DB=/path/to/specific/.beads/dolt
# Configure sync behavior
bd config set sync.branch beads-sync # Use separate sync branch
# Configure Dolt auto-commit
bd config set dolt.auto-commit true
bd dolt start for multi-writer)Note: Based on comprehensive internal testing. Real-world usage may reveal additional refinements needed.
# Monorepo with multiple service worktrees
git worktree add services/auth
git worktree add services/api
git worktree add services/web
# Each service team works in their worktree
cd services/auth
bd create "Add OAuth support" -t feature -p 1
cd ../api
bd create "Implement auth endpoints" -p 1
# Issues automatically linked and visible across worktrees
# Create feature worktree
git worktree add feature/user-profiles
cd feature/user-profiles
# Work on feature with full issue tracking
bd create "Design user profile schema" -t task -p 1
bd create "Implement profile API" -t task -p 1
bd create "Add profile UI components" -t task -p 2
# Issues tracked in shared database
# Code changes isolated to worktree
# Clean merge back to main when ready
For users who want complete separation between code history and issue tracking, beads supports storing issues in a completely separate git repository.
Option A: Initialize with BEADS_DIR (simplest)
# 1. Create the directory structure
mkdir -p ~/my-project-beads/.beads
# 2. Set BEADS_DIR and initialize from anywhere
export BEADS_DIR=~/my-project-beads/.beads
bd init --prefix myproj # Creates database at $BEADS_DIR
# 3. Initialize git in the beads repo (optional, for sync)
cd ~/my-project-beads && git init
Option B: Traditional approach
# 1. Create a dedicated beads repository (one-time)
mkdir ~/my-project-beads
cd ~/my-project-beads
git init
bd init --prefix myproj
# 2. Add a remote for cross-machine sync (optional)
git remote add origin [email protected]:you/my-project-beads.git
git push -u origin main
Set BEADS_DIR to point at your separate beads repository:
cd ~/my-project
export BEADS_DIR=~/my-project-beads/.beads
# All bd commands now use the separate repo
bd create "My task" -t task
bd list
bd dolt push # commits to ~/my-project-beads, pushes there
Option 1: Shell profile
# Add to ~/.bashrc or ~/.zshrc
export BEADS_DIR=~/my-project-beads/.beads
Option 2: direnv (per-project)
# In ~/my-project/.envrc
export BEADS_DIR=~/my-project-beads/.beads
Option 3: Wrapper script
# ~/bin/bd-myproj
#!/bin/bash
BEADS_DIR=~/my-project-beads/.beads exec bd "$@"
When BEADS_DIR points to a different git repository than your current directory:
bd dolt push detects "External BEADS_DIR"This was contributed by @dand-oss in PR #533.
This approach elegantly solves the worktree isolation problem:
# All worktrees share the same external beads repo
export BEADS_DIR=~/project-beads/.beads
cd ~/project/main && bd list # Same issues
cd ~/project/feature-1 && bd list # Same issues
cd ~/project/feature-2 && bd list # Same issues
No conflicts, no branch confusion - all worktrees see the same issues because they all use the same external repository.