1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//! Claude Code: `.claude/settings.json`, `PreToolUse`.
//!
//! One file per agent. Adding Cursor or Codex means another file with these
//! three functions, not an edit to the logic that decides what is protected —
//! which is the whole point of the policy being agent-independent.
use ;
/// The agent's file-writing tools.
///
/// `Bash` is deliberately absent: a hook cannot tell which paths an arbitrary
/// shell command will touch, and a matcher that pretends otherwise would give
/// false confidence — worse than an honest gap.
const MATCHER: &str = "Write|Edit|MultiEdit|NotebookEdit";
/// Where the agent keeps per-project settings, relative to the project root.
pub const SETTINGS: &str = ".claude/settings.json";
/// The event whose entries this hook belongs to.
pub const EVENT: &str = "PreToolUse";
/// The entry to install.
/// Whether an existing entry is one of ours, so installing twice updates it
/// instead of stacking duplicates.
// Reading the request and writing the refusal are shared: see `hook::targets`
// and `Decision::render`. Agents disagree about the key an edit's path lives
// under, and one unrecognised spelling is an edit waved through, so the check
// looks for every spelling rather than one per agent.