"मैं चाहता हूँ कि हर एडिट के बाद ऑटो-फ़ॉर्मैटिंग हो।" ".env या package-lock.json को कभी कोई रीराइट न कर पाए।" "ख़तरनाक rm -rf कमांड रोक दिए जाएँ।" इन "ऐसा हमेशा होना ही चाहिए" वाले नियमों को AI की मर्ज़ी पर निर्भर हुए बिना सच में लागू करने का तरीक़ा है Claude Code hooks। एक hook वह shell कमांड है जो Claude Code के लाइफ़साइकल में निश्चित बिंदुओं पर अपने-आप चलता है, और hooks plugins का एक बुनियादी हिस्सा भी हैं।

यह लेख आधिकारिक दस्तावेज़ के आधार पर बताता है कि hooks क्या हैं, इवेंट की सूची, उन्हें कैसे कॉन्फ़िगर करें, इनपुट/आउटपुट कॉन्ट्रैक्ट, उपयोग-केस और सुरक्षा। पहले तीन मुख्य बातें। ① एक hook "हार्नेस (यानी Claude Code ख़ुद) द्वारा चलाया जाने वाला डिटरमिनिस्टिक लॉजिक" है—यह पक्का चलता है, मॉडल के "करने का फ़ैसला" लेने का इंतज़ार किए बिना। ② आप hooks को settings.json में इवेंट नाम → matcher → command के रूप में लिखते हैं। PreToolUse जैसे इवेंट exit code 2 या JSON के ज़रिए "ब्लॉक" कर सकते हैं—सुरक्षित फ़ाइलों में एडिट या ख़तरनाक कमांड रोककर।

CLAUDE CODE · HOOKS

मुख्य लाइफ़साइकल बिंदुओं पर "पक्का" चलता है

— इसे हार्नेस डिटरमिनिस्टिक रूप से चलाता है, मॉडल के फ़ैसले से नहीं

SessionStart सेशन शुरू होता है। आउटपुट कॉन्टेक्स्ट के रूप में जोड़ा जाता है
UserPromptSubmit जब कोई प्रॉम्प्ट सबमिट होता है [ब्लॉक कर सकता है]
PreToolUse किसी टूल के चलने से ठीक पहले = गेटकीपर [ब्लॉक कर सकता है]
PostToolUse किसी टूल के सफल होने के बाद = ऑटो-फ़ॉर्मैट / ऑडिट
Stop जब कोई रिस्पॉन्स ख़त्म होता है = टेस्ट पास होने तक चलते रहो, आदि [ब्लॉक कर सकता है]

हर बिंदु पर आपका shell कमांड चलता है। क्लासिक उदाहरण: PreToolUse से ख़तरनाक कार्रवाइयाँ दरवाज़े पर ही रोकना, PostToolUse से ऑटो-फ़ॉर्मैट

1. Claude Code hooks क्या हैं?

आधिकारिक परिभाषा इस तरह है: "Hooks यूज़र द्वारा परिभाषित shell कमांड हैं जो Claude Code के लाइफ़साइकल में निश्चित बिंदुओं पर चलते हैं। ये Claude Code के व्यवहार पर डिटरमिनिस्टिक नियंत्रण देते हैं, यह सुनिश्चित करते हुए कि कुछ कार्रवाइयाँ हमेशा हों, बजाय इसके कि LLM उन्हें चलाने का चुनाव करे।" आप इनका इस्तेमाल प्रोजेक्ट नियम लागू करने, दोहराव वाले कामों को ऑटोमेट करने, और Claude Code को अपने मौजूदा टूल्स से जोड़ने के लिए करते हैं।

इसका मूल है डिटरमिनिज़्म। Claude से कहिए "टेस्ट चलाओ" और वह चलाएगा या नहीं, यह उसके "फ़ैसले" पर निर्भर करता है। पर एक hook के साथ हार्नेस उसे हमेशा चलाता है—कोई मर्ज़ी बीच में नहीं आती। कमांड (command) के अलावा अब HTTP, MCP टूल्स, LLM प्रॉम्प्ट और सबएजेंट वेरिफ़िकेशन जैसे हैंडलर टाइप भी हैं—पर शुरुआत के लिए hooks को "मुख्य बिंदुओं पर हमेशा एक shell कमांड चलाने की एक व्यवस्था" के रूप में सोचना काफ़ी है।

2. hook इवेंट

एक इवेंट दर्शाता है कि "लाइफ़साइकल में यह कहाँ चलता है।" नौ क्लासिक इवेंट से शुरू करें ("ब्लॉक कर सकता है" = आप उस कार्रवाई को exit code 2 या JSON के ज़रिए रोक सकते हैं)।

इवेंटकब चलता हैब्लॉक
SessionStartकोई सेशन शुरू या रिज़्यूम होता है (stdout कॉन्टेक्स्ट के रूप में जोड़ा जाता है)नहीं
UserPromptSubmitआप कोई प्रॉम्प्ट सबमिट करते हैं, Claude द्वारा उसे प्रोसेस करने से पहलेहाँ
PreToolUseकिसी टूल कॉल से ठीक पहले (मुख्य गेटकीपर)हाँ
PostToolUseकिसी टूल के सफल होने के बाद (कार्रवाई ख़ुद अनडू नहीं हो सकती)हाँ
Notificationकिसी नोटिफ़िकेशन पर (इनपुट/अनुमति का इंतज़ार, आदि)नहीं
Stopजब Claude जवाब देना ख़त्म करता है (ब्लॉक = काम करते रहो)हाँ
SubagentStopजब कोई सबएजेंट ख़त्म होता हैहाँ
SessionEndजब कोई सेशन समाप्त होता हैनहीं
PreCompactकॉन्टेक्स्ट कॉम्पैक्शन से पहलेहाँ

2026 के दस्तावेज़ में कई और इवेंट जोड़े गए हैं—PermissionRequest, PostToolUseFailure, ConfigChange, FileChanged, WorktreeCreate और अन्य। पर इवेंट नाम वर्शन के बीच जोड़े या बदले जा सकते हैं, इसलिए यह लेख स्थिर नौ क्लासिक इवेंट और अगले सेक्शन के कॉन्ट्रैक्ट पर आधारित है (मौजूदा पूरी सूची के लिए आधिकारिक दस्तावेज़ देखें)।

3. hooks कैसे कॉन्फ़िगर करें

आप hooks को settings.json में "hooks" की के तहत लिखते हैं। स्थान दायरा (scope) तय करता है: यूज़र (~/.claude/settings.json) / प्रोजेक्ट (.claude/settings.json, git-शेयर करने योग्य) / लोकल (.claude/settings.local.json) / मैनेज्ड पॉलिसी (संगठन) / किसी plugin का hooks/hooks.json। JSON का स्वरूप इस तरह दिखता है।

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

संरचना इस तरह है: "hooks → इवेंट नाम → { matcher, hooks:[...] } का एक ऐरे → हर hook में type + command।" matcher लक्ष्य टूल का नाम बताता है: "*" (या छोड़ देने पर) सभी से मैच करता है, "Edit|Write" एक |-विभाजित सूची है, और अन्य कैरेक्टर regex होते हैं (उदा. mcp__memory__.*)। यह केस-सेंसिटिव है। /hooks कमांड कॉन्फ़िगर किए गए hooks की सूची दिखाता है पर केवल-पढ़ने वाला (read-only) है—जोड़ने या बदलने के लिए सीधे settings.json एडिट करें। सबको बंद करने के लिए "disableAllHooks": true इस्तेमाल करें।

4. इनपुट/आउटपुट कॉन्ट्रैक्ट

एक hook स्टैंडर्ड इनपुट (stdin) पर JSON प्राप्त करता है और अपना परिणाम exit code या स्टैंडर्ड आउटपुट पर JSON के ज़रिए लौटाता है।

इनपुट (stdin): सामान्य फ़ील्ड में session_id, transcript_path, cwd और hook_event_name शामिल हैं। टूल इवेंट tool_name और tool_input जोड़ते हैं (उदा. {"command":"rm -rf /tmp/build"}); UserPromptSubmit prompt जोड़ता है। Exit codes: 0 = सफलता (कुछ इवेंट के लिए stdout कॉन्टेक्स्ट में जोड़ा जाता है—हालाँकि PreToolUse पर exit 0 "मंज़ूरी" नहीं है; सामान्य अनुमति प्रवाह फिर भी लागू रहता है), 2 = ब्लॉक (stderr को Claude को समायोजन की सामग्री के रूप में दिया जाता है, और JSON आउटपुट को अनदेखा किया जाता है)।

# उदाहरण: स्ट्रक्चर्ड JSON आउटपुट के ज़रिए PreToolUse से "deny" (stdout पर प्रिंट)
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Database writes are not allowed"
  }
}
# सामान्य फ़ील्ड: continue (false = पूरी तरह रुको) / decision:"block"+reason /
#                additionalContext (Claude के लिए जोड़ा जाता है) / updatedInput (आर्ग्स रीराइट करें)

सबसे अहम सिद्धांत: "hooks पाबंदियाँ सख़्त कर सकते हैं पर ढीली नहीं।" allow लौटाना केवल प्रॉम्प्ट छोड़ देता है; किसी भी दायरे (मैनेज्ड सेटिंग्स सहित) में deny नियम हमेशा प्राथमिकता पाते हैं। एक PreToolUse deny bypassPermissions / --dangerously-skip-permissions के तहत भी ब्लॉक करता है। व्यापक अनुमति मॉडल के लिए, देखें अनुमति मोड और सुरक्षा

5. उदाहरण उपयोग-केस

आधिकारिक क्लासिक उदाहरण, उनके कॉन्फ़िगरेशन के साथ।

USE CASES

क्लासिक ऑटोमेशन

एडिट के बाद ऑटो-फ़ॉर्मैट
PostToolUse + Edit|Write अपने-आप prettier / एक linter चलाता है।
अहम फ़ाइलों की सुरक्षा
PreToolUse .env, .git/ आदि में एडिट को ब्लॉक करता है (exit 2)
ख़तरनाक कमांड रोकें
PreToolUse rm -rf आदि का पता लगाकर deny लौटाता है।
कॉन्टेक्स्ट फिर से इंजेक्ट करें
SessionStart stdout हर बार नियम और नोट फिर से लोड करता है (कॉम्पैक्शन के बाद भी)।
नोटिफ़िकेशन और ऑडिट लॉग
Notification डेस्कटॉप अलर्ट के लिए; PostToolUse कमांड हिस्ट्री लॉग करने के लिए।
रुकने से पहले टेस्ट
Stop टेस्ट पास होने तक Claude को रुकने नहीं देता (हरा होने तक काम करते रहो)।

ध्यान दें: Claude Bash के ज़रिए भी फ़ाइलें बदल सकता है। हर बदलाव पकड़ने के लिए, एक Stop hook जोड़ें जो प्रति टर्न एक बार वर्किंग ट्री को स्कैन करे।

6. सुरक्षा

Hooks शक्तिशाली हैं, पर वे आपके अधिकारों के साथ अपने-आप मनमाने shell कमांड चलाते हैं—इसे हल्के में न लें।

⚠️ आधिकारिक चेतावनी

"Hooks अपने-आप मनमाने shell कमांड चलाते हैं। आप जो hooks कॉन्फ़िगर करते हैं उनकी सुरक्षा के लिए केवल आप ज़िम्मेदार हैं। अपने जोखिम पर इस्तेमाल करें।" Hooks फ़ाइलें पढ़ सकते हैं, आपका कोडबेस बदल सकते हैं, डेटा बाहर भेज सकते हैं, या कोई भी कमांड चला सकते हैं—केवल वही कॉन्फ़िगर करें जिन पर आप पूरी तरह भरोसा करते हैं

स्टार्टअप स्नैपशॉट (एक अहम सुरक्षा फ़ीचर): hook कॉन्फ़िगरेशन सेशन स्टार्टअप पर कैप्चर किया जाता है, इसलिए सेशन के बीच में किए गए कॉन्फ़िग बदलाव लागू नहीं होते। यह एक दुर्भावनापूर्ण प्रॉम्प्ट या टूल आउटपुट को सेशन के दौरान आपका hook कॉन्फ़िग रीराइट करने से रोकता है। बदलाव एक नए सेशन में लागू करें।

व्यवहार में: हमेशा इनपुट को वैलिडेट और कोट करें (jq से निकालें; बिना कोट वाले वैरिएबल अतिरिक्त आर्ग्स या shell सिंटैक्स बन सकते हैं), एब्सोल्यूट पाथ और ${CLAUDE_PROJECT_DIR} इस्तेमाल करें, .env या .ssh जैसी संवेदनशील फ़ाइलों को न छुएँ, और टूल आउटपुट को कभी eval न करें। Hooks बिना किसी कंट्रोलिंग टर्मिनल के चलते हैं (कोई /dev/tty नहीं)। संगठनों में, एडमिन allowManagedHooksOnly से hooks पर पाबंदी लगा सकते हैं।

सारांश

Claude Code hooks यूज़र द्वारा परिभाषित shell कमांड हैं जो मुख्य लाइफ़साइकल बिंदुओं पर अपने-आप चलते हैं, और "ऐसा हमेशा होना ही चाहिए" को मॉडल के फ़ैसले पर निर्भर हुए बिना सच और डिटरमिनिस्टिक बना देते हैं। क्लासिक इवेंट नौ हैं: SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Notification / Stop / SubagentStop / SessionEnd / PreCompact (PreToolUse और अन्य ब्लॉक कर सकते हैं—सुरक्षित फ़ाइलों में एडिट या ख़तरनाक कमांड रोककर)। आप इन्हें settings.json में "hooks" के तहत इवेंट → matcher → type + command के रूप में कॉन्फ़िगर करते हैं।

I/O है stdin पर JSON, exit code 0 (सफलता) / 2 (ब्लॉक), या stdout पर स्ट्रक्चर्ड JSON। सिद्धांत: "आप पाबंदियाँ सख़्त कर सकते हैं पर ढीली नहीं" (deny हमेशा जीतता है)। क्लासिक उपयोग-केस: ऑटो-फ़ॉर्मैट, फ़ाइलों की सुरक्षा, ख़तरनाक कमांड रोकना, कॉन्टेक्स्ट फिर से इंजेक्ट करना, ऑडिट, रुकने से पहले टेस्ट। पर चूँकि वे मनमाना कोड चलाते हैं, केवल सुरक्षित hooks पर भरोसा करने और इनपुट को वैलिडेट/कोट करने के बारे में सख़्त रहें, और समझें कि कॉन्फ़िग स्टार्टअप पर कैप्चर होता है। संबंधित: plugins, MCP, Claude Code त्रुटियाँ

FAQ

Q. hooks किसलिए हैं?
A. वे "ऐसा हमेशा होना ही चाहिए" को डिटरमिनिस्टिक रूप से ऑटोमेट करते हैं। "एडिट के बाद फ़ॉर्मैट करो," "सुरक्षित फ़ाइलें कभी रीराइट न हों," "ख़तरनाक rm -rf रोको," और "रुकने से पहले टेस्ट पास करो" जैसी चीज़ें AI के फ़ैसले पर निर्भर हुए बिना हार्नेस द्वारा पक्के तौर पर चलाई जाती हैं। एक hook एक shell कमांड है जो मुख्य लाइफ़साइकल बिंदुओं पर चलता है, और settings.json में कॉन्फ़िगर किया जाता है।

Q. कौन-कौन से इवेंट (समय) हैं?
A. क्लासिक नौ हैं: SessionStart (शुरू), UserPromptSubmit (सबमिट पर), PreToolUse (टूल से ठीक पहले), PostToolUse (टूल के बाद), Notification, Stop (रिस्पॉन्स ख़त्म), SubagentStop, SessionEnd (समाप्त), PreCompact (कॉम्पैक्शन से पहले)। इनमें से PreToolUse, UserPromptSubmit, Stop, PreCompact और अन्य ब्लॉक कर सकते हैं और कार्रवाई रोक सकते हैं। 2026 रिलीज़ कई और इवेंट जोड़ती है, पर नाम वर्शन के बीच बदल सकते हैं, इसलिए नवीनतम के लिए आधिकारिक दस्तावेज़ देखें।

Q. क्या मैं सुरक्षित फ़ाइलों में एडिट या ख़तरनाक कमांड रोक सकता हूँ?
A. हाँ—एक PreToolUse hook के साथ। एक स्क्रिप्ट tool_input में फ़ाइल पाथ या कमांड का निरीक्षण करती है, और अगर वह .env, rm -rf आदि से मैच करता है, तो उसे ब्लॉक करने के लिए exit code 2 (या permissionDecision:"deny" वाला JSON) लौटाती है। ख़ास बात, deny हमेशा प्राथमिकता पाता है और bypassPermissions के तहत भी रोकता है। Hooks केवल "पाबंदियाँ सख़्त करने" की दिशा में काम करते हैं।

Q. मैंने अपना कॉन्फ़िग बदला पर यह लागू नहीं हो रहा।
A. यह डिज़ाइन के अनुसार है (एक सुरक्षा फ़ीचर)। Hook कॉन्फ़िग सेशन स्टार्टअप पर एक स्नैपशॉट के रूप में कैप्चर होता है, इसलिए सेशन के बीच में किए बदलाव लागू नहीं होते। यह एक दुर्भावनापूर्ण प्रॉम्प्ट या टूल आउटपुट को चुपके से आपका hook कॉन्फ़िग रीराइट करने से रोकता है। इसे लागू करने के लिए एक नया सेशन शुरू करें। ध्यान दें कि /hooks एक केवल-पढ़ने वाली सूची है; hooks जोड़ने या बदलने के लिए सीधे settings.json एडिट करें।

Q. क्या hooks सुरक्षित हैं?
A. बिना शर्त नहीं। Hooks आपके अधिकारों के साथ मनमाने shell कमांड चलाते हैं, इसीलिए दस्तावेज़ कहते हैं "अपने जोखिम पर इस्तेमाल करें।" केवल उन hooks को कॉन्फ़िगर करें जिन पर आप भरोसा करते हैं, इनपुट को jq से वैलिडेट और कोट करें, एब्सोल्यूट पाथ इस्तेमाल करें और .env / .ssh को न छुएँ, और टूल आउटपुट को कभी eval न करें। संगठनों में, एडमिन allowManagedHooksOnly से hooks पर पाबंदी लगा सकते हैं।