fix(observe): no-op the Claude hook when .insta/observe/hook.js is absent#40
fix(observe): no-op the Claude hook when .insta/observe/hook.js is absent#40tonychang04 wants to merge 1 commit into
Conversation
…sent .claude/settings.json is often committed while ./.insta stays local-only, so a fresh clone (cloud code session, teammate checkout) gets the observe hook registered without the script. Every tool call then fails with 'PostToolUse hook error: node:internal/modules/cjs/loader:1386' (MODULE_NOT_FOUND). Guard the command on file existence so those checkouts no-op instead of erroring. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015PdkPrifSPAYEEX4QF89z4
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
jwfing
left a comment
There was a problem hiding this comment.
Summary
Small, well-scoped bug fix: the Claude PostToolUse hook command is now guarded so it no-ops when .insta/observe/hook.js is absent (fresh clones / cloud sessions), eliminating the per-tool-call MODULE_NOT_FOUND spam.
Requirements context
No matching spec/plan found — this repo has no /docs/superpowers/ or docs/specs/ directory (only README.md + .claude/skills/developing-insta-cli). Assessed against the PR description, the linked user report, and existing code/test conventions. I verified the stated gates locally: npm run typecheck clean and npm test → 74/74 passing, matching the PR's claims.
Findings
Critical
(none)
Suggestion
- Functionality —
src/observe/install.ts:68-71(codexEntry) has the same defect class. A committed.codex/hooks.jsonwith a local-only.instawill stillnode <abs path>and throwMODULE_NOT_FOUNDper tool call. The PR body explicitly and correctly defers this to keep scope tight — flagging only so it's tracked as a follow-up, not as a blocker for this PR.
Information
- Software engineering — good regression coverage.
test/observe-install.test.ts:33-46executes the emitted command viash -cand asserts both the absent case (exit 0, empty stderr) and the present case (script runs), which is exactly the behavior the fix targets. Follows the repo's scratch-dir / DI test pattern. - Correctness — guard logic is sound and idempotent. The
[ ! -f "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js" ] || node "…"short-circuit is correct POSIX (||runs node only when thetestfails, i.e. the file exists), the path is quoted so spaces are safe, and the string still contains theobserve/hook.substring soisInstaHook(install.ts:15-19) matches and re-install cleanly replaces the old unguarded entry rather than stacking. - Portability — pre-existing, not a regression. The command relies on a POSIX shell (
testbuiltin +||), as did the priornode "$CLAUDE_PROJECT_DIR/…"form ($VARexpansion). No cross-platform behavior changes here. - Security / Performance — no concerns. No new user input, secrets, or auth changes. The added
[ -f ]stat per tool-call is negligible and, if anything, avoids spawningnodeon the no-op path.
Verdict
approved (informational — a human still gives the GitHub approval). Zero Critical findings: the fix is correct, minimal, tested, and gates are green. The one Suggestion (Codex parity) is intentionally out of scope per the PR description.
Problem
Cloud code sessions (and any fresh clone) show this after every tool call:
insta observe installregisters the hook in.claude/settings.json(commonly committed) but materializes the script into./.insta/observe/(local-only). A checkout without.instafiresnode "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js"on every tool call and node throws MODULE_NOT_FOUND — thatcjs/loader:1386line is the first line of its stack on Node 22.Fix
Guard the hook command on file existence:
Checkouts without
.instano-op (exit 0, no stderr); checkouts with it behave as before.isInstaHookstill matches (observe/hook.substring), so re-runninginsta observe installafter upgrading replaces the old unguarded entry instead of stacking. Existing projects need that one re-run (orinsta observe uninstallin the affected repo) to pick up the guarded command.Tests
sh -c: exit 0 + empty stderr in a dir with no.insta, and runs the script when present.tscclean.Note (not in this PR)
codexEntry()has the same class of issue — it embeds an absolute local path, which also breaks on any other machine if.codex/hooks.jsonis committed. Kept this PR scoped to the reported Claude failure.🤖 Generated with Claude Code
https://claude.ai/code/session_015PdkPrifSPAYEEX4QF89z4
Summary by cubic
No-op the Claude PostToolUse hook when the local
.insta/observe/hook.jsscript is missing to stop noisy errors in fresh clones and cloud sessions. The hook command now checks for the file before running.Bug Fixes
[ ! -f "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js" ] || node "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js"..instaexit 0 with no stderr; behavior unchanged when the script exists.Migration
insta observe installto replace the old unguarded hook in.claude/settings.json(or uninstall/reinstall).Written for commit 4b52fd0. Summary will update on new commits.