Skip to content

नियम और हुक्स (Rules & Hooks): Codex में स्वचालित नियंत्रण और कपाट जोड़ना

📚 सीरीज नेविगेशन: पिछला लेख [23 प्लगइन्स (Plugins)] आपको थर्ड-पार्टी क्षमताओं को एक साथ पैक करके इंस्टॉल करना सिखाता है। यह लेख अधिक बुनियादी और आपके नियंत्रण की दो चीज़ों के बारे में बात करता है—नियम (Rules) यह नियंत्रित करते हैं कि 'कौन सी कमांड सैंडबॉक्स से बाहर चल सकती हैं', और हुक्स (Hooks) यह तय करते हैं कि 'कोडिंग प्रक्रिया के किसी विशिष्ट चरण पर स्वचालित रूप से कोई स्क्रिप्ट कैसे रन हो'। एक सुरक्षा सीमा है, और दूसरा ट्रिगर। इन्हें सेट करने के बाद, आपको बार-बार मैन्युअल रूप से निर्देश देने या कमांड्स चलाने की आवश्यकता नहीं होगी। अगला लेख [25 Worktrees समानांतर काम] यह समझाएगा कि कैसे आप एक साथ कई Codex सत्रों को बिना किसी टकराव के चला सकते हैं।

यहाँ पिछले महीने मेरे और मेरे सहयोगी के बीच हुई एक वास्तविक बातचीत का अंश है। हम एक ऐसे बग की जाँच कर रहे थे जिसके कारण CI बार-बार विफल हो रहा था:

मैं: "इस सप्ताह मैंने Codex द्वारा कोड बदलने के बाद मैन्युअल रूप से ruff format कम से कम दस बार चलाया होगा।" सहयोगी: "क्या तुमने AGENTS.md में 'कोड बदलने के बाद फ़ॉर्मेट करें' नहीं लिखा है?" मैं: "लिखा है। लेकिन यह तीन में से एक बार भूल जाता है—वह अनुरोध था, कोई गारंटी नहीं। एक बार भी भूलने पर CI की फ़ॉर्मेट जाँच विफल हो जाती है।" सहयोगी: "तो तुम एक हुक (hook) क्यों नहीं जोड़ देते? जैसे ही कोई घटना ट्रिगर होगी, स्क्रिप्ट स्वतः चल जाएगी, इसके लिए Codex को याद रखने की आवश्यकता नहीं होगी।"

इस बातचीत ने मुझे सोचने पर मजबूर किया। मैंने PostToolUse हुक सेटअप किया, और उसके बाद से Codex जब भी कोई फ़ाइल बदलता है, फ़ॉर्मेटिंग स्वतः हो जाती है। मुझे दुबारा कभी मैन्युअल रूप से फ़ॉर्मेट नहीं करना पड़ा और न ही CI कभी विफल हुआ। इस लेख में हम नियमों और हुक्स को विस्तार से समझेंगे—कि ये क्या हैं, इन्हें कैसे लिखा और टेस्ट किया जाता है।

इस लेख को पढ़ने के बाद, आपको मिलेगा:

  • नियम और हुक्स क्या नियंत्रित करते हैं, और वे AGENTS.md की तुलना में "निश्चितता" कैसे प्रदान करते हैं।
  • नियम (.rules फ़ाइल + prefix_rule) कैसे लिखे जाते हैं ताकि किसी कमांड को "हमेशा स्वीकृत" या "ब्लॉक" किया जा सके, और codex execpolicy check द्वारा जाँच।
  • हुक्स को किन फ़ाइलों में कॉन्फ़िगर किया जाता है, और उनके स्टार्टअप के लिए कौन से "घटनाक्रम (events)" (PreToolUse / PostToolUse / Stop / SessionStart आदि) उपलब्ध हैं।
  • Codex हुक्स का सुरक्षा नियम—नया हुक डिफ़ॉल्ट रूप से क्यों ब्लॉक रहता है और इसके लिए /hooks से अनुमोदन आवश्यक है।
  • हुक और Codex के बीच डेटा का आदान-प्रदान (stdin JSON, exit codes, stdout JSON), और Claude Code से कुछ भिन्नताएँ।
  • दो उपयोगी उदाहरण: कोड बदलने पर स्वचालित फ़ॉर्मेटिंग, और हानिकारक कमांड्स को ब्लॉक करना; तथा हुक काम न करने पर समाधान।

⚠️ नीचे दी गई सभी विशिष्ट कमांड्स, कॉन्फ़िगरेशन विकल्प और डिफ़ॉल्ट मान Codex आधिकारिक दस्तावेज़ों (Hooks / Rules) पर आधारित हैं। नियम (Rules) अभी एक प्रयोगात्मक फ़ीचर है जो भविष्य में बदल सकता है


01 नियम "सुरक्षा सीमा" हैं, और हुक्स "ट्रिगर"

दोनों में अंतर स्पष्ट रूप से समझें:

  • नियम (Rules) यह तय करते हैं कि "क्या कोई कमांड सैंडबॉक्स से बाहर चलने के योग्य है"—यह एक सुरक्षा सीमा है जो प्रत्येक कमांड की जाँच करके "स्वीकृत / अनुमोदन आवश्यक / ब्लॉक" का निर्णय लेती है।
  • हुक्स (Hooks) यह तय करते हैं कि "कोडिंग प्रक्रिया के किसी विशिष्ट चरण पर स्वचालित रूप से कोई स्क्रिप्ट चलनी चाहिए"—यह एक ट्रिगर है जो विशिष्ट घटनाओं पर स्वतः सक्रिय होता है, Codex के निर्णय से स्वतंत्र।

तुलना: सोसायटी के सुरक्षा नियमों और लिफ्ट की ऑटो-लाइट से। सुरक्षा नियमों में लिखा होता है कि "किसे प्रवेश की अनुमति है, किसे रजिस्टर में लिखना होगा, और किसे ब्लॉक रखना है"—यह नियम है: जब भी कोई प्रवेश करेगा, गार्ड नियमों की जाँच करेगा। वहीं, लिफ्ट में लगी लाइट जो "किसी के प्रवेश करने पर स्वतः जल जाती है" वह हुक है: उसे इससे मतलब नहीं कि आप कौन हैं, "व्यक्ति के प्रवेश करने" की घटना पर लाइट स्वतः जल जाएगी। एक सुरक्षा जाँच है और दूसरा स्वचालित ट्रिगर

इनका AGENTS.md (लेख 11) से अंतर क्या है?

AGENTS.md में लिखे निर्देश अनुरोध हैं; जबकि नियम या हुक्स के रूप में जोड़े गए निर्देश गारंटी हैं।

सरल शब्दों में:

  • AGENTS.md में लिखना कि "कोड बदलने पर फ़ॉर्मेट करें" या "उत्पादन डेटा को न छुएं"—यह Codex के लिए अनुरोध है, जिसका यह पालन करने का प्रयास करता है, लेकिन वह भूल सकता है।
  • हुक द्वारा फ़ॉर्मेट करना या नियम द्वारा कमांड ब्लॉक करना—यह तय स्थिति पर हमेशा लागू होगा, Codex के याद रखने पर निर्भर नहीं।

कुछ उपयोगी उदाहरण:

  • "gh pr view कमांड का मैं अक्सर उपयोग करता हूँ, इसके लिए बार-बार पॉप-अप न दिखाया जाए"—नियम द्वारा इसके लिए "हमेशा स्वीकृत" का विकल्प सेट करें।
  • "rm -rf या git push --force जैसी कमांड्स को पूरी तरह ब्लॉक करना"—नियम द्वारा इन्हें स्थायी रूप से ब्लॉक करें।
  • "कोड बदलने पर स्वचालित रूप से फ़ॉर्मेटिंग/लिनटर चलाना"—हुक का उपयोग करें ताकि यह स्वतः हो सके।

💡 संक्षेप में: नियम कमांड्स को सैंडबॉक्स से बाहर चलाने की सुरक्षा सीमा है, और हुक विशिष्ट घटनाओं पर स्वचालित रूप से स्क्रिप्ट चलाने का ट्रिगर है; दोनों नियमों को निश्चितता प्रदान करते हैं।


02 नियम (Rules): विशिष्ट कमांड्स के लिए सुरक्षा सीमा सेट करना

⚠️ प्रयोगात्मक, बदलाव संभव।

सैंडबॉक्स सुरक्षा (लेख 15) एक सामान्य सीमा है—जहाँ सीमा से बाहर जाने पर अनुमोदन माँगा जाता है। लेकिन यदि आप विशिष्ट कमांड के स्तर पर बारीक नियंत्रण चाहते हैं: जैसे "कमांड gh pr view को बिना पूछे चलने की अनुमति हो" या "grep की जगह rg का उपयोग अनिवार्य हो"। इसके लिए नियमों का उपयोग किया जाता है।

तुलना: सुरक्षा गार्ड को दी गई विशिष्ट सूची से। सैंडबॉक्स सामान्य नियम है (जैसे "अपरिचितों से पूछताछ करें"), और नियम विशिष्ट सूची है: जिसमें लिखा होता है कि "इन विश्वसनीय व्यक्तियों को बिना पूछे प्रवेश दें" और "इन व्यक्तियों को सीधे ब्लॉक रखें"। यह सुरक्षा को अधिक सुदृढ़ बनाता है।

इसके उपयोग:

  • अक्सर उपयोग होने वाली विश्वसनीय कमांड्स (जैसे gh, make test) को व्हाइटलिस्ट करना ताकि बार-बार अनुमोदन न करना पड़े।
  • अप्रचलित या असुरक्षित कमांड्स (जैसे grep) को ब्लॉक करके बेहतर टूल्स (जैसे rg) का उपयोग सुनिश्चित करना।
  • गंभीर रूप से हानिकारक कमांड्स (जैसे rm -rf /) को ब्लॉक करना।

नियम फ़ाइल कहाँ होती है और कैसी दिखती है

नियम .rules फ़ाइलों में लिखे जाते हैं, जिन्हें संबंधित सेटिंग्स निर्देशिका के rules/ फ़ोल्डर में रखा जाता है। उदाहरण के लिए, उपयोगकर्ता स्तर पर ~/.codex/rules/default.rules। इसका सिंटैक्स Python जैसा होता है (वास्तव में Starlark भाषा है)।

एक सरल नियम का उदाहरण: "gh pr view कमांड चलाने से पहले हमेशा अनुमोदन माँगा जाए":

python
# gh pr view कमांड चलाने से पहले अनुमति माँगें
prefix_rule(
    # कमांड का उपसर्ग (प्रत्येक भाग अलग से)
    pattern = ["gh", "pr", "view"],

    # निर्णय: allow (स्वीकृत) / prompt (अनुमोदन आवश्यक) / forbidden (ब्लॉक)
    decision = "prompt",

    # विवरण
    justification = "PR देखने की अनुमति है, लेकिन अनुमोदन आवश्यक है",

    # परीक्षण उदाहरण
    match = [
        "gh pr view 7888",
        "gh pr view --repo openai/codex",
    ],
    not_match = [
        "gh pr --repo openai/codex view 7888",
    ],
)

prefix_rule के विकल्प:

विकल्पविवरणटिप्पणी
pattern (आवश्यक)कमांड का उपसर्ग (प्रत्येक भाग अलग से)यह विशिष्ट शब्द या शब्दों का समूह हो सकता है
decision (डिफ़ॉल्ट allow)मैच होने पर निर्णयallow / prompt / forbidden (सबसे सख्त की जीत)
justification (वैकल्पिक)नियम का कारणयह अनुमोदन स्क्रीन पर दिखाई दे सकता है
match / not_match (वैकलक)नियम का परीक्षण करने के लिएसिस्टम नियम लोड करते समय इसकी जाँच करता है

decision की प्राथमिकता तय है—सबसे सख्त नियम की जीत होती है (forbidden > prompt > allow):

decisionविवरण
allowसैंडबॉक्स से बाहर सीधे चलाने की अनुमति, बिना पूछे
promptचलाने से पहले हमेशा अनुमति माँगी जाएगी
forbiddenसीधे ब्लॉक करें, न पूछें और न चलाने दें

बदलाव करने के बाद Codex को रीस्टार्ट करना आवश्यक है। जब आप CLI में किसी कमांड को "हमेशा स्वीकृत" करते हैं, तो Codex उसे स्वतः ~/.codex/rules/default.rules में लिख देता है, इसलिए यह फ़ाइल समय के साथ स्वतः भी अपडेट होती है।

सुरक्षा डिज़ाइन: एक साथ लिखी कई कमांड्स को अलग-अलग जाँचना

यह सुरक्षा के लिए बहुत महत्वपूर्ण है। यदि कोई git add . && rm -rf / जैसी एक ही लाइन में कई कमांड्स लिखता है, तो Codex सुरक्षा सुनिश्चित करने के लिए इन्हें अलग-अलग भागों में तोड़कर जाँचता है, और सबसे सख्त नियम को लागू करता है:

text
["bash", "-lc", "git add . && rm -rf /"]

इसे दो स्वतंत्र कमांड्स में विभाजित किया जाएगा:

text
["git", "add", "."]
["rm", "-rf", "/"]

यहाँ लाभ यह है: भले ही आपने git add को allow किया हो, rm -rf / को अलग से ब्लॉक कर दिया जाएगा। इससे खतरनाक कमांड्स को सुरक्षा नियमों को बायपास करके चलाने से रोका जा सकता है।

लेकिन ध्यान रखें: केवल सामान्य क्रमिक कमांड्स ही विभाजित की जा सकती हैं। यदि कमांड में रीडायरेक्शन (>), वेरिएबल रिप्लेसमेंट ($(...)), पर्यावरण वेरिएबल या वाइल्डकार्ड (*) का उपयोग किया गया है, तो Codex उसे विभाजित नहीं कर पाएगा और उसे एक ही कमांड bash -lc के रूप में जाँचेगा। इसलिए इसे बहुत जटिल न बनाएं।

नियमों की जाँच: execpolicy check का उपयोग

बदलावों को सीधे लागू करने से पहले उनका परीक्षण करें:

bash
codex execpolicy check --pretty \
  --rules ~/.codex/rules/default.rules \
  -- gh pr view 7888 --json title,body,comments

यह JSON आउटपुट दिखाएगा कि इस कमांड पर क्या निर्णय लिया गया है और कौन सा नियम लागू हुआ है। नियमों को लागू करने से पहले इस प्रकार जाँच कर लेना सही रहता है ताकि कोई उपयोगी कमांड ब्लॉक न हो जाए।

💡 संक्षेप में: नियम .rules फ़ाइल में लिखे जाते हैं और कमांड उपसर्ग की जाँच करते हैं (सबसे सख्त निर्णय लागू होता है); जटिल कमांड्स को विभाजित करके जाँचा जाता है; बदलावों की जाँच के लिए codex execpolicy check का उपयोग करें।


03 हुक्स (Hooks): सक्रिय होने के समय (Events)

हुक्स किसी भी समय सक्रिय नहीं होते, बल्कि वे Codex कोडिंग प्रक्रिया की विशिष्ट घटनाओं (events) पर सक्रिय होते हैं। सही हुक चुनने के लिए इन घटनाओं को समझना आवश्यक है।

लेख 02 में हमने देखा था कि Codex का काम "विचार → क्रिया → परिणाम" चक्र में चलता है। हुक्स इसी चक्र के विभिन्न चरणों पर सक्रिय होते हैं:

हुक चक्र

यह आरेख दिखाता है: सत्र शुरू होने पर SessionStart, निर्देश सबमिट करने पर UserPromptSubmit, और टूल्स के उपयोग के समय PreToolUse (रन होने से पहले) और PostToolUse (रन होने के बाद) सक्रिय होते हैं। सत्र समाप्त होने पर Stop सक्रिय होता है।

चार सबसे महत्वपूर्ण घटनाक्रम जिनका अक्सर उपयोग किया जाता है:

घटनाविवरणउपयोग
PreToolUseटूल रन होने से पहलेखतरनाक कमांड्स को ब्लॉक करना या बदलना (कमांड रोक सकता है)
PostToolUseटूल रन होने के बादकोड बदलने पर फ़ॉर्मेटिंग या लिनटर चलाना
StopCodex द्वारा उत्तर देने के बादकाम की जाँच करना (जैसे टेस्ट पास न होने पर सुधार के लिए दुबारा कहना)
SessionStartसत्र शुरू या रीस्टार्ट होने परप्रोजेक्ट की वर्तमान स्थिति को संदर्भ में जोड़ना

एक और महत्वपूर्ण घटना PermissionRequest है (अनुमोदन पॉप-अप से पहले सक्रिय होती है), जिसके द्वारा आप स्वचालित रूप से अनुमति दे या अस्वीकार कर सकते हैं।

नाम में Pre और Post से अंतर समझें: Pre क्रिया से "पहले" है, इसलिए केवल यही क्रिया को रोकने में सक्षम है; Post क्रिया के "बाद" है, इसलिए यह क्रिया को रोक नहीं सकता, केवल उसके बाद आवश्यक सुधार (जैसे फ़ॉर्मेटिंग) कर सकता है।

यह प्रक्रिया इस आरेख में दिखाई गई है:

हुक लाइफसाइकिल

यह आरेख दिखाता है कि सत्र शुरू होने से लेकर समाप्त होने तक विभिन्न चरणों पर हुक्स कैसे जुड़े होते हैं, और घटना होने पर वे स्वतः ट्रिगर होते हैं।

Claude Code से अंतर: Codex में Stop या PostToolUse घटनाओं पर decision: "block" का अर्थ कार्य को अस्वीकार करना नहीं है, बल्कि "कार्य को दुबारा जाँचना / आगे बढ़ाना" है। यह प्रतिक्रिया को दुबारा मॉडल के पास भेज देता है ताकि वह सुधार कर सके।

💡 संक्षेप में: हुक्स विशिष्ट जीवनचक्र घटनाओं पर सक्रिय होते हैं; मुख्य घटनाक्रम PreToolUse (पहले), PostToolUse (बाद में), Stop (उत्तर के बाद) और SessionStart (शुरुआत) हैं।


04 हुक्स कहाँ लिखे जाते हैं, और matcher का उपयोग

हुक्स को कॉन्फ़िगर करने के स्थान और तरीके:

हुक्स कहाँ कॉन्फ़िगर करें

हुक्स को दो स्थानों पर लिखा जा सकता है: एक स्वतंत्र hooks.json फ़ाइल में, या config.toml के भीतर [hooks] तालिका में। पथ विवरण:

फ़ाइल का स्थानप्रभावटीम के साथ साझा करना
~/.codex/hooks.jsonसभी प्रोजेक्ट्स परनहीं, केवल स्थानीय मशीन पर
~/.codex/config.tomlसभी प्रोजेक्ट्स परनहीं
<repo>/.codex/hooks.jsonकेवल वर्तमान प्रोजेक्ट परहाँ, Git में शामिल कर सकते हैं
<repo>/.codex/config.tomlकेवल वर्तमान प्रोजेक्ट परहाँ

नियम पहले जैसा ही है: पूरी टीम के लिए उपयोगी हुक्स को प्रोजेक्ट के .codex/ फ़ोल्डर में लिखें; व्यक्तिगत हुक्स को होम निर्देशिका ~/.codex/ में लिखें।

  • विभिन्न फ़ाइलों में लिखे गए हुक्स आपस में जुड़ जाते हैं और एक साथ चलते हैं।
  • एक ही स्थान पर hooks.json और config.toml दोनों में हुक्स न लिखें, इससे एरर आ सकता है।
  • प्रोजेक्ट स्तर के हुक्स केवल तभी लोड होते हैं जब प्रोजेक्ट पर भरोसा (Trust) किया गया हो।

हुक कॉन्फ़िगरेशन का उदाहरण

प्रोजेक्ट के .codex/hooks.json में लिखने का उदाहरण: "जब भी Codex कोई Bash कमांड चलाए, उसके बाद एक स्क्रिप्ट चले":

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use.py\"",
            "timeout": 30,
            "statusMessage": "Bash आउटपुट की समीक्षा"
          }
        ]
      }
    ]
  }
}

ढांचा तीन स्तरों में विभाजित है:

  1. "PostToolUse"—घटना (टूल रन होने के बाद)।
  2. "matcher": "Bash"—यह तय करना कि केवल Bash टूल के लिए ही यह सक्रिय हो।
  3. hooks सूची—चलने वाली स्क्रिप्ट: "type": "command" दर्शाता है कि यह एक कमांड है, और "command" उसका पथ है।

ध्यान रखने योग्य बातें:

  • timeout का मान सेकंड में होता है; न लिखने पर डिफ़ॉल्ट मान 600 सेकंड होता है।
  • अभी केवल "type": "command" प्रकार के हुक्स ही समर्थित हैं; अन्य को छोड़ दिया जाता है।
  • एक ही घटना पर कई हुक्स होने पर वे समानांतर में चलते हैं, एक हुक दूसरे को चलने से नहीं रोक सकता।
  • स्क्रिप्ट का पथ सेट करते समय वर्तमान वर्किंग निर्देशिका का ध्यान रखें—सुरक्षा के लिए $(git rev-parse --show-toplevel) द्वारा Git रूट से पूर्ण पथ लिखना सही रहता है (जैसा ऊपर उदाहरण में किया गया है)।
  • Windows के लिए आप command_windows विकल्प का उपयोग करके अलग कमांड लिख सकते हैं।

Claude Code से अंतर: Codex में timeout सेकंड में होता है (वहाँ मिलीसेकंड में होता है), और यहाँ disableAllHooks जैसा कोई सीधा विकल्प नहीं होता (हुक्स बंद करने के लिए [features] hooks = false लिखना होता है)।

config.toml में इसे लिखने का तरीका:

toml
[[hooks.PostToolUse]]
matcher = "^Bash$"

[[hooks.PostToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use.py"'
timeout = 30
statusMessage = "Bash आउटपुट की समीक्षा"

matcher: हुक को सीमित करना

matcher विकल्प यह नियंत्रित करता है कि हुक कब सक्रिय हो। यदि यह विकल्प नहीं लिखा जाता, तो हुक घटना होने पर हमेशा चलेगा; इसका उपयोग करके आप इसे विशिष्ट टूल्स तक सीमित रख सकते हैं।

तुलना: सुरक्षा कैमरे के मोशन डिटेक्टर से। यदि कैमरा पूरे हॉल की हलचल पर अलार्म बजाएगा, तो अनावश्यक अलार्म बजेंगे। आप मोशन डिटेक्शन को केवल "दरवाज़े के पास" सीमित करना चाहते हैं। matcher भी यही सीमा तय करता है।

Codex में matcher रेगुलर एक्सप्रेशन (regex) होता है। टूल घटनाओं (PreToolUse/PostToolUse) के लिए यह टूल के नाम की जाँच करता है। उदाहरण:

matcher मानविवरणउदाहरण
"Bash"केवल Bash टूल के लिएBash कमांड चलने पर सक्रिय
"^apply_patch$"फ़ाइल में बदलाव करने वाले टूल के लिएफ़ाइल संपादन पर सक्रिय
"Edit|Write"संपादन के अन्य नामफ़ाइल संपादन पर सक्रिय
"mcp__filesystem__.*"MCP फ़ाइल सिस्टम टूल्स के लिएसंबंधित MCP टूल रन होने पर
* या खाली छोड़नासभी टूल्स के लिएघटना होने पर हमेशा सक्रिय

ध्यान दें:

  • फ़ाइल संपादन टूल का मूल नाम apply_patch है। आप matcher में Edit या apply_patch का उपयोग कर सकते हैं, लेकिन स्क्रिप्ट में डेटा प्राप्त करते समय टूल का नाम हमेशा apply_patch ही दिखाई देगा।
  • सभी घटनाओं के लिए matcher काम नहीं करता। UserPromptSubmit और Stop के लिए इसका उपयोग नहीं किया जा सकता क्योंकि वे किसी टूल से संबंधित नहीं हैं, वे हमेशा सक्रिय होते हैं।
  • PreToolUse सभी प्रकार की कमांड्स को ब्लॉक नहीं कर सकता, यह केवल साधारण shell, apply_patch और MCP टूल्स पर ही काम करता है। इसलिए इसे सुरक्षा की एकमात्र परत न मानें।

💡 संक्षेप में: हुक्स को hooks.json या config.toml में लिखा जाता है; matcher Regular Expression का उपयोग करके इसे विशिष्ट टूल्स तक सीमित रखता है; timeout सेकंड में होता है।


05 सुरक्षा नियम: नया हुक स्टार्टअप पर ब्लॉक क्यों रहता है

यह Codex हुक्स की एक महत्वपूर्ण विशेषता है जो Claude Code से अलग है: जब आप कोई नया हुक लिखते हैं या पुराना बदलते हैं, तो वह डिफ़ॉल्ट रूप से सक्रिय नहीं होता—सुरक्षा कारणों से Codex उसे ब्लॉक रखता है।

चूँकि हुक आपकी मशीन पर आपके विशेषाधिकारों के साथ कोई भी कमांड चला सकते हैं, यदि किसी अपरिचित रिपोजिटरी में कोई हानिकारक हुक छिपा हो, तो वह मशीन को नुकसान पहुँचा सकता है। इसलिए सुरक्षा सुनिश्चित करने के लिए यह व्यवस्था की गई है।

तुलना: नए ऐप को अनुमति देने से। जब आप फोन में कोई ऐप इंस्टॉल करते हैं, तो क्रेडेंशियल्स या कैमरे के उपयोग के लिए अनुमति पॉप-अप दिखाई देता है, जब तक आप अनुमति नहीं देते वह काम नहीं कर सकता।

सुरक्षा नियम:

  • Codex हुक फ़ाइल के हैश (Hash) के आधार पर सुरक्षा स्थिति याद रखता है। नया हुक लिखने या उसमें एक भी अक्षर बदलने पर हैश बदल जाता है, और Codex उसे "समीक्षा आवश्यक" मानकर ब्लॉक कर देता है।
  • जुड़े हुए हुक्स की समीक्षा करने और उन्हें सक्रिय (trust) करने के लिए /hooks स्लैश कमांड का उपयोग करें।
  • यदि स्टार्टअप पर कोई हुक बिना अनुमति के ब्लॉक है, तो स्क्रीन पर चेतावनी दिखाई देगी।

कस्टम हुक लिखने के बाद Codex शुरू करें → /hooks चलाएं → हुक की जाँच करें और उसे अनुमति (trust) दें। इसके बाद ही वह सक्रिय होगा।

text
/hooks

एक इंटरफ़ेस खुलेगा जहाँ आप सभी हुक्स देख सकते हैं, और उन्हें अनुमति दे सकते हैं। सिस्टम द्वारा प्रबंधित (managed) हुक्स को आप यहाँ से बंद नहीं कर सकते क्योंकि वे एडमिनिस्ट्रेटर नियमों द्वारा लागू होते हैं।

परीक्षण या स्वचालित वातावरण (CI) के लिए आप --dangerously-bypass-hook-trust फ़्लैग का उपयोग करके सुरक्षा जाँच को बायपास कर सकते हैं, लेकिन स्थानीय मशीन पर ऐसा करने से बचें।

💡 संक्षेप में: सुरक्षा के लिए नए या बदले गए हुक्स ब्लॉक रहते हैं; उन्हें सक्रिय करने के लिए /hooks स्लैश कमांड चलाकर अनुमति देना आवश्यक है।


06 हुक और Codex के बीच डेटा का आदान-प्रदान: stdin, exit code, stdout

यह समझना आवश्यक है कि हुक स्क्रिप्ट Codex के साथ कैसे बातचीत करती है।

बातचीत तीन माध्यमों से होती है: Codex इनपुट डेटा stdin द्वारा भेजता है → स्क्रिप्ट काम करती है → स्क्रिप्ट exit code और stdout द्वारा परिणाम वापस देती है

इनपुट: JSON डेटा प्राप्त करना

जब हुक सक्रिय होता है, तो Codex संबंधित विवरण को JSON फॉर्मेट में stdin द्वारा भेजता है। इसके मुख्य विकल्प:

फ़ील्डविवरण
session_idसत्र आईडी
cwdकार्य निर्देशिका
hook_event_nameघटना का नाम
transcript_pathसत्र इतिहास का पथ
modelसत्र में सक्रिय मॉडल
permission_modeसुरक्षा स्तर

टूल आधारित घटनाओं में tool_name (जैसे "Bash") और tool_input (कमांड विवरण) भी शामिल होते हैं। उदाहरण:

json
{
  "session_id": "abc123",
  "cwd": "/Users/sarah/myproject",
  "hook_event_name": "PreToolUse",
  "tool_name": "Bash",
  "tool_input": {
    "command": "rm -rf /tmp/x"
  }
}

आपकी स्क्रिप्ट इस JSON से tool_input.command को पढ़कर जाँच कर सकती है कि कमांड सुरक्षित है या नहीं।

आउटपुट: exit code द्वारा नियंत्रण

काम होने के बाद, स्क्रिप्ट exit code द्वारा Codex को निर्देश देती है:

exit codeविवरण
0सामान्य—क्रिया जारी रखने की अनुमति
2विशेष निर्देश (रोकना / प्रतिक्रिया देना)

exit 2 का प्रभाव घटना के अनुसार बदलता है:

  • PreToolUse / UserPromptSubmit में: यह क्रिया या निर्देश को ब्लॉक (रोक) कर देता है, और एरर विवरण को stderr से Codex में भेजता है।
  • PostToolUse / Stop में: यह क्रिया को रोक नहीं सकता (चूँकि वह पहले ही हो चुकी है), बल्कि यह विवरण को सुधार के लिए मॉडल के पास वापस भेज देता है (चक्र आगे बढ़ाता है)।

यानी रोकने का काम केवल Pre घटनाओं में ही हो सकता है।

stdout द्वारा JSON परिणाम देना

अधिक नियंत्रण के लिए आप exit 0 सेट करके stdout पर JSON आउटपुट दे सकते हैं। उदाहरण:

1. PreToolUse में कमांड ब्लॉक करनाpermissionDecision: "deny" देना:

json
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "सुरक्षा कारणों से इस कमांड को ब्लॉक किया गया है"
  }
}

2. SessionStart में संदर्भ जोड़नाadditionalContext देना:

json
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "इस प्रोजेक्ट के नियमों का पालन करें।"
  }
}

ध्यान दें:

  • PreToolUse में stdout पर सामान्य टेक्स्ट लिखने से कोई प्रभाव नहीं होगा; संदर्भ के लिए JSON फॉर्मेट में additionalContext का उपयोग करें।
  • SessionStart और UserPromptSubmit में सामान्य टेक्स्ट का उपयोग किया जा सकता है; जबकि Stop में हमेशा JSON फॉर्मेट आवश्यक है।
  • PreToolUse में continue फ़ील्ड काम नहीं करती, ब्लॉक करने के लिए हमेशा permissionDecision या exit 2 का उपयोग करें।

💡 संक्षेप में: हुक Codex से stdin द्वारा JSON प्राप्त करता है, और exit code तथा stdout द्वारा परिणाम वापस देता है; exit 2 क्रिया को रोकने या प्रतिक्रिया देने के लिए है।


07 कोडिंग उदाहरण

दैनिक उपयोग के दो कोडिंग उदाहरण:

उदाहरण 1: कोड बदलने पर स्वचालित फ़ॉर्मेटिंग (PostToolUse)

यह सबसे उपयोगी हुक है जो कोडिंग शैली (Formatting) को स्वचालित रखता है।

चरण 1: .codex/hooks/format.py स्क्रिप्ट बनाएं (यह कोड बदलने पर फ़ॉर्मेटिंग कमांड चलाएगी):

python
#!/usr/bin/env python3
import json, subprocess, sys

data = json.load(sys.stdin)
# प्रोजेक्ट निर्देशिका में Ruff फ़ॉर्मेटर चलाना
subprocess.run(["ruff", "format", "."])

चरण 2: प्रोजेक्ट के .codex/hooks.json में इसे पंजीकृत करें, और apply_patch (फ़ाइल बदलाव) के साथ जोड़ें:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/format.py\"",
            "timeout": 30,
            "statusMessage": "कोड फ़ॉर्मेट करना"
          }
        ]
      }
    ]
  }
}

चरण 3: Codex शुरू करें और /hooks चलाकर इसे अनुमति (trust) दें। अब जब भी Codex कोई फ़ाइल बदलेगा, फ़ॉर्मेटिंग स्वतः हो जाएगी। आप ruff की जगह prettier या gofmt का भी उपयोग कर सकते हैं।

उदाहरण 2: खतरनाक कमांड्स को ब्लॉक करना (PreToolUse)

यह सुरक्षा के लिए उपयोगी है।

चरण 1: .codex/hooks/block-dangerous.py स्क्रिप्ट बनाएं:

python
#!/usr/bin/env python3
import json, sys

data = json.load(sys.stdin)
command = data.get("tool_input", {}).get("command", "")

if "rm -rf" in command:
    print("Block: rm -rf कमांड प्रतिबंधित है", file=sys.stderr) # एरर संदेश
    sys.exit(2)                                                 # ब्लॉक करने के लिए exit 2

sys.exit(0) # अन्य कमांड्स को सामान्य रूप से चलने दें

चरण 2: .codex/hooks.json में Bash टूल के साथ जोड़ें:

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/block-dangerous.py\"",
            "statusMessage": "कमांड की सुरक्षा जाँच"
          }
        ]
      }
    ]
  }
}

चरण 3: /hooks से अनुमति दें। अब यदि Codex rm -rf कमांड चलाने का प्रयास करेगा, तो हुक उसे ब्लॉक कर देगा।

नियम: साधारण कमांड प्रतिबंधों के लिए नियमों (Rules) का उपयोग करें, और जटिल तार्किक जाँच के लिए हुक्स (Hooks) का उपयोग करें।

💡 संक्षेप में: उदाहरणों में फ़ॉर्मेटिंग के लिए PostToolUse और ब्लॉक करने के लिए PreToolUse (exit 2 के साथ) का उपयोग किया जाता है; इन्हें कॉन्फ़िगर करने के बाद /hooks से सक्रिय करना आवश्यक है।


08 अभ्यास: सरल हुक बनाना और चलाना

आइए एक सरल हुक बनाने और उसे चलाने का अभ्यास करें—जो Codex द्वारा Bash कमांड चलाने पर उसे एक लॉग फ़ाइल में नोट करेगा। यह पूरी तरह सुरक्षित अभ्यास है।

Windows उपयोगकर्ताओं के लिए: Python पथ का ध्यान रखें और Git Bash या WSL का उपयोग करें। अभ्यास से पहले प्रोजेक्ट में git init चला लें ताकि Git रूट का पथ मिल सके।

चरण 1: स्क्रिप्ट और कॉन्फ़िगरेशन फ़ाइलें बनाएं

.codex/hooks/log-bash.py फ़ाइल बनाएं और यह लिखें:

python
#!/usr/bin/env python3
import json, sys, os

data = json.load(sys.stdin)
command = data.get("tool_input", {}).get("command", "")
log = os.path.expanduser("~/codex-bash-log.txt")
with open(log, "a") as f:
    f.write(command + "\n")

.codex/hooks.json फ़ाइल बनाएं और यह लिखें:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/log-bash.py\"",
            "statusMessage": "Bash कमांड लॉग करना"
          }
        ]
      }
    ]
  }
}

चरण 2: Codex शुरू करें और हुक को अनुमति दें

bash
codex

चैट में चलाएं:

text
/hooks

सूची में आपको नया हुक दिखाई देगा, उस पर जाकर उसे अनुमति (trust) दें।

चरण 3: एक कमांड चलाएं

इसे एक सरल कमांड चलाने के लिए कहें:

text
कृपया वर्तमान निर्देशिका की फ़ाइलें देखने के लिए ls चलाएं।

कमांड चलने पर हुक सक्रिय होगा।

चरण 4: लॉग फ़ाइल की जाँच करें

सत्र से बाहर आकर टर्मिनल में देखें:

bash
cat ~/codex-bash-log.txt

(Windows पर type ~/codex-bash-log.txt चलाएं)

अपेक्षित परिणाम: फ़ाइल में आपको चलाई गई ls कमांड दिखाई देगी। यह दर्शाता है कि हुक ने अपना काम किया है।

चरण 5: हटाना (वैकल्पिक)

अभ्यास के बाद .codex/hooks.json से हुक सेटिंग्स हटा दें और लॉग फ़ाइल डिलीट कर दें।

💡 संक्षेप में: अभ्यास के चरण हैं—स्क्रीप्ट और कॉन्फ़िगरेशन फ़ाइलें बनाना → /hooks से अनुमति देना → टूल रन करना → लॉग फ़ाइल की जाँच करना


09 समस्या निवारण (Troubleshooting)

यदि हुक काम नहीं कर रहा है, तो निम्नलिखित की जाँच करें:

समस्यासमाधान
हुक सक्रिय नहीं हो रहा① क्या आपने /hooks में इसे अनुमति (trust) दी है? (यह सबसे आम कारण है); ② क्या स्क्रिप्ट बदलने के बाद दुबारा अनुमति दी है? ③ क्या घटना या matcher नाम सही है?
हुक सूची में दिखाई नहीं दे रहा① JSON प्रारूप की जाँच करें (यहाँ अंतिम कॉमा या टिप्पणियाँ मान्य नहीं हैं); ② फ़ाइल का पथ और नाम जाँचें; ③ क्या एक ही स्तर पर config.toml और hooks.json दोनों में हुक्स लिखे हैं?
कमांड नॉट फाउंड एररस्क्रिप्ट का पथ सही नहीं है। $(git rev-parse --show-toplevel) द्वारा हमेशा पूर्ण पथ का उपयोग करें,相对 (relative) पथ से बचें।
ब्लॉक करने की कोशिश विफल हुई① क्या आपने PreToolUse घटना का उपयोग किया है? Post ब्लॉक नहीं कर सकता; ② क्या स्क्रिप्ट में exit 2 या permissionDecision: "deny" दिया है?
हुक टाइमआउट एररtimeout मान सेकंड में होता है। यदि काम बड़ा है तो टाइमआउट बढ़ाएं।

परीक्षण के लिए आप सीधे कमांड लाइन पर डेटा पास करके स्क्रिप्ट की जाँच कर सकते हैं:

bash
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /tmp/x"}}' | python3 .codex/hooks/block-dangerous.py
echo $?   # exit code की जाँच करें: ब्लॉक होने पर 2 आना चाहिए

हुक्स को पूरी तरह अक्षम करने के लिए config.toml में यह लिखें:

toml
[features]
hooks = false

💡 संक्षेप में: हुक काम न करने पर सबसे पहले /hooks अनुमति की जाँच करें, पथ की जाँच करें, और रेगुलर एक्सप्रेशन (regex) की पुष्टि करें।


10 सारांश

इस लेख में हमने नियमों (Rules) और हुक्स (Hooks) को समझा है—कि ये किस प्रकार कोडिंग गतिविधियों को नियंत्रित और स्वचालित करते हैं।

मुख्य बिंदुओं का सारांश:

विषयसाधनमुख्य बिंदु
कमांड नियंत्रणनियम prefix_ruleallow/prompt/forbidden (सबसे सख्त की जीत); execpolicy check द्वारा जाँच
हुक सक्रिय होने का समयघटनाक्रम (Events)Pre (क्रिया से पहले, ब्लॉक करने में सक्षम), Post (क्रिया के बाद), Stop, SessionStart
हुक फ़ाइलhooks.json / config.tomlतीन स्तर: घटना + matcher + क्रिया; timeout सेकंड में
सुरक्षा सक्रियण/hooksनया हुक डिफ़ॉल्ट रूप से ब्लॉक रहता है, अनुमति (trust) आवश्यक है
डेटा विनिमयstdin / exit code / stdoutJSON डेटा; exit 2 द्वारा नियंत्रण

अब आप यह कर सकते हैं: नियमों और हुक्स के उद्देश्यों को समझाना, नियम फ़ाइल लिखना, घटना चक्र को समझना, hooks.json में हुक कॉन्फ़िगर करना और /hooks से सक्रिय करना, और समस्याओं को हल करना। यह क्षमता आपके कोडिंग वातावरण को अधिक सुरक्षित और स्वचालित बनाती है।


अगला लेख [25 Worktrees समानांतर काम]—अब तक आप एक समय में एक ही Codex सत्र चला रहे थे। लेकिन बड़े प्रोजेक्ट्स में काम करते समय, आप चाहेंगे कि एक सत्र में बग ठीक हो और दूसरे में नया फ़ीचर बने, बिना किसी फ़ाइल टकराव के। अगले लेख में हम Git worktree का उपयोग करके कार्यों को पृथक रखना सीखेंगे।


अनुशंसित पठन