# 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](https://github.com/spf13/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`: ```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): ```yaml # 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 " # 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 ```bash bd config set bd config set --json # JSON output ``` Examples: ```bash 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 ```bash bd config get bd config get --json # JSON output ``` Examples: ```bash 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 ```bash 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: ```json { "compact_tier1_days": "90", "compact_tier1_dep_levels": "2", "jira.project": "PROJ", "jira.url": "https://company.atlassian.net" } ``` ### Unset Configuration ```bash bd config unset bd config unset --json # JSON output ``` Example: ```bash 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 ```bash # 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](ADAPTIVE_IDS.md) for detailed documentation. ### Example: Export Error Handling Controls how export operations handle errors when fetching issue data (labels, comments, dependencies). ```bash # 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:** ```bash # 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: ```bash # 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:** ```bash # 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): ```bash # 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 ```bash # 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:** ```bash # 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): ```bash 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: ```bash 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: ```bash 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):** ```bash 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:** ```bash # 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 ```bash # 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: ```bash #!/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: ```python 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 - [README.md](../README.md) - Main documentation - [EXTENDING.md](EXTENDING.md) - Database schema and compaction config