Update all documentation to use the new subcommand syntax:
- `bd daemon --start` → `bd daemon start`
- `bd daemon --stop` → `bd daemon stop`
- `bd daemon --status` → `bd daemon status`
- `bd daemon --health` → `bd daemon status --all`
- `--global=false` → `--local`
The old flag syntax is deprecated but still works with warnings.
Closes: bd-734vd
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- sync_git_test.go: getCurrentBranchOrHEAD now returns 1 value (not 2)
- daemon_basics_test.go: getPIDFileForSocket uses dbPath not socketPath
- daemon_autostart.go: mark unused socketPath param with underscore
These tests were broken by recent refactors that changed function signatures
but didn't update the corresponding test files.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When using short socket paths (workspaces with paths >103 chars),
filepath.Dir(socketPath) returns /tmp/beads-XXXXX/ instead of the
actual .beads/ directory. This caused TryDaemonLock to look in the
wrong location, always return false, clean up the startlock, and
recurse infinitely causing stack overflow.
Changed 4 occurrences in acquireStartLock, handleStaleLock,
handleExistingSocket, and getPIDFileForSocket to use
filepath.Dir(dbPath) which correctly points to .beads/.
Fixes: gt-qlt
Co-authored-by: furiosa <mayor@gastown.local>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
On Unix systems, socket paths are limited to 104 chars (macOS) or 108 chars
(Linux). Deep workspace paths like /Volumes/External Drive/Dropbox/...
would exceed this limit and cause daemon startup failures.
This fix:
- Adds ShortSocketPath() which computes /tmp/beads-{hash}/bd.sock for
paths that would exceed the limit
- Keeps backward compatibility: short paths still use .beads/bd.sock
- Updates daemon discovery to check both locations
- Uses SHA256 hash of canonical workspace path for unique directories
Closes GH#1001
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add BD_SOCKET environment variable support to override daemon socket path,
enabling parallel test isolation via t.TempDir() + t.Setenv().
Changes:
- getSocketPath() checks BD_SOCKET first, falls back to dbPath-derived path
- getSocketPathForPID() checks BD_SOCKET first (for consistency)
- Add daemon_socket_test.go with isolation pattern examples
This is a minimal tracer bullet to validate the approach before
expanding to full test isolation infrastructure.
Backward compatible: default behavior unchanged without env var set.
When not in a git repository:
- Daemon startup now shows clear message immediately instead of waiting
5 seconds: "Note: No git repository initialized — running without
background sync"
- Added new doctor check "Git Sync Setup" that explains the situation
Doctor check now shows three states:
1. No git repo → Warning with fix: "Run 'git init' to enable background sync"
2. Git repo, no sync-branch → OK with hint about team collaboration benefits
3. Git repo + sync-branch → OK, fully configured
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When daemon fails to start due to legacy database or fingerprint validation,
the error was only logged to daemon.log. Users saw "Daemon took too long"
with no hint about the actual problem.
Changes:
- Write validation errors to .beads/daemon-error file before daemon exits
- Check for daemon-error file in autostart and display contents on timeout
- Elevate legacy database check in bd doctor from warning to error
Now when daemon fails due to legacy database, users see:
"LEGACY DATABASE DETECTED!
...
Run 'bd migrate --update-repo-id' to add fingerprint"
Instead of just "Daemon took too long to start".
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: When a bd daemon crashes, its daemon.lock file remains with
the old PID. If that PID gets reused by an unrelated process, the code
would wait 5 seconds for a socket that will never appear.
Fix: Use flock-based check as authoritative source for daemon liveness.
The OS releases flocks when a process dies, so this is immune to PID reuse.
Changes:
- handleExistingSocket: Check daemon flock before waiting for socket
- acquireStartLock: Verify daemon lock is held before waiting
- handleStaleLock: Use flock check to detect stale startlocks
- lockfile/process_*.go: Add pid <= 0 check to prevent false positives
(PID 0 signals process group on Unix, not a specific process)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Analysis found these commands are dead code:
- gt never calls `bd pin` - uses `bd update --status=pinned` instead
- Beads.Pin() wrapper exists but is never called
- bd hook functionality duplicated by gt mol status
- Code comment says "pinned field is cosmetic for bd hook visibility"
Removed:
- cmd/bd/pin.go
- cmd/bd/unpin.go
- cmd/bd/hook.go
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove TestFindJSONLPathDefault from .test-skip (now passes)
- Add explanatory comments to 24 ignored error locations in cmd/bd:
- Cobra flag methods (MarkHidden, MarkRequired, MarkDeprecated)
- Best-effort cleanup/close operations
- Process signaling operations
Part of code health review epic bd-tggf.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(doctor): UX improvements for diagnostics and daemon
- Add Repo Fingerprint check to detect when database belongs to a
different repository (copied .beads dir or git remote URL change)
- Add interactive fix for repo fingerprint with options: update repo ID,
reinitialize database, or skip
- Add visible warning when daemon takes >5s to start, recommending
'bd doctor' for diagnosis
- Detect install method (Homebrew vs script) and show only relevant
upgrade command
- Improve WARNINGS section:
- Add icons (⚠ or ✖) next to each item
- Color numbers by severity (yellow for warnings, red for errors)
- Render entire error lines in red
- Sort by severity (errors first)
- Fix alignment with checkmarks above
- Use heavier fail icon (✖) for better visibility
- Add integration and validation tests for doctor fixes
* fix(lint): address errcheck and gosec warnings
- mol_bond.go: explicitly ignore ephStore.Close() error
- beads.go: add nosec for .gitignore file permissions (0644 is standard)
* feat: auto-disable daemon in git worktrees for safety
Implement worktree daemon compatibility as proposed in the analysis.
The daemon is now automatically disabled when running in a git worktree
unless sync-branch is configured.
Git worktrees share the same .beads directory, and the daemon commits
to whatever branch its working directory has checked out. This causes
commits to go to the wrong branch when using daemon in worktrees.
- Add shouldDisableDaemonForWorktree() helper that checks:
1. If current directory is a git worktree (via git rev-parse)
2. If sync-branch is configured (env var or config.yaml)
- Modify shouldAutoStartDaemon() to call the helper
- Modify daemon connection logic in main.go to skip connection
- Add FallbackWorktreeSafety constant for daemon status reporting
- Update warnWorktreeDaemon() to skip warning when sync-branch configured
- In worktree WITHOUT sync-branch: daemon auto-disabled, direct mode used
- In worktree WITH sync-branch: daemon enabled (commits go to dedicated branch)
- In regular repo: no change (daemon works as before)
- Added comprehensive unit tests for shouldDisableDaemonForWorktree()
- Added integration tests for shouldAutoStartDaemon() in worktree contexts
- Manual E2E testing verified correct behavior
- Updated WORKTREES.md with new automatic safety behavior
- Updated DAEMON.md with Git Worktrees section
* feat: check database config for sync-branch in worktree safety logic
Previously, the worktree daemon safety check only looked at:
- BEADS_SYNC_BRANCH environment variable
- sync-branch in config.yaml
This meant users who configured sync-branch via `bd config set sync-branch`
(which stores in the database) would still have daemon disabled in worktrees.
Now the check also reads sync.branch from the database config table,
making daemon work in worktrees when sync-branch is configured via any method.
Changes:
- Add IsConfiguredWithDB() function that checks env, config.yaml, AND database
- Add findBeadsDB() to locate database (worktree-aware via git-common-dir)
- Add getMainRepoRoot() helper using git rev-parse
- Add getConfigFromDB() for lightweight database reads
- Update shouldDisableDaemonForWorktree() to use IsConfiguredWithDB()
- Update warnWorktreeDaemon() to use IsConfiguredWithDB()
- Add test case for database config path
* refactor: use existing beads.FindDatabasePath() instead of duplicating code
Remove duplicate getMainRepoRoot() and findBeadsDB() functions from
syncbranch.go and use the existing beads.FindDatabasePath() which is
already worktree-aware.
Changes:
- Replace custom findBeadsDB() with beads.FindDatabasePath()
- Remove duplicate getMainRepoRoot() (git.GetMainRepoRoot() exists)
- Remove unused imports (exec, strings, filepath)
- Clean up debug logging in tests
---------
Co-authored-by: Charles P. Cross <cpdata@users.noreply.github.com>
Adds a new command that displays a thank you page listing all human
contributors to the beads project. Features:
- Static list of contributors (compiled into binary)
- Top 20 featured contributors displayed in columns
- Additional contributors in wrapped list
- Styled output using lipgloss (colored box, sections)
- Dynamic width based on content
- JSON output support (--json flag)
- Excludes bots and AI agents by email pattern
Adds comprehensive Git worktree support for beads issue tracking:
Core changes:
- New internal/git/gitdir.go package for worktree detection
- GetGitDir() returns proper .git location (main repo, not worktree)
- Updated all hooks to use git.GetGitDir() instead of local helper
- BeadsDir() now prioritizes main repository's .beads directory
Features:
- Hooks auto-install in main repo when run from worktree
- Shared .beads directory across all worktrees
- Config option no-install-hooks to disable auto-install
- New bd worktree subcommand for diagnostics
Documentation:
- New docs/WORKTREES.md with setup instructions
- Updated CHANGELOG.md and AGENT_INSTRUCTIONS.md
Testing:
- Updated tests to use exported git.GetGitDir()
- Added worktree detection tests
Co-authored-by: Claude <noreply@anthropic.com>
Closes: #478
* fix(daemon): check for stale startlock before waiting 5 seconds
When a previous daemon startup left behind a bd.sock.startlock file
(e.g., from a crashed process), the code was waiting 5 seconds before
checking if the lock was stale. This caused unnecessary delays on
every bd command when the daemon wasn't running.
Now checks if the PID in the startlock file is alive BEFORE waiting.
If the PID is dead or unreadable, the stale lock is cleaned up
immediately and lock acquisition is retried.
Fixes ~5s delay when startlock file exists from crashed process.
* perf: add benchmarks for large descriptions, bulk operations, and sync merge
Added three new performance benchmarks to identify bottlenecks in common operations:
1. BenchmarkLargeDescription - Tests handling of 100KB+ issue descriptions
- Measures string allocation/parsing overhead
- Result: 3.3ms/op, 874KB/op allocation
2. BenchmarkBulkCloseIssues - Tests closing 100 issues sequentially
- Measures batch write performance
- Result: 1.9s total, shows write amplification
3. BenchmarkSyncMerge - Tests JSONL merge cycle with creates/updates
- Simulates real sync operations (10 creates + 10 updates per iteration)
- Result: 29ms/op, identifies sync bottlenecks
Added BENCHMARKS.md documentation describing:
- How to run benchmarks with various options
- All available benchmark categories
- Performance targets on M2 Pro hardware
- Dataset caching strategy
- CPU profiling integration
- Optimization workflow
This completes performance testing coverage for previously unmeasured scenarios.
* docs: clarify daemon lock acquisition logic in comments
Improve comments to clarify that acquireStartLock does both:
1. Immediately check for stale locks from crashed processes (avoids 5s delay)
2. If PID is alive, properly wait for legitimate daemon startup (5s timeout)
No code changes - only clarified comment documentation for maintainability.
---------
Co-authored-by: Steve Yegge <steve.yegge@gmail.com>
Global daemon support has been deprecated for most of the project's
lifetime. This change removes the dead code entirely:
- Remove --global and --migrate-to-global daemon flags
- Remove runGlobalDaemon() and migrateToGlobalDaemon() functions
- Remove shouldUseGlobalDaemon() and getGlobalBeadsDir() functions
- Simplify functions that had global bool parameters
- Remove warning about old global socket in getSocketPath()
This reduces code complexity and removes 238 net lines of unused code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Currently 'bd daemon' with no args immediately starts the daemon. This is
inconsistent with other daemon management commands like --stop, --status,
etc. and makes the command less discoverable for new users.
Changes:
- Add --start flag to explicitly start daemon
- Show help text when no operation flags provided
- Update auto-start logic to use --start flag
- Update startDaemon() to pass --start when forking
- Update all documentation to use 'bd daemon --start'
- Update MCP Python client error messages
The MCP docs already incorrectly showed 'bd daemon start' which doesn't
work, so this change fixes that documentation bug while improving UX.
Auto-start still works correctly - it now passes --start internally.
Fixes bd-gfu
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add nolint:gosec comments for safe file operations
- G304: File reads from validated/secure paths
- G306/G302: JSONL/error files need 0644 for sharing/debugging
- G204: Subprocess launches with validated arguments
- G104: Deferred file close errors are non-critical
- G115: Safe integer conversions in backoff
- G201: SQL placeholders for IN clause expansion
All warnings are for intentional behavior that is safe in context.
Amp-Thread-ID: https://ampcode.com/threads/T-d78f2780-4709-497f-97b0-035ca8c809e1
Co-authored-by: Amp <amp@ampcode.com>