Files
beads/CONFIG.md
Steve Yegge 4da8caef24 Migrate to Viper for unified configuration management (bd-78)
- Add Viper dependency and create internal/config package
- Initialize Viper singleton with config file search paths
- Bind all global flags to Viper with proper precedence (flags > env > config > defaults)
- Replace manual os.Getenv() calls with config.GetString/GetBool/GetDuration
- Update CONFIG.md with comprehensive Viper documentation
- Add comprehensive tests for config precedence and env binding
- Walk up parent directories to discover .beads/config.yaml from subdirectories
- Add env key replacer for hyphenated keys (BD_NO_DAEMON -> no-daemon)
- Remove deprecated prefer-global-daemon setting
- Move Viper config apply before early-return to support version/init/help commands

Hybrid architecture maintains separation:
- Viper: User-specific tool preferences (--json, --no-daemon, etc.)
- bd config: Team-shared project data (Jira URLs, Linear tokens, etc.)

All tests passing. Closes bd-78, bd-79, bd-80, bd-81, bd-82, bd-83.

Amp-Thread-ID: https://ampcode.com/threads/T-0d0f8c1d-b877-4fa9-8477-b6fea63fb664
Co-authored-by: Amp <amp@ampcode.com>
2025-10-23 17:30:05 -07:00

7.6 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)

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