Files
beads/CONFIG.md
Steve Yegge ff8f6ecadf feat(import): add import.orphan_handling config with 4 modes
- Add GetOrphanHandling() helper to SQLiteStorage (reads from config table)
- Add --orphan-handling flag to 'bd import' command
- Wire OrphanHandling through ImportOptions -> importer.Options
- Auto-read config if flag not provided (default: 'allow')
- Document in CONFIG.md with detailed mode explanations

Modes:
- strict: Fail on missing parent (safest)
- resurrect: Auto-create parent tombstones from JSONL
- skip: Skip orphans with warning
- allow: Import without validation (default, most permissive)

Closes bd-8072, bd-b92a

Amp-Thread-ID: https://ampcode.com/threads/T-fd18d4a5-06b3-4400-9073-194d570846d8
Co-authored-by: Amp <amp@ampcode.com>
2025-11-04 23:59:50 -08:00

10 KiB

Configuration System

bd has two complementary configuration systems:

  1. Tool-level configuration (Viper): User preferences for tool behavior (flags, output format)
  2. Project-level configuration (bd config): Integration data and project-specific settings

Tool-Level Configuration (Viper)

Overview

Tool preferences control how bd behaves globally or per-user. These are stored in config files or environment variables and managed by Viper.

Configuration precedence (highest to lowest):

  1. Command-line flags (--json, --no-daemon, etc.)
  2. Environment variables (BD_JSON, BD_NO_DAEMON, etc.)
  3. Config file (~/.config/bd/config.yaml or .beads/config.yaml)
  4. Defaults

Config File Locations

Viper searches for config.yaml in these locations (in order):

  1. .beads/config.yaml - Project-specific tool settings (version-controlled)
  2. ~/.config/bd/config.yaml - User-specific tool settings
  3. ~/.beads/config.yaml - Legacy user settings

Supported Settings

Tool-level settings you can configure:

Setting Flag Environment Variable Default Description
json --json BD_JSON false Output in JSON format
no-daemon --no-daemon BD_NO_DAEMON false Force direct mode, bypass daemon
no-auto-flush --no-auto-flush BD_NO_AUTO_FLUSH false Disable auto JSONL export
no-auto-import --no-auto-import BD_NO_AUTO_IMPORT false Disable auto JSONL import
db --db BD_DB (auto-discover) Database path
actor --actor BD_ACTOR $USER Actor name for audit trail
flush-debounce - BEADS_FLUSH_DEBOUNCE 5s Debounce time for auto-flush
auto-start-daemon - BEADS_AUTO_START_DAEMON true Auto-start daemon if not running

Example Config File

~/.config/bd/config.yaml:

# Default to JSON output for scripting
json: true

# Disable daemon for single-user workflows
no-daemon: true

# Custom debounce for auto-flush (default 5s)
flush-debounce: 10s

# Auto-start daemon (default true)
auto-start-daemon: true

.beads/config.yaml (project-specific):

# Project team prefers longer flush delay
flush-debounce: 15s

Why Two Systems?

Tool settings (Viper) are user preferences:

  • How should I see output? (--json)
  • Should I use the daemon? (--no-daemon)
  • How should the CLI behave?

Project config (bd config) is project data:

  • What's our Jira URL?
  • What are our Linear tokens?
  • How do we map statuses?

This separation is correct: tool settings are user-specific, project config is team-shared.

Agents benefit from bd config's structured CLI interface over manual YAML editing.

Project-Level Configuration (bd config)

Overview

Project configuration is:

  • Per-project: Isolated to each .beads/*.db database
  • Version-control-friendly: Stored in SQLite, queryable and scriptable
  • Machine-readable: JSON output for automation
  • Namespace-based: Organized by integration or purpose

Commands

Set Configuration

bd config set <key> <value>
bd config set --json <key> <value>  # JSON output

Examples:

bd config set jira.url "https://company.atlassian.net"
bd config set jira.project "PROJ"
bd config set jira.status_map.todo "open"

Get Configuration

bd config get <key>
bd config get --json <key>  # JSON output

Examples:

bd config get jira.url
# Output: https://company.atlassian.net

bd config get --json jira.url
# Output: {"key":"jira.url","value":"https://company.atlassian.net"}

List All Configuration

bd config list
bd config list --json  # JSON output

Example output:

Configuration:
  compact_tier1_days = 90
  compact_tier1_dep_levels = 2
  jira.project = PROJ
  jira.url = https://company.atlassian.net

JSON output:

{
  "compact_tier1_days": "90",
  "compact_tier1_dep_levels": "2",
  "jira.project": "PROJ",
  "jira.url": "https://company.atlassian.net"
}

Unset Configuration

bd config unset <key>
bd config unset --json <key>  # JSON output

Example:

bd config unset jira.url

Namespace Convention

Configuration keys use dot-notation namespaces to organize settings:

Core Namespaces

  • compact_* - Compaction settings (see EXTENDING.md)
  • issue_prefix - Issue ID prefix (managed by bd init)
  • max_collision_prob - Maximum collision probability for adaptive hash IDs (default: 0.25)
  • min_hash_length - Minimum hash ID length (default: 4)
  • max_hash_length - Maximum hash ID length (default: 8)
  • import.orphan_handling - How to handle hierarchical issues with missing parents during import (default: allow)

Integration Namespaces

Use these namespaces for external integrations:

  • jira.* - Jira integration settings
  • linear.* - Linear integration settings
  • github.* - GitHub integration settings
  • custom.* - Custom integration settings

Example: Adaptive Hash ID Configuration

# Configure adaptive ID lengths (see docs/ADAPTIVE_IDS.md)
# Default: 25% max collision probability
bd config set max_collision_prob "0.25"

# Start with 4-char IDs, scale up as database grows
bd config set min_hash_length "4"
bd config set max_hash_length "8"

# Stricter collision tolerance (1%)
bd config set max_collision_prob "0.01"

# Force minimum 5-char IDs for consistency
bd config set min_hash_length "5"

See docs/ADAPTIVE_IDS.md for detailed documentation.

Example: Import Orphan Handling

Controls how imports handle hierarchical child issues when their parent is missing from the database:

# Strictest: Fail import if parent is missing (safest, prevents orphans)
bd config set import.orphan_handling "strict"

# Auto-resurrect: Search JSONL history and recreate missing parents as tombstones
bd config set import.orphan_handling "resurrect"

# Skip: Skip orphaned issues with warning (partial import)
bd config set import.orphan_handling "skip"

# Allow: Import orphans without validation (default, most permissive)
bd config set import.orphan_handling "allow"

Mode details:

  • strict - Import fails immediately if a child's parent is missing. Use when database integrity is critical.
  • resurrect - Searches the full JSONL file for missing parents and recreates them as tombstones (Status=Closed, Priority=4). Preserves hierarchy with minimal data. Dependencies are also resurrected on best-effort basis.
  • skip - Skips orphaned children with a warning. Partial import succeeds but some issues are excluded.
  • allow - Imports orphans without parent validation. Most permissive, works around import bugs. This is the default because it ensures all data is imported even if hierarchy is temporarily broken.

Override per command:

# Override config for a single import
bd import -i issues.jsonl --orphan-handling strict

# Auto-import (sync) uses config value
bd sync  # Respects import.orphan_handling setting

When to use each mode:

  • Use allow (default) for daily imports and auto-sync - ensures no data loss
  • Use resurrect when importing from another database that had parent deletions
  • Use strict only for controlled imports where you need to guarantee parent existence
  • Use skip rarely - only when you want to selectively import a subset

Example: Jira Integration

# Configure Jira connection
bd config set jira.url "https://company.atlassian.net"
bd config set jira.project "PROJ"
bd config set jira.api_token "YOUR_TOKEN"

# Map bd statuses to Jira statuses
bd config set jira.status_map.open "To Do"
bd config set jira.status_map.in_progress "In Progress"
bd config set jira.status_map.closed "Done"

# Map bd issue types to Jira issue types
bd config set jira.type_map.bug "Bug"
bd config set jira.type_map.feature "Story"
bd config set jira.type_map.task "Task"

Example: Linear Integration

# Configure Linear connection
bd config set linear.api_token "YOUR_TOKEN"
bd config set linear.team_id "team-123"

# Map statuses
bd config set linear.status_map.open "Backlog"
bd config set linear.status_map.in_progress "In Progress"
bd config set linear.status_map.closed "Done"

Example: GitHub Integration

# Configure GitHub connection
bd config set github.org "myorg"
bd config set github.repo "myrepo"
bd config set github.token "YOUR_TOKEN"

# Map bd labels to GitHub labels
bd config set github.label_map.bug "bug"
bd config set github.label_map.feature "enhancement"

Use in Scripts

Configuration is designed for scripting. Use --json for machine-readable output:

#!/bin/bash

# Get Jira URL
JIRA_URL=$(bd config get --json jira.url | jq -r '.value')

# Get all config and extract multiple values
bd config list --json | jq -r '.["jira.project"]'

Example Python script:

import json
import subprocess

def get_config(key):
    result = subprocess.run(
        ["bd", "config", "get", "--json", key],
        capture_output=True,
        text=True
    )
    data = json.loads(result.stdout)
    return data["value"]

def list_config():
    result = subprocess.run(
        ["bd", "config", "list", "--json"],
        capture_output=True,
        text=True
    )
    return json.loads(result.stdout)

# Use in integration
jira_url = get_config("jira.url")
jira_project = get_config("jira.project")

Best Practices

  1. Use namespaces: Prefix keys with integration name (e.g., jira.*, linear.*)
  2. Hierarchical keys: Use dots for structure (e.g., jira.status_map.open)
  3. Document your keys: Add comments in integration scripts
  4. Security: Store tokens in config, but add .beads/*.db to .gitignore (bd does this automatically)
  5. Per-project: Configuration is project-specific, so each repo can have different settings

Integration with bd Commands

Some bd commands automatically use configuration:

  • bd compact uses compact_tier1_days, compact_tier1_dep_levels, etc.
  • bd init sets issue_prefix

External integration scripts can read configuration to sync with Jira, Linear, GitHub, etc.

See Also