1# Chapter 8: jevhooks-events/src, thirty-three events and three roles
2
3Claude Code 2.1.287 raises thirty-three kinds of settings-hook event, and
4`HookEvent` in [lib.rs](lib.rs) names every one, spelled exactly as the
5hooks are (`PreToolUse`, `Stop`, `UserPromptSubmit`, ...). The plugin's
6claim is "every Claude Code hook event backed by Jev", and this is where
7that is made concrete: every event has a **role**, and the function that
8gives it one, `HookEvent::role`, has no default case.
9
10| Role | Events | What happens |
11| --- | --- | --- |
12| `Decide` | `PreToolUse`, `Stop` | Sent to the daemon and waited on: the answer changes what happens. |
13| `Observe` | `UserPromptSubmit`, `PostToolUse`, `PostToolUseFailure`, `PermissionDenied`, `SessionEnd` | Sent to the daemon without waiting: the daemon needs them to decide (the prompt a turn's end is judged against, what became of a command it judged, a session to forget). |
14| `Ignore` | the other twenty-six | Not sent. Nothing is judged on them, or needed for a judgment, yet. |
15
16> **Aside: why "no default case" matters.** In Rust a `match` must cover
17> every variant, or the program does not compile. `role` lists all
18> thirty-three by name, with no `_ =>` catch-all. So the day Claude Code
19> adds a thirty-fourth event and someone adds it to `HookEvent`, the build
20> stops until they say what is done with it. An event cannot slip in as
21> "ignored" because nobody thought about it.
22
23Then two more types for the answer:
24
25- **`Verdict`**: `Allow` (run it without asking), `Ask` (ask the user
26  first, or, for a `Stop`, do not stop yet), `Pass` (no opinion: whatever
27  would have happened without the plugin happens). Lowercase on the wire.
28- **`Decision`**: the daemon's whole answer to a deciding event: the
29  `verdict`, a `line` for the user (what Jev said and how sure it was, or
30  why nothing was asked), `ms` (the daemon's time, Jev included) and
31  `session_usd` (what this session's questions have cost so far).
32
33> **Try it.** `cargo test -p jevhooks-events`. `every_event_is_listed_once`
34> walks `HookEvent::ALL` and checks for thirty-three distinct events;
35> `names_are_the_hook_names` checks that `PreToolUse` travels as
36> `"PreToolUse"` and that `"Stop"` reads back as `Stop`.
37
38## For the people who maintain it
39
40Roles are not the whole routing. The mod narrows them per call (chapter
4110): a tool event for anything but Bash, or for a plainly read-only Bash
42command, is ignored whatever its role says.
43
44### In this folder
45
46| Path | What |
47| --- | --- |
48| [lib.rs](lib.rs) | `HookEvent` and `HookEvent::ALL`, `HookEvent::role`, `Role`, `Verdict`, `Decision`, and the two tests. |
49
50← Previous: [Chapter 7, jevhooks-events/](../) · Up: [jevhooks-events](../) · Next: [Chapter 9, jevhooks-mod/](../../jevhooks-mod/) →