The Problem
AI coding tools reward laziness. Type “fix this bug” and you get a fix. Type “what should I use for state management?” and you get a recommendation. The tool does exactly what you asked, which is the problem. You never had to understand the bug or reason through the tradeoffs. The tool did your thinking for you and you learned nothing.
I noticed this in my own workflow: my prompts were getting vaguer over time while the tool made more decisions for me.
The fix is not to stop using AI. The fix is to build a feedback loop that catches low-effort prompts before they go through.
The Idea
Claude Code has a hook system. Hooks are shell commands that fire in response to events like tool calls, session start, or prompt submission. The one I cared about was UserPromptSubmit, which fires every time you hit enter on a prompt.
The hook can inject additional context into the conversation. Whatever text it outputs gets added to what Claude sees alongside your prompt. Claude does not know the difference between context you typed and context the hook injected. It just sees instructions and follows them.
So the idea is: inject a rubric that tells Claude to evaluate your prompt before responding to it. If the prompt is low-effort, Claude coaches you toward a better one instead of answering. If the prompt is high-effort, Claude responds normally and you never know the evaluation happened.
The evaluation costs nothing extra. Claude is already processing your prompt. The rubric adds a few hundred tokens of instructions. No separate API call, no external service, no latency beyond what was already there.
The Rubric
The rubric scores three things from 1 to 5: how specific the intent is, whether the user made the key decisions, and how much diagnostic work they did. “Fix this bug” scores poorly; a prompt that names the failure, evidence, and likely cause scores well.
Below 3, Claude asks questions tailored to the request. At 3 or above, it responds normally without showing the evaluation.
You can always override with “continue anyway” and Claude proceeds with the original prompt.
The Implementation
The whole thing is two files.
A rubric file at ~/.claude/thinking-check-rubric.md that contains the evaluation instructions. This is what gets injected into every conversation. You can edit it anytime to adjust the criteria, change the threshold, or modify the coaching style.
A hook entry in ~/.claude/settings.json that reads the rubric and outputs it as additional context:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "cat ~/.claude/thinking-check-rubric.md | jq -Rs '{hookSpecificOutput: {hookEventName: \"UserPromptSubmit\", additionalContext: .}}'",
"timeout": 5
}
]
}
]
}
}The command reads the rubric, wraps it in the JSON structure Claude Code expects, and outputs it. That is the entire hook. Five seconds timeout for reading a local file. No dependencies beyond jq.
Boundaries
The hook does not mechanically block prompts or track scores. It skips follow-up answers and slash commands, and it always allows an explicit override.
Takeaway
The default incentive of AI tools is to remove friction. Type less, get more. But friction is where thinking happens. If you remove all of it, you end up with working code and no understanding of why it works.
This hook adds a small amount of deliberate friction at exactly the right moment: before you ask. It is a mirror that reflects the quality of your question back at you. Not to slow you down, but to make sure you actually thought before you asked. And if you did think, you never even know it was there.