Skip to content

القواعد والخطافات (Rules & Hooks): إعداد نقاط التحقق ومفاتيح التشغيل التلقائي لـ Codex

📚 التنقل في السلسلة: المقال السابق [23 · الإضافات (Plugins)] علمك كيفية تثبيت حزم من القدرات المجهزة لـ Codex بضغطة زر. يناقش هذا المقال فكرتين أكثر عمقاً وأهمية للتحكم بالعمليات - القواعد (Rules) وتختص بـ "تحديد الأوامر البرمجية المسموح لها بالخروج والعمل خارج بيئة المعزل"، والخطافات (Hooks) وتختص بـ "تشغيل سكربت معين تلقائياً عند وصول المساعد لنقطة محددة في سير عمله". تمثل القواعد البوابة الأمنية، وتمثل الخطافات مفتاح التشغيل التلقائي، وبتهيئتها تتخلص من عناء متابعة المهام المتكررة وكتابتها يدوياً. المقال التالي [25 · فروع العمل المتوازية (Worktrees)] سيتحدث عن كيفية تشغيل مهام Codex متعددة بالتوازي ودون تداخل.

أعرض عليكم أولاً حواراً واقعياً دار بيني وبين زميلي في العمل الشهر الماضي أثناء تتبع مشكلة تكرار فشل اختبارات التكامل المستمر (CI):

أنا: "قمت هذا الأسبوع بتعديل الكود باستخدام Codex عدة مرات، ونسيت تشغيل أمر ruff format يدوياً بعد التعديل ما لا يقل عن عشر مرات." الزميل: "ألم تكتب في ملف CLAUDE.md أو AGENTS.md إرشاداً ينص على 'تذكر تشغيل التنسيق بعد التعديل'؟" أنا: "كتبت ذلك بالفعل. ولكنه ينسى تشغيل التنسيق مرة من كل ثلاث مرات تقريباً - فالكتابة في ملف الإرشادات تمثل رجاءً، وليست ضماناً حتمياً. ونسيانه لمرة واحدة يعني رفض اختبارات CI وإجبارنا على إعادة فحص وتنسيق الكود يدوياً." الزميل: "لماذا لا تستخدم خطافاً (hook)؟ بمجرد تفعيل الحدث المناسب، سيعمل سكربت التنسيق حتماً، ولن يؤثر نسيان المساعد على النتيجة."

كانت هذه الجملة بمثابة الحل. عدت فوراً وقمت بتهيئة خطاف PostToolUse أمني، ومنذ ذلك اليوم، بمجرد قيام Codex بتعديل أي ملف، يتم تشغيل التنسيق التلقائي فوراً، ولم أضطر لتشغيل التنسيق يدوياً مجدداً، كما تخلصنا من رفض اختبارات CI بسبب التنسيق. يشرح هذا المقال القواعد والخطافات بالتفصيل - ما هي، كيف تكتب، وكيف يتم اختبارها وتفعيلها.

بقراءة هذا المقال، ستحصل على:

  • التمييز بين وظيفة القواعد والخطافات، ولماذا توفر ضمانة حتمية لا يوفرها ملف AGENTS.md
  • كيفية كتابة القواعد (ملفات .rules ودالة prefix_rule) للسماح التلقائي بأوامر معينة أو حظرها بالكامل، والاستعانة بأمر codex execpolicy check لاختبار سلامة القواعد قبل تطبيقها
  • ملفات تهيئة الخطافات، والتعرف على أحداث دورة حياة Codex المتاحة للربط (مثل PreToolUse و PostToolUse و Stop و SessionStart)
  • آلية تأكيد الثقة بالخطافات الخاصة بـ Codex - لماذا يُمنع تشغيل الخطافات الجديدة تلقائياً، وكيف تقوم بمراجعتها والموافقة عليها باستخدام أمر /hooks
  • كيفية تفاعل الخطاف مع Codex (عبر قراءة نصوص JSON من stdin، استخدام رموز الخروج exit codes، وإرسال مخرجات JSON عبر stdout)، والفروق الهامة عن أسلوب Claude Code
  • مثالين عمليين جاهزين للنقل: التنسيق التلقائي للملفات بعد التعديل، وحظر الأوامر عالية الخطورة؛ مع خطوات تتبع وحل مشاكل عدم تفعيل الخطافات

⚠️ جميع الأوامر والخيارات والقيم الافتراضية المذكورة أدناه تستند للوثائق الرسمية لـ Codex. وتعتبر ميزة القواعد (Rules) حالياً ميزة تجريبية قد تتغير، لذا اعتمد على ما يظهر لديك محلياً عند التشغيل.


01 وظيفة القواعد والخطافات

نبدأ بتحديد دور كل مكون بوضوح نظراً للبس الشائع في المسميات للمبتدئين:

  • القواعد (Rules): تختص بتحديد صلاحية تشغيل الأمر المحدد خارج بيئة المعزل. فهي تمثل البوابة الأمنية التي تفحص الأمر المطلوب وتتخذ قراراً بـ (السماح التلقائي / طلب الإذن / أو الحظر الفوري) بناءً على الشروط المكتوبة.
  • الخطافات (Hooks): تختص بـ تشغيل سكربت أو أداة معينة تلقائياً عند وصول المساعد لنقطة محددة في سير عمله. فهي تمثل مفتاح التشغيل التلقائي المرتبط بأحداث محددة، ويعمل السكربت بمجرد وقوع الحدث بصرف النظر عن تقدير أو ذاكرة Codex.

تشبيه: بوابة الدخول ونظام الإضاءة التلقائي لمدخل المبنى. تمثل البوابة الأمنية لوحة القواعد: حيث تحتوي على قائمة بالأسماء المسموح لها بالدخول تلقائياً، والأسماء التي تتطلب التحقق وتدوين البيانات، والأسماء المحظورة من الدخول؛ ويقوم النظام بفحص هوية القادم ومطابقتها مع القائمة لاتخاذ القرار. بينما يمثل نظام الإضاءة التلقائي الخطاف: فهو لا يهتم بهوية القادم أو وجهته، ويكتفي برصد حدث "مرور شخص من الممر" لتشغيل الإضاءة تلقائياً. فالأول يختص بـ فحص الصلاحيات والاستحقاق، والثاني يختص بـ الاستجابة التلقائية للأحداث - وتجنب خلط وظائفهما.

ما هو وجه الاختلاف بينهما وبين القواعد المكتوبة في ملف AGENTS.md (مشروع دليل العمل الموضح في المقال 11)؟ يكمن الاختلاف في مستوى الحتمية والضمان:

تمثل النصوص المكتوبة في ملف AGENTS.md رجاءً وتوجيهاً؛ بينما تمثل القواعد والخطافات المكتوبة ضماناً حتمياً.

بمعنى بسيط:

  • عندما تكتب في ملف AGENTS.md "تذكر تشغيل التنسيق بعد التعديل" أو "يحظر استخدام الأوامر الحساسة" - فكأنك تطلب من Codex الالتزام بالتعليمات، وغالباً ما يلتزم بها، ولكنه يظل خاضعاً لتقديره الشخصي مما يفتح المجال للنسيان والخطأ.
  • وعند تهيئة خطاف للتنسيق أو قاعدة لحظر أمر معين - فبمجرد تحقق الشرط المكتوب، يتم تنفيذ العملية حتمياً (أو حظر الأمر فوراً) دون تدخل أو خيار للمساعد.

ولهذا نلجأ لإعداد القواعد والخطافات للمهام الحساسة التي تتطلب ضماناً تاماً:

  • عند استخدام أمر الاستعلام عن PRs باستمرار gh pr view والرغبة في تفادي ظهور نافذة الموافقة في كل مرة - نكتب قاعدة للسماح التلقائي بالأمر.
  • عند الرغبة في حظر استخدام أوامر الحذف الكلي مثل rm -rf أو الرفع الإجباري git push --force بشكل تام - نكتب قاعدة أو خطافاً لحظرها حتمياً.
  • عند الرغبة في تنسيق الكود أو فحص الأخطاء تلقائياً بعد كل تعديل - نكتب خطافاً لتشغيل الفحص دون انتظار طلب يدوي.

💡 ملخص في جملة واحدة: تمثل القاعدة بوابة لتحديد صلاحية تشغيل الأوامر، ويمثل الخطاف مفتاح تشغيل تلقائي لسكربتاتك عند وقوع أحداث محددة؛ وتكمن قيمتهما في تحويل إرشادات ملف AGENTS.md الاختيارية إلى ضمانات حتمية.


02 القواعد (Rules): كتابة شروط تشغيل الأوامر

⚠️ ميزة تجريبية. تمثل القواعد ميزة تجريبية في Codex، وتعتمد الخيارات والشروط على التحديثات الحالية للبرنامج.

نوضح أولاً المشاكل التي تعالجها القواعد. شرحنا في المقال 15 أن بيئة المعزل تحدد حدوداً عامة وصارمة - فإما أن تسمح بالعمل خارجها أو تحظره بالكامل. ولكن في بعض الأحيان قد تحتاج لتحكم دقيق ومحدد بكل أمر: مثل السماح بأمر عرض تفاصيل PR gh pr view تلقائياً لتسهيل العمل، وحظر أمر البحث المعتاد grep لإجبار المطورين على استخدام الأداة الأسرع rg. وتوسيع صلاحيات بيئة المعزل بالكامل لحل مثل هذه التفاصيل يعد إجراءً خاطئاً، وتكون كتابة قاعدة محددة للأمر هي الحل الأنسب.

تشبيه: منح حارس الأمن ورقة تعليمات خاصة. يمثل المعزل قاعدة العمل العامة للحارس (مثل "يمنع دخول أي شخص غريب دون تسجيل")، وتمثل القواعد ورقتين إضافيتين تمنحهما له: الأولى تحتوي على أسماء موظفين مسموح بدخولهم مباشرة دون أسئلة، والثانية تحتوي على أسماء أشخاص يمنع دخولهم نهائياً. ويسهل اتباع هذه الورقتين عمل الحارس ويحمي خصوصية المبنى مقارنة بإلغاء نظام الأمن بالكامل.

أهم حالات استخدام القواعد:

  • السماح التلقائي بالتشغيل للأوامر المتكررة والآمنة مثل أوامر Git المشتركة أو أوامر الفحص make test لتجنب كثرة نوافذ الموافقة.
  • حظر الأوامر القديمة أو غير المستحبة في العمل لحث المطورين على البدء في استخدام الأدوات الحديثة (مثل حظر find وتوجيههم لـ fd).
  • فرض قيود أمنية صارمة للشركة مثل حظر الوصول لملفات الخصوصية أو مفاتيح SSH تلقائياً ومنع تجاوز الحدود الأمنية.

مسار حفظ ملفات القواعد وتنسيقها

تكتب القواعد داخل ملفات تنتهي بالامتداد .rules، ويتم حفظ هذه الملفات داخل مجلد فرعي يسمى rules/ بجانب ملفات التكوين المعتمدة، مثل ملف القواعد العام للمستخدم في المسار ~/.codex/rules/default.rules. وتكتب القواعد بلغة Starlark (وهي لغة برمجية مبسطة تشبه بايثون، وتتميز بالأمان وتمنع التفاعل العشوائي مع نظام الملفات على جهازك).

إليك مثالاً مبسطاً لكتابة قاعدة - "السماح التلقائي بالاستعلام عن PRs":

python
# قاعدة لتسهيل الاستعلام عن PRs تلقائياً.
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 (إلزامي)تحديد أجزاء الأمر المستهدف بالترتيبيقبل كتابة الكلمات المباشرة أو استخدام مصفوفة خيارات مثل ["view", "list"]
decision (اختياري)الإجراء المطلوب عند مطابقة الأمرالخيارات المتاحة: allow / prompt / forbidden
justification (اختياري)شرح سبب فرض القاعدةيظهر للمستخدم في واجهات التنبيه أو الرفض
match / not_match (اختياري)كتابة أمثلة لاختبار سلامة القاعدةيقوم Codex بتشغيلها عند التحميل لضمان دقة عمل الشروط

وعند مطابقة عدة خيارات للأمر، يطبق المساعد الإجراء الأكثر صرامة وأماناً دائماً (الترتيب: forbidden > prompt > allow):

خيار الإجراءالنتيجة المترتبة
allowالسماح بتشغيل الأمر خارج بيئة المعزل مباشرة ودون نوافذ إذن
promptالتوقف وطلب إذن المطور صراحة قبل بدء تشغيل الأمر
forbiddenمنع وحظر تشغيل الأمر نهائياً وإعلام المطور بذلك

وتذكر إعادة تشغيل برنامج Codex بعد تعديل ملفات القواعد لتطبيق الشروط الجديدة. ونشير لخاصية هامة: عند قيامك بالموافقة على أمر معين خارج بيئة المعزل من واجهة CLI واختيار خيار "السماح دائماً"، يقوم Codex بكتابة هذا الإذن تلقائياً في ملف القواعد العام ~/.codex/rules/default.rules لتسهيل العمل مستقبلاً دون كتابة يدوية.

معالجة الأوامر المتعددة وحظر محاولات التجاوز أمنياً

نوضح هنا ركيزة أمنية هامة قمنا بالإشارة إليها في المقال 15. عند قيام المساعد بمحاولة دمج عدة أوامر في سطر واحد (مثل git add . && rm -rf /): يقوم Codex بالاستعانة بمحرك التحليل البرمجي tree-sitter لتفكيك السطر والتحقق من صلاحية كل أمر بشكل مستقل، ويطبق الإجراء الأكثر صرامة عليها بالكامل لمنع التجاوز:

الأمر المطلوب:

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

يقوم النظام بتحليله وفحصه كأمرين منفصلين:

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

وتكمن أهمية هذا الفحص في: حظر السطر بالكامل لوجود أمر الحذف الحساس rm، ومنع محاولات إخفاء الأوامر الضارة خلف أوامر عادية وسليمة لتجاوز البوابة الأمنية.

ولكن تنبه لهذه النقطة الفنية: يقتصر التحليل التلقائي على الأسطر البسيطة والواضحة. وإذا احتوى السطر على متغيرات بيئة أو علامات معقدة (مثل إعادة التوجيه >، الاستدعاء المتداخل $(...) أو العلامات العامة *)، فيعجز النظام عن تفكيكها ويتعامل مع السطر بالكامل كأمر واحد بصيغة bash -lc "<السطر_كامل>" ويخضعه للفحص الأمني الشامل. لذا احرص على إبقاء القواعد بسيطة ومباشرة.

فحص واختبار القواعد عبر أمر execpolicy check

تجنب تطبيق القواعد مباشرة دون اختبار. يوفر Codex أمر execpolicy check لاختبار سلامة شروط القواعد ومعرفة الإجراء المتوقع للأمر:

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

يعيد الأمر نتيجة بصيغة JSON توضح الإجراء الأمني المتوقع والقواعد التي تطابقت مع الأمر مع عرض حقل التوضيح المكتوب. ونوصي بـ: اختبار القواعد وتأكيد عدم حظر الأوامر السليمة بالخطأ قبل تفعيلها وإعادة تشغيل البرنامج لتلافي تعطيل العمل اليومي للمطورين.

💡 ملخص في جملة واحدة: تكتب القواعد في ملفات .rules باستخدام دالة prefix_rule لتحديد صلاحيات الأوامر (حيث يطبق الخيار الأكثر صرامة وأماناً دائماً)؛ ويقوم النظام بتفكيك الأسطر المدمجة لمنع التجاوز؛ ويتم اختبار القواعد بأمر execpolicy check قبل تفعيلها.


03 الخطافات (Hooks): أحداث دورة حياة المساعد المتاحة للربط

ننتقل للخطافات. لا تعمل الخطافات بشكل عشوائي، بل ترتبط بنقاط زمنية محددة داخل دورة تشغيل البرنامج - وتسمى الأحداث (events). ويتطلب إعداد الخطاف تحديد الحدث الأنسب للمهمة المطلوبة.

أشرنا في المقال 02 لدورة عمل المساعد التكرارية (التفكير ← التنفيذ ← المراجعة). وتتوزع الأحداث على مسار هذه الدورة. يوضح المخطط التالي أهم الأحداث ومواقعها:

أحداث دورة عمل Codex

يوضح المخطط مسار العمل: عند بدء الجلسة يفعل حدث SessionStart، وعند إرسال رسالتك يفعل UserPromptSubmit، وعند اتخاذ قرار استخدام الأداة تبدأ دورة الفحص - حيث يفعل حدث PreToolUse قبل تشغيل الأداة، وحدث PostToolUse بعد التنفيذ، وعند انتهاء الدورة يفعل حدث Stop. ويسهل ربط السكربت بالحدث المناسب لتنفيذ المطلوب تلقائياً.

يوفر Codex أحداثاً متعددة (مثل خطافات الضغط وتوفير الذاكرة PreCompact و PostCompact، وبدء وإيقاف الوكلاء الفرعيين SubagentStart و SubagentStop ونوافذ التراخيص PermissionRequest)، ونوضح هنا الأحداث الأربعة الأساسية التي تغطي معظم الاحتياجات اليومية للمطورين:

الحدثوقت التفعيلالاستخدام الأنسب
PreToolUseقبل بدء تشغيل الأداة أو الأمرلفحص الأوامر والتحقق من سلامتها وحظرها عند الخطر (يملك صلاحية منع التشغيل)
PostToolUseبعد انتهاء عمل الأداة ورصد المخرجاتلتنسيق الملفات تلقائياً، تشغيل الفحص والتحقق من جودة الكود
Stopعند انتهاء جولة التفكير الحالية وعرض الإجابةللطلب من المساعد مراجعة النتائج وإصلاح الأخطاء المتبقية بالتكرار
SessionStartعند بدء تشغيل جلسة جديدة أو استعادتهالجلب وعرض حالة المشروع الحالية في محادثة العمل (مثل سجل التعديلات الأخيرة)

وهناك حدث خامس مفيد وهو PermissionRequest (يفعل عند محاولة إظهار نافذة إذن)، ويتيح لك الموافقة أو الرفض تلقائياً وبشكل ديناميكي، ليكون رديفاً مرناً للقواعد الموضحة سابقاً.

ولسهولة التذكر: انتبه للبادئتين Pre و Post في الأسماء - حيث تعني Pre (قبل البدء) وتملك صلاحية حظر ومنع العملية قبل وقوعها؛ وتعني Post (بعد الانتهاء) حيث تفعل بعد حدوث الأثر الجانبي وتصلح لتعديل المخرجات أو تشغيل أدوات إضافية تالية.

مواقع تفعيل الخطافات في دورة حياة Codex

توضح الرسمة مسارات التفعيل: تتوزع نقاط التشغيل التلقائي على خط سير الجلسة (بدء الجلسة ← قبل استخدام الأداة ← بعد التنفيذ ← انتهاء الجولة)، وبمجرد وصول المساعد لإحدى هذه النقاط، يتم تشغيل السكربت المرتبط بالحدث تلقائياً بصرف النظر عن ذاكرة Codex.

وننبه لـ فارق فني هام عن أسلوب Claude Code: عند ضبط قيمة الإجراء كـ decision: "block" في حدث Stop في Codex، فهذا لا يعني حظر الإجابة، بل العكس تماماً - فهو يوجه Codex لـ "الاستمرار وعدم التوقف وتشغيل جولة تفكير جديدة" مع تمرير حقل reason كرسالة توجيهية إضافية من المستخدم. ويماثل ذلك سلوك decision: "block" في حدث PostToolUse حيث يعيد مخرجات الأداة للنموذج لإعادة فحصها وتعديل الكود بناءً عليها. فالأمر يعني "الإعادة والتوجيه" وليس "الحظر والإلغاء" في هذين الحدثين.

💡 ملخص في جملة واحدة: ترتبط الخطافات بأحداث محددة في دورة تشغيل Codex؛ وتتمثل الأحداث الأساسية في PreToolUse (قبل التنفيذ للحظر)، و PostToolUse (بعد التنفيذ للتنسيق)، و Stop (بعد الإجابة لإعادة التوجيه)، و SessionStart (عند البدء)؛ ويعني خيار block في Stop و PostToolUse الإعادة والتوجيه وليس الحظر.


04 ملفات تهيئة الخطافات وقواعد حصر التفعيل عبر matcher

بعد فهم الأحداث ومواقع تفعيلها، نأتي لكيفية كتابتها وتحديد مسارات الحفظ.

مسارات حفظ ملفات الخطافات

تكتب الخطافات إما في ملف مستقل باسم hooks.json، أو تكتب كجدول إعدادات مدمج تحت قسم [hooks] في ملف config.toml. وتتوزع مسارات الحفظ كالتالي:

ملف الإعداداتنطاق التأثيرشروط المشاركة مع الفريق
~/.codex/hooks.jsonيعمل في جميع مشاريع المطورلا يشارك (يقتصر على جهازك الحالي)
~/.codex/config.tomlيعمل في جميع مشاريع المطورلا يشارك
<repo>/.codex/hooks.jsonيقتصر على المشروع الحالي فقطنعم، يرفع في المستودع ليعمل لدى الجميع
<repo>/.codex/config.tomlيقتصر على المشروع الحالي فقطنعم

وتتطابق القواعد الأمنية مع ملفات التكوين الموضحة في المقال 15: فالخطافات العامة المشتركة للفريق تكتب في ملف .codex/ للمشروع وتدخل في Git؛ وتكتب الخطافات الشخصية المخصصة لجهازك في مجلد المستخدم العام ~/.codex/.

ونشير لثلاثة تفاصيل هامة:

  • يتم تحميل وتفعيل الخطافات من جميع المصادر المتاحة معاً - ولا يلغي وجود ملف الخطافات في المشروع تفعيل خطافات المستخدم العامة، بل يتم تشغيلها بالتوازي.
  • تجنب دمج ملف hooks.json وقسم [hooks] في نفس مستوى المجلد لتفادي تضارب الإعدادات وظهور رسائل التحذير عند تشغيل البرنامج.
  • لا يتم تحميل خطافات المشروع المحلي إلا إذا تم تأكيد الثقة في مجلد المشروع .codex/ (كما سنوضح في القسم 05)؛ وفي حال غياب الثقة يكتفي البرنامج بتشغيل الخطافات العامة للمستخدم والنظام فقط لحمايتك.

نموذج لكتابة ملف الخطافات

نعرض مثالاً لكتابة ملف الخطافات - "تشغيل سكربت بعد استخدام أداة Bash" في ملف .codex/hooks.json للمشروع:

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" فقط؛ ويتم تجاهل الأنواع الأخرى مثل prompt و agent عند كتابتها؛ كما يتم تجاهل المعالجات غير المتزامنة async: true في الإصدار الحالي.
  • عند وجود عدة خطافات متوافقة مع نفس الحدث، يتم تشغيلها بالتوازي في نفس الوقت - ويحظر افتراض أن خطاف الحظر سيمنع بقية الخطافات من البدء في نفس اللحظة. ويختلف هذا السلوك عن أسلوب Claude Code لذا يرجى الانتباه عند كتابة خطافات PreToolUse.
  • يكون مسار تشغيل السكربتات هو مجلد العمل الحالي للجلسة cwd. ولتلافي مشاكل تغيير المجلد أثناء العمل، تنصح الإرشادات بـ تجنب كتابة المسارات النسبية مثل .codex/hooks/...، والاستعانة بأمر Git لجلب المسار المطلق لجذر المشروع $(git rev-parse --show-toplevel) لضمان دقة التشغيل (كما هو موضح في المثال).
  • ولأنظمة Windows، يمكنك استخدام حقل command_windows (أو commandWindows في TOML) لكتابة سطر التشغيل المتوافق مع نظام Windows وتفادي مشاكل توافق الأنظمة.

ونلخص هنا الفروق الهامة عن أسلوب Claude Code لمنع الأخطاء عند نقل الإعدادات: تقاس قيمة timeout في Codex بـ الثواني (في Claude Code تقاس بالملي ثانية)، ولا يدعم متغير البيئة $CLAUDE_PROJECT_DIR (واستبدله بأمر Git الموضح سابقاً)، ولا يوفر خيار التعطيل العام 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 بهذه الوظيفة للخطافات.

يكتب حقل matcher في Codex كـ تعبير نمطي (regular expression)، ويتم مطابقته مع اسم الأداة المستدعاة في أحداث الأدوات (PreToolUse/PostToolUse). وتوضح القائمة التالية طرق كتابة شروط المطابقة:

شرط matcherوظيفتهمثال التطبيق
"Bash"مطابقة أداة Bashيفعل الخطاف عند تشغيل أوامر سطر الأوامر فقط
"^apply_patch$"مطابقة دقيقة للأداةيفعل الخطاف عند محاولة تعديل الملفات فقط
"Edit|Write"استخدام الأسماء المستعارة (علامة | للخيارات)يفعل الخطاف عند تعديل أو كتابة الملفات
"mcp__filesystem__.*"مطابقة خوادم MCP المحددةيفعل الخطاف عند استدعاء أدوات خادم الملفات لـ MCP
"*" / "" / خلو الحقلالسماح بالتشغيل دائماًيفعل الخطاف عند استدعاء أي أداة في هذا الحدث

إليك أهم النقاط الفنية لتلافي الأخطاء:

  • يسمى المعالج المسؤول عن تعديل الملفات بـ apply_patch وليس Edit أو Write. ويستخدم Codex آلية apply_patch لإجراء التعديلات - ورغم قبول حقل matcher للأسماء المستعارة Edit أو Write لتسهيل الكتابة، إلا أن نصوص JSON المرسلة للسكربت ستحتوي دائماً على اسم الأداة الفعلي "apply_patch" في حقل tool_name.
  • لا تدعم كل الأحداث استخدام حقل matcher. فحدثا إرسال الطلب UserPromptSubmit وانتهاء الجولة Stop يتجاهلان حقل matcher ويعملان دائماً عند كل دورة تشغيل لعدم ارتباطهما بأداة معينة. بينما يدعم حدث إيقاف الوكلاء SubagentStop التصفية بناءً على نوع الوكيل المستدعى agent_type. وفي حدث بدء الجلسة SessionStart يتم المطابقة مع حالة بدء الجلسة (startup/resume/clear/compact).
  • يحذر من الاعتماد على PreToolUse كحاجز أمان مطلق. توضح الإرشادات أن الخطاف يعمل كحاجز إضافي وليس كجدار حماية محكم - فهو يغطي الأوامر البسيطة وأداة تعديل الملفات وأدوات MCP، ولكنه يعجز عن فحص وتصفية الأوامر المعقدة أو الاستعلامات الخارجية. لذا استخدمه كخط دفاع ثانٍ بجانب بيئة المعزل.

💡 ملخص في جملة واحدة: تحفظ الخطافات في ملف hooks.json أو ملف config.toml للمشروع أو المستخدم؛ وتتكون البنية من ثلاثة مستويات (الحدث، matcher، والعملية)؛ وتقاس أوقات الانتظار بـ الثواني، ويسمى معالج التعديل بـ apply_patch، وتحدد شروط الأدوات باستخدام التعبيرات النمطية في حقل matcher.


05 آلية تأكيد الثقة بالخطافات: لماذا لا تعمل الخطافات الجديدة تلقائياً؟

يتميز Codex بوجود آلية أمان صارمة ومختلفة عن أسلوب العمل في الأدوات الأخرى: فبمجرد إضافة أو تعديل خطاف، يمتنع البرنامج عن تشغيله تلقائياً حتى تقوم بمراجعته والموافقة عليه صراحة.

لماذا يفرض النظام هذا الإجراء؟ لأن الخطافات تمثل سكربتات برمجية تعمل بصلاحيات حسابك وتملك القدرة على الوصول لملفاتك والإنترنت. وإذا قمت بفتح مستودع يحتوي على خطافات ضارة وتم تشغيلها تلقائياً دون علمك، فقد تتعرض ملفاتك للتلف أو السرقة. لذا تفرض المنصة إجراء "المراجعة والتوقيع".

تشبيه: طلب التطبيق الجديد صلاحية الوصول لصور الهاتف. عند تثبيت تطبيق جديد، يمتنع نظام الهاتف عن منحه صلاحية الصور تلقائياً - بل يتوقف ويعرض نافذة تسألك صراحة "هل تسمح للتطبيق بالوصول للصور؟" ولن يعمل التطبيق بدون موافقتك. وتماثل آلية الثقة بالخطافات هذا الفحص: فالخطافات غير المدارة (المحلية والخاصة) تتطلب مراجعتك وموافقتك الصريحة لتتمكن من العمل.

وتسير آلية الثقة وفق القواعد التالية:

  • يقوم Codex بحفظ قيم التحقق (Hash) الخاصة بملفات الخطافات. وتعتبر الخطافات الجديدة أو التي تم تعديلها خطافات "تحت المراجعة" ويتم تجاوزها وتجاهل تشغيلها تلقائياً حتى تعلن موافقتك. وأي تعديل بسيط في السكربت يغير قيمة الهاش ويتطلب إعادة الموافقة.
  • استخدم الأمر المائل /hooks داخل الجلسة لمراجعة الخطافات المضافة والتعديلات التي تمت عليها وتأكيد الثقة فيها أو تعطيلها.
  • وفي حال وجود خطافات تتطلب المراجعة عند تشغيل Codex، يظهر تنبيه تحذيري في الطرفية يطلب منك مراجعة الخطافات عبر أمر /hooks.

لذا، عند كتابة أو تعديل أي خطاف، احرص على تشغيل Codex أولاً والدخول للأمر المائل للموافقة:

text
/hooks

المتوقع: ظهور واجهة مراجعة الخطافات وتوضح حالة كل خطاف (تحت المراجعة review، موثوق trusted، أو مدار managed). وتمثل الخطافات المدارة (managed) الخطافات الرسمية المدمجة في النظام أو التي تفرضها إدارة تقنية المعلومات للشركة، ولا يمكن إيقافها أو تعديلها من هذه الواجهة.

ويمكنك استخدام خيار التشغيل --dangerously-bypass-hook-trust لتخطي فحص الثقة عند تشغيل الاختبارات المؤتمتة (CI). وتذكر أن استخدام خيار dangerously يحذر منه في الاستخدام اليومي لجهازك نظراً لأنه يلغي تماماً صمام الأمان الأساسي للبرنامج.

⚠️ تذكر التوجيهات الأمنية للمقال 16: افحص محتويات وأكواد السكربتات جيداً قبل الموافقة وتأكيد الثقة بها، ولا توافق على خطافات مجهولة المصدر تم جلبها من مشاريع خارجية. تظل موافقتك هي خط الدفاع الأهم لحماية بياناتك.

💡 ملخص في جملة واحدة: يفرض Codex آلية تأكيد ثقة صارمة بالاعتماد على قيم الهاش للسكربتات؛ ويتم حظر تشغيل الخطافات الجديدة أو المعدلة تلقائياً حتى تقوم بمراجعتها والموافقة عليها عبر أمر /hooks؛ لتفادي مخاطر تشغيل الأكواد الخبيثة دون علمك.


06 تفاعل الخطاف مع Codex: قنوات الاتصال والبيانات

نوضح هنا طريقة تبادل البيانات بين Codex والسكربتات البرمجية، وكيفية صياغة مخرجات السكربت لتوجيه قرارات المساعد.

تتم العملية عبر ثلاث قنوات اتصال أساسية وبسيطة: يمرر Codex بيانات الحدث لسكربتك عبر القناة القياسية (stdin) ← يقوم السكربت بالمعالجة ← ويعيد التوجيه لـ Codex بالاعتماد على (رمز الخروج exit code والمخرجات القياسية stdout).

أولاً: البيانات المرسلة للسكربت عبر stdin

عند تفعيل الحدث، يرسل Codex بيانات الحدث بصيغة JSON لسكربتك. وتضم البيانات الحقول العامة التالية:

الحقلالوصف
session_idمعرف الجلسة الحالية
cwdمجلد التشغيل الحالي للجلسة
hook_event_nameاسم الحدث الذي فعل الخطاف
transcript_pathمسار ملف سجلات الجلسة (قد يكون فارغاً)
modelاسم النموذج الفعال حالياً (يساعدك في تخصيص عمل السكربت بناءً على نوع النموذج)
permission_modeوضع الصلاحيات المعتمد للجلسة

وتحتوي أحداث الأدوات على حقول إضافية مثل اسم الأداة المستدعاة tool_name (مثل "Bash" أو "apply_patch") وتفاصيل المدخلات tool_input (حيث يضم حقل tool_input.command نص الأمر المطلوب تشغيله). وإليك مثالاً للبيانات المرسلة لحدث PreToolUse عند محاولة تشغيل أمر Bash:

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 codes) لإصدار الأوامر

يعتمد السكربت على رموز الخروج لإعلام Codex بقرار الفحص كالتالي:

رمز الخروجالنتيجة المتوقعة
0الموافقة على العملية واستمرار العمل بشكل طبيعي (ويعتبر خلو المخرجات موافقة أيضاً)
2رمز الإجراء الخاص (تختلف وظيفته بحسب نوع الحدث كما سنوضح أدناه)

نوضح هنا سلوك رمز الخروج exit 2 في الأحداث المختلفة لتلافي الأخطاء:

  • في أحداث ما قبل التنفيذ (PreToolUse و UserPromptSubmit): يعني الرمز حظر ومنع تشغيل الأداة أو الطلب، ويقوم Codex بقراءة رسالة الخطأ المكتوبة في القناة القياسية للأخطاء (stderr) وعرضها للنموذج.
  • في أحداث ما بعد التنفيذ والانتهاء (PostToolUse و Stop): لا يمكن حظر العملية (نظراً لاكتمال تشغيلها)، ويعني الرمز إعادة توجيه النتائج للنموذج - حيث تستبدل مخرجات الأداة في PostToolUse برسالة الخطأ لإجبار النموذج على مراجعتها، وتفتح جولة تفكير جديدة في Stop لتعديل الكود.

وتذكر أن المنع والحظر الفعلي يقتصر على أحداث ما قبل التنفيذ Pre فقط.

ثالثاً: استخدام القناة القياسية (stdout) للتحكم الدقيق

لإرسال توجيهات متقدمة (مثل توضيح أسباب الحظر أو تمرير سياق إضافي للنموذج)، أعد رمز الخروج كـ 0 واكتب مخرجات بصيغة JSON في القناة القياسية (stdout) كالتالي:

1. حظر الأمر مع عرض رسالة مخصصة في حدث PreToolUse - كتابة حقل permissionDecision كـ "deny":

json
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "يحظر تشغيل أوامر الحذف أو تعديل الملفات الحساسة أمنياً."
  }
}

يدعم النظام الصيغة القديمة {"decision": "block", "reason": "..."} للمطابقة، وننصح بالاعتماد على الصيغة الجديدة لسلامة المعالجة.

2. تمرير سياق وتوجيهات إضافية للنموذج في حدث SessionStart - كتابة حقل additionalContext:

json
{
  "hookSpecificOutput": {
    "hookEventName": "SessionStart",
    "additionalContext": "تنبيه: التزم بأسلوب كتابة التعليقات باللغة العربية في هذا المشروع."
  }
}

إليك أهم التنبيهات الفنية لبيانات المخرجات القياسية:

  • يتم تجاهل النصوص العادية المكتوبة في stdout في حدث PreToolUse - ويشترط استخدام صيغة JSON الموضحة لتمرير التوجيهات أو حظر الأمر.
  • يقبل حدثا SessionStart و UserPromptSubmit قراءة النصوص العادية مباشرة من stdout لإضافتها كسياق للنموذج؛ بينما تشترط بقية الأحداث (مثل Stop و SubagentStop) كتابة البيانات بصيغة JSON حصراً ويعتبر إرجاع النصوص العادية فيها خطأ برمجياً.
  • لا يدعم حدث PreToolUse استخدام حقول التوجيه مثل continue أو stopReason، وكتابتها تؤدي لفشل معالجة الخطاف ويستمر Codex في تشغيل الأداة دون حظر.

💡 ملخص في جملة واحدة: يتفاعل السكربت مع Codex بقراءة JSON من stdin، وإصدار قرارات المنع برمز الخروج exit 2 (لأحداث Pre للمنع ولأحداث Post للإعادة)، وتمرير بيانات التوجيه المتقدمة بصيغة JSON عبر stdout.


07 مثالان عمليان جاهزان للاستخدام

نعرض مثالين عمليين للأحداث الأساسية لتسهيل تهيئة وتأمين بيئة عملك.

المثال الأول: التنسيق التلقائي للملفات بعد التعديل (حدث PostToolUse)

يحل هذا المثال مشكلة نسيان التنسيق الموضحة في بداية المقال، ويتميز بالأمان العالي وننصح بإضافته لجميع المشاريع البرمجية.

الخطوة الأولى: أنشأ سكربت بايثون في المسار .codex/hooks/format.py لقراءة مسار الملفات وتشغيل أداة التنسيق عليها:

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

# قراءة بيانات الحدث
data = json.load(sys.stdin)

# تشغيل أداة التنسيق ruff على كامل المشروع لضمان التنسيق
subprocess.run(["ruff", "format", "."])

الخطوة الثانية: سجل السكربت في ملف الخطافات الرئيسي .codex/hooks.json للمشروع ليرتبط بحدث تعديل الملفات (نستخدم الاسم المستعار Edit|Write لمطابقة أداة تعديل الملفات):

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": "تنسيق الملفات تلقائياً بعد التعديل"
          }
        ]
      }
    ]
  }
}

الخطوة الثالثة: افتح Codex واكتب أمر /hooks لتأكيد الثقة بالخطاف لبدء العمل. وسيقوم المساعد بتنسيق الأكواد تلقائياً بعد كل تعديل. ويمكنك استبدال أداة ruff بأي أداة تنسيق أخرى تناسب لغة مشروعك (مثل prettier أو gofmt).

المثال الثاني: حظر تشغيل الأوامر الحساسة (حدث PreToolUse)

يستخدم هذا المثال لمنع تشغيل الأوامر عالية الخطورة عن طريق فحص نص الأمر قبل البدء وإرجاع رمز الخروج exit 2 لمنع التنفيذ.

الخطوة الأولى: احفظ السكربت التالي في المسار .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:
    # طباعة رسالة التحذير في stderr لعرضها للمساعد
    print("خطأ أمني: يحظر تشغيل أوامر الحذف الكلي rm -rf في هذا المشروع.", file=sys.stderr)
    # رمز الخروج 2 لإعلام Codex بإلغاء ومنع العملية
    sys.exit(2)

# السماح بتشغيل بقية الأوامر العادية
sys.exit(0)

الخطوة الثانية: سجل السكربت في ملف الخطافات .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": "فحص سلامة الأوامر قبل التشغيل"
          }
        ]
      }
    ]
  }
}

الخطوة الثالثة: وافق على تشغيل الخطاف عبر أمر /hooks. وبمجرد محاولة Codex تشغيل أي أمر يحتوي على rm -rf سيقوم الخطاف بحظره وإظهار رسالة التحذير للنموذج.

⚠️ نوضح أن حظر الأوامر البسيطة يفضل إنجازه عبر القواعد (Rules) الموضحة في القسم 02 لسهولة كتابتها وخلوها من التعقيد البرمجي؛ ونلجأ للخطافات عند الحاجة لإجراء فحص برمي معقد (مثل حظر الحذف لمجلدات معينة فقط والسماح بمجلدات أخرى). وتجنب تكرار كتابة نفس الشروط في الجهتين منعاً لتداخل العمليات.

يوضح الجدول التالي الفروق الأساسية بين المثالين:

وجه المقارنةالمثال الأول: التنسيق التلقائيالمثال الثاني: حظر الأوامر
الحدث المرتبطPostToolUse (بعد التنفيذ)PreToolUse (قبل التنفيذ)
أداة المطابقة matcherEdit|Write (أداة تعديل الملفات)Bash (سطر الأوامر)
آلية العملتنسيق الملف بعد تعديله، ولا تمنع العمليةإرجاع رمز الخروج exit 2 لمنع وحظر تشغيل الأمر
مستوى الخطورةآمن تماماً وينصح به للجميعيتطلب دقة لمنع حظر الأوامر السليمة بالخطأ
البديل عبر القواعدلا يمكن (القواعد تختص بالصلاحيات فقط)نعم، يفضل استخدام القواعد للأوامر البسيطة

💡 ملخص في جملة واحدة: يفضل استخدام خطافات PostToolUse للتنسيق التلقائي للملفات وخطافات PreToolUse مع رمز الخروج exit 2 لحظر الأوامر البرمجية؛ واحرص على استخدام مسارات Git المطلقة للسكربتات وتأكيد ثقتها عبر /hooks لبدء العمل.


08 تدريب عملي: كتابة خطاف وتسجيل مخرجاته

نطبق معاً تدريباً عملياً متكاملاً: كتابة سكربت لتسجيل أوامر Bash المستدعاة ← تسجيل السكربت في ملف الخطافات للمشروع ← الموافقة عليه ← وتشغيل أمر للتحقق من كتابة السجلات تلقائياً.

سندمج سكربت بسيطاً يقوم بتسجيل أي أمر يكتبه Codex في ملف نصي على جهازك للرجوع إليه وتتبع العمليات.

الخطوة الأولى: إنشاء مجلد السكربت وكتابة كود التسجيل

أنشأ مجلداً للاستخدام الحسابي في بيئة عملك، وأنشأ سكربت بايثون في المسار .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_path = os.path.expanduser("~/codex-bash-log.txt")

# تسجيل الأمر في نهاية الملف النصي
with open(log_path, "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": "تسجيل أوامر سطر الأوامر"
          }
        ]
      }
    ]
  }
}

تنبيه: يعتمد تحديد المسار على أمر Git، لذا تأكد من تهيئة مجلد التدريب كمستودع Git بكتابة git init ليعمل السكربت بنجاح؛ أو يمكنك كتابة المسار المطلق للسكربت على جهازك مباشرة بدلاً من دالة Git.

الخطوة الثانية: تشغيل المساعد والموافقة على الخطاف

شغل جلسة Codex:

bash
codex

اكتب الأمر المائل التالي لمراجعة والموافقة على الخطاف الجديد:

text
/hooks

المتوقع: ظهور الخطاف الجديد في قائمة المراجعة كـ "تحت المراجعة review"، قم باختياره وتأكيد الموافقة عليه لتتحول حالته لـ "موثوق trusted".

الخطوة الثالثة: الطلب من Codex تشغيل أمر Bash

اطلب منه استعراض الملفات للتأكد من تفعيل الخطاف:

text
اعرض لي قائمة الملفات الحالية في المجلد باستخدام أمر ls

سيقوم Codex باستدعاء أداة Bash وتشغيل أمر استعراض الملفات ls. ويتم تشغيل خطاف PostToolUse المسجل تلقائياً بعد اكتمال التنفيذ وبشكل صامت.

الخطوة الرابعة: مراجعة سجل الأوامر للتأكد من نجاح العملية

افتح نافذة طرفية أخرى واقرأ محتويات الملف النصي:

bash
cat ~/codex-bash-log.txt

المتوقع: ظهور أمر استعراض الملفات ls مكتوباً في سطر مستقل بالملف، مما يثبت نجاح تفعيل وتشغيل الخطاف تلقائياً بعد تشغيل أداة Bash.

الخطوة الخامسة: حذف إعدادات التدريب

لإزالة الإعدادات بعد انتهاء التدريب، احذف أسطر الخطاف من ملف .codex/hooks.json (لا تتوفر أوامر خاصة للحذف ويكفي إزالة النصوص من الملف)، واحذف ملف السجلات بكتابة rm ~/codex-bash-log.txt.

بإتمام هذه الخطوات، تكون قد أتممت بنجاح دورة عمل الخطافات: كتابة السكربت وتكوينه ← مراجعته والموافقة عليه عبر /hooks ← تفعيل الحدث تلقائياً ← والتحقق من النتيجة النهائية.

💡 ملخص في جملة واحدة: خطوات التدريب هي: كتابة سكربت تسجيل أوامر Bash وتكوينه في ملف المشروع ← تأكيد ثقته بأمر /hooks ← الطلب منه تشغيل أمر ls ← والتحقق من كتابة الأمر في ملف السجلات الموحد؛ لفهم دورة تشغيل وتأمين الخطافات.


09 تتبع وحل مشاكل عدم تفعيل الخطافات

إذا واجهت مشكلة في تشغيل الخطافات أو تعذر التعرف عليها، فراجع قائمة الفحص التالية لتحديد موضع العطل:

العطل المتوقعالسبب الأكثر احتمالاً وطريقة المعالجة
الخطاف لا يعمل نهائياً1. هل نسيت الموافقة وتأكيد ثقة الخطاف في واجهة /hooks؟ هذا هو السبب الأهم في أغلب الحالات.
2. هل قمت بتعديل السكربت وتغيير قيمة الهاش دون إعادة تأكيد الثقة؟
3. هل اخترت الحدث أو اسم الأداة بشكل غير صحيح في حقل matcher؟
تعذر ظهور الخطاف في قائمة /hooks1. وجود خطأ في بنية ملف JSON (مثل الفواصل الزائدة أو كتابة تعليقات نصية غير معتمدة).
2. كتابة اسم الملف أو مسار الحفظ بشكل خاطئ (تأكد من كتابة hooks.json أو التكوين يدوياً في config.toml).
3. دمج الطريقتين في نفس مستوى المجلد وتداخل الإعدادات.
4. تذكر إعادة تشغيل البرنامج لتنشيط قائمة الملفات.
ظهور خطأ تعذر العثور على السكربت أو الأمركتابة مسار نسبي غير دقيق. تذكر أن مسار التشغيل هو مجلد الجلسة الحالي، واستخدم مسارات Git المطلقة $(git rev-parse --show-toplevel) لتفادي مشاكل المسارات.
فشل حظر ومنع تشغيل الأوامر1. كتابة الخطاف في حدث PostToolUse وهو حدث يقع بعد انتهاء التنفيذ ولا يملك صلاحية المنع. استخدم حدث PreToolUse دائماً للحظر.
2. استخدام الأوامر المعقدة التي تعجز أداة PreToolUse عن تصفيتها وحظرها.
3. إغفال إرجاع رمز الخروج exit 2 أو كتابة موافقة الحظر بصيغة JSON الصحيحة.
إيقاف تشغيل الخطاف لانتهاء الوقت الأقصىانتبه لقياس وقت الانتظار timeout بـ الثواني وليس بالملي ثانية؛ وارفع قيمته للمهام الطويلة والمعقدة.

ونعرض طريقتين عمليتين لتتبع الأخطاء قبل ربط السكربت بـ Codex:

1. اختبار السكربت يدوياً بتمرير نصوص JSON ومراجعة رمز الخروج:

bash
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /tmp/x"}}' | python3 .codex/hooks/block-dangerous.py
echo $?   # مراجعة رمز الخروج: ويجب أن يعيد القيمة 2 للحظر

يساعدك هذا الفحص في التأكد من سلامة كود السكربت وتعامله مع نصوص JSON بشكل صحيح قبل تحميله للبرنامج.

2. استخدام أمر execpolicy check لاختبار شروط القواعد (كما وضحنا في القسم 02) للتحقق من عدم تداخل القواعد أو حظر الأوامر السليمة بالخطأ.

وعند الرغبة في إيقاف عمل كل الخطافات مؤقتاً، فيمكنك كتابة الإعداد التالي في ملف config.toml العام:

toml
[features]
hooks = false

💡 ملخص في جملة واحدة: عند مواجهة عطل في الخطاف، تفقد أولاً حالة ثقته وموافقته في قائمة /hooks، وراجع سلامة صيغة ملف JSON، واستعن باختبار السكربت يدوياً بتمرير نصوص JSON ومراجعة رمز الخروج لتسهيل التتبع.


10 ملخص

شرحنا في هذا المقال نظام القواعد والخطافات (Rules & Hooks) في Codex بالتفصيل - وكيفية تحديد صلاحيات الأوامر أمنياً، وتفعيل السكربتات تلقائياً عند الأحداث المختلفة، وتأمين تشغيلها ومراجعة أخطائها.

دعنا نلخص النقاط الأساسية معاً بشكل سريع:

الجانبالمفهوم الأساسينقاط هامة
وظيفة القواعدتحديد صلاحيات تشغيل الأوامر خارج بيئة المعزلتكتب بـ Starlark في ملفات .rules وتدعم خيارات السماح، السؤال، أو الحظر، ويطبق الخيار الأكثر صرامة
وظيفة الخطافاتتشغيل سكربت معين تلقائياً عند وصول المساعد لنقطة محددةترتبط بأحداث دورة حياة البرنامج وتعمل حتمياً بصرف النظر عن ذاكرة Codex
الأحداث الأساسيةأربعة أحداث لتغطية أغلب المتطلباتPreToolUse للحظر، و PostToolUse للتنسيق، و Stop للإعادة، و SessionStart للتهيئة عند البدء
حصر التفعيلاستخدام حقل matcher لتحديد الأدواتيكتب كتعبير نمطي (regex) لمطابقة أسماء الأدوات في أحداث الأدوات (تعديل الملفات يسمى apply_patch)
آلية تأكيد الثقةصمام الأمان الأساسي للخطافاتيُمنع تشغيل الخطافات الجديدة أو المعدلة تلقائياً، ويشترط موافقتك اليدوية الصريحة عبر أمر /hooks
تفاعل السكربتاتقنوات الاتصال والتبادلقراءة JSON من stdin، إصدار قرارات المنع برمز الخروج exit 2، وتمرير البيانات المتقدمة بصيغة JSON عبر stdout

يجب أن تكون الآن قادراً على: توضيح دور القواعد والخطافات في فرض المعايير والضمانات الحتمية؛ وكتابة قواعد بسيطة للأوامر واختبارها بأمر execpolicy check؛ وتحديد الحدث الأنسب لعمل الخطاف وتصفيته بحسب الأداة في حقل matcher؛ وإنشاء ومزامنة ملفات التكوين والسكربتات وتأكيد ثقتها عبر أمر /hooks؛ ومراجعة تفاعل السكربتات أمنياً وتتبع أعطالها. هذه القدرة على فرض القواعد وتشغيل السكربتات تلقائياً هي ما يتيح لك تأمين وتوحيد بيئة عملك اليومية والاعتماد على الأتمتة لفرض المعايير البرمجية.

تذكر دائماً الفروق التقنية للأنظمة - واحفظ قواعد "قراءة وتأكيد ثقة الخطافات الجديدة أولاً، وقياس وقت الانتظار بالثواني، واستخدام مسارات Git المطلقة للسكربتات، وحظر تشغيل الخطافات تلقائياً أمنياً" لتسريع العمل وتأمين الأجهزة.


المقال التالي [25 · فروع العمل المتوازية (Worktrees)] - ساعدتنا القواعد والخطافات على تأمين وتسيير مهام التنسيق والفحص التلقائي بنجاح، ولكن يقتصر عملنا حالياً على معالجة مهمة واحدة في مستودع الكود. ماذا لو تطلب العمل تسيير مهمتين مختلفتين بالتوازي (مثل إصلاح خطأ برمجي مستعجل وفي نفس الوقت تطوير ميزة جديدة) دون تداخل التعديلات أو مسح تقدم العمل؟ سنتحدث في المقال القادم بالتفصيل عن فروع العمل المتوازية (Git Worktrees): وكيفية حجز وتخصيص مجلد عمل مستقل لكل مهمة لتمكين Codex من العمل بالتوازي ودون تداخل، لتسريع العمل وتنسيق المهام الكبيرة.


قراءات مقترحة