Claude Code is breaking your builds and introducing type errors and you don’t know why?

Claude can't have 100% of the context of your project in mind so it may introduce bugs because, of course, it can make mistakes.
It has happened to me that it changes a type, for example, but it doesn't check if that change affects anything else besides the code it has in the context. Later I catch the error when I see my pipelines turn red. Got tired of it and fixed it using a really powerful tool Claude already includes: Hooks
Claude Code has a hook system that lets you intercept its tool use at specific lifecycle points. We are gonna register two PostToolUse hooks - meaning they run after Claude has already written a file, as a validation layer.
If a hook exits with code 2, Claude Code treats it as a blocking error: it surfaces the stderr(standard error)output directly in the session, and Claude is expected to read that output and fix the problem before moving on.
To write the hooks we are gonna use (yeah you guessed it) Claude Code!
One hook to try to build the code it edited and one to run typechecks in the code it added, edited and dependencies (code that uses or relies on the code edited)
I will give you the prompt since my hooks include some stuff that is really specific to my repo(working on a monorepo so my hooks checks by package and tracks cross references)
"I want to build two claude hooks. build-ts and check-ts hooks.
These two hooks are gonna be post tool use hooks, with matcher edit/write.
The purpose of the hooks is avoid claude code to introduce type or build errors.
We've experienced changes that break types, do not follow typing safety guidelines,
change types to make newcode work but break old reliable code and that break builds.
These hooks should check the files that has been edited in the tool use
(and the affected files if thecode that was edited has dependencies) and type check and build.
You can check our @package.json file to see the scripts we use to typecheck and build typescript.
These hooks will only run in .ts and .tsx files."
After generating the scripts, you just need to register them in your Claude settings.
If you want them locally:
.claude/settings.local.json
If you want to share them with your team:
.claude/settings.json
This is what it looks like:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "bash $CLAUDE_PROJECT_DIR/.claude/hooks/check-ts.sh",
"timeout": 30,
"statusMessage": "Type-checking..."
},
{
"type": "command",
"command": "bash $CLAUDE_PROJECT_DIR/.claude/hooks/build-ts.sh",
"timeout": 60,
"statusMessage": "Building..."
}
]
}
]
}
}
How it actually works
- PostToolUse → runs after Claude edits or creates a file
- matcher: "Edit|Write" → triggers on both file edits and new files
- Hooks run sequentially
$CLAUDE_PROJECT_DIR→ ensures paths work across environments
The feedback loop Claude can't silently introduce a type error and continue. The moment it edits a .ts/.tsx file, it gets immediate tsc feedback, the same way a developer would see a red squiggle in their IDE.
Claude edits a .ts file
↓
Edit tool completes
↓
check-ts.sh runs → tsc - noEmit
build-ts.sh runs → tsc - build
↓
errors? → exit 2 → stderr injected into Claude's context
→ Claude reads the tsc output
→ Claude fixes the file
→ hooks run again
→ clean? → exit 0 → proceed
The two hooks complement each other: check-ts gives a fast signal (no disk writes), while build-ts gives the authoritative signal including whether cross-package dependencies still compile. If check-ts passes but build-ts fails, it means a dependency package was broken by the edit. Claude still doesn't have full context. That hasn't changed.
But now it can't ignore the consequences of that.