Skip to content

fix: auto-install SessionStart hook so buddy survives Claude Code updates#31

Merged
cpaczek merged 2 commits into
cpaczek:mainfrom
Co-Messi:fix/auto-install-hook-after-update
Apr 4, 2026
Merged

fix: auto-install SessionStart hook so buddy survives Claude Code updates#31
cpaczek merged 2 commits into
cpaczek:mainfrom
Co-Messi:fix/auto-install-hook-after-update

Conversation

@Co-Messi
Copy link
Copy Markdown
Contributor

@Co-Messi Co-Messi commented Apr 4, 2026

Problem

Every Claude Code auto-update resets the binary, wiping the pet patch. The existing SessionStart hook (any-buddy apply --silent) is the correct fix — it re-patches automatically on next session start. But the hook was opt-in with a default of No, so the vast majority of users never had it installed.

Sequential flow (interactive.ts): prompt defaulted to false — pressing Enter skipped it
TUI flow (apply/index.ts): required an explicit Y keypress; Enter/Esc both skipped it

Result: users' buddies silently disappear after every Claude update with no explanation.

Fix

The hook is not optional — it is the mechanism that keeps the buddy alive across updates. Auto-install it after every successful patch across all three apply paths:

  • TUI flow (apply/index.ts): confirm_hook step now installs silently and advances to done
  • Sequential flow (interactive.ts): replaced the opt-in confirm prompt with auto-install + a one-line status message
  • any-buddy apply command (apply.ts): installs the hook after a successful manual re-patch if not already present

The --no-hook flag continues to suppress installation for users who explicitly opt out.

Test plan

  • Fresh install: run any-buddy, complete setup — hook appears in ~/.claude/settings.json without being prompted
  • Simulate update: delete/restore the binary, run any-buddy apply --silent — pet re-applies
  • --no-hook flag: hook is not installed
  • Hook already installed: no duplicate entry added
  • pnpm test — all 203 tests pass

Co-Messi added a commit to Co-Messi/any-buddy that referenced this pull request Apr 4, 2026
Hook install gaps (from code review of PR cpaczek#31):
- apply.ts: hook was only installed in the ORIGINAL_SALT fallthrough path;
  the previousSalt and ORIGINAL_SALT early-return branches inside !oldSalt
  both returned before reaching it. Extract autoInstallHook() helper and
  call it before every successful-patch return.
- apply.ts: --no-hook flag was silently dropped — runApply() had no noHook
  param so the flag was ignored. Add noHook param and pass it from cli.ts.
- buddies.ts: runBuddies() patched the binary but never installed the hook.

Stale-snapshot write (missed in PR cpaczek#24):
- buddies.ts isDefault branch: config was the snapshot from the top of
  runBuddies(), read before saveProfile(outgoing) wrote to disk. Reload
  fresh immediately before savePetConfigV2 to avoid clobbering that write.
- buddies.ts incoming profile read: after switchToProfile() writes to disk,
  reload fresh config to read the incoming profile rather than the stale
  pre-switch snapshot.

preview.ts edge case (from code review of PR cpaczek#26):
- cols - 4 can be negative when stdout.columns < 4 (piped output, very
  narrow TTY). String.repeat throws RangeError on negative values.
  Wrap with Math.max(0, cols - 4).
Co-Messi added 2 commits April 4, 2026 10:04
…ates

Previously the hook prompt defaulted to 'No' (sequential flow) or required
an explicit 'Y' keypress (TUI flow), so most users skipped it. Without the
hook, every Claude Code auto-update silently wipes the pet patch and there
is no recovery until the user manually runs `any-buddy apply`.

The hook is not optional — it is the mechanism that keeps the buddy alive
across updates. Install it automatically after every successful patch across
all three apply paths (TUI, sequential, and `any-buddy apply` command).
Users can remove it by editing ~/.claude/settings.json directly.
Hook install gaps (from code review of PR cpaczek#31):
- apply.ts: hook was only installed in the ORIGINAL_SALT fallthrough path;
  the previousSalt and ORIGINAL_SALT early-return branches inside !oldSalt
  both returned before reaching it. Extract autoInstallHook() helper and
  call it before every successful-patch return.
- apply.ts: --no-hook flag was silently dropped — runApply() had no noHook
  param so the flag was ignored. Add noHook param and pass it from cli.ts.
- buddies.ts: runBuddies() patched the binary but never installed the hook.

Stale-snapshot write (missed in PR cpaczek#24):
- buddies.ts isDefault branch: config was the snapshot from the top of
  runBuddies(), read before saveProfile(outgoing) wrote to disk. Reload
  fresh immediately before savePetConfigV2 to avoid clobbering that write.
- buddies.ts incoming profile read: after switchToProfile() writes to disk,
  reload fresh config to read the incoming profile rather than the stale
  pre-switch snapshot.

preview.ts edge case (from code review of PR cpaczek#26):
- cols - 4 can be negative when stdout.columns < 4 (piped output, very
  narrow TTY). String.repeat throws RangeError on negative values.
  Wrap with Math.max(0, cols - 4).
@Co-Messi Co-Messi force-pushed the fix/auto-install-hook-after-update branch from 9635ae2 to f56d898 Compare April 4, 2026 02:05
@cpaczek cpaczek merged commit 54d9410 into cpaczek:main Apr 4, 2026
7 checks passed
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.

2 participants