एक बार मैं जिस agent की निगरानी कर रहा था उसने दो घंटे के अनकमिटेड काम वाली एक ब्रांच पर git reset --hard origin/main चलाने की कोशिश की। उसने तय किया था कि वर्किंग ट्री "गंदी" है और उसे एक साफ स्लेट चाहिए। एकमात्र कारण कि मेरे पास अभी भी वो काम है, वो एक PreToolUse hook है जो किसी भी git reset --hard को ब्लॉक करता है।
यही Claude Code hooks का पूरा पिच है। ये "मॉडल आमतौर पर सही व्यवहार करता है" और "मॉडल शाब्दिक रूप से वो काम नहीं कर सकता" के बीच का फर्क हैं। Prompts सुझाव हैं। Hooks कानून हैं, क्योंकि हार्नेस उन्हें चलाता है, मॉडल नहीं।
क्यों एक hook हर बार prompt को हरा देता है
आप अपने सिस्टम prompt में कैप्स लॉक और तीन विस्मयादिबोधक चिह्नों के साथ "कभी भी विनाशकारी git कमांड न चलाएं" लिख सकते हैं। Opus 4.8 पर यह ज्यादातर काम करता है — वो निर्देशों का बारीकी से पालन करता है। लेकिन "ज्यादातर" ही समस्या है। मॉडल का व्यवहार एक प्रायिकता वितरण है। एक hook एक कंडीशनल है। जब सुरक्षा सीमा वास्तव में मायने रखती है — डेटा हटाना, प्रोडक्शन में पुश करना, ईमेल भेजना — आप कंडीशनल चाहते हैं, वितरण नहीं।
इसके पीछे एक गहरा कारण है कि ये मॉडल टूल्स के बारे में कैसे सोचते हैं। मॉडल एक टूल कॉल उत्सर्जित करता है; आपका हार्नेस तय करता है कि उसके साथ क्या करना है। एक bash टूल हार्नेस को एक अपारदर्शी कमांड स्ट्रिंग देता है। एक hook वो जगह है जहाँ आप उस स्ट्रिंग को खोलते हैं और एक नियतात्मक निर्णय लेते हैं: अनुमति दें, ब्लॉक करें, या पूछें। मॉडल का इरादा इसमें कभी नहीं आता।
तीन hooks जो मैं वास्तव में चलाता हूँ
PreToolUse — बाउंसर। टूल के चलने से पहले फायर होता है। टूल का नाम और इनपुट मिलता है। ब्लॉक निर्णय लौटाएं और कॉल कभी नहीं होती। यहीं मेरा git reset --hard गार्ड रहता है, साथ ही स्क्रैच डायरेक्टरी के बाहर rm -rf और किसी भी शेल में पाइप होने वाले curl पर ब्लॉक।
# PreToolUse: bash टूल पर विनाशकारी git को अस्वीकार करें
if echo "$TOOL_INPUT" | grep -qE 'git reset --hard|git clean -[a-z]*f|git push --force'; then
echo '{"decision":"block","reason":"Destructive git blocked. Stash or commit, then ask me."}'
exit 0
fi
reason मायने रखता है। यह मॉडल को वापस जाता है, इसलिए भटकने की बजाय agent "stash करो या commit करो, फिर मुझे बताओ" पढ़ता है और वही करता है। एक चुप ब्लॉक agent को वेरिएशन आज़माने पर मजबूर करता है जब तक कि उसे आपकी regex से छूटी हुई फ्रेज़िंग न मिल जाए। उसे बताएं क्यों।
PostToolUse — इंस्पेक्टर। टूल चलने के बाद फायर होता है। मैं इसे हर फ़ाइल एडिट के बाद एक त्वरित lint या type-check चलाने के लिए उपयोग करता हूँ, और विफलताएं सीधे वापस फीड करता हूँ। Agent को बग लिखने के दो सेकंड बाद टाइप एरर मिलता है, न कि तीन subtasks बाद जब कुछ भी बिल्ड नहीं होता। उस फीडबैक लूप को कसने से किसी भी prompt बदलाव से ज्यादा मेरे agents की कोड गुणवत्ता में सुधार हुआ।
Stop — ऑफ स्विच। जब agent सोचता है कि वो पूरा हो गया तब फायर होता है। यह आपका आखिरी मौका है यह कहने का कि "नहीं, अभी नहीं।" रन समाप्त होने देने से पहले मैं जांचता हूँ कि टेस्ट वास्तव में पास होते हैं। अगर नहीं होते, तो Stop hook स्टॉप को ब्लॉक करता है और agent को उन्हें ठीक करने के लिए कहता है। यहीं पहले बताया गया लूप-डिटेक्शन काउंटर भी रहता है — बहुत ज्यादा एडिट, पूरी चीज़ को रोक दो।
hooks कहाँ रहते हैं
Hooks settings.json में कॉन्फ़िगर किए जाते हैं, मॉडल की मेमोरी या आपके CLAUDE.md में नहीं। यह लोगों को लगातार उलझाता है। "अब से, एडिट के बाद हमेशा linter चलाएं" वो चीज़ नहीं है जो आप मॉडल को बताते हैं — वो टर्न 30 तक भूल जाएगा। यह एक PostToolUse hook है जिसे हार्नेस हर बार चलाता है। स्वचालित, दोहराया जाने वाला व्यवहार settings.json में जाता है। पसंद मेमोरी में जाती है। उन्हें मिक्स मत करो।
त्वरित संरचना, बिना औपचारिकता के:
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{"type": "command", "command": "~/.claude/guards/git-guard.sh"}]
}]
}
}
matcher hook को एक टूल तक सीमित करता है। कसकर स्कोप करें। एक PreToolUse hook जो हर टूल पर फायर होता है, हर इनपुट को पार्स करता है, और shell को कॉल करता है, पूरे रन में latency जोड़ता है। मैंने यह धीमे तरीके से सीखा जब एक अनावश्यक नेटवर्क कॉल वाले गार्ड स्क्रिप्ट ने 300-कॉल सेशन में हर एक bash कॉल में एक सेकंड जोड़ दिया।
वो गलती जो सब करते हैं
ब्लैकलिस्ट। आपकी पहली प्रवृत्ति बुरे कमांड को ब्लैकलिस्ट करने की होती है। rm -rf, git reset, DROP TABLE। मॉडल आपकी ब्लैकलिस्ट से ज्यादा रचनात्मक है। वो find . -delete खोज लेगा, या कमांड को base64-एनकोड कर देगा, या कोई टूल इस्तेमाल करेगा जिसे आप भूल गए थे।
जहाँ हो सके, सुरक्षित ऑपरेशन को व्हाइटलिस्ट करें। एक रीड-ओनली रिसर्च agent के लिए, grep, glob, read, web_search को अनुमति दें और बाकी सब को डिफ़ॉल्ट रूप से ब्लॉक करें। सेट अप करना ज्यादा झंझट है। यह एकमात्र वर्ज़न भी है जो तब टिकता है जब मॉडल चालाक हो जाता है। एक ब्लैकलिस्ट आपको उन विफलताओं से बचाती है जिनकी आपने कल्पना की थी। एक व्हाइटलिस्ट आपको उनसे बचाती है जिनकी नहीं की।
मेरे सेटअप में बिना निगरानी के चलने वाले agents में एक विशेषता साझा है: मैं hooks पर भरोसा करता हूँ, मॉडल पर नहीं। मॉडल स्मार्ट और तेज है और कभी-कभी तय करता है कि आपके दो घंटे का काम गंदा दिखता है। hook बेवकूफ है और कभी अपना मन नहीं बदलता। जब कुछ अपरिवर्तनीय दांव पर हो, बेवकूफ और अडिग ठीक वही है जो आप चाहते हैं।
क्लब में किसी को अंदर आने देने से पहले बाउंसर लिखो।
