Back to Beads

Configuration System

docs/CONFIG.md

1.0.333.7 KB
Original Source

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, --dolt-auto-commit, etc.)
  2. Environment variables (BD_JSON, BD_DOLT_AUTO_COMMIT, 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:

SettingFlagEnvironment VariableDefaultDescription
json--jsonBD_JSONfalseOutput in JSON format
no-push--no-pushBD_NO_PUSHfalseSkip pushing to remote in bd dolt push
federation.remote-BD_FEDERATION_REMOTE(none)Dolt remote URL for federation
federation.sovereignty-BD_FEDERATION_SOVEREIGNTY(none)Data sovereignty tier: T1, T2, T3, T4
dolt.auto-commit--dolt-auto-commitBD_DOLT_AUTO_COMMITon(Dolt backend) Automatically create a Dolt commit after successful write commands
create.require-description-BD_CREATE_REQUIRE_DESCRIPTIONfalseRequire description when creating issues
validation.on-create-BD_VALIDATION_ON_CREATEnoneTemplate validation on create: none, warn, error
validation.on-sync-BD_VALIDATION_ON_SYNCnoneTemplate 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_SIGNfalseDisable 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
backup.enabled-BD_BACKUP_ENABLEDfalseEnable periodic Dolt-native backup to .beads/backup/
backup.interval-BD_BACKUP_INTERVAL15mMinimum time between auto-backups
dolt.auto-push-BD_DOLT_AUTO_PUSHfalseAuto-push to Dolt remote after writes (explicit opt-in)
dolt.auto-push-interval-BD_DOLT_AUTO_PUSH_INTERVAL5mMinimum time between auto-pushes
dolt.shared-server--shared-serverBEADS_DOLT_SHARED_SERVERfalseShare a single Dolt server across all projects at ~/.beads/shared-server/
dolt.idle-timeout--30mIdle auto-stop timeout ("0" disables)
db--dbBD_DB(auto-discover)Database path
actor--actorBEADS_ACTORgit config user.nameActor name for audit trail (see below)

Backend note: Dolt is the only storage backend. By default, Dolt runs in embedded mode (in-process, no server). Use bd init --server or BEADS_DOLT_SERVER_MODE=1 for server mode. See DOLT.md for details.

Dolt Auto-Commit (SQL commit vs Dolt commit)

When using the Dolt backend, there are two different kinds of “commit”:

  • SQL transaction commit: what happens when a bd command updates tables successfully (durable in the Dolt working set).
  • Dolt version-control commit: what records those changes into Dolt’s history (visible in bd vc log, push/pull/merge workflows).

By default, bd is configured to auto-commit Dolt history after each successful write command:

  • Default: dolt.auto-commit: on
  • Disable for a single command:
bash
bd --dolt-auto-commit off create "No commit for this one"
  • Disable in config (.beads/config.yaml or ~/.config/bd/config.yaml):
yaml
dolt:
  auto-commit: off

Caveat: enabling this creates more Dolt commits over time (one per write command). This is intentional so changes are not left only in the working set.

Auto-Backup

Periodic Dolt-native backup to .beads/backup/ provides an off-machine recovery path. Local Dolt snapshots (via dolt.auto-commit) remain the primary safety net; backup is a secondary layer.

yaml
backup:
  enabled: true    # Enable auto-backup after write commands
  interval: 15m    # Minimum time between auto-backups

How it works:

  • After each write command (in PersistentPostRun), bd checks the Dolt HEAD commit hash against the last backup state
  • If data changed and the throttle interval has passed, a Dolt-native backup is synced to .beads/backup/
  • Full commit history is preserved in the backup
  • State is tracked in .beads/backup/backup_state.json

Manual commands:

  • bd backup init <path> — register a backup destination (filesystem or DoltHub URL)
  • bd backup sync — push to the configured backup destination
  • bd backup restore [path] — restore from a backup (--force to overwrite)
  • bd backup remove — unregister the backup destination
  • bd backup status — show backup configuration and last sync time

Dolt Auto-Push

By default, bd does not push automatically after write commands. Auto-push is explicit opt-in because concurrent pushes to git-protocol Dolt remotes can corrupt or strand remote history when multiple writers race.

yaml
dolt:
  auto-push: false      # Explicit opt-in only; set true for single-writer setups
  auto-push-interval: 5m  # Minimum time between auto-pushes

How it works:

  • After each write command (in PersistentPostRun, after auto-commit and auto-backup), bd checks whether a push is due
  • Pushes are debounced: skipped if the last push was less than dolt.auto-push-interval ago
  • Change detection: skipped if the Dolt HEAD commit hasn't changed since last push
  • Push failures are warnings only (non-fatal)
  • Last push time and commit are tracked in the metadata table

Opt in:

yaml
dolt:
  auto-push: true

Actor Identity Resolution

The actor name (used for created_by in issues and audit trails) is resolved in this order:

  1. --actor flag (explicit override)
  2. BEADS_ACTOR environment variable
  3. BD_ACTOR environment variable (deprecated alias, kept for backwards compatibility)
  4. git config user.name
  5. $USER environment variable (system username fallback)
  6. "unknown" (final fallback)

For most developers, no configuration is needed - beads will use your git identity automatically. This ensures your issue authorship matches your commit authorship.

To override, set BEADS_ACTOR in your shell profile:

bash
export BEADS_ACTOR="my-github-handle"

Sync Mode Configuration

The sync mode controls how beads synchronizes data with git and/or Dolt remotes.

Sync Mode

Beads uses dolt-native sync mode exclusively. Dolt remotes handle sync directly with cell-level merge. Use bd export for issue portability, and bd backup init / bd backup sync / bd backup restore for Dolt-native backups.

Federation Configuration

  • federation.remote: Dolt remote URL (e.g., dolthub://org/beads, gs://bucket/beads, s3://bucket/beads, az://account.blob.core.windows.net/container/beads)
  • federation.sovereignty: Data sovereignty tier:
    • T1: Full sovereignty - data never leaves controlled infrastructure
    • T2: Regional sovereignty - data stays within region/jurisdiction
    • T3: Provider sovereignty - data with trusted cloud provider
    • T4: No restrictions - data can be anywhere

Example Configuration

yaml
# .beads/config.yaml
# Optional: Dolt federation
federation:
  remote: dolthub://myorg/beads
  sovereignty: T2

Example Config File

~/.config/bd/config.yaml:

yaml
# Default to JSON output for scripting
json: true

# Dolt auto-commit (creates Dolt history commit after each write)
dolt:
  auto-commit: on

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

yaml
# 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 <[email protected]>"  # 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

# Feedback title formatting for mutating commands (GH#1384)
# 0 = hide titles, N > 0 = truncate to N characters
output:
  title-length: 255

# 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
  other-project: /path/to/other-project

Why Two Systems?

Tool settings (Viper) are user preferences:

  • How should I see output? (--json)
  • Should Dolt auto-commit? (--dolt-auto-commit)
  • 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/ database
  • Version-control-friendly: Stored in the database, queryable and scriptable
  • Machine-readable: JSON output for automation
  • Namespace-based: Organized by integration or purpose

Commands

Set Configuration

bash
bd config set <key> <value>
bd config set --json <key> <value>  # 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 <key>
bd config get --json <key>  # 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 <key>
bd config unset --json <key>  # 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)
  • issue_id_mode - ID generation mode: hash (default) or counter (sequential integers)
  • 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.auto - Refresh the git-tracked JSONL file after every write command (default: true)
  • export.path - Output filename relative to .beads/ (default: issues.jsonl)
  • export.interval - Minimum time between auto-exports (default: 60s)
  • export.git-add - Run git add on the export file after writing (default: true)
  • 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
  • ado.* - Azure DevOps integration settings
  • custom.* - Custom integration settings

Status and Type Customization

  • status.custom - Custom issue statuses with optional categories (comma-separated)
  • types.custom - Custom issue types (comma-separated)

Custom statuses support category annotations that control behavior:

bash
# Format: name:category (category is optional)
bd config set status.custom "in_review:active,qa_testing:wip,on_hold:frozen,archived:done"

# Categories: active, wip, done, frozen
# - active: shows in bd ready, included in default bd list
# - wip: excluded from bd ready, included in default bd list
# - done: excluded from bd ready AND default bd list (terminal)
# - frozen: excluded from bd ready AND default bd list (on hold)
# - (none): excluded from bd ready, included in default bd list (backward compatible)

Custom types:

bash
bd config set types.custom "agent,molecule,event"

See bd statuses and bd types commands to list all configured statuses and types.

Example: Sequential Counter IDs (issue_id_mode=counter)

By default, beads generates hash-based IDs (e.g., bd-a3f2, bd-7f3a8). For projects that prefer short sequential IDs (e.g., bd-1, bd-2, bd-3), enable counter mode:

bash
bd config set issue_id_mode counter

Valid values:

ValueBehavior
hash(default) Hash-based IDs, adaptive length, collision-safe
counterSequential integers per prefix: bd-1, bd-2, bd-3, ...

Counter mode behavior:

  • Each prefix (bd, plug, etc.) has its own independent counter
  • Counter is stored atomically in the database; concurrent creates within a single Dolt session are safe
  • Explicit --id flag always overrides counter mode (the counter is not incremented)

Enabling counter mode:

bash
bd config set issue_id_mode counter

# Now new issues get sequential IDs
bd create "First issue" -p 1
# → bd-1

bd create "Second issue" -p 2
# → bd-2

Migration warning: If you switch an existing repository to counter mode, seed the counter to avoid collisions with existing IDs. Find your highest current integer ID and set the counter accordingly:

bash
# Check your highest existing sequential ID (if any)
bd list --json | jq -r '.[].id' | grep -E '^bd-[0-9]+$' | sort -t- -k2 -n | tail -1

# Seed the counter (e.g., if highest existing ID is bd-42)
bd config set issue_id_mode counter
# The counter auto-initializes at 0; new issues start at 1
# If you already have bd-1 through bd-42, manually set counter:
# (no direct CLI for seeding — use bd dolt sql or create/delete N issues)

For fresh repositories switching to counter mode before any issues exist, no seeding is needed.

Per-prefix counter isolation:

Each issue prefix maintains its own counter independently. In multi-repo or routed setups, bd-* issues and plug-* issues each start at 1:

bash
# Prefix "bd" and prefix "plug" have independent counters
bd create "Core task" -p 1          # → bd-1
bd create "Plugin task" -p 1        # → plug-1 (if prefix is "plug")

Tradeoff — hash vs. counter:

Hash IDsCounter IDs
Human readabilityLower (e.g., bd-a3f2)Higher (e.g., bd-1)
Distributed/concurrent safetyExcellent (collision-free across branches)Needs care (counters can diverge on parallel branches)
PredictabilityUnpredictableSequential
Best forMulti-agent, multi-branch workflowsSingle-writer or project-management UIs

Counter IDs are well-suited for linear project-management workflows and human-facing issue tracking. Hash IDs are safer when multiple agents or branches create issues concurrently, since each hash is independently unique without coordination.

See ADAPTIVE_IDS.md for full documentation on hash-based ID generation.

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 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 dolt push, manual export commands) use export.error_policy (default: strict).

Auto-exports (git hook 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 - Fails immediately if a child's parent is missing. Use when database integrity is critical.
  • resurrect - Searches 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. This is the default because it ensures all data is imported even if hierarchy is temporarily broken.

These modes apply when bootstrapping a database with bd init --from-jsonl or when bd dolt pull merges remote data:

bash
# Override config for a single pull
bd config set import.orphan_handling "resurrect"
bd dolt pull  # Respects import.orphan_handling setting

When to use each mode:

  • Use allow (default) for daily sync - ensures no data loss
  • Use resurrect when pulling from remotes that had parent deletions
  • Use strict only when 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 dolt push 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.projects "PROJ1,PROJ2"   # Multiple projects (comma-separated)
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"

# Multiple team IDs (comma-separated; can also use LINEAR_TEAM_IDS env var)
bd config set linear.team_ids "uuid-team-1,uuid-team-2"

When linear.team_ids is set, bd linear sync fetches issues from all listed teams. For push operations with multiple teams, use the --team flag to specify the target. The singular linear.team_id is still supported for backward compatibility.

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"

Example: Azure DevOps (ADO) Integration

Azure DevOps integration provides bidirectional sync between bd and ADO work items.

Required configuration:

bash
# Personal access token (can also use AZURE_DEVOPS_PAT environment variable)
bd config set ado.pat "YOUR_PAT"

# Organization name (can also use AZURE_DEVOPS_ORG environment variable)
bd config set ado.org "myorg"

# Project name (can also use AZURE_DEVOPS_PROJECT environment variable)
bd config set ado.project "MyProject"

# Multiple projects (comma-separated; can also use AZURE_DEVOPS_PROJECTS env var)
bd config set ado.projects "Project1,Project2"

When ado.projects is set, bd ado sync fetches work items from all listed projects in a single WIQL query. The singular ado.project is still supported for backward compatibility.

Optional configuration:

bash
# Custom base URL for Azure DevOps Server (on-prem) instances
# (can also use AZURE_DEVOPS_URL environment variable)
# When set, ado.org is not required — the URL replaces the default dev.azure.com base.
bd config set ado.url "https://ado.internal.example.com/DefaultCollection"

Getting your Azure DevOps PAT:

  1. Go to Azure DevOps → User Settings (top-right icon) → Personal access tokens
  2. Click "New Token"
  3. Select the organization and set an expiration
  4. Grant Work Items: Read & Write scope (minimum for sync)
  5. Copy the token — it is only shown once

State mapping (ADO Agile template defaults → Beads statuses):

ADO uses process-template-specific states (Agile, Scrum, CMMI). The defaults use the Agile template. Override with ado.state_map.* for your process:

bash
# Default Agile mapping (built-in, no config needed):
#   New      → open
#   Active   → in_progress
#   Resolved → closed
#   Closed   → closed
#   Removed  → deferred

# Override for Scrum template:
bd config set ado.state_map.open "New"
bd config set ado.state_map.in_progress "Committed"
bd config set ado.state_map.blocked "Committed"
bd config set ado.state_map.deferred "Removed"
bd config set ado.state_map.closed "Done"

Type mapping (ADO work item types ↔ Beads issue types):

bash
# Default mapping (built-in, no config needed):
#   Bug               → bug
#   User Story        → feature
#   Product Backlog Item → feature
#   Task              → task
#   Epic              → epic

# Override for your process template:
bd config set ado.type_map.bug "Bug"
bd config set ado.type_map.feature "Feature"
bd config set ado.type_map.task "Task"
bd config set ado.type_map.epic "Epic"
bd config set ado.type_map.chore "Task"

Priority mapping (ADO 1-4 → Beads 0-4):

ADO uses a 1-4 scale; Beads uses 0-4. The mapping is:

  • ADO 1 (Critical) → Beads 0 (Critical)
  • ADO 2 (High) → Beads 1 (High)
  • ADO 3 (Medium) → Beads 2 (Medium)
  • ADO 4 (Low) → Beads 3 (Low)
  • Beads 4 (Backlog) → ADO 4 (lossy: backlog collapses to low)

Priority mapping is not configurable — it is handled automatically.

Environment variables:

All ADO config keys have environment variable equivalents:

Config KeyEnvironment Variable
ado.patAZURE_DEVOPS_PAT
ado.orgAZURE_DEVOPS_ORG
ado.projectAZURE_DEVOPS_PROJECT
ado.projectsAZURE_DEVOPS_PROJECTS
ado.urlAZURE_DEVOPS_URL

Environment variables take effect when the corresponding bd config key is not set.

Sync commands:

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

# Pull only (import from Azure DevOps)
bd ado sync --pull-only

# Push only (export to Azure DevOps)
bd ado sync --push-only

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

# Conflict resolution options
bd ado sync --prefer-local    # Local version wins on conflicts
bd ado sync --prefer-ado      # Azure DevOps version wins on conflicts
bd ado sync --prefer-newer    # Most recent version wins (default)

# Check sync status and configuration
bd ado status

# List accessible projects (useful for finding your project name)
bd ado projects --json

Automatic sync tracking:

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

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 ensure .beads/dolt/ and .beads/*.db are in .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