Files
beads/README.md
Steve Yegge a2957f5ee3 Highlight distributed database architecture in README
Added new section "The Magic: Distributed Database via Git" explaining
the key insight: bd provides the illusion of a centralized database
while actually distributing via git.

Key points:
- Feels like centralized DB (query, update from any machine)
- Actually distributed via git (JSONL source of truth)
- Local SQLite cache for fast queries (<100ms)
- No server, daemon, or configuration needed
- AI-assisted conflict resolution for the rare conflicts

Updated Features section:
- 📦 Git-versioned - JSONL records stored in git
- 🌍 Distributed by design - Multiple machines share one logical DB

Updated comparison table to emphasize no-server advantage:
- "Distributed via git" vs "Git-native storage"
- "No server required" vs "Self-hosted"

This clarifies what makes bd unique: you get database-like behavior
(queries, transactions, dependencies) without database-like operations
(server setup, hosting, network config). Just install bd, clone repo.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-12 10:31:56 -07:00

15 KiB

bd - Beads Issue Tracker 🔗

Issues chained together like beads.

A lightweight, dependency-aware issue tracker designed for AI-supervised coding workflows. Track dependencies, find ready work, and let agents chain together tasks automatically.

Features

  • Zero setup - bd init creates project-local database
  • 🔗 Dependency tracking - Four dependency types (blocks, related, parent-child, discovered-from)
  • 📋 Ready work detection - Automatically finds issues with no open blockers
  • 🤖 Agent-friendly - --json flags for programmatic integration
  • 📦 Git-versioned - JSONL records stored in git, synced across machines
  • 🌍 Distributed by design - Agents on multiple machines share one logical database via git
  • 🏗️ Extensible - Add your own tables to the SQLite database
  • 🔍 Project-aware - Auto-discovers database in .beads/ directory
  • 🌲 Dependency trees - Visualize full dependency graphs
  • 🎨 Beautiful CLI - Colored output for humans, JSON for bots
  • 💾 Full audit trail - Every change is logged

Installation

go install github.com/steveyegge/beads/cmd/bd@latest

Or build from source:

git clone https://github.com/steveyegge/beads
cd beads
go build -o bd ./cmd/bd

Quick Start

For Humans

Beads is designed for AI coding agents to use on your behalf. As a human, you typically just:

# 1. Initialize beads in your project
bd init

# 2. Add a note to your agent instructions (CLAUDE.md, AGENTS.md, etc.)
echo "We track work in Beads instead of Markdown. Run \`bd quickstart\` to see how." >> CLAUDE.md

# 3. Let agents handle the rest!

Most tasks will be created and managed by agents during conversations. You can check on things with:

bd list                  # See what's being tracked
bd show <issue-id>       # Review a specific issue
bd ready                 # See what's ready to work on
bd dep tree <issue-id>   # Visualize dependencies

For AI Agents

Run the interactive guide to learn the full workflow:

bd quickstart

Quick reference for agent workflows:

# Find ready work
bd ready --json | jq '.[0]'

# Create issues during work
bd create "Discovered bug" -t bug -p 0 --json

# Link discovered work back to parent
bd dep add <new-id> <parent-id> --type discovered-from

# Update status
bd update <issue-id> --status in_progress --json

# Complete work
bd close <issue-id> --reason "Implemented" --json

The Magic: Distributed Database via Git

Here's the crazy part: bd acts like a centralized database, but it's actually distributed via git.

When you install bd on any machine with your project repo, you get:

  • Full query capabilities (dependencies, ready work, etc.)
  • Fast local operations (<100ms via SQLite)
  • Shared state across all machines (via git)
  • No server, no daemon, no configuration
  • AI-assisted merge conflict resolution

How it works:

  1. Each machine has a local SQLite cache (.beads/*.db) - gitignored
  2. Source of truth is JSONL (.beads/issues.jsonl) - committed to git
  3. bd export syncs SQLite → JSONL before commits
  4. bd import syncs JSONL → SQLite after pulls
  5. Git handles distribution; AI handles merge conflicts

The result: Agents on your laptop, your desktop, and your coworker's machine all query and update what feels like a single shared database, but it's really just git doing what git does best - syncing text files across machines.

No PostgreSQL instance. No MySQL server. No hosted service. Just install bd, clone the repo, and you're connected to the "database."

Usage

Creating Issues

bd create "Fix bug" -d "Description" -p 1 -t bug
bd create "Add feature" --description "Long description" --priority 2 --type feature
bd create "Task" -l "backend,urgent" --assignee alice

# Get JSON output for programmatic use
bd create "Fix bug" -d "Description" --json

Options:

  • -d, --description - Issue description
  • -p, --priority - Priority (0-4, 0=highest)
  • -t, --type - Type (bug|feature|task|epic|chore)
  • -a, --assignee - Assign to user
  • -l, --labels - Comma-separated labels
  • --json - Output in JSON format

Viewing Issues

bd show bd-1              # Show full details
bd list                   # List all issues
bd list --status open     # Filter by status
bd list --priority 1      # Filter by priority
bd list --assignee alice  # Filter by assignee

# JSON output for agents
bd list --json
bd show bd-1 --json

Updating Issues

bd update bd-1 --status in_progress
bd update bd-1 --priority 2
bd update bd-1 --assignee bob
bd close bd-1 --reason "Completed"
bd close bd-1 bd-2 bd-3   # Close multiple

# JSON output
bd update bd-1 --status in_progress --json
bd close bd-1 --json

Dependencies

# Add dependency (bd-2 depends on bd-1)
bd dep add bd-2 bd-1
bd dep add bd-3 bd-1 --type blocks

# Remove dependency
bd dep remove bd-2 bd-1

# Show dependency tree
bd dep tree bd-2

# Detect cycles
bd dep cycles

Finding Work

# Show ready work (no blockers)
bd ready
bd ready --limit 20
bd ready --priority 1
bd ready --assignee alice

# Show blocked issues
bd blocked

# Statistics
bd stats

# JSON output for agents
bd ready --json

Database Discovery

bd automatically discovers your database in this order:

  1. --db flag: bd --db /path/to/db.db create "Issue"
  2. $BEADS_DB environment variable: export BEADS_DB=/path/to/db.db
  3. .beads/*.db in current directory or ancestors (walks up like git)
  4. ~/.beads/default.db as fallback

This means you can:

  • Initialize per-project databases with bd init
  • Work from any subdirectory (bd finds the database automatically)
  • Override for testing or multiple projects

Example:

# Initialize in project root
cd ~/myproject
bd init --prefix myapp

# Work from any subdirectory
cd ~/myproject/src/components
bd create "Fix navbar bug"  # Uses ~/myproject/.beads/myapp.db

# Override for a different project
bd --db ~/otherproject/.beads/other.db list

Dependency Model

Beads has four types of dependencies:

  1. blocks - Hard blocker (affects ready work calculation)
  2. related - Soft relationship (just for context)
  3. parent-child - Epic/subtask hierarchy
  4. discovered-from - Tracks issues discovered while working on another issue

Only blocks dependencies affect the ready work queue.

Dependency Type Usage

  • blocks: Use when issue X cannot start until issue Y is completed

    bd dep add bd-5 bd-3 --type blocks  # bd-5 blocked by bd-3
    
  • related: Use for issues that are connected but don't block each other

    bd dep add bd-10 bd-8 --type related  # bd-10 related to bd-8
    
  • parent-child: Use for epic/subtask hierarchies

    bd dep add bd-15 bd-12 --type parent-child  # bd-15 is child of epic bd-12
    
  • discovered-from: Use when you discover new work while working on an issue

    # While working on bd-20, you discover a bug
    bd create "Fix edge case bug" -t bug -p 1
    bd dep add bd-21 bd-20 --type discovered-from  # bd-21 discovered from bd-20
    

The discovered-from type is particularly useful for AI-supervised workflows, where the AI can automatically create issues for discovered work and link them back to the parent task.

AI Agent Integration

bd is designed to work seamlessly with AI coding agents:

# Agent discovers ready work
WORK=$(bd ready --limit 1 --json)
ISSUE_ID=$(echo $WORK | jq -r '.[0].id')

# Agent claims and starts work
bd update $ISSUE_ID --status in_progress --json

# Agent discovers new work while executing
bd create "Fix bug found in testing" -t bug -p 0 --json > new_issue.json
NEW_ID=$(cat new_issue.json | jq -r '.id')
bd dep add $NEW_ID $ISSUE_ID --type discovered-from

# Agent completes work
bd close $ISSUE_ID --reason "Implemented and tested" --json

The --json flag on every command makes bd perfect for programmatic workflows.

Ready Work Algorithm

An issue is "ready" if:

  • Status is open
  • It has NO open blocks dependencies
  • All blockers are either closed or non-existent

Example:

bd-1 [open] ← blocks ← bd-2 [open] ← blocks ← bd-3 [open]

Ready work: [bd-1] Blocked: [bd-2, bd-3]

Issue Lifecycle

open → in_progress → closed
       ↓
     blocked (manually set, or has open blockers)

Architecture

beads/
├── cmd/bd/              # CLI entry point
│   ├── main.go          # Core commands (create, list, show, update, close)
│   ├── init.go          # Project initialization
│   ├── quickstart.go    # Interactive guide
│   └── ...
├── internal/
│   ├── types/           # Core data types (Issue, Dependency, etc.)
│   └── storage/         # Storage interface
│       └── sqlite/      # SQLite implementation
└── EXTENDING.md         # Database extension guide

Extending bd

Applications can extend bd's SQLite database with their own tables. See EXTENDING.md for the full guide.

Quick example:

-- Add your own tables to .beads/myapp.db
CREATE TABLE myapp_executions (
    id INTEGER PRIMARY KEY,
    issue_id TEXT NOT NULL,
    status TEXT NOT NULL,
    started_at DATETIME,
    FOREIGN KEY (issue_id) REFERENCES issues(id)
);

-- Query across layers
SELECT i.*, e.status as execution_status
FROM issues i
LEFT JOIN myapp_executions e ON i.id = e.issue_id
WHERE i.status = 'in_progress';

This pattern enables powerful integrations while keeping bd simple and focused.

Comparison to Other Tools

Feature bd GitHub Issues Jira Linear
Zero setup
Dependency tracking ⚠️
Ready work detection
Agent-friendly (JSON) ⚠️ ⚠️ ⚠️
Distributed via git
Works offline
AI-resolvable conflicts
Extensible database
No server required

Why bd?

bd is designed for AI coding agents, not humans.

Traditional issue trackers (Jira, GitHub Issues, Linear) assume humans are the primary users. Humans click through web UIs, drag cards on boards, and manually update status.

bd assumes AI agents are the primary users, with humans supervising:

  • Agents discover work - bd ready --json gives agents unblocked tasks to execute
  • Dependencies prevent wasted work - Agents don't duplicate effort or work on blocked tasks
  • Discovery during execution - Agents create issues for work they discover while executing, linked with discovered-from
  • Agents lose focus - Long-running conversations can forget tasks; bd remembers everything
  • Humans supervise - Check on progress with bd list and bd dep tree, but don't micromanage

In human-managed workflows, issues are planning artifacts. In agent-managed workflows, issues are memory - preventing agents from forgetting tasks during long coding sessions.

Traditional issue trackers were built for human project managers. bd is built for autonomous agents.

Architecture: JSONL + SQLite

bd uses a dual-storage approach:

  • JSONL files (.beads/issues.jsonl) - Source of truth, committed to git
  • SQLite database (.beads/*.db) - Ephemeral cache for fast queries, gitignored

This gives you:

  • Git-friendly storage - Text diffs, AI-resolvable conflicts
  • Fast queries - SQLite indexes for dependency graphs
  • Simple workflow - Export before commit, import after pull
  • No daemon required - In-process SQLite, ~10-100ms per command

When you run bd create, it writes to SQLite. Before committing to git, run bd export to sync to JSONL. After pulling, run bd import to sync back to SQLite. Git hooks can automate this.

Export/Import (JSONL Format)

bd can export and import issues as JSON Lines (one JSON object per line). This is perfect for git workflows and data portability.

Export Issues

# Export all issues to stdout
bd export --format=jsonl

# Export to file
bd export --format=jsonl -o issues.jsonl

# Export filtered issues
bd export --format=jsonl --status=open -o open-issues.jsonl

Issues are exported sorted by ID for consistent git diffs.

Import Issues

# Import from stdin
cat issues.jsonl | bd import

# Import from file
bd import -i issues.jsonl

# Skip existing issues (only create new ones)
bd import -i issues.jsonl --skip-existing

Import behavior:

  • Existing issues (same ID) are updated with new values
  • New issues are created
  • All imports are atomic (all or nothing)

JSONL Format

Each line is a complete JSON issue object:

{"id":"bd-1","title":"Fix login bug","status":"open","priority":1,"issue_type":"bug","created_at":"2025-10-12T10:00:00Z","updated_at":"2025-10-12T10:00:00Z"}
{"id":"bd-2","title":"Add dark mode","status":"in_progress","priority":2,"issue_type":"feature","created_at":"2025-10-12T11:00:00Z","updated_at":"2025-10-12T12:00:00Z"}

Git Workflow

Recommended approach: Use JSONL export as source of truth, SQLite database as ephemeral cache (not committed to git).

Setup

Add to .gitignore:

.beads/*.db
.beads/*.db-*

Add to git:

.beads/issues.jsonl

Workflow

# Export before committing
bd export -o .beads/issues.jsonl
git add .beads/issues.jsonl
git commit -m "Update issues"
git push

# Import after pulling
git pull
bd import -i .beads/issues.jsonl

Automated with Git Hooks

Create .git/hooks/pre-commit:

#!/bin/bash
bd export -o .beads/issues.jsonl
git add .beads/issues.jsonl

Create .git/hooks/post-merge:

#!/bin/bash
bd import -i .beads/issues.jsonl

Make hooks executable:

chmod +x .git/hooks/pre-commit .git/hooks/post-merge

Why JSONL?

  • Git-friendly: One line per issue = clean diffs
  • Mergeable: Concurrent appends rarely conflict
  • Human-readable: Easy to review changes
  • Scriptable: Use jq, grep, or any text tools
  • Portable: Export/import between databases

Handling Conflicts

When two developers create new issues:

 {"id":"bd-1","title":"First issue",...}
 {"id":"bd-2","title":"Second issue",...}
+{"id":"bd-3","title":"From branch A",...}
+{"id":"bd-4","title":"From branch B",...}

Git may show a conflict, but resolution is simple: keep both lines (both changes are compatible).

See TEXT_FORMATS.md for detailed analysis of JSONL merge strategies and conflict resolution.

Documentation

  • README.md - You are here! Complete guide
  • TEXT_FORMATS.md - JSONL format analysis and merge strategies
  • GIT_WORKFLOW.md - Historical analysis of binary vs text approaches
  • EXTENDING.md - Database extension patterns
  • Run bd quickstart for interactive tutorial

Development

# Run tests
go test ./...

# Build
go build -o bd ./cmd/bd

# Run
./bd create "Test issue"

License

MIT

Credits

Built with ❤️ by developers who love tracking dependencies and finding ready work.

Inspired by the need for a simpler, dependency-aware issue tracker.