mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
* chore(claude): session-start and pre-bash hooks, deny .env reads scripts/claude-hook.mjs, wired in .claude/settings.json: - SessionStart warns when core.hooksPath is not .githooks, so a clone or a new machine cannot silently run without the repo git hooks. - PreToolUse on Bash refuses a top-level cd: the tool's shell is persistent, so a cd leaks into every later command and a gate can report green from the wrong directory. Subshells, git -C and root-relative paths pass. permissions.deny gains Read(**/.env): the gitignored env files never enter the model's context. Server/.env.example stays readable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jwaz4CHGAz85Rpypjvto5a * chore(lint): durationcheck on the server, noImplicitOverride on the client Both measured at zero hits on dev, so they cost nothing today and only block regressions: a Duration multiplied by a Duration-typed value, and an override left behind when its base method is renamed. rowserrcheck and sqlclosecheck were measured too and rejected: their six production hits are all correct code (rows.Err is checked inside scanEventRows behind the rowsScanner interface; the three Close sites close on every path by hand). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jwaz4CHGAz85Rpypjvto5a --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
50 lines
2.0 KiB
JavaScript
50 lines
2.0 KiB
JavaScript
// Claude Code hooks for this repository, wired in .claude/settings.json.
|
|
//
|
|
// session-start warn when the repo git hooks are not installed, so a clone
|
|
// or a new machine cannot silently run without them.
|
|
// pre-bash refuse a top-level `cd`. The Bash tool's shell is
|
|
// persistent, so a `cd` leaks its directory into every later
|
|
// command; a relative path then resolves somewhere else and a
|
|
// gate can report a green result from the wrong directory.
|
|
// Use a subshell `( cd DIR && ... )`, `git -C DIR`, or paths
|
|
// from the repository root instead.
|
|
//
|
|
// Exit code 2 from a PreToolUse hook blocks the tool call and shows stderr to
|
|
// the model; anything else lets it through.
|
|
import { execFileSync } from "node:child_process";
|
|
import { readFileSync } from "node:fs";
|
|
|
|
const mode = process.argv[2];
|
|
|
|
if (mode === "session-start") {
|
|
let hooksPath = "";
|
|
try {
|
|
hooksPath = execFileSync("git", ["config", "core.hooksPath"], {
|
|
encoding: "utf8",
|
|
stdio: ["ignore", "pipe", "ignore"],
|
|
}).trim();
|
|
} catch {
|
|
// unset: git exits 1
|
|
}
|
|
if (hooksPath !== ".githooks") {
|
|
console.log(
|
|
"WARNING: the repo git hooks are not installed (core.hooksPath is not .githooks). Run `npm run hooks:install` at the repository root.",
|
|
);
|
|
}
|
|
} else if (mode === "pre-bash") {
|
|
let command = "";
|
|
try {
|
|
command = JSON.parse(readFileSync(0, "utf8")).tool_input?.command ?? "";
|
|
} catch {
|
|
// no or malformed input: nothing to check
|
|
}
|
|
// A `cd` that starts the command or follows a chain operator or newline is a
|
|
// top-level statement; `( cd DIR && ... )` is not matched.
|
|
if (/(^|\n|&&|\|\||;)\s*cd(\s|$)/.test(command)) {
|
|
console.error(
|
|
"Blocked: a top-level `cd` leaks the persistent shell cwd into every later command. Use a subshell `( cd DIR && ... )`, `git -C DIR`, or paths from the repository root.",
|
|
);
|
|
process.exit(2);
|
|
}
|
|
}
|