When code depends on runtime configuration (tooling paths, IDE/CLI context, feature flags), treat environment variables as an explicit contract and don’t rely on implicit process state.
Apply these rules: 1) Prefer documented env inputs over assumed I/O
USER_PROMPT), read from that env var, parse the expected JSON shape, and fail fast (or fail-open only if the contract requires).2) When spawning subprocesses, make the child’s environment deterministic
bun/other binaries via inherited PATH.env (including a known-good PATH or required tool locations), and/orprocess.execPath) so the child doesn’t depend on PATH.Code example (env-safe spawn):
function runCore(hookFile: string, input: Record<string, unknown>) {
const childExe = process.execPath; // don’t depend on PATH
return Bun.spawnSync([childExe, join(HOOKS_DIR, hookFile)], {
stdin: "pipe",
env: process.env, // or explicitly set PATH/bun dir if needed
encoding: "utf-8",
// ...forward other required options
});
}
Checklist for reviews: