Skip to content

fix: self-heal legacy untagged ccstatusline hooks on sync#490

Merged
sirmalloc merged 3 commits into
sirmalloc:mainfrom
bit-saver:fix/self-heal-legacy-ccstatusline-hooks
Jun 30, 2026
Merged

fix: self-heal legacy untagged ccstatusline hooks on sync#490
sirmalloc merged 3 commits into
sirmalloc:mainfrom
bit-saver:fix/self-heal-legacy-ccstatusline-hooks

Conversation

@bit-saver

Copy link
Copy Markdown
Contributor

Problem

stripManagedHooks removes only entries tagged ccstatusline-managed. Untagged hooks — written by pre-tag versions, an npx-vs-global-binary command variant, settings synced from another machine, or a manual edit — are invisible to it. So every syncWidgetHooks leaves them in place and adds a fresh managed copy beside them: ccstatusline hooks accumulate in ~/.claude/settings.json, and saving from the configurator never converges.

Fix

stripManagedHooks now also drops untagged entries whose hook command matches the ccstatusline --hook invocation (/ccstatusline.* --hook(?:\s|$)/), then re-adds the deduped managed set as before. Hook sync becomes idempotent even for legacy installs — it migrates old/untagged hooks into the managed set automatically. Non-ccstatusline user hooks are untouched.

The match requires a space before --hook and a trailing word boundary so it can't catch unrelated --hook* substrings.

Tests

Adds vitest cases to src/utils/__tests__/hooks.test.ts (real temp CLAUDE_CONFIG_DIR, no mocks):

  • legacy untagged ccstatusline hooks heal to a single managed hook per event (no duplication), while a non-ccstatusline user hook is preserved;
  • repeated syncs starting from a legacy state stay at one managed hook per event (idempotent).

bun run lint passes clean; the hooks suite passes.

bit-saver and others added 3 commits June 27, 2026 19:54
stripManagedHooks only removed entries tagged 'ccstatusline-managed', so
untagged hooks written by pre-tag versions survived every sync and piled up
beside the freshly-written managed hooks. Also strip untagged entries whose
command matches the ccstatusline --hook invocation, making hook sync idempotent
for legacy installs. Non-ccstatusline user hooks are untouched.
Treat the ccstatusline-managed tag as whole-entry ownership, but handle legacy untagged ccstatusline hooks at the individual command level. This prevents sync and uninstall cleanup from dropping unrelated user commands that share the same Claude hook entry with an old ccstatusline --hook command.

Add regression coverage for mixed legacy hook entries in both syncWidgetHooks and removeManagedHooks so future cleanup changes keep user-managed hook commands intact.
@sirmalloc sirmalloc merged commit 477164e into sirmalloc:main Jun 30, 2026
3 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