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

287 lines
7.6 KiB
Markdown

# 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 |
| `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`:
```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):
```yaml
# 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
```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`)
### 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
```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
```bash
# 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
```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 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
- [examples/integrations/](examples/integrations/) - Integration examples