feat(setup claude): add --stealth flag

Add a `--stealth` flag to `bd setup claude` that installs
Claude Code hooks using `bd prime --stealth` instead of
`bd prime`. This extends the stealth workflow introduced for
`bd prime` to the setup command, enabling workflows where git
operations should be deferred or handled separately from bd
database flushing.

When `--stealth` is specified, the installed hooks call
`bd prime --stealth`, which outputs only `bd sync --flush-only`
in the close protocol, omitting all git operations.

Update `RemoveClaude()` to remove both command variants
(`bd prime` and `bd prime --stealth`) for backwards
compatibility with existing installations. Update
`hasBeadsHooks()` to detect either variant as a valid
installation.

Add comprehensive test coverage for stealth mode: hook
installation with stealth command, removal of both variants,
detection of both variants, and idempotency with stealth mode.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Abhinav Gupta
2025-12-03 18:05:08 -08:00
parent c9eeecf0c3
commit 4a7d7b0b41
3 changed files with 153 additions and 11 deletions

View File

@@ -8,7 +8,7 @@ import (
)
// InstallClaude installs Claude Code hooks
func InstallClaude(project bool) {
func InstallClaude(project bool, stealth bool) {
var settingsPath string
if project {
@@ -49,13 +49,19 @@ func InstallClaude(project bool) {
settings["hooks"] = hooks
}
// Determine which command to use
command := "bd prime"
if stealth {
command = "bd prime --stealth"
}
// Add SessionStart hook
if addHookCommand(hooks, "SessionStart", "bd prime") {
if addHookCommand(hooks, "SessionStart", command) {
fmt.Println("✓ Registered SessionStart hook")
}
// Add PreCompact hook
if addHookCommand(hooks, "PreCompact", "bd prime") {
if addHookCommand(hooks, "PreCompact", command) {
fmt.Println("✓ Registered PreCompact hook")
}
@@ -137,9 +143,11 @@ func RemoveClaude(project bool) {
return
}
// Remove bd prime hooks
// Remove bd prime hooks (both variants for backwards compatibility)
removeHookCommand(hooks, "SessionStart", "bd prime")
removeHookCommand(hooks, "PreCompact", "bd prime")
removeHookCommand(hooks, "SessionStart", "bd prime --stealth")
removeHookCommand(hooks, "PreCompact", "bd prime --stealth")
// Write back
data, err = json.MarshalIndent(settings, "", " ")
@@ -284,7 +292,9 @@ func hasBeadsHooks(settingsPath string) bool {
if !ok {
continue
}
if cmdMap["command"] == "bd prime" {
// Check for either variant
cmd := cmdMap["command"]
if cmd == "bd prime" || cmd == "bd prime --stealth" {
return true
}
}