Problem Statement
In a nix-shell / direnv project the hook never runs. LD_LIBRARY_PATH is set by the shell (e.g. /nix/store/...gcc-15.3.0-lib/lib), and the Deno hook host blocks any Deno.Command that inherits it unless the variable is allowlisted. The user sees NotCapable: Requires --allow-run permissions to spawn subprocess with LD_LIBRARY_PATH and the fallback prints "comment-checker did not run, so nothing checked this write" — no file is checked at all. The binary itself does not need LD_LIBRARY_PATH and runs hermetically inside bwrap.
Goal
The PostToolUse hook executes comment-checker --strip (or the direnv exec fallback) and returns its exit code when LD_LIBRARY_PATH is present in the environment, for all nix-shell and non-nix-shell invocations.
Evidence: Current Behavior
hooks/run.ts:1 — allowlist omits LD_LIBRARY_PATH:
#!/usr/bin/env -S deno run --allow-read --allow-run=comment-checker,direnv --allow-env=CLAUDE_PROJECT_DIR,PATH,HOME
hooks/run.ts:24-37 — spawn inherits ambient env and throws before the binary runs:
async function run(cmd: string, args: string[]): Promise<number | undefined> {
try {
const { code } = await new Deno.Command(cmd, {
args,
stdin: 'inherit',
stdout: 'inherit',
stderr: 'inherit',
}).output()
Runtime error observed at write time (Deno 2.9.4, LD_LIBRARY_PATH=/nix/store/r48746qznwqxxl9qzd8f08ny8mg1dg2y-gcc-15.3.0-lib/lib):
error: Uncaught (in promise) NotCapable: Requires --allow-run permissions to spawn subprocess with LD_LIBRARY_PATH environment variable.
Orientation
Affected: hooks/run.ts and flake.nix / wrapper bin/comment-checker (bwrap sandbox). The inner binary at /nix/store/...comment-checker-0.3.4/bin/comment-checker is an ELF with RPATH to its nix glibc and needs no LD_LIBRARY_PATH (ldd resolves libc.so.6 and libgcc_s.so.1 from /nix/store directly). Match existing hook pattern (try comment-checker on PATH, then direnv exec).
Non-Counting Outcomes
- Adding
LD_LIBRARY_PATH to --allow-env without verifying the hook actually succeeds when the variable is set (allowlist change alone, no spawn fix).
- Stripping
LD_LIBRARY_PATH only on the direnv fallback but not on the direct comment-checker path.
- Suppressing the
NotCapable with a catch that returns success — hook goes green while nothing is checked.
- Documenting "unset LD_LIBRARY_PATH before running" instead of fixing the hook.
- Verifying only outside nix-shell (no
LD_LIBRARY_PATH) and claiming the fix works.
Acceptance Criteria
Boundaries
- Never: require the user to unset
LD_LIBRARY_PATH manually.
- Always: preserve bwrap sandboxing of the inner binary (wrapper at
bin/comment-checker).
Problem Statement
In a nix-shell / direnv project the hook never runs.
LD_LIBRARY_PATHis set by the shell (e.g./nix/store/...gcc-15.3.0-lib/lib), and the Deno hook host blocks anyDeno.Commandthat inherits it unless the variable is allowlisted. The user seesNotCapable: Requires --allow-run permissions to spawn subprocess with LD_LIBRARY_PATHand the fallback prints "comment-checker did not run, so nothing checked this write" — no file is checked at all. The binary itself does not needLD_LIBRARY_PATHand runs hermetically insidebwrap.Goal
The PostToolUse hook executes
comment-checker --strip(or thedirenv execfallback) and returns its exit code whenLD_LIBRARY_PATHis present in the environment, for all nix-shell and non-nix-shell invocations.Evidence: Current Behavior
hooks/run.ts:1— allowlist omitsLD_LIBRARY_PATH:hooks/run.ts:24-37— spawn inherits ambient env and throws before the binary runs:Runtime error observed at write time (Deno 2.9.4,
LD_LIBRARY_PATH=/nix/store/r48746qznwqxxl9qzd8f08ny8mg1dg2y-gcc-15.3.0-lib/lib):Orientation
Affected:
hooks/run.tsandflake.nix/ wrapperbin/comment-checker(bwrap sandbox). The inner binary at/nix/store/...comment-checker-0.3.4/bin/comment-checkeris an ELF withRPATHto its nixglibcand needs noLD_LIBRARY_PATH(lddresolveslibc.so.6andlibgcc_s.so.1from/nix/storedirectly). Match existing hook pattern (trycomment-checkeronPATH, thendirenv exec).Non-Counting Outcomes
LD_LIBRARY_PATHto--allow-envwithout verifying the hook actually succeeds when the variable is set (allowlist change alone, no spawn fix).LD_LIBRARY_PATHonly on thedirenvfallback but not on the directcomment-checkerpath.NotCapablewith a catch that returns success — hook goes green while nothing is checked.LD_LIBRARY_PATH) and claiming the fix works.Acceptance Criteria
LD_LIBRARY_PATH=/nix/store/r48746qznwqxxl9qzd8f08ny8mg1dg2y-gcc-15.3.0-lib/libin the environment,hooks/run.tsspawnscomment-checker --stripwithoutNotCapableand returns its exit code (gatekeeper:LD_LIBRARY_PATH=/nix/store/r48746qznwqxxl9qzd8f08ny8mg1dg2y-gcc-15.3.0-lib/lib deno run --allow-read --allow-run=comment-checker,direnv --allow-env=CLAUDE_PROJECT_DIR,PATH,HOME,LD_LIBRARY_PATH hooks/run.tsor equivalent with the fix — verifier runs hook with the variable set and checks exit code).direnv execpaths both handleLD_LIBRARY_PATH(unset or allowlisted) — no path still throwsNotCapable.LD_LIBRARY_PATH) behavior is unchanged — hook still findscomment-checkeronPATHor viadirenv exec.deno task check(ordeno lint/deno checkas defined in repo) exits 0 after the change — no allowlist regression.Boundaries
LD_LIBRARY_PATHmanually.bin/comment-checker).