title: Document deletions manifest in AGENTS.md and README

description:
Parent: bd-imj

## Task
Add documentation about the deletions manifest feature.

## Locations to Update

### AGENTS.md
- Explain that deletions.jsonl is tracked in git
- Document that `bd delete` records to the manifest
- Explain cross-clone propagation mechanism

### README.md
- Brief mention in .beads directory structure section
- Link to detailed docs if needed

### docs/deletions.md (new file)
- Full technical documentation
- Format specification
- Pruning policy
- Git history fallback
- Troubleshooting

## Acceptance Criteria
- AGENTS.md updated with deletion workflow
- README.md mentions deletions.jsonl purpose
- New docs/deletions.md with complete reference

status: closed

issue_type: task


title: Proposal: Custom status states via config

description:
Proposal to add 'custom status states' via `bd config`.
Users could define an optional issue status enum (e.g., awaiting_review, review_in_progress) in the config.
This would enable multi-step pipelines to process issues where each step correlates to a specific status.

Examples:
- awaiting_verification
- awaiting_docs
- awaiting_testing

status: open

issue_type: feature


title: Expand checkHooksQuick to verify all hook versions

description: Currently checkHooksQuick only checks post-merge hook version. Should also check pre-commit, pre-push, and post-checkout for completeness. Keep it lightweight but catch more outdated hooks.


title: Rename last_import_hash metadata key to jsonl_content_hash

description:
The metadata key 'last_import_hash' is misleading because it's updated on both import AND export (sync.go:614, import.go:320).

Better names:
- jsonl_content_hash (more accurate)
- last_sync_hash (clearer intent)

This is a breaking change requiring migration of existing metadata values.


title: Audit remaining cmd/bd files for error handling consistency

description: Extend ERROR_HANDLING_AUDIT.md to cover: daemon_sync.go, update.go, list.go, show.go, close.go, reopen.go, dep.go, label.go, comments.go, delete.go, compact.go, config.go, validate.go and other high-usage command files


description:
Parent: bd-imj

Ensure deletions.jsonl is tracked in git (not ignored).

Update bd init and gitignore upgrade logic to:
1. NOT add deletions.jsonl to .gitignore
2. Ensure it is committed alongside beads.jsonl

The file must be in git for cross-clone propagation to work.

Acceptance criteria:
- bd init does not ignore deletions.jsonl
- Existing .gitignore files are not broken
- File appears in git status when modified


title: Fix failing integration tests in beads-mcp

description: The `beads-mcp` test suite has failures in `tests/test_bd_client_integration.py` (assertion error in `test_init_creates_beads_directory`) and errors in `tests/test_worktree_separate_dbs.py` (setup failures finding database). These need to be investigated and fixed to ensure a reliable CI baseline.


title: Add test coverage for internal/git package

design: Git package has 1 test file. Critical package needs comprehensive testing. Target: 70% coverage

acceptance_criteria:
- At least 4 test files
- Package coverage >= 70%
- Tests cover git commands, error handling


title: bd prime: Detect ephemeral branches and adjust workflow output

description:
When 'bd prime' runs on a branch with no upstream (ephemeral branch), it should output a different SESSION CLOSE PROTOCOL.

**Current output (wrong for ephemeral branches):**
```
[ ] 1. git status
[ ] 2. git add <files>
[ ] 3. bd sync
[ ] 4. git commit -m "..."
[ ] 5. bd sync
[ ] 6. git push
```

**Needed output for ephemeral branches:**
```
[ ] 1. git status
[ ] 2. git add <files>
[ ] 3. bd sync --from-main  (pull updates from main)
[ ] 4. git commit -m "..."
[ ] 5. (no push - branch is ephemeral)
```

**Detection:** `git rev-parse --abbrev-ref --symbolic-full-name @{u}` returns error code 128 if no upstream.

Also update Sync & Collaboration section to mention `bd sync --from-main` for ephemeral branches.

**Use case:** Gastown polecats work on ephemeral local branches that are never pushed. Their code gets merged to main via local merge, and beads changes stay local (communicated via gm mail to Overseer).


title: Refactor path canonicalization into helper function

description:
The path canonicalization logic (filepath.Abs + EvalSymlinks) is duplicated in 3 places:
- beads.go:131-137 (BEADS_DIR handling)
- cmd/bd/main.go:446-451 (--no-db cleanup)
- cmd/bd/nodb.go:26-31 (--no-db initialization)

Refactoring suggestion:
Extract to a helper function like:
  func canonicalizePath(path string) string

This would:
- Reduce code duplication
- Make the logic easier to maintain
- Ensure consistent behavior across all path handling

Related to bd-e16b implementation.

issue_type: chore


title: Add programmatic tip injection API

description: Allow tips to be programmatically injected at runtime based on detected conditions. This enables dynamic tips (not just pre-defined ones) to be shown with custom priority and frequency.

type: blocks

created_by: daemon


title: Optimize Memory backend GetIssueByExternalRef with index

description:
Currently GetIssueByExternalRef in Memory storage uses O(n) linear search through all issues.

Current code (memory.go:282-308):
for _, issue := range m.issues {
    if issue.ExternalRef != nil && *issue.ExternalRef == externalRef {
        return &issueCopy, nil
    }
}

Proposed optimization:
- Add externalRefToID map[string]string to MemoryStorage
- Maintain it in CreateIssue, UpdateIssue, DeleteIssue
- Achieve O(1) lookup like SQLite's index

Impact: Low (--no-db mode typically has smaller datasets)
Related: bd-1022


title: Create Docker image for Agent Mail

description:
Containerize Agent Mail server for easy deployment.

Acceptance Criteria:
- Dockerfile with Python 3.14
- Health check endpoint
- Volume mount for storage
- Environment variable configuration
- Multi-arch builds (amd64, arm64)

File: deployment/agent-mail/Dockerfile


title: Refactor check-health DB access to avoid repeated path resolution

description: The runCheckHealth lightweight checks (hintsDisabled, checkVersionMismatch, checkSyncBranchQuick) each have duplicated database path resolution logic. Extract a helper function to DRY this up.


title: Git history fallback doesn't escape regex special chars in IDs

description:
## Problem

In `batchCheckGitHistory`, IDs are directly interpolated into a regex pattern:

```go
patterns = append(patterns, fmt.Sprintf(\`"id":"%s"\`, id))
searchPattern := strings.Join(patterns, "|")
cmd := exec.Command("git", "log", "--all", "-G", searchPattern, ...)
```

If an ID contains regex special characters (e.g., `bd-foo.bar` or `bd-test+1`), the pattern will be malformed or match unintended strings.

## Location
`internal/importer/importer.go:923-926`

## Impact
- False positives: IDs with `.` could match any character
- Regex errors: IDs with `[` or `(` could cause git to fail
- Security: potential for regex injection (low risk since IDs are validated)

## Fix
Escape regex special characters:

```go
import "regexp"

escapedID := regexp.QuoteMeta(id)
patterns = append(patterns, fmt.Sprintf(\`"id":"%s"\`, escapedID))
```

issue_type: bug


title: Git history fallback assumes .beads is direct child of repo root

description:
## Problem

`checkGitHistoryForDeletions` assumes the repo structure:

```go
repoRoot := filepath.Dir(beadsDir)  // Assumes .beads is in repo root
jsonlPath := filepath.Join(".beads", "beads.jsonl")
```

But `.beads` could be in a subdirectory (monorepo, nested project), and the actual JSONL filename could be different (configured via `metadata.json`).

## Location
`internal/importer/importer.go:865-869`

## Impact
- Git search will fail silently for repos with non-standard structure
- Monorepo users won't get deletion propagation

## Fix
1. Use `git rev-parse --show-toplevel` to find actual repo root
2. Compute relative path from repo root to JSONL
3. Or use `git -C <dir>` to run from beadsDir directly


title: Improve compact/daemon/merge documentation and UX

description:
Multiple documentation and UX issues encountered:
1. "bd compact --analyze" fails with misleading "requires SQLite storage" error when daemon is running. Needs --no-daemon or better error.
2. "bd merge" help text is outdated (refers to 3-way merge instead of issue merging).
3. Daemon mode purpose isn't clear to local-only users.
4. Compact/cleanup commands are hard to discover.

Proposed fixes:
- Fix compact+daemon interaction or error message.
- Update "bd merge" help text.
- Add "when to use daemon" section to docs.
- Add maintenance section to quickstart.


title: Extract database search logic into helper function

description:
The logic for finding a database in a beads directory is duplicated:
- FindDatabasePath() BEADS_DIR section (beads.go:141-169)
- findDatabaseInTree() (beads.go:248-280)

Both implement the same search order:
1. Check config.json first (single source of truth)
2. Fall back to canonical beads.db
3. Search for *.db files, filtering backups and vc.db

Refactoring suggestion:
Extract to a helper function like:
  func findDatabaseInBeadsDir(beadsDir string) string

Benefits:
- Single source of truth for database search logic
- Easier to maintain and update search order
- Reduces code duplication

Related to [deleted:bd-e16b] implementation.


title: Refactor: Move staleness check inside daemon branch

description:
## Problem

Currently ensureDatabaseFresh() is called before the daemon mode check, but it checks daemonClient != nil internally and returns early. This is redundant.

**Location:** All read commands (list.go:196, show.go:27, ready.go:102, status.go:80, etc.)

## Current Pattern

Call happens before daemon check, function checks daemonClient internally.

## Better Pattern

Move staleness check to direct mode branch only, after daemon check.

## Impact
Low - minor performance improvement (avoids one function call per command in daemon mode)

## Effort
Medium - requires refactoring 8 command files

## Priority
Low - can defer to future cleanup PR


title: Create tip system infrastructure for contextual hints

description: Implement a tip/hint system that shows helpful contextual messages after successful commands. This is different from the existing error-path "Hint:" messages - tips appear on success paths to educate users about features they might not know about.


title: Improve timestamp comparison readability in import

description:
The timestamp comparison logic uses double-negative which can be confusing:

Current code:
if !incoming.UpdatedAt.After(existing.UpdatedAt) {
    // skip update
}

More readable:
if incoming.UpdatedAt.After(existing.UpdatedAt) {
    // perform update
} else {
    // skip (local is newer)
}

This is a minor refactor for code clarity.

Related: bd-1022
Files: internal/importer/importer.go:411, 488


title: Add test coverage for internal/autoimport package

design: The autoimport package has only 1 test file. Need comprehensive tests. Target: 70% coverage

acceptance_criteria:
- At least 3 test files
- Package coverage >= 70%
- Tests cover main functionality, error paths, edge cases


title: Git history fallback missing timeout - could hang on large repos

description:
## Problem

The git commands in `checkGitHistoryForDeletions` have no timeout. On large repos with extensive history, `git log --all -S` or `git log --all -G` can take a very long time (minutes).

## Location
`internal/importer/importer.go:899` and `:930`

## Impact
- Import could hang indefinitely
- User has no feedback that git search is running
- No way to cancel except killing the process

## Fix
Add context with timeout to git commands:

```go
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, "git", ...)
```

Also consider adding a `--since` flag to bound the git history search.


title: Improve Beads test coverage from 46% to 80%

design:
Currently at 46% test coverage. Need to systematically improve coverage across all subsystems, focusing first on packages with minimal or no tests.

Target: 80% overall coverage

Approach:
- Break down by subsystem (internal/* packages)
- Prioritize packages with 0-1 test files
- Each child issue targets specific coverage goals
- Focus on unit tests for core logic, error paths, and edge cases

This epic will be executed by the VC executor to test its ability to handle sustained multi-issue work.

acceptance_criteria:
- Overall test coverage reaches 80% or higher
- All internal/* packages have at least 60% coverage
- All packages with only 1 test file now have at least 3 test files
- Quality gates (go test, golangci-lint) pass
- Tests are maintainable and test actual behavior, not implementation details

issue_type: epic


title: Implement health checks in daemon event loop

description:
Add health checks to checkDaemonHealth() function in daemon_event_loop.go:170:
- Database integrity check
- Disk space check
- Memory usage check

Currently it's just a no-op placeholder.


title: Implement auto-merge functionality in duplicates command

description: The duplicates.go file has a TODO at line 95 to implement the performMerge function for automatic duplicate merging. Currently it just prints a warning message. This would automate the merge process instead of just suggesting commands.


title: Deletion propagation via deletions manifest

description:
## Problem

When `bd cleanup -f` or `bd delete` removes issues in one clone, those deletions don't propagate to other clones. The import logic only creates/updates, never deletes. This causes "resurrection" where deleted issues reappear.

## Root Cause

Import sees DB issues not in JSONL and assumes they're "local unpushed work" rather than "intentionally deleted upstream."

## Solution: Deletions Manifest

Add `.beads/deletions.jsonl` - an append-only log of deleted issue IDs with metadata.

### Format
```jsonl
{"id":"bd-xxx","ts":"2025-11-25T10:00:00Z","by":"stevey"}
{"id":"bd-yyy","ts":"2025-11-25T10:05:00Z","by":"claude","reason":"duplicate of bd-zzz"}
```

### Fields
- `id`: Issue ID (required)
- `ts`: ISO 8601 UTC timestamp (required)
- `by`: Actor who deleted (required)
- `reason`: Optional context ("cleanup", "duplicate of X", etc.)

### Import Logic
```
For each DB issue not in JSONL:
  1. Check deletions manifest → if found, delete from DB
  2. Fallback: check git history → if found, delete + backfill manifest
  3. Neither → keep (local unpushed work)
```

### Conflict Resolution
Simultaneous deletions from multiple clones are handled naturally:
- Append-only design means both clones append their deletion records
- On merge, file contains duplicate entries (same ID, different timestamps)
- `LoadDeletions` deduplicates by ID (keeps any/first entry)
- Result: deletion propagates correctly, duplicates are harmless

### Pruning Policy
- Default retention: 7 days (configurable via `deletions.retention_days`)
- Auto-compact during `bd sync` is **opt-in** (disabled by default)
- Hard cap: `deletions.max_entries` (default 50000)
- Git fallback handles pruned entries (self-healing)

### Self-Healing
When git fallback catches a resurrection (pruned entry), it backfills the manifest. One-time git scan cost, then fast again.

### Size Estimates
- ~80 bytes/entry
- 7-day retention with 100 deletions/day = ~56KB
- Git compressed: ~10KB

## Benefits
- ✅ Deletions propagate across clones
- ✅ O(1) lookup (no git scan in normal case)
- ✅ Works in shallow clones
- ✅ Survives history rewrite
- ✅ Audit trail (who deleted what when)
- ✅ Self-healing via git fallback
- ✅ Bounded size via time-based pruning

## References
- Investigation session: 2025-11-25
- Related: bd-2q6d (stale database warnings)

issue_id: bd-imj

depends_on_id: bd-qsm

depends_on_id: bd-bhd

depends_on_id: bd-bgs

depends_on_id: bd-mdw


title: Fix mypy errors in beads-mcp

description: Running `mypy .` in `integrations/beads-mcp` reports 287 errors. These should be addressed to improve type safety and code quality.


title: Enhance dep tree to show full dependency graph

description:
When running `bd dep tree <issue-id>`, the current output only shows the issue itself without its dependency relationships.

## Current Behavior

```
$ bd dep tree gt-0iqq
🌲 Dependency tree for gt-0iqq:

→ gt-0iqq: Implement Boss (global overseer) [P2] (open)
```

This doesn't show any of the dependency structure.

## Desired Behavior

Show the full dependency DAG rooted at the given issue. For example:

```
$ bd dep tree gt-0iqq
🌲 Dependency tree for gt-0iqq:

gt-0iqq: Implement Boss (global overseer) [P2] (open)
├── gt-0xh4: Boss session management [P2] (open) [READY]
│   ├── gt-le7c: Boss mail identity [P2] (open)
│   │   ├── gt-r8fe: Boss human escalation queue [P2] (open)
│   │   └── gt-vdak: Boss dispatch loop [P2] (open)
│   │       └── gt-kgy6: Boss resource management [P2] (open)
│   │           └── gt-93iv: Boss wake daemon [P2] (open)
│   └── gt-vdak: (shown above)
```

## Suggested Options

- `--direction=down|up|both` - Show dependents (what this blocks), dependencies (what blocks this), or both
- `--status=open` - Filter to only show issues with a given status
- `--depth=N` - Limit tree depth
- Handle DAG cycles gracefully (show "(shown above)" or similar for already-displayed nodes)

## Use Case

When reorganizing a set of related issues (like I just did with the Boss implementation), being able to visualize the full dependency graph helps verify the structure is correct before syncing.


title: Duplicate DefaultRetentionDays constants

description:
## Problem

There are now two constants for the same value:

1. `deletions.DefaultRetentionDays = 7` in `internal/deletions/deletions.go:184`
2. `configfile.DefaultDeletionsRetentionDays = 7` in `internal/configfile/configfile.go:102`

## Impact
- DRY violation
- Risk of values getting out of sync
- Confusing which one to use

## Fix
Remove the constant from `deletions` package and have it import from `configfile`, or create a shared constants package.


title: Performance Testing Framework

description:
Add comprehensive performance testing for beads focusing on optimization guidance and validating 10K+ database scale. Uses standard Go tooling, follows existing patterns, minimal complexity.

Components:
- Benchmark suite for critical operations at 10K-20K scale
- Fixture generator for realistic test data (epic hierarchies, cross-links)
- User diagnostics via bd doctor --perf
- Always-on profiling integration

Goals:
- Identify bottlenecks for optimization work
- Validate performance at 10K+ issue scale
- Enable users to collect diagnostics for bug reports
- Support both SQLite and JSONL import paths


title: Add test coverage for internal/validation package

design: Validation package has 1 test file. Critical for data integrity. Target: 80% coverage

acceptance_criteria:
- At least 4 test files
- Package coverage >= 80%
- Tests cover all validation rules


title: Add .beads/README.md during 'bd init' for project documentation and promotion

description:
When 'bd init' is run, automatically generate a .beads/README.md file that:

1. Briefly explains what Beads is (AI-native issue tracking that lives in your repo)
2. Links to the main repository: https://github.com/steveyegge/beads
3. Provides a quick reference of essential commands:
   - bd create: Create new issues
   - bd list: View all issues
   - bd update: Modify issue status/details
   - bd show: View issue details
   - bd sync: Sync with git remote
4. Highlights key benefits for AI coding agents and developers
5. Encourages developers to try it out

The README should be enthusiastic and compelling to get open source contributors excited about using Beads for their AI-assisted development workflows.


title: Add integration test for cross-clone deletion propagation


title: Investigate performance issues in VS Code Copilot (Windows)

description:
Beads unusable in Windows 11 VS Code Copilot chat with Sonnet 4.5.
Summary event happens every 3-4 turns, taking 3 minutes.
Copilot summarizes after ~125k tokens despite model supporting 1M.
Large context size of beads might be triggering aggressive summarization.
Need workaround or optimization for context size.


title: Fix Homebrew warning about Ruby file location

description:
Homebrew warning: Found Ruby file outside steveyegge/beads tap formula directory.
Warning points to: /opt/homebrew/Library/Taps/steveyegge/homebrew-beads/bd.rb
It should likely be inside a Formula/ directory or similar structure expected by Homebrew taps.


title: Clarify .beads/.gitattributes handling in Protected Branches docs

description:
Protected Branches docs quick start leaves untracked `.beads` directory and `.gitattributes`.
Question: Are these changes meant to be checked into the protected branch?
Need to clarify if these should be ignored or committed, or if the instructions are missing a step.


title: Auto-compact deletions during bd sync

description:
Parent: bd-imj

## Task
Optionally prune deletions manifest during sync when threshold exceeded.

**Note: Opt-in feature** - disabled by default to avoid sync latency.

## Implementation

In `bd sync`:
```go
func (s *Syncer) Sync() error {
    // ... existing sync logic ...

    // Auto-compact only if enabled
    if s.config.GetBool("deletions.auto_compact", false) {
        deletionCount := deletions.Count(".beads/deletions.jsonl")
        threshold := s.config.GetInt("deletions.auto_compact_threshold", 1000)

        if deletionCount > threshold {
            retentionDays := s.config.GetInt("deletions.retention_days", 7)
            if err := s.compactor.PruneDeletions(retentionDays); err != nil {
                log.Warnf("Failed to auto-compact deletions: %v", err)
                // Non-fatal, continue sync
            }
        }
    }

    // ... rest of sync ...
}
```

## Configuration
```yaml
deletions:
  retention_days: 7
  auto_compact: false              # Opt-in, disabled by default
  auto_compact_threshold: 1000     # Trigger when > N entries (if enabled)
```

## Acceptance Criteria
- [ ] Auto-compact disabled by default
- [ ] Enabled via config `deletions.auto_compact: true`
- [ ] Sync checks deletion count only when enabled
- [ ] Auto-prunes when threshold exceeded
- [ ] Failure is non-fatal (logged warning)
- [ ] Test: no compaction when disabled
- [ ] Test: compaction triggers when enabled and threshold exceeded


title: Consider extracting error handling helpers

description: Evaluate creating FatalError() and WarnError() helpers as suggested in ERROR_HANDLING.md to reduce boilerplate and enforce consistency. Prototype in a few files first to validate the approach.


title: Add test coverage for internal/config package

design: Config package has 1 test file. Need comprehensive tests. Target: 70% coverage

acceptance_criteria:
- At least 3 test files
- Package coverage >= 70%


title: Add Claude setup tip with dynamic priority

description: Add a predefined tip that suggests running `bd setup claude` when Claude Code is detected but not configured. This tip should have higher priority (shown more frequently) until the setup is complete.

issue_id: bd-tne


title: Update documentation for bd prime and Claude integration

description: Update AGENTS.md, README.md, and QUICKSTART.md to document the new `bd prime` command, `bd setup claude` command, and tip system.


title: Git history fallback has incorrect logic for detecting deletions

description:
## Problem

The `wasInGitHistory` function in `internal/importer/importer.go:891` returns true if the ID is found **anywhere** in git history. But finding an ID in history doesn't necessarily mean it was deleted - it could mean:

1. The issue was added (appears in a commit adding it)
2. The issue was modified (appears in commits updating it)
3. The issue was deleted (appears in a commit removing it)

The current logic incorrectly treats all three cases as 'deleted'.

## Correct Logic

`git log -S` with `--oneline` shows commits where the string was added OR removed. To detect deletion specifically:

1. ID appears in git history (was once in JSONL)
2. ID is NOT currently in JSONL

The second condition is already checked by the caller (`purgeDeletedIssues`), so technically the logic is correct in context. But the function name and doc comment are misleading.

## Fix Options

1. **Rename function** to `wasEverInJSONL` and update doc comment to clarify
2. **Add explicit check** for current JSONL state in the function itself

Option 1 is simpler and correct since caller already filters.


title: Deletions pruning doesn't include results in JSON output

description:
## Problem

When `bd compact --json` runs with deletions pruning, the prune results are silently discarded:

```go
// Only report if there were deletions to prune
if result.PrunedCount > 0 {
    if jsonOutput {
        // JSON output will be included in the main response
        return  // <-- BUG: results are NOT included anywhere
    }
    ...
}
```

## Location
`cmd/bd/compact.go:925-929`

## Impact
- JSON consumers don't know deletions were pruned
- No way to audit pruning via automation

## Fix
Return prune results and include in JSON output structure:

```json
{
  "success": true,
  "compacted": {...},
  "deletions_pruned": {
    "count": 5,
    "retention_days": 7
  }
}
```


title: Document CLI + hooks as recommended approach over MCP

description: Update documentation to position CLI + bd prime hooks as the primary recommended approach over MCP server, explaining why minimizing context matters even with large context windows (compute cost, energy, environment, latency).

design:
## Goals

Position CLI + `bd prime` hooks as the **primary recommended approach** for AI agent integration, with MCP server as a legacy/fallback option.

Explore **hybrid mode** - if certain commands benefit from MCP (UX/DX advantages like no approval prompts), minimize MCP surface area to only those commands.

This requires production validation first - only update docs after CLI mode is proven reliable.

## Why Minimize Context (Even With Large Windows)

**Context window size ≠ free resource**

Large context windows (100k+, 200k+) don't mean we should fill them wastefully. Every token in context has real costs:

### Compute Cost
- **Processing overhead**: Larger context = more GPU/CPU cycles per request
- **Memory usage**: 10.5k tokens consume significant RAM/VRAM
- **Scaling impact**: Multiplied across all users, all sessions, all requests

### Energy & Environment
- **Electricity**: More compute = more power consumption
- **Carbon footprint**: Data centers running on grid power (not all renewable)
- **Sustainability**: Unnecessary token usage contributes to AI's environmental impact
- **Responsibility**: Efficient tools are better for the planet

### User Experience
- **Latency**: Larger context = slower processing (noticeable at 10k+ tokens)
- **Cost**: Many AI services charge per token (input + output)
- **Rate limits**: Context counts against API quotas

### Engineering Excellence
- **Efficiency**: Good engineering minimizes resource usage
- **Scalability**: Efficient tools scale better
- **Best practices**: Optimize for the common case

**The comparison:**

| Approach | Standing Context | Efficiency | User Cost | Environmental Impact |
|----------|-----------------|------------|-----------|---------------------|
| **CLI + hooks** | ~1-2k tokens | 80-90% reduction | Lower | Sustainable ✓ |
| **MCP minimal** | ~2-4k tokens | 60-80% reduction | Medium | Better ✓ |
| **MCP full** | ~10.5k tokens | Baseline | Higher | Wasteful ✗ |

**Functional equivalence:**
- CLI via Bash tool works just as well as MCP native calls
- Same features, same reliability
- No downside except initial learning curve

## Hybrid Mode: Minimal MCP Surface Area

**Philosophy:** MCP server doesn't have to expose everything.

If certain commands have legitimate UX/DX benefits from MCP (e.g., no approval prompts, cleaner syntax), we can expose ONLY those commands via MCP while using CLI for everything else.

### Potential MCP-Only Candidates (TBD)

Commands that might benefit from MCP native calls:
- `ready` - frequently checked, no side effects, approval prompt annoying
- `show` - read-only, frequently used, approval slows workflow
- `list` - read-only, no risk, approval adds friction

Commands that work fine via CLI:
- `create` - complex parameters, benefits from explicit confirmation
- `update` - state changes, good to see command explicitly
- `close` - state changes, explicit is better
- `dep` - relationships, good to see what's being linked
- `sync` - git operations, definitely want visibility

### Token Budget

**Full MCP** (current): ~10.5k tokens
- All ~20+ bd commands exposed
- All parameter schemas
- All descriptions and examples

**Minimal MCP** (proposed): ~2-4k tokens
- 3-5 high-frequency read commands only
- Simplified schemas
- Minimal descriptions
- Everything else via CLI

**Pure CLI**: ~1-2k tokens (only on SessionStart/PreCompact)
- No MCP tools loaded
- All commands via Bash

### Investigation Required

Before implementing hybrid mode, validate:

1. **Do MCP calls actually skip approval prompts?**
   - Test with Claude Code approval settings
   - Compare MCP tool calls vs Bash tool calls
   - Measure UX difference in real usage

2. **What's the actual token breakdown per command?**
   - Measure individual command schemas
   - Calculate token savings for minimal vs full

3. **Is approval prompt the only benefit?**
   - Are there other UX advantages to MCP?
   - Does native syntax actually improve experience?
   - User testing with both approaches

4. **Can we dynamically load MCP tools?**
   - Only load MCP when certain commands needed?
   - Hot-swap between CLI and MCP?
   - Probably not - MCP loads at startup

### Hybrid Mode Documentation (If Validated)

```markdown
## Choosing Your Integration Approach

Beads supports three AI agent integration approaches:

### CLI + Hooks (Recommended - Most Efficient)

**Setup:** `bd setup claude`

Uses Claude Code hooks to inject workflow context via `bd prime` command. Agent uses bd via Bash tool.

**Tokens:** ~1-2k (on SessionStart/PreCompact only)

**Pros:**
- Maximum efficiency (80-90% reduction vs full MCP)
- Lowest compute/energy usage
- Same functionality as MCP

**Cons:**
- Bash tool calls may require approval prompts
- Slightly more verbose in conversation

### Minimal MCP + Hooks (Balanced)

**Setup:** Install minimal MCP server (read-only commands) + `bd setup claude`

Exposes only high-frequency read commands via MCP (ready, show, list). Everything else via CLI.

**Tokens:** ~2-4k MCP + ~1-2k hooks

**Pros:**
- 60-80% reduction vs full MCP
- No approval prompts for common queries
- Cleaner syntax for frequent operations
- Still efficient

**Cons:**
- Requires MCP server (additional setup)
- Mixed interface (some MCP, some CLI)

### Full MCP + Hooks (Legacy)

**Setup:** Install full MCP server + `bd setup claude`

**Tokens:** ~10.5k MCP + hooks

**Pros:**
- All commands as native function calls
- Consistent interface

**Cons:**
- Highest token usage (worst for compute/energy/cost)
- Slowest processing
- Less sustainable

### Recommendation

1. **Start with CLI + hooks** - most efficient, works great
2. **Try minimal MCP** if approval prompts become annoying
3. **Avoid full MCP** - wasteful with no significant benefit
```

## Production Validation Checklist

Before making these documentation changes, validate CLI approach works reliably:

### Phase 1: Pure CLI Validation
- [ ] `bd prime` implemented and tested
- [ ] Hooks installed and working in Claude Code
- [ ] Real-world usage by at least 2-3 developers for 1+ weeks
- [ ] No significant usability issues reported
- [ ] Agent successfully uses bd via Bash tool
- [ ] Document which commands (if any) have approval prompt issues

### Phase 2: Hybrid Mode Investigation (Optional)
- [ ] Test if MCP calls skip approval prompts vs Bash calls
- [ ] Measure token cost per MCP command
- [ ] Identify minimal set of commands worth exposing via MCP
- [ ] Build minimal MCP server variant
- [ ] Validate token savings (should be 60-80% vs full MCP)
- [ ] User testing shows actual UX improvement

### Phase 3: Documentation Update
- [ ] Update based on validation results
- [ ] Include measured token counts (not estimates)
- [ ] Provide clear migration paths
- [ ] Update `bd doctor` recommendations

## Migration Guide (Optional)

For users currently using MCP:

```markdown
### Migrating from Full MCP to CLI + Hooks

Already using full MCP server? You can switch to the more efficient CLI approach:

1. Install hooks: `bd setup claude`
2. Test it works (hooks inject context, agent uses Bash tool)
3. Remove MCP server from `~/.claude/settings.json`
4. Restart Claude Code

You'll get the same functionality with 80-90% less token usage.

### Migrating to Minimal MCP (If Available)

If you find approval prompts annoying for certain commands:

1. Replace full MCP with minimal MCP in `~/.claude/settings.json`
2. Restart Claude Code
3. Verify high-frequency commands (ready, show, list) work via MCP
4. Everything else automatically uses CLI

You'll get 60-80% token reduction vs full MCP while keeping the UX benefits.
```

## Files to Update

- `README.md` - Add recommendation in AI Integration section
- `AGENTS.md` - Add "Choosing Your Integration Approach" section early
- `QUICKSTART.md` - Update AI integration section
- `docs/` - Any other AI integration docs if they exist
- `mcp-server/` - Create minimal variant if hybrid validated

## Future: Update `bd init`

Once validated, update `bd init` to:
- Default to recommending `bd setup claude` (hooks only)
- Mention minimal MCP as option for UX improvement
- Detect existing full MCP and suggest migration
- Provide token usage estimates for each approach

## MCP Server Architecture Note

**Key insight:** MCP server doesn't have to expose all bd functionality.

Current design exposes ~20+ commands (all bd subcommands). This is over-engineered.

**Better design:**
- **Minimal MCP**: 3-5 read-only commands (~2-4k tokens)
- **CLI**: Everything else via Bash tool
- **Hooks**: Context injection via `bd prime`

This achieves best of both worlds:
- Low token usage (efficient)
- No approval prompts for common queries (UX)
- Explicit visibility for state changes (safety)

If validation shows NO meaningful benefit to MCP (even minimal), skip hybrid mode entirely and recommend pure CLI.

acceptance_criteria:
- Documentation explains CLI + hooks as recommended approach
- Explains why context size matters (compute/energy/cost/latency)
- Token comparison table shows 80-90% reduction
- Migration guide for existing MCP users
- Only deployed AFTER production validation
- Clear that both approaches are supported


title: PruneDeletions iterates map non-deterministically

description:
## Problem

`PruneDeletions` iterates over `loadResult.Records` which is a map. Go maps iterate in random order, so:

1. `result.PrunedIDs` order is non-deterministic
2. `kept` slice order is non-deterministic → `WriteDeletions` output order varies

## Location
`internal/deletions/deletions.go:213`

## Impact
- Git diffs are noisy (file changes order on each prune)
- Tests could be flaky if they depend on order
- Harder to debug/audit

## Fix
Sort by ID or timestamp before iterating:

```go
// Convert map to slice and sort
var records []DeletionRecord
for _, r := range loadResult.Records {
    records = append(records, r)
}
sort.Slice(records, func(i, j int) bool {
    return records[i].ID < records[j].ID
})
```


title: Add bd deleted command for audit trail

description:
Parent: bd-imj

Add command to view deletion history.

Usage:
  bd deleted              # Show recent deletions (last 7 days)
  bd deleted --since=30d  # Show deletions in last 30 days
  bd deleted --all        # Show all tracked deletions
  bd deleted bd-xxx       # Show deletion details for specific issue

Output format:
  bd-xxx  2025-11-25 10:00  stevey  duplicate of bd-yyy
  bd-yyy  2025-11-25 10:05  claude  cleanup

Acceptance criteria:
- List deletions with timestamp, actor, reason
- Filter by time range
- Lookup specific issue ID
- JSON output option for scripting


title: Consolidate check-health DB opens into single connection

description: The --check-health flag opens the database 3 separate times (once per quick check). Consolidate into a single DB open for better performance, especially on slower filesystems.


title: Refactor AGENTS.md to use external references

description:
Suggestion to use external references (e.g., "ALWAYS REFER TO ./beads/prompt.md") instead of including all instructions directly within AGENTS.md.
Reasons:
1. Agents can follow external references.
2. Prevents context pollution/stuffing in AGENTS.md as more tools append instructions.


title: troubleshoot GH#278 daemon exits every few secs


title: Performance Testing Documentation

description:
Create docs/performance-testing.md documenting the performance testing framework.

Sections:
1. Overview - What the framework does, goals
2. Running Benchmarks
   - make bench command
   - Running specific benchmarks
   - Interpreting output (ns/op, allocs/op)
3. Profiling and Analysis
   - Viewing CPU profiles with pprof
   - Reading flamegraphs
   - Memory profiling
   - Finding hotspots
4. User Diagnostics
   - bd doctor --perf usage
   - Sharing profiles with bug reports
   - Understanding the report output
5. Comparing Performance
   - Using benchstat for before/after comparisons
   - Detecting regressions
6. Tips for Optimization
   - Common patterns
   - When to profile vs benchmark

Style:
- Concise, practical examples
- Screenshots/examples of pprof output
- Clear command-line examples
- Focus on workflow, not theory