feat: initial companion repo for CC-024 Hooks
This commit is contained in:
commit
cd834a7476
7 changed files with 790 additions and 0 deletions
173
exercises/02-audit-trail.md
Normal file
173
exercises/02-audit-trail.md
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
# Exercise 02: Build an Audit Trail
|
||||
|
||||
**Concept:** Hooks (CC-024)
|
||||
**Level:** Intermediate
|
||||
**Time:** ~15 minutes
|
||||
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
Add a post-tool-use hook that logs every tool call Claude makes to a
|
||||
local file. You will give Claude a multi-step task, then read the audit
|
||||
log to see everything it did.
|
||||
|
||||
This is the foundation for compliance logging, debugging, and
|
||||
understanding what Claude actually does during a session.
|
||||
|
||||
---
|
||||
|
||||
## Before You Start
|
||||
|
||||
Confirm you have completed Exercise 01, or at minimum:
|
||||
|
||||
- [ ] `hooks/post-tool-use.sh` exists in this repo
|
||||
- [ ] `.claude/settings.json` exists with the PreToolUse hook from Exercise 01
|
||||
|
||||
---
|
||||
|
||||
## Instructions
|
||||
|
||||
**Step 1:** Read the post-tool-use hook.
|
||||
|
||||
Open `hooks/post-tool-use.sh` and read through it. Notice:
|
||||
|
||||
- It always exits 0. Post-tool-use hooks cannot block.
|
||||
- It extracts different keys depending on the tool (`command`, `file_path`, `pattern`)
|
||||
- It appends to `hooks/audit.log` in the same directory as the script itself
|
||||
- The timestamp format is UTC ISO 8601
|
||||
|
||||
**Step 2:** Make the script executable.
|
||||
|
||||
```bash
|
||||
chmod +x hooks/post-tool-use.sh
|
||||
```
|
||||
|
||||
**Step 3:** Add the PostToolUse hook to `.claude/settings.json`.
|
||||
|
||||
Update your `.claude/settings.json` to include both hooks:
|
||||
|
||||
```json
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(ls:*)",
|
||||
"Bash(cat:*)",
|
||||
"Bash(echo:*)",
|
||||
"Bash(pwd)",
|
||||
"Bash(date)",
|
||||
"Read",
|
||||
"Write",
|
||||
"Edit",
|
||||
"Glob",
|
||||
"Grep"
|
||||
],
|
||||
"deny": [
|
||||
"Bash(rm -rf *)",
|
||||
"Bash(sudo *)"
|
||||
]
|
||||
},
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash hooks/pre-tool-use.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": ".*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash hooks/post-tool-use.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `matcher: ".*"` pattern matches every tool, not just Bash. This
|
||||
means every Read, Write, Grep, and WebSearch call will be logged.
|
||||
|
||||
**Step 4:** Start or restart Claude Code.
|
||||
|
||||
```bash
|
||||
cd claude-code-hooks
|
||||
claude
|
||||
```
|
||||
|
||||
If Claude Code is already running, restart it so it picks up the new
|
||||
settings file.
|
||||
|
||||
**Step 5:** Give Claude a multi-step task.
|
||||
|
||||
Paste this prompt into Claude Code:
|
||||
|
||||
```
|
||||
List the files in this directory, then read README.md, then tell me
|
||||
how many lines it has.
|
||||
```
|
||||
|
||||
This will trigger multiple tool calls: a Bash call for `ls`, a Read
|
||||
call for README.md, and a Bash call for `wc -l`.
|
||||
|
||||
**Step 6:** Read the audit log.
|
||||
|
||||
After Claude finishes, paste this prompt:
|
||||
|
||||
```
|
||||
Show me the contents of hooks/audit.log
|
||||
```
|
||||
|
||||
Or read it directly from your terminal:
|
||||
|
||||
```bash
|
||||
cat hooks/audit.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Expected Output
|
||||
|
||||
The audit log should contain entries like:
|
||||
|
||||
```
|
||||
2026-03-30T04:12:33Z | Bash | ls -la
|
||||
2026-03-30T04:12:34Z | Read | README.md
|
||||
2026-03-30T04:12:35Z | Bash | wc -l README.md
|
||||
```
|
||||
|
||||
Each line shows the UTC timestamp, the tool name, and the primary
|
||||
argument (command, file path, or search pattern).
|
||||
|
||||
If `audit.log` does not exist after the task, check that `post-tool-use.sh`
|
||||
is executable and that the `PostToolUse` hook is in `settings.json`.
|
||||
|
||||
---
|
||||
|
||||
## What You Learned
|
||||
|
||||
- **PostToolUse hooks run after every tool call.** They receive the same
|
||||
JSON input as PreToolUse hooks but cannot influence the outcome. Their
|
||||
job is observation, not control.
|
||||
- **`matcher: ".*"` captures everything.** Narrowing the matcher to `"Bash"`
|
||||
would log only shell commands. Using `".*"` logs all tool types.
|
||||
- **Audit logs survive sessions.** The log file persists between Claude
|
||||
Code sessions. This makes it useful for compliance and debugging:
|
||||
you can always reconstruct what happened.
|
||||
- **Logs are per-project.** The log path is relative to the script, so
|
||||
each project has its own audit trail.
|
||||
|
||||
---
|
||||
|
||||
## Next
|
||||
|
||||
Move to [Exercise 03: Prompt-Based Approval](./03-prompt-hooks.md).
|
||||
Loading…
Add table
Add a link
Reference in a new issue