Skip to content

fix(setup): skip duplicate hooks when beads plugin is installed#3196

Open
sjsyrek wants to merge 1 commit intogastownhall:mainfrom
sjsyrek:fix/setup-claude-skip-duplicate-plugin-hooks
Open

fix(setup): skip duplicate hooks when beads plugin is installed#3196
sjsyrek wants to merge 1 commit intogastownhall:mainfrom
sjsyrek:fix/setup-claude-skip-duplicate-plugin-hooks

Conversation

@sjsyrek
Copy link
Copy Markdown
Contributor

@sjsyrek sjsyrek commented Apr 11, 2026

Summary

Fixes #3192. When both the beads Claude Code plugin and bd setup claude are active, bd prime fires twice per session — wasting ~1-2k tokens each time. The plugin already declares identical SessionStart/PreCompact hooks in its plugin.json, so project-level hooks from bd setup claude are redundant.

Changes Made

  • Added hasBeadsPlugin() — checks project, global, and legacy settings files for an enabled beads entry in enabledPlugins
  • Modified installClaude() — skips writing SessionStart/PreCompact hooks when the plugin is detected; still installs the CLAUDE.md section (which the plugin does not provide)
  • Modified checkClaude() — reports "✓ Hooks provided by beads plugin (plugin-managed)" as a valid success state instead of "✗ No hooks installed"
  • Added 7 tests covering plugin detection (project/global/disabled/absent), install skip behavior, normal install without plugin, and check --plugin-managed path

Backward Compatibility

No breaking changes: Users without the plugin see identical behavior
Users with plugin: bd setup claude now skips hooks instead of duplicating them
bd setup claude --remove: Still works unconditionally (removes any project-level hooks regardless of plugin state)
CLAUDE.md section: Still installed even with plugin present

Technical Details

  • Reuses the same enabledPlugins detection pattern from cmd/bd/doctor/claude.go, but adapted for the claudeEnv abstraction to keep tests hermetic
  • Disabled plugins ("beads@...": false) correctly do not trigger the skip
  • Plugin detection uses env.readFile (not os.ReadFile) so tests don't touch the real filesystem

Test plan

  • go test ./cmd/bd/setup/ — all 105 tests pass (98 existing + 7 new)
  • go vet ./cmd/bd/setup/ — clean
  • go build ./cmd/bd/... — compiles successfully
  • Manual: run bd setup claude in a project with the plugin installed → should print "plugin-managed, skipping"
  • Manual: run bd setup claude --check with plugin but no project hooks → should report "plugin-managed"
  • Manual: run bd setup claude without plugin → should register hooks as before

Size: Small ✓

Two-file change, straightforward conditional + detection function.

🤖 Generated with Claude Code

…192)

When both the beads Claude Code plugin and `bd setup claude` are active,
bd prime fires twice per session — wasting ~1-2k tokens each time. The
plugin already declares identical SessionStart/PreCompact hooks in its
plugin.json, so project-level hooks are redundant.

Now `bd setup claude` detects the plugin via enabledPlugins in settings
files and skips writing hooks when the plugin is already providing them.
The CLAUDE.md integration section is still installed since the plugin
does not provide that. `bd setup claude --check` reports "plugin-managed"
as a valid success state instead of "No hooks installed".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bd setup claude and the Claude Code plugin install duplicate SessionStart hooks

1 participant