एक Claude Code सेशन में 30 hook इवेंट ट्रिगर होते हैं। सिर्फ़ 3 जवाब दे सकते हैं।
Claude Code के hook इवेंट की पूरी सूची, हर इवेंट कब ट्रिगर होता है, कौन से 15 ब्लॉक कर सकते हैं, और वह stdout नियम जो ज़्यादातर hook आउटपुट को चुपचाप निगल जाता है। हज़ारों एजेंट सेशन में प्रोडक्शन पर hooks चलाकर बनाया गया एक फ़ील्ड रेफ़रेंस।
जब लोग Claude Code में hooks जोड़ते हैं तो दो नाकामियाँ बार-बार सामने आती हैं, और दोनों एक-दूसरे से बिल्कुल अलग दिखती हैं।
पहली: आप एक hook जोड़ते हैं, कुछ नहीं होता। न कोई एरर, न कोई चेतावनी, न कोई लॉग लाइन। वह hook बस कभी चलता ही नहीं।
दूसरी: hook साफ़ तौर पर चलता है, डिस्क पर उसके असर आप देख सकते हैं, लेकिन एजेंट के लिए वह जो संदेश प्रिंट करता है वह कभी नहीं पहुँचता। एजेंट ऐसे बर्ताव करता है जैसे hook ने कुछ कहा ही न हो।
दोनों की जड़ एक ही है। hook सिस्टम उन गिने-चुने इवेंट से कहीं बड़ा और कहीं कम एकरूप है जिन्हें ज़्यादातर लेख कवर करते हैं, और एजेंट से कौन बात कर सकता है इसके नियम वे नहीं हैं जिनका आप अंदाज़ा लगाएँगे। यह वही रेफ़रेंस है जो हम चाहते थे कि हमारे पास होता। हम AgentsRoom को इन्हीं hooks पर बनाते हैं, और नीचे जो कुछ है वह या तो आधिकारिक रेफ़रेंस से उद्धृत है या प्रोडक्शन में मापा गया है।
30 इवेंट हैं, छह नहीं
ज़्यादातर गाइड PreToolUse, PostToolUse, UserPromptSubmit, Stop, Notification और SubagentStop को कवर करती हैं। ये छह असली हैं, और उपयोगी काम का ज़्यादातर हिस्सा यही उठाते हैं। ये जो मौजूद है उसका पाँचवाँ हिस्सा भी हैं।
पूरी सूची, इस आधार पर समूहबद्ध कि हर इवेंट क्या देखता है:
| समूह | इवेंट |
|---|---|
| सेशन | SessionStart, SessionEnd, Setup |
| प्रॉम्प्ट | UserPromptSubmit, UserPromptExpansion |
| टूल | PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch |
| अनुमतियाँ | PermissionRequest, PermissionDenied |
| टर्न | Stop, StopFailure |
| सबएजेंट और टास्क | SubagentStart, SubagentStop, TaskCreated, TaskCompleted, TeammateIdle |
| कॉन्टेक्स्ट | PreCompact, PostCompact, InstructionsLoaded |
| एनवायरनमेंट | FileChanged, CwdChanged, ConfigChange |
| Worktrees | WorktreeCreate, WorktreeRemove |
| इंटरफ़ेस | Notification, MessageDisplay |
| MCP elicitation | Elicitation, ElicitationResult |

एक ही सेशन में इवेंट किस क्रम में ट्रिगर होते हैं। टूल वाला ब्लॉक हर टूल कॉल पर एक बार दोहराता है, और पूरा प्रॉम्प्ट ब्लॉक हर टर्न पर एक बार।
इनमें से कुछ इवेंट सिस्टम को देखने का आपका नज़रिया बदल देते हैं। PostToolUseFailure मौजूद है, इसलिए "टूल चला या नहीं" वाली शाखा एक इवेंट है, कोई ऐसी चीज़ नहीं जिसका अंदाज़ा आप किसी पेलोड से लगाते हैं। PostToolBatch समानांतर टूल कॉल का एक बैच पूरा होने के बाद एक बार ट्रिगर होता है, और यही वह सही जगह है जहाँ linter को हर एडिट पर एक बार के बजाय कुल एक बार चलाया जाए। InstructionsLoaded तब ट्रिगर होता है जब CLAUDE.md पढ़ी जाती है, जिससे आपको यह जाँचने का एक hook पॉइंट मिलता है कि एजेंट ने सचमुच वही नियम लोड किए हैं जो आप समझ रहे हैं।
वह stdout नियम जो ज़्यादातर hook आउटपुट को निगल जाता है
इस पेज पर सबसे काम की बात यही एक है।
एग्ज़िट कोड 0 पर, Claude Code stdout को JSON आउटपुट फ़ील्ड के लिए पार्स करता है। लेकिन वह stdout एजेंट को कभी दिखेगा या नहीं, यह इवेंट पर निर्भर करता है, और अपवादों की सूची छोटी है। रेफ़रेंस से:
ज़्यादातर इवेंट के लिए, stdout डिबग लॉग में लिखा जाता है पर ट्रांसक्रिप्ट में नहीं दिखता। अपवाद हैं
UserPromptSubmit,UserPromptExpansionऔरSessionStart, जहाँ stdout को ऐसे कॉन्टेक्स्ट के रूप में जोड़ा जाता है जिसे Claude देख सकता है और जिस पर वह काम कर सकता है।
तीस में से तीन इवेंट। अगर आप किसी PostToolUse hook से echo "warning: this migration is destructive" करते हैं और उम्मीद रखते हैं कि एजेंट उसे पढ़ेगा, तो वह कभी नहीं पढ़ेगा। आपका टेक्स्ट डिबग लॉग में चला गया।
किसी भी दूसरे इवेंट से एजेंट के सामने टेक्स्ट रखने के ठीक दो तरीक़े हैं:
- एग्ज़िट 2 करें और stderr पर लिखें। एग्ज़िट 2 पर, Claude Code stdout और उसमें मौजूद किसी भी JSON को नज़रअंदाज़ कर देता है, और stderr को एरर संदेश के रूप में एजेंट तक वापस भेजता है।
- एग्ज़िट 0 करें और एक JSON ऑब्जेक्ट प्रिंट करें जो
hookSpecificOutput.additionalContextलेकर आए।
पहले वाले में विषमता पर ध्यान दें। एग्ज़िट 0 का मतलब है stdout मायने रखता है और stderr नहीं। एग्ज़िट 2 का मतलब है stderr मायने रखता है और stdout पूरी तरह फेंक दिया जाता है। इसे उलटा समझ लेना ही वह वजह है जिससे एक hook बिल्कुल सही दिखते हुए भी गूँगा रह सकता है।
कोई भी दूसरा एग्ज़िट कोड एक नॉन-ब्लॉकिंग एरर है। ट्रांसक्रिप्ट में stderr की पहली लाइन के साथ <hook name> hook error सूचना दिखती है, निष्पादन जारी रहता है, और पूरा stderr डिबग लॉग में पहुँच जाता है।

एग्ज़िट कोड के हिसाब से कौन सा चैनल एजेंट तक पहुँचता है। बिंदुदार रास्ता वही है जिसके होने का लोग अंदाज़ा लगाते हैं और जो है ही नहीं।
इनमें से ठीक आधे ब्लॉक कर सकते हैं
पंद्रह इवेंट एग्ज़िट 2 पर कार्रवाई रोक देते हैं। पंद्रह उसे नज़रअंदाज़ करके आगे बढ़ जाते हैं।
ब्लॉक कर सकते हैं: PreToolUse, PermissionRequest, UserPromptSubmit, UserPromptExpansion, Stop, SubagentStop, TeammateIdle, TaskCreated, TaskCompleted, ConfigChange, PostToolBatch, PreCompact, Elicitation, ElicitationResult, WorktreeCreate।
ब्लॉक नहीं कर सकते: PostToolUse, PostToolUseFailure, PermissionDenied, StopFailure, Notification, SubagentStart, SessionStart, Setup, SessionEnd, CwdChanged, FileChanged, PostCompact, WorktreeRemove, InstructionsLoaded, MessageDisplay।
व्यावहारिक नतीजा: कोई भी सुरक्षा-अवरोध PreToolUse पर लगता है, PostToolUse पर कभी नहीं। PostToolUse टूल के सफल होने के बाद ट्रिगर होता है। वहाँ एग्ज़िट 2 करने से लिखा हुआ वापस नहीं होता, बस एक एरर छपता है जबकि नुक़सान डिस्क पर बैठा रहता है। अगर आपको rm -rf रोकना है, तो ऐसा करने की ठीक एक जगह है।
PostToolBatch का ब्लॉक करना, जबकि PostToolUse नहीं करता, दोबारा देखने लायक़ है। इसका मतलब है कि समानांतर एडिट लैंड होने के बाद भी बैच-स्तर की एक जाँच टर्न रोक सकती है, और लिखे जाने के बाद वीटो के सबसे नज़दीक सिस्टम यही देता है।
Matcher सटीक होते हैं, जब तक अचानक नहीं रह जाते
matcher फ़ील्ड अपने ही अक्षरों के आधार पर मूल्यांकन की रणनीति बदल देता है, और कुछ भी आपको नहीं बताता कि उसने कौन सा रास्ता लिया।
| Matcher | किस रूप में मूल्यांकित |
|---|---|
"*", "", या अनुपस्थित | सब कुछ मैच करता है |
सिर्फ़ अक्षर, अंक, _, -, स्पेस, ,, | | सटीक स्ट्रिंग, या | या , पर बँटी सटीक स्ट्रिंग की सूची |
| इसके अलावा कुछ भी | बिना एंकर वाली JavaScript रेगुलर एक्सप्रेशन |
जाल "बिना एंकर" में है। रेफ़रेंस साफ़ कहता है कि regex को RegExp.prototype.test से जाँचा जाता है, जो वैल्यू में कहीं भी मैच मिलने पर सफल हो जाता है। इसलिए Edit.* Edit और NotebookEdit दोनों से मैच करता है। अगर आपका मतलब एक ही टूल था, तो ^Edit$ लिखिए।
दो व्यवहार वर्शन पर निर्भर हैं, और ग़लत चीज़ डिबग करने से पहले इन्हें जान लेना बेहतर है:
- कॉमा को सेपरेटर मानने और स्पेस की सहनशीलता के लिए Claude Code v2.1.191 या उसके बाद का वर्शन चाहिए।
- हाइफ़न v2.1.195 में सटीक-मैच वाले अक्षर-समूह में शामिल हुए। उससे पहले,
code-reviewerजैसे matcher को बिना एंकर वाली regex माना जाता था, इसलिए वहsenior-code-reviewerपर भी ट्रिगर होता था।
AgentsRoom में हम अपने file-attribution hook को Write|Edit|MultiEdit|NotebookEdit से सीमित करते हैं, जो सटीक-स्ट्रिंग वाले रास्ते पर ही रहता है और उन्हीं चार टूल से मैच करता है, किसी और से नहीं। हम जो लाइफ़साइकिल hooks इंस्टॉल करते हैं उनमें कोई matcher होता ही नहीं, क्योंकि वे हमेशा हमसे जुड़े होते हैं।
छह जगहें hooks परिभाषित कर सकती हैं, और वे मर्ज होती हैं
पहली सहज प्रतिक्रिया होती है प्राथमिकता का क्रम ढूँढ़ना। कोई क्रम है ही नहीं, और दिलचस्प बात यही है।
| जगह | दायरा |
|---|---|
~/.claude/settings.json | आपके सारे प्रोजेक्ट, आपकी मशीन तक सीमित |
.claude/settings.json | एक प्रोजेक्ट, कमिट किया जा सकता है |
.claude/settings.local.json | एक प्रोजेक्ट, Claude Code इसे gitignore करता है |
| Managed policy settings | पूरे संगठन में, एडमिन के नियंत्रण में |
प्लगिन का hooks/hooks.json | जब तक प्लगिन सक्षम है |
| स्किल या एजेंट का frontmatter | जब तक कंपोनेंट सक्रिय है |
रेफ़रेंस से:
hook एंट्रीज़ settings के स्तरों में एक-दूसरे की जगह लेने के बजाय मर्ज होती हैं: user, project और local settings मैनेज्ड hooks को हटाए बिना अपने hooks जोड़ते हैं, और
disableAllHooksसेटिंग मैनेज्ड settings के बाहर से मैनेज्ड hooks को अक्षम नहीं कर सकती।
तो कोई प्रोजेक्ट hook किसी ग्लोबल hook की जगह कभी नहीं लेता, वह उसके ऊपर जुड़ जाता है। छह स्रोत, सभी जोड़ने वाले। आपके user settings में और फिर प्रोजेक्ट में परिभाषित एक PostToolUse फ़ॉर्मैटर हर एडिट पर दो बार चलता है, और इसका इकलौता लक्षण यह है कि चीज़ें धीमी लगने लगती हैं।

छह स्रोत, एक मर्ज किया हुआ सेट। यहाँ कुछ भी किसी चीज़ की जगह नहीं लेता।
इससे यह भी समझ आता है कि किसी टूल के लिए किसी और के प्रोजेक्ट में hook इंस्टॉल करने की सही जगह .claude/settings.local.json क्यों है। यह प्रोजेक्ट तक सीमित है, Claude Code इसे gitignore करता है, और यह बिना किसी CLI फ़्लैग के लोड होता है। AgentsRoom अपनी एंट्रीज़ वहीं लिखता है, ताकि उपयोगकर्ता की कमिट की हुई .claude/settings.json कभी छुई न जाए और उसके सहकर्मियों को कभी कोई मशीन-विशिष्ट पाथ विरासत में न मिले।
प्रोडक्शन में hooks चलाकर हमने क्या सीखा
AgentsRoom हर उस प्रोजेक्ट में hooks इंस्टॉल करता है जिसे वह खोलता है, ताकि एजेंट का स्टेटस निश्चित रूप से ट्रैक हो और बदली गई फ़ाइलें सही एजेंट के खाते में जाएँ। कुछ चीज़ें उसी पैमाने पर जाकर दिखती हैं।
अनजान इवेंट नाम चुपचाप नज़रअंदाज़ हो जाते हैं। यह डॉक्युमेंटेशन में नहीं है, और हम इस पर निर्भर हैं। जब हम अपने इंस्टॉलर में कोई नया लाइफ़साइकिल इवेंट जोड़ते हैं, तो पुराने CLI वाले उपयोगकर्ताओं को ऐसा settings.local.json मिलता है जिसमें एक ऐसा इवेंट नाम है जो उनकी बाइनरी ने कभी सुना ही नहीं। कुछ नहीं टूटता, कोई चेतावनी नहीं आती, वह एंट्री छोड़ दी जाती है। यही इंस्टॉलर को CLI रिलीज़ से पहले भेजने लायक़ सुरक्षित बनाता है। और यही, लाज़मी तौर पर, वह वजह भी है कि एक टाइपो एरर के बजाय पूरी ख़ामोशी पैदा करता है।
agent_id से ही आपको पता चलता है कि आप किसी सबएजेंट के भीतर हैं। यह फ़ील्ड सिर्फ़ तब मौजूद होता है जब hook किसी सबएजेंट कॉल के भीतर ट्रिगर होता है। यह जितना लगता है उससे ज़्यादा मायने रखता है: Stop तब भी ट्रिगर होता है जब कोई सबएजेंट अपना टर्न पूरा करता है, सिर्फ़ मुख्य एजेंट पर नहीं। "Stop आने पर सेशन को पूरा मान लो" जैसा भोला नियम पहली बार किसी भी सबएजेंट के लौटते ही पूरे सेशन को ख़त्म मान लेता है। हम ठीक इसी वजह से agent_id लेकर आने वाले टर्न इवेंट छोड़ देते हैं।
चालू टर्न के लिए transcript_path मत पढ़िए। रेफ़रेंस चेतावनी देता है कि ट्रांसक्रिप्ट असिंक्रोनस तरीक़े से लिखी जाती है और मेमोरी में चल रही बातचीत से पीछे रह सकती है, इसलिए जब आपका hook ट्रिगर होता है तब सबसे नए संदेश वहाँ अभी न भी हों। Stop और SubagentStop को last_assistant_message ठीक इसीलिए मिलता है, ताकि आपको कभी फ़ाइल से होड़ न लगानी पड़े।
स्टेटस का इकलौता भरोसेमंद संकेत hooks ही हैं। hooks से पहले, हम PTY को स्क्रैप करके तय करते थे कि एजेंट सोच रहा है, इंतज़ार कर रहा है या काम पूरा कर चुका है। यह उसी पल टूट जाता है जब CLI टर्मिनल के अल्टरनेट स्क्रीन बफ़र से रेंडर करता है, और /tui fullscreen यही करता है। hooks हर रेंडरर के नीचे एक जैसे ट्रिगर होते हैं। अगर आप ऐसा कुछ भी बना रहे हैं जो किसी एजेंट को बाहर से देखता है, तो नींव यही परत है, और स्क्रैपिंग ज़्यादा से ज़्यादा एक फ़ॉलबैक भर रहती है।
async: true की कोई क़ीमत नहीं है। कोई hook कमांड async: true घोषित कर सकती है, और एजेंट उसका इंतज़ार नहीं करता। हमारा hook 2 सेकंड की सीमा के साथ एक लोकल एंडपॉइंट पर POST करता है और लौट आता है; एजेंट के टर्न की लेटेंसी पर कोई असर नहीं पड़ता, तब भी नहीं जब लेने वाला ऐप बंद हो। अगर आपका hook सिर्फ़ देखता है और कभी फ़ैसला नहीं लेता, तो उसे async बना दीजिए और उसकी क़ीमत चुकाना बंद कीजिए।
किसी hook को टर्मिनल में कचरा लिखने मत दीजिए। हमारी स्क्रिप्ट हर अपवाद को निगल जाती है, सबसे ऊपरी स्तर पर भी। किसी hook से आया बिना संभाला हुआ ट्रेसबैक सिर्फ़ चुपचाप नाकाम नहीं होता, वह उपयोगकर्ता के काम के बीचोंबीच उसके टर्मिनल सेशन में एक Python स्टैक ट्रेस छाप देता है।
टाइमआउट
डिफ़ॉल्ट उदार हैं, तीन अपवादों को छोड़कर जो उदार नहीं हैं:
| hook का प्रकार | डिफ़ॉल्ट टाइमआउट |
|---|---|
command, http, mcp_tool | 600 s |
prompt | 30 s |
agent | 60 s |
UserPromptSubmit (command, http, mcp_tool) | 30 s |
MessageDisplay (command, http, mcp_tool) | 10 s |
SessionEnd | सभी hooks में साझा 1.5 s, किसी hook के लंबे timeout से मेल खाने के लिए बढ़ाया जाता है, अधिकतम 60 s |
SessionEnd का बजट ही लोगों को चौंकाता है। यह एक साझा बजट है, हर hook का अलग कोटा नहीं, इसलिए तीन क्लीनअप hooks आपस में 1.5 सेकंड बाँट रहे होते हैं, बशर्ते आप उसे साफ़ तौर पर बढ़ा न दें।
छोटा सार
- 30 इवेंट मौजूद हैं। छह मशहूर हैं।
- stdout एजेंट तक सिर्फ़
UserPromptSubmit,UserPromptExpansionऔरSessionStartपर पहुँचता है। बाक़ी हर जगह, stderr के साथ एग्ज़िट 2 करें, या JSON मेंadditionalContextभेजें। - 15 इवेंट एग्ज़िट 2 पर ब्लॉक करते हैं, 15 उसे नज़रअंदाज़ करते हैं। सुरक्षा-अवरोध
PreToolUseपर जाते हैं। - Matcher तब तक सटीक स्ट्रिंग रहते हैं जब तक कोई विशेष अक्षर उन्हें बिना एंकर वाली regex में न बदल दे।
- settings के छह स्रोत जुड़कर मर्ज होते हैं। कुछ भी किसी की जगह नहीं लेता।
- ग़लत वर्तनी वाला इवेंट नाम पूरी तरह ख़ामोशी से नाकाम होता है।
अगर आप इन इवेंट के बारे में सोचने के बजाय उन्हें ट्रिगर होते देखना चाहते हैं, तो हमने वही बनाया है: AgentsRoom हर hook ट्रिगर को दिखाता है, हर एजेंट, हर प्रोजेक्ट और हर रन के हिसाब से, दर्जनों समानांतर एजेंट और सबएजेंट सेशन तक। आप अपने settings में जो hooks कॉन्फ़िगर करते हैं वे ठीक वैसे ही काम करते रहते हैं जैसे लिखे गए हैं, क्योंकि यह असली CLI चलाता है।
पढ़ते रहें
कैसे एक डेवलपमेंट टीम में AI कोडिंग एजेंट्स को स्केल करें
एक डेवलपर के पास एक कोडिंग एजेंट होने से उत्पादकता की कहानी बनती है। पांच डेवलपर्स के पास बीस एजेंट्स होने से समन्वय की समस्या होती है। यहाँ बताया गया है कि जब एक टीम बढ़ती है तो सबसे पहले क्या टूटता है, और वह सेटअप जो टिकता है: प्रतिबद्ध संदर्भ फ़ाइलें, स्पष्ट फ़ाइल स्वामित्व, विस्फोटक क्षेत्र द्वारा समीक्षा, और लागत जिसे आप वास्तव में देख सकते हैं।
लेख पढ़ेंAgentsRoom में अब Kimi Code का समर्थन
Moonshot AI का टर्मिनल कोडिंग एजेंट Kimi Code अब AgentsRoom में पूरी तरह समर्थित प्रोवाइडर है। इसे Claude, Codex, Antigravity CLI, OpenCode, Aider, Grok Build और Mistral Vibe के साथ चलाइए, और बातचीत के बीच में ही स्विच कीजिए।
लेख पढ़ेंक्या आपको अभी भी अपने AI एजेंट के कोड की समीक्षा करनी चाहिए?
आपके एजेंट आधे पुल अनुरोधों से बेहतर कोड लिखते हैं जिन्हें आप पहले मर्ज करते थे। तो क्या आप अभी भी हर लाइन पढ़ते हैं? दोनों पक्षों के लिए ईमानदार मामला, 10 संकेत जो बताते हैं कि एक एजेंट ने गलती की, और प्रत्येक परिवर्तन को वास्तव में कितनी समीक्षा की आवश्यकता है।
लेख पढ़ें
AgentsRoom डाउनलोड करें
अपने AI एजेंट्स (Claude, Codex, Antigravity CLI, OpenCode, Aider, Grok Build, Mistral Vibe, Kimi Code) को अपने सभी प्रोजेक्ट्स पर एक ही विंडो से चलाएं।
कंपेनियन ऐप: चलते-फिरते अपने एजेंट्स मॉनिटर करें
Claude, Codex, Antigravity CLI या किसी अन्य AI प्रदाता का उपयोग करें।
बग और अनुरोध सीधे अपने सार्वजनिक बैकलॉग में भेजें।
AgentsRoom को कार्य करते देखें।