Skip to content

Hooks silently exit 2 with no stderr when CLAGENTIC_LITE_HOME points at an invalid directory #174

Description

@jmwest96

Summary
session-start.sh and prompt-inject.sh (and likely the other hook shims using
the same pattern) fail with exit code 2 and completely empty stdout/stderr
when CLAGENTIC_LITE_HOME is set to a directory that doesn't contain
scripts/platform.sh. Claude Code surfaces this as "No stderr output," which
gives the user no actionable signal — the hook just silently blocks every
prompt.

Confirmed still present on current HEAD (a22e1a4, 2026-08-14), i.e. not
fixed by a normal clagentic-lite update.

Root cause
Both hooks do:
: "${CLAGENTIC_LITE_HOME:=/home/jwest/.clagentic/lite}"
. "$CLAGENTIC_LITE_HOME/scripts/platform.sh" 2>/dev/null || true

  1. The := default only applies when the var is unset. It's a no-op if
    the var is set to any wrong/stale value — there's no validation that
    CLAGENTIC_LITE_HOME actually resolves to a real checkout.
  2. Under POSIX sh/dash, . (source) is a special builtin. A "file not
    found" error inside a special builtin is a fatal shell error that
    terminates the script immediately. || true cannot catch it (it only
    fires on a normal nonzero exit, not a special-builtin fatal abort), and
    the preceding 2>/dev/null swallows dash's own diagnostic before it
    ever reaches Claude Code's hook runner. Net effect: exit 2, no stdout,
    no stderr, completely undiagnosable from the user's side.

This is easy to hit in practice: it's exactly what happens when a user has
a stale CLAGENTIC_LITE_HOME (or CLAGENTIC_HOME) left over from before the
env-var/path rename in fd7c3bc (lr-e84c), or any other environment drift
that leaves the var pointing at a directory that no longer exists.

Repro
env -i CLAGENTIC_LITE_HOME=/tmp/nonexistent-clagentic
/path/to/.claude/hooks/session-start.sh
echo $?
# -> 2, zero bytes on both stdout and stderr

Same result for prompt-inject.sh.

Suggested fix

  • Before sourcing anything, validate that CLAGENTIC_LITE_HOME points at a
    real checkout (e.g. test -f "$CLAGENTIC_LITE_HOME/scripts/platform.sh")
    and print a clear message to stderr + exit nonzero with an actionable
    hint if not, e.g.:
    "clagentic-lite: CLAGENTIC_LITE_HOME=$CLAGENTIC_LITE_HOME has no
    scripts/platform.sh — check ~/.bashrc and ~/.config/clagentic/config for
    a stale path (run clagentic-lite doctor)."
  • Avoid . "$X" 2>/dev/null || true as a "make missing-file source
    non-fatal" idiom under dash/POSIX sh generally — it does not work for
    special builtins. Guard with an explicit [ -f "$X" ] && . "$X" instead.
  • doctor already has a fairly good "env var migration" check (added
    recently) that catches this exact class of drift when the user runs it
    directly — but the hooks themselves have no equivalent guard, so a
    user hits total silence before ever thinking to run doctor.

Environment

  • clagentic-lite install at ~/.clagentic/lite, HEAD a22e1a4 (2026-08-14).
  • Originally discovered via a stale CLAGENTIC_LITE_HOME left in ~/.bashrc
    after the CLAGENTIC_HOME -> CLAGENTIC_LITE_HOME / ~/.clagentic-lite ->
    ~/.clagentic/lite rename (fd7c3bc, lr-e84c). Reproduced independently of
    that specific cause via the env -i repro above, confirming it's a
    general hook robustness gap, not specific to that one rename.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions