feat: ship bstack as a Claude Code plugin — installer-immune hooks (BRO-1926)#94
Conversation
…RO-1926)
Add .claude-plugin/plugin.json + .claude-plugin/marketplace.json + hooks/hooks.json
so the six governance hooks load as a Claude Code plugin (bstack@skills-dir when
vendored under ~/.claude/skills/, or marketplace-installable) with
${CLAUDE_PLUGIN_ROOT}-relative paths, instead of hand-wired absolute paths in each
consuming workspace's settings.json that a `npx skills update` re-pull of the
primer-only monorepo skill can strip (the incident that broke all six hooks
2026-07-15; distinct from the now-fixed vercel-labs/skills#1523).
Additive/non-breaking: the settings.json.snippet wiring stays for backward-compat.
Adoption is opt-in (enable plugin + remove the six settings.json entries in the same
change to avoid double-fire). Bump 0.34.1 -> 0.35.0 (minor: new hooks-as-plugin).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 46 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughBstack is packaged as a Claude Code plugin at version 0.35.0, with marketplace metadata and ChangesClaude plugin packaging
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant ClaudeCode
participant HooksConfig as hooks/hooks.json
participant GovernanceScripts as Governance scripts
ClaudeCode->>HooksConfig: Load plugin hook mappings
HooksConfig->>GovernanceScripts: Invoke ${CLAUDE_PLUGIN_ROOT}-relative commands
GovernanceScripts-->>ClaudeCode: Complete hook execution
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…uto-load double-fire (P20) Skills-dir plugins auto-load AND auto-enable on presence (no install step, per plugins-reference), so once this manifest reaches a vendored ~/.claude/skills/bstack it would fire all six hooks alongside the still-present settings.json snippet = silent double-fire (two leverage-sensor.py writers race on .control/leverage-state.json; l3-stability-pretool double-counts the L3 rate budget). Set defaultEnabled:false in plugin.json + the marketplace entry so the plugin loads DISABLED until an explicit `claude plugin enable bstack@skills-dir`. Rewrite CHANGELOG to state the auto-load trigger honestly, the <2.1.154 client residual (field ignored → enables on presence), the source:"." ≥2.1.196 floor, and the 3-step adoption (enable + delete the six snippet hooks in one change). Caught by P20 Strata-B adversarial review (score 6/10, this was the lone MAJOR). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Adds a Claude Code plugin manifest to bstack so its six governance hooks travel as one versioned unit instead of hand-wired absolute paths in every consuming workspace's
settings.json..claude-plugin/plugin.json— plugin manifest (v0.35.0).claude-plugin/marketplace.json— single-plugin marketplace (source: ".") →claude plugin marketplace add broomva/bstackhooks/hooks.json— the 6 hooks,commands self-locating via${CLAUDE_PLUGIN_ROOT}VERSION0.34.1 → 0.35.0 ·CHANGELOG.mdprependedWhy
The six hooks pointed at
~/.claude/skills/bstack/scripts/*.sh, under the skills-CLI-managed dir. Anpx skills update -gthat re-pulls the monorepo's primer-onlybstackskill (skills/governance/bstack/, intentionally SKILL.md-only) stripsscripts//bin/and breaks all six hooks withNo such file or directory— the incident on 2026-07-15. As a plugin: hook paths self-locate via${CLAUDE_PLUGIN_ROOT}, the checkout is structurally invisible to the vercel-labs skills CLI, and the unit is versioned + marketplace-installable.(Distinct from vercel-labs/skills#1523, the repo-root sibling-drop bug fixed in
skills@1.5.18— bstack's clobber came from the primer-only monorepo source, not #1523. RELEASE.md already documents why bstack is clone-installed; this reinforces it.)Hooks provided (event → script)
Safety / scope
assets/templates/settings.json.snippetwiring stays. No install changes behavior until a workspace opts in.settings.jsonhook entries in the same change, or every hook fires twice. Vendored installs (rm -rf .git) do not auto-pull, so merging this does not auto-apply the manifest anywhere.arc-continuation-hook.shexpects to run after a workspace's capture hooks — cross-source ordering validated on first session at adoption time (workspace-side, BRO-1926 Phase 2).Validation
jq -e .on all three new JSON files: passclaude plugin validate .claude-plugin/marketplace.json --strict: passclaude plugin validate .claude-plugin/plugin.json: pass (1 benign warning — CLAUDE.md-at-root not loaded as plugin context; bstack's CLAUDE.md is a governance doc, intentionally kept)Ticket: BRO-1926 (Phase 1 of 3). Phase 2 = workspace adoption; Phase 3 =
bstack bootstrapprefers the plugin.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores