Skip to content

Latest commit

 

History

History
596 lines (441 loc) · 20.3 KB

File metadata and controls

596 lines (441 loc) · 20.3 KB

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
no-push --no-push BD_NO_PUSH false Skip pushing to remote in bd sync
create.require-description - BD_CREATE_REQUIRE_DESCRIPTION false Require description when creating issues
validation.on-create - BD_VALIDATION_ON_CREATE none Template validation on create: none, warn, error
validation.on-sync - BD_VALIDATION_ON_SYNC none Template validation before sync: none, warn, error
git.author - BD_GIT_AUTHOR (none) Override commit author for beads commits
git.no-gpg-sign - BD_GIT_NO_GPG_SIGN false Disable GPG signing for beads commits
directory.labels - - (none) Map directories to labels for automatic filtering
external_projects - - (none) Map project names to paths for cross-project deps
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
daemon-log-max-size - BEADS_DAEMON_LOG_MAX_SIZE 50 Max daemon log size in MB before rotation
daemon-log-max-backups - BEADS_DAEMON_LOG_MAX_BACKUPS 7 Max number of old log files to keep
daemon-log-max-age - BEADS_DAEMON_LOG_MAX_AGE 30 Max days to keep old log files
daemon-log-compress - BEADS_DAEMON_LOG_COMPRESS true Compress rotated log files

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

# Daemon log rotation settings
daemon-log-max-size: 50      # MB per file (default 50)
daemon-log-max-backups: 7    # Number of old logs to keep (default 7)
daemon-log-max-age: 30       # Days to keep old logs (default 30)
daemon-log-compress: true    # Compress rotated logs (default true)

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

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

# Require descriptions on all issues (enforces context for future work)
create:
  require-description: true

# Template validation settings (bd-t7jq)
# Validates that issues include required sections based on issue type
# Values: none (default), warn (print warning), error (block operation)
validation:
  on-create: warn   # Warn when creating issues missing sections
  on-sync: none     # No validation on sync (backwards compatible)

# Git commit signing options (GH#600)
# Useful when you have Touch ID commit signing that prompts for each commit
git:
  author: "beads-bot <beads@example.com>"  # Override commit author
  no-gpg-sign: true                         # Disable GPG signing

# Directory-aware label scoping for monorepos (GH#541)
# When running bd ready/list from a matching directory, issues with
# that label are automatically shown (as if --label-any was passed)
directory:
  labels:
    packages/maverick: maverick
    packages/agency: agency
    packages/io: io

# Cross-project dependency resolution (bd-h807)
# Maps project names to paths for resolving external: blocked_by references
# Paths can be relative (from cwd) or absolute
external_projects:
  beads: ../beads
  gastown: /path/to/gastown

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)
  • export.error_policy - Error handling strategy for exports (default: strict)
  • export.retry_attempts - Number of retry attempts for transient errors (default: 3)
  • export.retry_backoff_ms - Initial backoff in milliseconds for retries (default: 100)
  • export.skip_encoding_errors - Skip issues that fail JSON encoding (default: false)
  • export.write_manifest - Write .manifest.json with export metadata (default: false)
  • auto_export.error_policy - Override error policy for auto-exports (default: best-effort)
  • sync.branch - Name of the dedicated sync branch for beads data (see docs/PROTECTED_BRANCHES.md)
  • sync.require_confirmation_on_mass_delete - Require interactive confirmation before pushing when >50% of issues vanish during a merge AND more than 5 issues existed before (default: false)

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 ADAPTIVE_IDS.md for detailed documentation.

Example: Export Error Handling

Controls how export operations handle errors when fetching issue data (labels, comments, dependencies).

# Strict: Fail fast on any error (default for user-initiated exports)
bd config set export.error_policy "strict"

# Best-effort: Skip failed operations with warnings (good for auto-export)
bd config set export.error_policy "best-effort"

# Partial: Retry transient failures, skip persistent ones with manifest
bd config set export.error_policy "partial"
bd config set export.write_manifest "true"

# Required-core: Fail on core data (issues/deps), skip enrichments (labels/comments)
bd config set export.error_policy "required-core"

# Customize retry behavior
bd config set export.retry_attempts "5"
bd config set export.retry_backoff_ms "200"

# Skip individual issues that fail JSON encoding
bd config set export.skip_encoding_errors "true"

# Auto-export uses different policy (background operation)
bd config set auto_export.error_policy "best-effort"

Policy details:

  • strict (default) - Fail immediately on any error. Ensures complete exports but may block on transient issues like database locks. Best for critical exports and migrations.

  • best-effort - Skip failed batches with warnings. Continues export even if labels or comments fail to load. Best for auto-exports and background sync where availability matters more than completeness.

  • partial - Retry transient failures (3x by default), then skip with manifest file. Creates .manifest.json alongside JSONL documenting what succeeded/failed. Best for large databases with occasional corruption.

  • required-core - Fail on core data (issues, dependencies), skip enrichments (labels, comments) with warnings. Best when metadata is secondary to issue tracking.

When to use each mode:

  • Use strict (default) for production backups and critical exports
  • Use best-effort for auto-exports (default via auto_export.error_policy)
  • Use partial when you need visibility into export completeness
  • Use required-core when labels/comments are optional

Context-specific behavior:

User-initiated exports (bd sync, manual export commands) use export.error_policy (default: strict).

Auto-exports (daemon background sync) use auto_export.error_policy (default: best-effort), falling back to export.error_policy if not set.

Example: Different policies for different contexts:

# Critical project: strict everywhere
bd config set export.error_policy "strict"

# Development project: strict user exports, permissive auto-exports
bd config set export.error_policy "strict"
bd config set auto_export.error_policy "best-effort"

# Large database with occasional corruption
bd config set export.error_policy "partial"
bd config set export.write_manifest "true"
bd config set export.retry_attempts "5"

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: Sync Safety Options

Controls for the sync branch workflow (see docs/PROTECTED_BRANCHES.md):

# Configure sync branch (required for protected branch workflow)
bd config set sync.branch beads-sync

# Enable mass deletion protection (optional, default: false)
# When enabled, if >50% of issues vanish during a merge AND more than 5
# issues existed before the merge, bd sync will:
# 1. Show forensic info about vanished issues
# 2. Prompt for confirmation before pushing
bd config set sync.require_confirmation_on_mass_delete "true"

When to enable sync.require_confirmation_on_mass_delete:

  • Multi-user workflows where accidental mass deletions could propagate
  • Critical projects where data loss prevention is paramount
  • When you want manual review before pushing large changes

When to keep it disabled (default):

  • Single-user workflows where you trust your local changes
  • CI/CD pipelines that need non-interactive sync
  • When you want hands-free automation

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

Linear integration provides bidirectional sync between bd and Linear via GraphQL API.

Required configuration:

# API Key (can also use LINEAR_API_KEY environment variable)
bd config set linear.api_key "lin_api_YOUR_API_KEY"

# Team ID (find in Linear team settings or URL)
bd config set linear.team_id "team-uuid-here"

Getting your Linear credentials:

  1. API Key: Go to Linear → Settings → API → Personal API keys → Create key
  2. Team ID: Go to Linear → Settings → General → Team ID (or extract from URLs)

Priority mapping (Linear 0-4 → Beads 0-4):

Linear and Beads both use 0-4 priority scales, but with different semantics:

  • Linear: 0=no priority, 1=urgent, 2=high, 3=medium, 4=low
  • Beads: 0=critical, 1=high, 2=medium, 3=low, 4=backlog

Default mapping (configurable):

bd config set linear.priority_map.0 4    # No priority -> Backlog
bd config set linear.priority_map.1 0    # Urgent -> Critical
bd config set linear.priority_map.2 1    # High -> High
bd config set linear.priority_map.3 2    # Medium -> Medium
bd config set linear.priority_map.4 3    # Low -> Low

State mapping (Linear state types → Beads statuses):

Map Linear workflow state types to Beads statuses:

bd config set linear.state_map.backlog open
bd config set linear.state_map.unstarted open
bd config set linear.state_map.started in_progress
bd config set linear.state_map.completed closed
bd config set linear.state_map.canceled closed

# For custom workflow states, use lowercase state name:
bd config set linear.state_map.in_review in_progress
bd config set linear.state_map.blocked blocked
bd config set linear.state_map.on_hold blocked

Label to issue type mapping:

Infer bd issue type from Linear labels:

bd config set linear.label_type_map.bug bug
bd config set linear.label_type_map.defect bug
bd config set linear.label_type_map.feature feature
bd config set linear.label_type_map.enhancement feature
bd config set linear.label_type_map.epic epic
bd config set linear.label_type_map.chore chore
bd config set linear.label_type_map.maintenance chore
bd config set linear.label_type_map.task task

Relation type mapping (Linear relations → Beads dependencies):

bd config set linear.relation_map.blocks blocks
bd config set linear.relation_map.blockedBy blocks
bd config set linear.relation_map.duplicate duplicates
bd config set linear.relation_map.related related

Sync commands:

# Bidirectional sync (pull then push, with conflict resolution)
bd linear sync

# Pull only (import from Linear)
bd linear sync --pull

# Push only (export to Linear)
bd linear sync --push

# Dry run (preview without changes)
bd linear sync --dry-run

# Conflict resolution options
bd linear sync --prefer-local    # Local version wins on conflicts
bd linear sync --prefer-linear   # Linear version wins on conflicts
# Default: newer timestamp wins

# Check sync status
bd linear status

Automatic sync tracking:

The linear.last_sync config key is automatically updated after each sync, enabling incremental sync (only fetch issues updated since last sync).

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 admin 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