How I built a trust scoring hook for Claude Code
Source: Dev.to
Overview
I’ve been using Claude Code for a while and realized I had zero visibility into what the agent was doing across sessions— which tools it called, whether it touched files it shouldn’t have, and how many calls it made per task. To address this, I built a hook that scores every session.
The hook listens to three Claude Code events:
- PostToolUse – records every tool call, checks it against an allowlist, and flags protected‑path access.
- PreToolUse – blocks tool calls that touch sensitive files like
.envor SSH keys. - Stop – computes the final trust score and logs it.
At the end of each session you get output such as:
[authe.me] Trust Score: 92 (reliability=100 | scope=75 | cost=100)
[authe.me] tools=14 violations=1 failed=0
Scoring Model
The trust score is a weighted combination of three dimensions:
| Dimension | Weight | Description |
|---|---|---|
| Reliability | 40 % | Percentage of tool calls that succeeded. |
| Scope | 35 % | Whether the agent stayed within allowed tools and paths. Each violation drops the score by 25 points. |
| Cost | 25 % | Number of tool calls made. Under 20 is fine; over 100 starts flagging. |
Implementation Details
Hash‑chaining of tool calls
Every tool‑call event is hashed together with the previous hash, creating a simple chain. If the log is tampered with, the chain breaks— a lightweight blockchain‑style audit trail.
import hashlib, json
def compute_hash(prev_hash, data):
payload = f"{prev_hash}:{json.dumps(data, sort_keys=True)}"
return hashlib.sha256(payload.encode()).hexdigest()[:16]
PreToolUse denial example
The PreToolUse hook checks if Claude is about to read or edit a sensitive file. If it matches a protected path, the hook returns a denial decision with a reason that Claude receives as feedback:
result = {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "authe.me policy: .env is a protected path."
}
}
Claude sees the denial reason and adjusts its plan accordingly.
Installation
mkdir -p ~/.claude/hooks ~/.authe
curl -fsSL https://raw.githubusercontent.com/autheme/claude-code-hook/main/authe-hook.py \
-o ~/.claude/hooks/authe-hook.py
chmod +x ~/.claude/hooks/authe-hook.py
Hook configuration
Add the following to ~/.claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "AUTHE_HOOK_EVENT=PostToolUse python3 ~/.claude/hooks/authe-hook.py"
}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "AUTHE_HOOK_EVENT=Stop python3 ~/.claude/hooks/authe-hook.py"
}
]
}
]
}
}
The hook is a single file, has zero external dependencies, and is pure Python.
Future Work
- Remote reporting – aggregate scores across sessions and agents.
- OpenClaw plugin – provide equivalent functionality for the OpenClaw ecosystem.
The repository is available at:
Built with Claude. I’d love feedback from anyone running Claude Code in production.