Claude Code 2.1.288 hooks fail closed: a Sume spend guard script
Claude Code 2.1.288 now blocks a tool call when a PreToolUse hook can't match or serialize input. A small guard script for Sume paid calls.

Claude Code 2.1.288 (2026-10-02) makes PreToolUse and PermissionRequest hooks fail closed: if matching fails or the tool input cannot be serialized to JSON, the call is blocked instead of running. That makes a Sume spend guard safer, because an error in the hook can no longer let a paid call through.
The script below blocks Sume write calls that lack an idempotency_key or a max_spend_usd.
What changed
The same release re-prompts when an OAuth scope grows and fixes an MCP call that ran twice for results over 16 MB. The hook change is the one that matters for guards.
At a glance
| Situation | Result |
|---|---|
| Hook exits 0 | Call proceeds |
| Hook exits 2 | Call blocked, stderr shown |
| Matching fails or input not JSON-serializable | Call blocked (fail closed) |
| Sume write call lacks idempotency_key | Rejected by Sume |
A guard script
A command hook reads JSON on stdin and exits with code 2 to block, writing a reason to stderr. The matcher should cover the Sume server's tools; adjust the name prefix to the name you gave the server.
Sume itself requires idempotency_key on write and paid tools and offers max_spend_usd as an option, so the script enforces the option you want to make mandatory.
#!/usr/bin/env python3
import json, sys
data = json.load(sys.stdin)
name = data.get("tool_name", "")
args = data.get("tool_input", {})
if name.startswith("mcp__sume__"):
paid_like = "idempotency_key" in args
if paid_like and "max_spend_usd" not in args:
sys.stderr.write("Sume write call needs max_spend_usd")
sys.exit(2)
sys.exit(0)Limits and what is not verified
The script is a sketch: the tool-name prefix depends on your server name, and I did not run it against Claude Code. Hook configuration lives in Claude Code's settings, which this post does not reproduce.
Sources
Related posts
More in Developers
- allowManagedModsOnly in Claude Code: does hosted Sume MCP still load?
allowManagedModsOnly keeps users' own Claude Code mods from loading. What it leaves alone, how a policy mod reviews the rest, and the Sume MCP connection.
- Claude Code .mcp.json oauth.scopes: mcp:read first, mcp:write later
Claude Code's .mcp.json oauth block takes a space-separated scopes string that overrides discovery. Start Sume at mcp:read and widen to mcp:write when needed.
- Claude Code mod: stop paid Sume calls after N in a session
Write a Claude Code mod that counts paid Sume MCP calls with a tool.call hook, denies call N+1, and fails closed. Code, matcher, and what it cannot cap.
- Claude Code mod hook skipped and a paid Sume call still ran
A Claude Code mod hook that throws or times out is skipped, so the call runs anyway. Add .catch to fail closed, and know what a mod still cannot guarantee.
Written by Sume