docs/CLI_REFERENCE.md
For: AI agents and developers using bd command-line interface
Version: 0.21.0+
# Check database path and server status
bd info --json
# Example output:
# {
# "database_path": "/path/to/.beads/beads.db",
# "issue_prefix": "bd",
# "agent_mail_enabled": false
# }
# Find ready work (no blockers, not already claimed)
bd ready --json
# Atomically claim an issue from the ready queue
bd update <id> --claim --json # Fails if already claimed
# Find stale issues (not updated recently)
bd stale --days 30 --json # Default: 30 days
bd stale --days 90 --status in_progress --json # Find abandoned claims
bd stale --limit 20 --json # Limit results
# Basic creation
# IMPORTANT: Always quote titles and descriptions with double quotes
bd create "Issue title" -t bug|feature|task -p 0-4 -d "Description" --json
# Create with explicit ID (for parallel workers)
bd create "Issue title" --id worker1-100 -p 1 --json
# Create with labels (--labels or --label work)
bd create "Issue title" -t bug -p 1 -l bug,critical --json
bd create "Issue title" -t bug -p 1 --label bug,critical --json
# Examples with special characters (all require quoting):
bd create "Fix: auth doesn't validate tokens" -t bug -p 1 --json
bd create "Add support for OAuth 2.0" -d "Implement RFC 6749 (OAuth 2.0 spec)" --json
bd create "Implement auth" --spec-id "docs/specs/auth.md" --json
# Create multiple issues from markdown file
bd create -f feature-plan.md --json
# Create with description from file (avoids shell escaping issues)
bd create "Issue title" --body-file=description.md --json
bd create "Issue title" --body-file description.md -p 1 --json
# Read description from stdin
echo "Description text" | bd create "Issue title" --stdin --json
cat description.md | bd create "Issue title" --stdin -p 1 --json
# --body-file=- also works:
echo "Description text" | bd create "Issue title" --body-file=- --json
# Create epic with hierarchical child tasks
bd create "Auth System" -t epic -p 1 --json # Returns: bd-a3f8e9
bd create "Login UI" -p 1 --parent bd-a3f8e9 --json # Auto-assigned: bd-a3f8e9.1
bd create "Backend validation" -p 1 --parent bd-a3f8e9 --json # Auto-assigned: bd-a3f8e9.2
bd create "Tests" -p 1 --parent bd-a3f8e9 --json # Auto-assigned: bd-a3f8e9.3
# Create and link discovered work (one command)
bd create "Found bug" -t bug -p 1 --deps discovered-from:<parent-id> --json
# Create with external reference (v0.9.2+)
bd create "Fix login" -t bug -p 1 --external-ref "gh-123" --json # Short form
bd create "Fix login" -t bug -p 1 --external-ref "https://github.com/org/repo/issues/123" --json # Full URL
bd create "Jira task" -t task -p 1 --external-ref "jira-PROJ-456" --json # Custom prefix
# Update one or more issues
bd update <id> [<id>...] --claim --json
bd update <id> [<id>...] --priority 1 --json
bd update <id> [<id>...] --spec-id "docs/specs/auth.md" --json
# Update external reference (v0.9.2+)
bd update <id> --external-ref "gh-456" --json # Short form
bd update <id> --external-ref "jira-PROJ-789" --json # Custom prefix
# Atomically claim an issue for work (prevents race conditions)
# Sets assignee to you and status to in_progress in one atomic operation
# Fails if already claimed (assignee is not empty)
bd update <id> --claim --json
# Edit issue fields in $EDITOR (HUMANS ONLY - not for agents)
# NOTE: This command is intentionally NOT exposed via the MCP server
# Agents should use 'bd update' with field-specific parameters instead
bd edit <id> # Edit description
bd edit <id> --title # Edit title
bd edit <id> --design # Edit design notes
bd edit <id> --notes # Edit notes
bd edit <id> --acceptance # Edit acceptance criteria
# Complete work (supports multiple IDs)
bd close <id> [<id>...] --reason "Done" --json
# Reopen closed issues (supports multiple IDs)
bd reopen <id> [<id>...] --reason "Reopening" --json
# Show dependency tree
bd dep tree <id>
# Get issue details (supports multiple IDs)
bd show <id> [<id>...] --json
# Show the currently active issue (in-progress, hooked, or last touched)
bd show --current
# Link discovered work (old way - two commands)
bd dep add <discovered-id> <parent-id> --type discovered-from
# Create and link in one command (new way - preferred)
bd create "Issue title" -t bug -p 1 --deps discovered-from:<parent-id> --json
# Label management (supports multiple IDs)
bd label add <id> [<id>...] <label> --json
bd label remove <id> [<id>...] <label> --json
bd label list <id> --json
bd label list-all --json
For operational state tracking on role beads. Uses <dimension>:<value> label convention.
See LABELS.md for full pattern documentation.
# Query current state value
bd state <id> <dimension> # Output: value
bd state agent-abc patrol # Output: active
bd state --json agent-abc patrol # {"issue_id": "...", "dimension": "patrol", "value": "active"}
# List all state dimensions on an issue
bd state list <id> --json
bd state list agent-abc # patrol: active, mode: normal, health: healthy
# Set state (creates event + updates label atomically)
bd set-state <id> <dimension>=<value> --reason "explanation" --json
bd set-state agent-abc patrol=muted --reason "Investigating stuck worker"
bd set-state agent-abc mode=degraded --reason "High error rate"
Common dimensions:
patrol: active, muted, suspendedmode: normal, degraded, maintenancehealth: healthy, warning, failingstatus: idle, working, blockedWhat set-state does:
<dimension>:* label if exists<dimension>:<value> label (cache)# Filter by status, priority, type
bd list --status open --priority 1 --json # Status and priority
bd list --assignee alice --json # By assignee
bd list --type bug --json # By issue type
bd list --id bd-123,bd-456 --json # Specific IDs
bd list --spec "docs/specs/" --json # Spec prefix
# Labels (AND: must have ALL)
bd list --label bug,critical --json
# Labels (OR: has ANY)
bd list --label-any frontend,backend --json
# Title search (substring)
bd list --title "auth" --json
# Pattern matching (case-insensitive substring)
bd list --title-contains "auth" --json # Search in title
bd list --desc-contains "implement" --json # Search in description
bd list --notes-contains "TODO" --json # Search in notes
# Find beads issue by external reference
bd list --json | jq -r '.[] | select(.external_ref == "gh-123") | .id'
# Date range filters (YYYY-MM-DD or RFC3339)
bd list --created-after 2024-01-01 --json # Created after date
bd list --created-before 2024-12-31 --json # Created before date
bd list --updated-after 2024-06-01 --json # Updated after date
bd list --updated-before 2024-12-31 --json # Updated before date
bd list --closed-after 2024-01-01 --json # Closed after date
bd list --closed-before 2024-12-31 --json # Closed before date
# Empty/null checks
bd list --empty-description --json # Issues with no description
bd list --no-assignee --json # Unassigned issues
bd list --no-labels --json # Issues with no labels
# Priority ranges
bd list --priority-min 0 --priority-max 1 --json # P0 and P1 only
bd list --priority-min 2 --json # P2 and below
# Combine multiple filters
bd list --status open --priority 1 --label-any urgent,critical --no-assignee --json
Global flags work with any bd command and must appear before the subcommand.
Auto-detection (v0.21.1+): bd automatically detects sandboxed environments and enables sandbox mode.
When detected, you'll see: ℹ️ Sandbox detected, using direct mode
Manual override:
# Explicitly enable sandbox mode
bd --sandbox <command>
What it does:
When to use: Sandboxed environments where the Dolt server can't be controlled (permission restrictions), or when auto-detection doesn't trigger.
# JSON output for programmatic use
bd --json <command>
# Disable auto-sync
bd --no-auto-flush <command> # Disable auto-flush
bd --no-auto-import <command> # Disable auto-import
# Custom database path
bd --db /path/to/.beads/beads.db <command>
# Custom actor for audit trail
bd --actor alice <command>
See also:
# Clean up closed issues (bulk deletion)
bd admin cleanup --force --json # Delete ALL closed issues
bd admin cleanup --older-than 30 --force --json # Delete closed >30 days ago
bd admin cleanup --dry-run --json # Preview what would be deleted
bd admin cleanup --older-than 90 --cascade --force --json # Delete old + dependents
Find issues referenced in git commits that were never closed:
# Basic usage - scan current repo
bd orphans
# Cross-repo: scan CODE repo's commits against external BEADS database
cd ~/my-code-repo
bd orphans --db ~/my-beads-repo/.beads/beads.db
# JSON output
bd orphans --json
Use case: When your beads database lives in a separate repository from your code, run bd orphans from the code repo and point --db to the external database. This scans commits in your current directory while checking issue status from the specified database.
# Find and merge duplicate issues
bd duplicates # Show all duplicates
bd duplicates --auto-merge # Automatically merge all
bd duplicates --dry-run # Preview merge operations
# Merge specific duplicate issues
bd merge <source-id...> --into <target-id> --json # Consolidate duplicates
bd merge bd-42 bd-43 --into bd-41 --dry-run # Preview merge
# Agent-driven compaction
bd admin compact --analyze --json # Get candidates for review
bd admin compact --analyze --tier 1 --limit 10 --json # Limited batch
bd admin compact --apply --id bd-42 --summary summary.txt # Apply compaction
bd admin compact --apply --id bd-42 --summary - < summary.txt # From stdin
bd admin compact --stats --json # Show statistics
# Legacy AI-powered compaction (requires ANTHROPIC_API_KEY)
bd admin compact --auto --dry-run --all # Preview
bd admin compact --auto --all --tier 1 # Auto-compact tier 1
# Restore compacted issue from git history
bd restore <id> # View full history at time of compaction
# Rename issue prefix (e.g., from 'knowledge-work-' to 'kw-')
bd rename-prefix kw- --dry-run # Preview changes
bd rename-prefix kw- --json # Apply rename
Remove all local beads data and return to uninitialized state.
# Preview what would be removed (dry-run)
bd admin reset
# Actually perform the reset
bd admin reset --force
What gets removed:
.beads/ directory (database, config).git/beads-worktrees/)What does NOT get removed:
Important: If you want a complete clean slate (including remote data), see Troubleshooting: Old data returns after reset.
Note: The --hard and --skip-init flags mentioned in some discussions were never implemented. Use --force to perform the reset.
Beads uses a chemistry metaphor for template-based workflows. See MOLECULES.md for full documentation.
| Phase | State | Storage | Command |
|---|---|---|---|
| Solid | Proto | .beads/ | bd formula list |
| Liquid | Mol | .beads/ | bd mol pour |
| Vapor | Wisp | .beads/ (Ephemeral=true, not exported) | bd mol wisp |
# List available formulas (templates)
bd formula list --json
# Show proto structure and variables
bd mol show <proto-id> --json
# Extract proto from ad-hoc epic
bd mol distill <epic-id> --json
# Instantiate proto as persistent mol (solid → liquid)
bd mol pour <proto-id> --var key=value --json
# Preview what would be created
bd mol pour <proto-id> --var key=value --dry-run
# Assign root issue
bd mol pour <proto-id> --var key=value --assignee alice --json
# Attach additional protos during pour
bd mol pour <proto-id> --attach <other-proto> --json
# Instantiate proto as ephemeral wisp (solid → vapor)
bd mol wisp <proto-id> --var key=value --json
# List all wisps
bd mol wisp list --json
bd mol wisp list --all --json # Include closed
# Garbage collect orphaned wisps
bd mol wisp gc --json
bd mol wisp gc --age 24h --json # Custom age threshold
bd mol wisp gc --dry-run # Preview what would be cleaned
# Purge all closed wisps (bulk cleanup)
bd mol wisp gc --closed # Preview closed wisp deletion
bd mol wisp gc --closed --force # Delete all closed wisps
bd mol wisp gc --closed --dry-run # Detailed dry-run preview
# Polymorphic combine - handles proto+proto, proto+mol, mol+mol
bd mol bond <A> <B> --json
# Bond types
bd mol bond <A> <B> --type sequential --json # B runs after A (default)
bd mol bond <A> <B> --type parallel --json # B runs alongside A
bd mol bond <A> <B> --type conditional --json # B runs only if A fails
# Phase control
bd mol bond <proto> <mol> --pour --json # Force persistent spawn
bd mol bond <proto> <mol> --wisp --json # Force ephemeral spawn
# Dynamic bonding (custom child IDs)
bd mol bond <proto> <mol> --ref arm-{{name}} --var name=ace --json
# Preview bonding
bd mol bond <A> <B> --dry-run
# Compress wisp to permanent digest
bd mol squash <ephemeral-id> --json
# With agent-provided summary
bd mol squash <ephemeral-id> --summary "Work completed" --json
# Preview
bd mol squash <ephemeral-id> --dry-run
# Keep wisp children after squash
bd mol squash <ephemeral-id> --keep-children --json
# Delete wisp without digest (destructive)
bd mol burn <ephemeral-id> --json
# Preview
bd mol burn <ephemeral-id> --dry-run
# Skip confirmation
bd mol burn <ephemeral-id> --force --json
Note: Mol commands use the standard Dolt database access path.
Gates are async wait conditions that block dependent work until external conditions are met. See DEPENDENCIES.md for full documentation.
# List open gates
bd gate list
bd gate list --all # Including closed
# Show gate details
bd gate show <gate-id>
# Evaluate gates and close resolved ones
bd gate check # All gates
bd gate check --type=gh:pr # Only PR merge gates
bd gate check --type=gh:run # Only CI run gates
bd gate check --type=timer # Only timer gates
bd gate check --type=bead # Only cross-rig bead gates
bd gate check --dry-run # Preview without changes
bd gate check --escalate # Escalate failed gates
# Manually resolve a gate
bd gate resolve <gate-id> --reason "Approved"
# Auto-discover CI run IDs for gh:run gates
bd gate discover
bd gate discover --dry-run --branch main
# Add a waiter to a gate
bd gate add-waiter <gate-id> <waiter>
# Export issues to issue JSONL
bd export -o issues.jsonl
# Dolt-native backup (preserves full commit history)
bd backup init /path/to/backup # Register a backup destination
bd backup sync # Push to backup destination
bd backup restore [path] # Restore from a backup
bd backup remove # Remove backup destination
bd backup status # Show backup status
# Bootstrap a new database from an issue export
bd init --from-jsonl # Reads .beads/issues.jsonl
# Configure orphan handling for pulls and bootstrapping
bd config set import.orphan_handling "resurrect"
bd dolt pull # Respects import.orphan_handling setting
Orphan handling modes (apply to bd dolt pull and bd init --from-jsonl):
allow (default) - Import orphaned children without parent validation. Most permissive, ensures no data loss even if hierarchy is temporarily broken.resurrect - Search for deleted parents and recreate them as tombstones (Status=Closed, Priority=4). Preserves hierarchy with minimal data.skip - Skip orphaned children with warning. Partial import succeeds but some issues are excluded.strict - Fail immediately if a child's parent is missing. Use when database integrity is critical.See CONFIG.md and TROUBLESHOOTING.md for more details.
# Migrate databases after version upgrade
bd migrate # Detect and migrate old databases
bd migrate --dry-run # Preview migration
bd migrate --cleanup --yes # Migrate and remove old files
# AI-supervised migration (check before running bd migrate)
bd migrate --inspect --json # Show migration plan for AI agents
bd info --schema --json # Get schema, tables, config, sample IDs
Migration workflow for AI agents:
--inspect to see pending migrations and warningsmissing_config (like issue_prefix)invariants_to_check for safety guaranteesbd migrate safelyMigration safety invariants:
These invariants prevent data loss and would have caught issues like GH #201 (missing issue_prefix after migration).
Set up a dedicated sync branch for beads data, keeping your working branches clean.
# Basic setup (creates orphan branch by default)
bd migrate sync beads-sync # Create orphan sync branch
bd migrate sync beads-sync --dry-run # Preview without changes
# Force reconfigure if already set up
bd migrate sync beads-sync --force # Reconfigure sync branch
# Migrate existing non-orphan branch to orphan
bd migrate sync beads-sync --orphan # Delete and recreate as orphan
Behavior:
| Scenario | Result |
|---|---|
| Branch doesn't exist | Creates orphan branch (no shared history) |
| Branch exists locally | Uses existing branch as-is |
Branch exists + --orphan | Migrates: deletes and recreates as orphan |
| Remote only | Fetches from remote |
Remote only + --orphan | Creates local orphan (ignores remote) |
Why orphan branches?
.beads/ directoryAfter setup:
bd dolt push commits beads changes to the sync branch via worktreeSafety features for --orphan migration:
--force to override.git push --force to update it after migration.# Manual sync (push changes to remote)
bd dolt push
# Pull changes from remote
bd dolt pull
# What these do:
# bd dolt push - Commit pending changes to Dolt and push to remote
# bd dolt pull - Pull from remote and merge any updates
Store user-defined key-value pairs that persist across sessions. Useful for feature flags, environment config, or agent memory.
# Set a value
bd kv set <key> <value>
bd kv set feature_flag true
bd kv set api_endpoint https://api.example.com
# Get a value
bd kv get <key>
bd kv get feature_flag # Prints: true
bd kv get missing_key # Prints: missing_key (not set), exits 1
# Delete a key
bd kv clear <key>
bd kv clear feature_flag
# List all key-value pairs
bd kv list
bd kv list --json # Machine-readable output
Storage notes:
kv. prefixUse cases:
bd set debug_mode truebd set staging_url https://staging.example.combd set last_migration 20240115_add_users.sqlbd set current_sprint 42bug - Something broken that needs fixingfeature - New functionalitytask - Work item (tests, docs, refactoring)epic - Large feature composed of multiple issues (supports hierarchical children)chore - Maintenance work (dependencies, tooling)Hierarchical children: Epics can have child issues with dotted IDs (e.g., bd-a3f8e9.1, bd-a3f8e9.2). Children are auto-numbered sequentially. Up to 3 levels of nesting supported.
open - Ready to be worked onin_progress - Currently being worked onblocked - Cannot proceed (waiting on dependencies)deferred - Deliberately put on ice for laterclosed - Work completedtombstone - Deleted issue (suppresses resurrections)pinned - Stays open indefinitely (used for hooks, anchors)Note: The pinned status is used by orchestrators for hook management and persistent work items that should never be auto-closed or cleaned up.
Define custom statuses with optional categories that control behavior in bd ready and bd list:
# Simple format (backward compatible — statuses get no category)
bd config set status.custom "in_review,qa_testing,on_hold"
# Category-annotated format
bd config set status.custom "in_review:active,qa_testing:wip,on_hold:frozen"
# Mixed format (some with categories, some without)
bd config set status.custom "in_review:active,legacy_status,archived:done"
Categories:
| Category | bd ready | Default bd list | Icon | Description |
|---|---|---|---|---|
active | ✓ included | ✓ included | ○ | Ready for work (like open) |
wip | ✗ excluded | ✓ included | ◐ | Work-in-progress (like in_progress) |
done | ✗ excluded | ✗ excluded | ✓ | Terminal state (like closed) |
frozen | ✗ excluded | ✗ excluded | ❄ | On hold (like deferred) |
| (none) | ✗ excluded | ✓ included | ◇ | No category — backward compatible default |
List all statuses (built-in and custom):
bd statuses # Human-readable table
bd statuses --json # JSON output for programmatic use
Rules:
[a-z][a-z0-9_-]* (lowercase, letter-first)bd list --status <name>0 - Critical (security, data loss, broken builds)1 - High (major features, important bugs)2 - Medium (nice-to-have features, minor bugs)3 - Low (polish, optimization)4 - Backlog (future ideas)blocks - Hard dependency (issue X blocks issue Y)related - Soft relationship (issues are connected)parent-child - Epic/subtask relationshipdiscovered-from - Track issues discovered during workOnly blocks dependencies affect the ready work queue.
Note: When creating an issue with a discovered-from dependency, the new issue automatically inherits the parent's source_repo field.
The --external-ref flag (v0.9.2+) links beads issues to external trackers:
gh-123) or full URL (https://github.com/...)jira-PROJ-456, linear-789)Always use --json flag for programmatic use:
# Single issue
bd show bd-42 --json
# List of issues
bd ready --json
# Operation result
bd create "Issue" -p 1 --json
Default output without --json:
bd ready
# ○ bd-42 [P1] [bug] - Fix authentication bug
# ○ bd-43 [P2] [feature] - Add user settings page
Dependency visibility: When issues have blocking dependencies, they appear inline:
bd list --parent epic-123
# ○ bd-123.1 [P1] [task] - Design API (blocks: bd-123.2, bd-123.3)
# ○ bd-123.2 [P1] [task] - Implement endpoints (blocked by: bd-123.1, blocks: bd-123.3)
# ○ bd-123.3 [P1] [task] - Add tests (blocked by: bd-123.1, bd-123.2)
This makes blocking relationships visible without running bd show on each issue.
# 1. Find available work
bd ready --json
# 2. Claim issue
bd update bd-42 --claim --json
# 3. Work on it...
# 4. Close when done
bd close bd-42 --reason "Implemented and tested" --json
# While working on bd-100, discover a bug
# Old way (two commands):
bd create "Found auth bug" -t bug -p 1 --json # Returns bd-101
bd dep add bd-101 bd-100 --type discovered-from
# New way (one command):
bd create "Found auth bug" -t bug -p 1 --deps discovered-from:bd-100 --json
# Update multiple issues at once
bd update bd-41 bd-42 bd-43 --priority 0 --json
# Close multiple issues
bd close bd-41 bd-42 bd-43 --reason "Batch completion" --json
# Add label to multiple issues
bd label add bd-41 bd-42 bd-43 urgent --json
# Start of session
bd ready --json # Find work
# During session
bd create "..." -p 1 --json
bd update bd-42 --claim --json
# ... work ...
# End of session (IMPORTANT!)
bd dolt push # Force immediate sync, bypass debounce
ALWAYS run bd dolt push at end of agent sessions to ensure changes are committed/pushed immediately.
# Setup editor integration (choose based on your editor)
bd setup factory # Factory.ai Droid - creates/updates AGENTS.md (universal standard)
bd setup codex # Codex CLI - creates/updates AGENTS.md
bd setup mux # Mux - creates/updates AGENTS.md
bd setup claude # Claude Code - installs hooks + manages CLAUDE.md (minimal profile)
bd setup gemini # Gemini CLI - installs hooks + manages GEMINI.md (minimal profile)
bd setup cursor # Cursor IDE - creates .cursor/rules/beads.mdc
bd setup aider # Aider - creates .aider.conf.yml
# Check if integration is installed
bd setup factory --check
bd setup codex --check
bd setup mux --check
bd setup claude --check
bd setup gemini --check
bd setup cursor --check
bd setup aider --check
# Remove integration
bd setup factory --remove
bd setup codex --remove
bd setup mux --remove
bd setup claude --remove
bd setup gemini --remove
bd setup cursor --remove
bd setup aider --remove
Claude Code options:
bd setup claude # Install globally (~/.claude/settings.json)
bd setup claude --project # Install for this project only
bd setup claude --stealth # Use stealth mode (flush only, no git operations)
bd setup gemini # Install globally (~/.gemini/settings.json)
bd setup gemini --project # Install for this project only
bd setup gemini --stealth # Use stealth mode (flush only, no git operations)
bd setup mux --project # Also install .mux/AGENTS.md workspace layer
bd setup mux --global # Also install ~/.mux/AGENTS.md global layer
What each setup does:
bd setup factory): Creates or updates AGENTS.md with beads workflow instructions (full profile — works with multiple AI tools using the AGENTS.md standard)bd setup codex): Creates or updates AGENTS.md with beads workflow instructions for Codex (full profile)bd setup mux): Creates or updates AGENTS.md with beads workflow instructions for Mux workspaces (full profile)bd setup claude): Adds hooks to Claude Code's settings.json that run bd prime on SessionStart and PreCompact events and manages a minimal-profile beads section in CLAUDE.mdbd setup gemini): Adds hooks to Gemini's settings.json that run bd prime on SessionStart and PreCompress events and manages a minimal-profile beads section in GEMINI.mdbd setup cursor): Creates .cursor/rules/beads.mdc with workflow instructionsbd setup aider): Creates .aider.conf.yml with bd workflow instructions--check behavior: For section-based integrations (including Claude/Gemini instruction files), reports status as current (up to date), stale (legacy or hash mismatch — run setup to update), or missing (no beads section). Stale and missing return non-zero exit codes.
See also: