Skip to content

fix(observe): no-op the Claude hook when .insta/observe/hook.js is absent#40

Open
tonychang04 wants to merge 1 commit into
mainfrom
fix/observe-hook-guard
Open

fix(observe): no-op the Claude hook when .insta/observe/hook.js is absent#40
tonychang04 wants to merge 1 commit into
mainfrom
fix/observe-hook-guard

Conversation

@tonychang04

@tonychang04 tonychang04 commented Jul 15, 2026

Copy link
Copy Markdown
Member

Problem

Cloud code sessions (and any fresh clone) show this after every tool call:

PostToolUse:Bash hook error
Failed with non-blocking status code: node:internal/modules/cjs/loader:1386

insta observe install registers the hook in .claude/settings.json (commonly committed) but materializes the script into ./.insta/observe/ (local-only). A checkout without .insta fires node "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js" on every tool call and node throws MODULE_NOT_FOUND — that cjs/loader:1386 line is the first line of its stack on Node 22.

Fix

Guard the hook command on file existence:

[ ! -f "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js" ] || node "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js"

Checkouts without .insta no-op (exit 0, no stderr); checkouts with it behave as before. isInstaHook still matches (observe/hook. substring), so re-running insta observe install after upgrading replaces the old unguarded entry instead of stacking. Existing projects need that one re-run (or insta observe uninstall in the affected repo) to pick up the guarded command.

Tests

  • Updated the command-string assertion.
  • New test executes the emitted command via sh -c: exit 0 + empty stderr in a dir with no .insta, and runs the script when present.
  • Full suite: 74/74 passing, tsc clean.

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.json is 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.js script is missing to stop noisy errors in fresh clones and cloud sessions. The hook command now checks for the file before running.

  • Bug Fixes

    • Guarded command: [ ! -f "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js" ] || node "$CLAUDE_PROJECT_DIR/.insta/observe/hook.js".
    • Fresh clones without .insta exit 0 with no stderr; behavior unchanged when the script exists.
    • Tests updated to assert the command string and shell-run behavior.
  • Migration

    • Re-run insta observe install to replace the old unguarded hook in .claude/settings.json (or uninstall/reinstall).

Written for commit 4b52fd0. Summary will update on new commits.

Review in cubic

…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
@tonychang04 tonychang04 marked this pull request as ready for review July 15, 2026 02:06
@cursor

cursor Bot commented Jul 15, 2026

Copy link
Copy Markdown

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 jwfing left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 test74/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.json with a local-only .insta will still node <abs path> and throw MODULE_NOT_FOUND per 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-46 executes the emitted command via sh -c and 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 the test fails, i.e. the file exists), the path is quoted so spaces are safe, and the string still contains the observe/hook. substring so isInstaHook (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 (test builtin + ||), as did the prior node "$CLAUDE_PROJECT_DIR/…" form ($VAR expansion). 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 spawning node on 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.

@jwfing jwfing left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - approved.

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