feat: add Git worktree compatibility (PR #478)

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
This commit is contained in:
matt wilkie
2025-12-13 10:40:40 -08:00
committed by Steve Yegge
parent de7b511765
commit e01b7412d9
64 changed files with 1895 additions and 3708 deletions

View File

@@ -256,7 +256,7 @@ func isClaudeSetupComplete() bool {
// Check if beads plugin is installed - plugin now provides hooks automatically
settingsPath := filepath.Join(home, ".claude", "settings.json")
// #nosec G304 -- settingsPath is constructed from user home dir, not user input
// #nosec G304 - path is constructed from user home directory
if data, err := os.ReadFile(settingsPath); err == nil {
var settings map[string]interface{}
if err := json.Unmarshal(data, &settings); err == nil {
@@ -279,7 +279,8 @@ func isClaudeSetupComplete() bool {
}
// Project-level hooks in .claude/settings.local.json
if hasBeadsPrimeHooks(".claude/settings.local.json") {
localSettingsPath := filepath.Join(home, ".claude", "settings.local.json")
if hasBeadsPrimeHooks(localSettingsPath) {
return true
}
@@ -288,7 +289,8 @@ func isClaudeSetupComplete() bool {
// hasBeadsPrimeHooks checks if a settings file has bd prime hooks configured
func hasBeadsPrimeHooks(settingsPath string) bool {
data, err := os.ReadFile(settingsPath) // #nosec G304 -- path is either from home dir or relative project path
// #nosec G304 - path is constructed from user home directory
data, err := os.ReadFile(settingsPath)
if err != nil {
return false
}