CC-301c · Module 2
Post-Tool Formatting Hooks
3 min read
Post-tool formatting hooks solve a persistent annoyance: Claude generates code that is logically correct but does not match your project's formatting conventions. Indentation is inconsistent, imports are unordered, trailing commas are missing, or line lengths exceed your project's maximum. You could add formatting rules to CLAUDE.md, but formatting rules compete with logic rules for attention — and logic should always win.
The elegant solution is a PostToolUse hook that runs your formatter after every file edit. Claude writes the code. Prettier reformats it. The result matches your project's formatting conventions exactly, every time, without consuming a single token of Claude's attention on formatting rules. Claude focuses on logic. The formatter handles aesthetics. Separation of concerns at the tooling level.
The implementation is concise. A PostToolUse hook that matches on file write events detects the file extension, applies the appropriate formatter (Prettier for JS/TS, Black for Python, rustfmt for Rust), and writes the formatted output back. The hook runs silently — no stdout output needed because PostToolUse hooks do not send instructions to Claude. They modify the artifact and return.
Extend this pattern to import sorting (isort for Python, import-sort for TypeScript), license header injection (prepend a copyright header to new files), and file-level validation (JSON schema validation after .json file edits). Each extension is a small addition to the PostToolUse hook. The cumulative effect is that every file Claude touches is automatically formatted, sorted, licensed, and validated before you ever see it. The "last 10%" of file quality — the part that fails CI and triggers formatting PRs — is handled automatically.