Summary
Running bigpowers setup (or npx bigpowers) with the claude target replaces the user's existing ~/.claude/hooks/rtk-rewrite.sh with the package's own version, without prompting, backing up, or checking what was there. The two files are functionally different.
Evidence
scripts/lib/install-helpers.js (claude case, installGlobal) calls:
linkHook(
path.join(repoRoot, 'scripts', 'hooks', 'rtk-rewrite.sh'),
path.join(hooksDir, 'rtk-rewrite.sh')
);
linkHook does fs.rmSync(dst, { force: true }) before symlinking — no existence check, no backup, no prompt. The same destructive pattern applies to the skills dirs (linkSkills → rmSync(dst, { recursive: true }) before symlink), so any pre-existing directory with a colliding name is recursively deleted.
Observed on a machine where ~/.claude/hooks/rtk-rewrite.sh was RTK's own v2 delegating hook (from rtk >= 0.23.0):
- Existing hook: 2.5 KB,
rtk-hook-version: 2, thin delegator calling rtk rewrite, with jq presence check, rtk presence check, version guard (>= 0.23.0), and explicit permissionDecision: allow + updatedInput output for Claude Code.
- bigpowers hook: 295 bytes,
exec rtk hook claude when rtk is on PATH, else pass-through.
The replacement is not just an older version of the same file — it changes the rewrite mechanism (RTK's documented rtk hook claude subcommand vs the v2 inline rtk rewrite protocol), and silently drops the version guard and the permissionDecision/updatedInput output contract. A user running rtk below the version that introduced rtk hook claude would silently lose command rewriting.
Expected behavior
- If the destination exists and is not already a bigpowers-managed symlink, the installer should refuse (or ask, or back up to
<dst>.bak before replacing).
- Same guard for the skills-dir
rmSync(recursive) path — never recursively delete a pre-existing non-managed directory.
- The uninstall path (
removeSymlink) is fine; it is the install path that is destructive.
Environment
- bigpowers v2.87.5
- macOS, Claude Code hooks at
~/.claude/hooks/
Summary
Running
bigpowers setup(ornpx bigpowers) with the claude target replaces the user's existing~/.claude/hooks/rtk-rewrite.shwith the package's own version, without prompting, backing up, or checking what was there. The two files are functionally different.Evidence
scripts/lib/install-helpers.js(claude case,installGlobal) calls:linkHookdoesfs.rmSync(dst, { force: true })before symlinking — no existence check, no backup, no prompt. The same destructive pattern applies to the skills dirs (linkSkills→rmSync(dst, { recursive: true })before symlink), so any pre-existing directory with a colliding name is recursively deleted.Observed on a machine where
~/.claude/hooks/rtk-rewrite.shwas RTK's own v2 delegating hook (from rtk >= 0.23.0):rtk-hook-version: 2, thin delegator callingrtk rewrite, with jq presence check, rtk presence check, version guard (>= 0.23.0), and explicitpermissionDecision: allow+updatedInputoutput for Claude Code.exec rtk hook claudewhen rtk is on PATH, else pass-through.The replacement is not just an older version of the same file — it changes the rewrite mechanism (RTK's documented
rtk hook claudesubcommand vs the v2 inlinertk rewriteprotocol), and silently drops the version guard and the permissionDecision/updatedInput output contract. A user running rtk below the version that introducedrtk hook claudewould silently lose command rewriting.Expected behavior
<dst>.bakbefore replacing).rmSync(recursive)path — never recursively delete a pre-existing non-managed directory.removeSymlink) is fine; it is the install path that is destructive.Environment
~/.claude/hooks/