Files
beads/examples/git-hooks
Steve Yegge 584cd1ebfc Implement auto-import to complete automatic git sync workflow
Adds auto-import feature to complement bd-35's auto-export, completing
the automatic sync workflow for git collaboration.

**Implementation:**
- Auto-import checks if JSONL is newer than DB on command startup
- Silently imports JSONL when modification time is newer
- Skips import command itself to avoid recursion
- Can be disabled with --no-auto-import flag

**Documentation updates:**
- Updated README.md git workflow section
- Updated CLAUDE.md workflow and pro tips
- Updated bd quickstart with auto-sync section
- Updated git hooks README to clarify they're now optional

**Testing:**
- Tested auto-import by touching JSONL and running commands
- Tested auto-export with create/close operations
- Complete workflow verified working

Closes bd-33

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-13 22:48:30 -07:00
..

Git Hooks for Beads

Optional git hooks for immediate export/import of beads issues.

NOTE: As of bd v0.9+, auto-sync is enabled by default! These hooks are optional and provide:

  • Immediate export (no 5-second debounce wait)
  • Guaranteed import after every git operation
  • Extra safety for critical workflows

What These Hooks Do

  • pre-commit: Exports SQLite → JSONL before every commit (immediate, no debounce)
  • post-merge: Imports JSONL → SQLite after git pull/merge (guaranteed)
  • post-checkout: Imports JSONL → SQLite after branch switching (guaranteed)

This keeps your .beads/issues.jsonl (committed to git) in sync with your local SQLite database (gitignored).

Do You Need These Hooks?

Most users don't need hooks anymore! bd automatically:

  • Exports after CRUD operations (5-second debounce)
  • Imports when JSONL is newer than DB

Install hooks if you:

  • Want immediate export (no waiting 5 seconds)
  • Want guaranteed import after every git operation
  • Need extra certainty for team workflows
  • Prefer explicit automation over automatic behavior

Installation

Quick Install

cd /path/to/your/project
./examples/git-hooks/install.sh

The installer will prompt before overwriting existing hooks.

Manual Install

# Copy hooks to .git/hooks/
cp examples/git-hooks/pre-commit .git/hooks/
cp examples/git-hooks/post-merge .git/hooks/
cp examples/git-hooks/post-checkout .git/hooks/

# Make them executable
chmod +x .git/hooks/pre-commit
chmod +x .git/hooks/post-merge
chmod +x .git/hooks/post-checkout

Usage

Once installed, the hooks run automatically:

# Creating/updating issues
bd create "New feature" -p 1
bd update bd-1 --status in_progress

# Committing changes - hook exports automatically
git add .
git commit -m "Update feature"
# 🔗 Exporting beads issues to JSONL...
# ✓ Beads issues exported and staged

# Pulling changes - hook imports automatically
git pull
# 🔗 Importing beads issues from JSONL...
# ✓ Beads issues imported successfully

# Switching branches - hook imports automatically
git checkout feature-branch
# 🔗 Importing beads issues from JSONL...
# ✓ Beads issues imported successfully

How It Works

The Workflow

  1. You work with bd commands (create, update, close)
  2. Changes are stored in SQLite (.beads/*.db) - fast local queries
  3. Before commit, hook exports to JSONL (.beads/issues.jsonl) - git-friendly
  4. JSONL is committed to git (source of truth)
  5. After pull/merge/checkout, hook imports JSONL back to SQLite
  6. Your local SQLite cache is now in sync with git

Why This Design?

SQLite for speed:

  • Fast queries (dependency trees, ready work)
  • Rich SQL capabilities
  • Sub-100ms response times

JSONL for git:

  • Clean diffs (one issue per line)
  • Mergeable (independent lines)
  • Human-readable
  • AI-resolvable conflicts

Best of both worlds!

Troubleshooting

Hook not running

# Check if hook is executable
ls -l .git/hooks/pre-commit
# Should show -rwxr-xr-x

# Make it executable if needed
chmod +x .git/hooks/pre-commit

Export/import fails

# Check if bd is in PATH
which bd

# Check if you're in a beads-initialized directory
bd list

Merge conflicts in issues.jsonl

If you get merge conflicts in .beads/issues.jsonl:

  1. Most conflicts are safe to resolve by keeping both sides
  2. Each line is an independent issue
  3. Look for <<<<<<< HEAD markers
  4. Keep all lines that don't conflict
  5. For actual conflicts on the same issue, choose the newest

Example conflict:

<<<<<<< HEAD
{"id":"bd-3","title":"Updated title","status":"closed","updated_at":"2025-10-12T10:00:00Z"}
=======
{"id":"bd-3","title":"Updated title","status":"in_progress","updated_at":"2025-10-12T09:00:00Z"}
>>>>>>> feature-branch

Resolution: Keep the HEAD version (newer timestamp).

After resolving:

git add .beads/issues.jsonl
git commit
bd import -i .beads/issues.jsonl  # Sync to SQLite

Uninstalling

rm .git/hooks/pre-commit
rm .git/hooks/post-merge
rm .git/hooks/post-checkout

Customization

Skip hook for one commit

git commit --no-verify -m "Skip hooks"

Add to existing hooks

If you already have git hooks, you can append to them:

# Append to existing pre-commit
cat examples/git-hooks/pre-commit >> .git/hooks/pre-commit

Filter exports

Export only specific issues:

# Edit pre-commit hook, change:
bd export --format=jsonl -o .beads/issues.jsonl

# To:
bd export --format=jsonl --status=open -o .beads/issues.jsonl

See Also