القواعد والخطافات (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":
# قاعدة لتسهيل الاستعلام عن 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 لتفكيك السطر والتحقق من صلاحية كل أمر بشكل مستقل، ويطبق الإجراء الأكثر صرامة عليها بالكامل لمنع التجاوز:
الأمر المطلوب:
["bash", "-lc", "git add . && rm -rf /"]يقوم النظام بتحليله وفحصه كأمرين منفصلين:
["git", "add", "."]
["rm", "-rf", "/"]وتكمن أهمية هذا الفحص في: حظر السطر بالكامل لوجود أمر الحذف الحساس rm، ومنع محاولات إخفاء الأوامر الضارة خلف أوامر عادية وسليمة لتجاوز البوابة الأمنية.
ولكن تنبه لهذه النقطة الفنية: يقتصر التحليل التلقائي على الأسطر البسيطة والواضحة. وإذا احتوى السطر على متغيرات بيئة أو علامات معقدة (مثل إعادة التوجيه >، الاستدعاء المتداخل $(...) أو العلامات العامة *)، فيعجز النظام عن تفكيكها ويتعامل مع السطر بالكامل كأمر واحد بصيغة bash -lc "<السطر_كامل>" ويخضعه للفحص الأمني الشامل. لذا احرص على إبقاء القواعد بسيطة ومباشرة.
فحص واختبار القواعد عبر أمر execpolicy check
تجنب تطبيق القواعد مباشرة دون اختبار. يوفر Codex أمر execpolicy check لاختبار سلامة شروط القواعد ومعرفة الإجراء المتوقع للأمر:
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 لدورة عمل المساعد التكرارية (التفكير ← التنفيذ ← المراجعة). وتتوزع الأحداث على مسار هذه الدورة. يوضح المخطط التالي أهم الأحداث ومواقعها:

يوضح المخطط مسار العمل: عند بدء الجلسة يفعل حدث SessionStart، وعند إرسال رسالتك يفعل UserPromptSubmit، وعند اتخاذ قرار استخدام الأداة تبدأ دورة الفحص - حيث يفعل حدث PreToolUse قبل تشغيل الأداة، وحدث PostToolUse بعد التنفيذ، وعند انتهاء الدورة يفعل حدث Stop. ويسهل ربط السكربت بالحدث المناسب لتنفيذ المطلوب تلقائياً.
يوفر Codex أحداثاً متعددة (مثل خطافات الضغط وتوفير الذاكرة PreCompact و PostCompact، وبدء وإيقاف الوكلاء الفرعيين SubagentStart و SubagentStop ونوافذ التراخيص PermissionRequest)، ونوضح هنا الأحداث الأربعة الأساسية التي تغطي معظم الاحتياجات اليومية للمطورين:
| الحدث | وقت التفعيل | الاستخدام الأنسب |
|---|---|---|
PreToolUse | قبل بدء تشغيل الأداة أو الأمر | لفحص الأوامر والتحقق من سلامتها وحظرها عند الخطر (يملك صلاحية منع التشغيل) |
PostToolUse | بعد انتهاء عمل الأداة ورصد المخرجات | لتنسيق الملفات تلقائياً، تشغيل الفحص والتحقق من جودة الكود |
Stop | عند انتهاء جولة التفكير الحالية وعرض الإجابة | للطلب من المساعد مراجعة النتائج وإصلاح الأخطاء المتبقية بالتكرار |
SessionStart | عند بدء تشغيل جلسة جديدة أو استعادتها | لجلب وعرض حالة المشروع الحالية في محادثة العمل (مثل سجل التعديلات الأخيرة) |
وهناك حدث خامس مفيد وهو PermissionRequest (يفعل عند محاولة إظهار نافذة إذن)، ويتيح لك الموافقة أو الرفض تلقائياً وبشكل ديناميكي، ليكون رديفاً مرناً للقواعد الموضحة سابقاً.
ولسهولة التذكر: انتبه للبادئتين Pre و Post في الأسماء - حيث تعني Pre (قبل البدء) وتملك صلاحية حظر ومنع العملية قبل وقوعها؛ وتعني Post (بعد الانتهاء) حيث تفعل بعد حدوث الأثر الجانبي وتصلح لتعديل المخرجات أو تشغيل أدوات إضافية تالية.

توضح الرسمة مسارات التفعيل: تتوزع نقاط التشغيل التلقائي على خط سير الجلسة (بدء الجلسة ← قبل استخدام الأداة ← بعد التنفيذ ← انتهاء الجولة)، وبمجرد وصول المساعد لإحدى هذه النقاط، يتم تشغيل السكربت المرتبط بالحدث تلقائياً بصرف النظر عن ذاكرة 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 للمشروع:
{
"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 تلقائياً"
}
]
}
]
}
}يتكون الهيكل البرمجي من ثلاثة مستويات بسيطة:
"PostToolUse": تحديد الحدث المستهدف (هنا: بعد تشغيل الأداة)."matcher": "Bash": تحديد اسم الأداة التي تفعل الخطاف عند استخدامها (هنا: عند تشغيل أداة Bash فقط).- مصفوفة
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 يدوياً:
[[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 أولاً والدخول للأمر المائل للموافقة:
/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:
{
"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":
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "يحظر تشغيل أوامر الحذف أو تعديل الملفات الحساسة أمنياً."
}
}يدعم النظام الصيغة القديمة
{"decision": "block", "reason": "..."}للمطابقة، وننصح بالاعتماد على الصيغة الجديدة لسلامة المعالجة.
2. تمرير سياق وتوجيهات إضافية للنموذج في حدث SessionStart - كتابة حقل additionalContext:
{
"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 لقراءة مسار الملفات وتشغيل أداة التنسيق عليها:
#!/usr/bin/env python3
import json, subprocess, sys
# قراءة بيانات الحدث
data = json.load(sys.stdin)
# تشغيل أداة التنسيق ruff على كامل المشروع لضمان التنسيق
subprocess.run(["ruff", "format", "."])الخطوة الثانية: سجل السكربت في ملف الخطافات الرئيسي .codex/hooks.json للمشروع ليرتبط بحدث تعديل الملفات (نستخدم الاسم المستعار Edit|Write لمطابقة أداة تعديل الملفات):
{
"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:
#!/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 قبل التنفيذ:
{
"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 (قبل التنفيذ) |
| أداة المطابقة matcher | Edit|Write (أداة تعديل الملفات) | Bash (سطر الأوامر) |
| آلية العمل | تنسيق الملف بعد تعديله، ولا تمنع العملية | إرجاع رمز الخروج exit 2 لمنع وحظر تشغيل الأمر |
| مستوى الخطورة | آمن تماماً وينصح به للجميع | يتطلب دقة لمنع حظر الأوامر السليمة بالخطأ |
| البديل عبر القواعد | لا يمكن (القواعد تختص بالصلاحيات فقط) | نعم، يفضل استخدام القواعد للأوامر البسيطة |
💡 ملخص في جملة واحدة: يفضل استخدام خطافات
PostToolUseللتنسيق التلقائي للملفات وخطافاتPreToolUseمع رمز الخروجexit 2لحظر الأوامر البرمجية؛ واحرص على استخدام مسارات Git المطلقة للسكربتات وتأكيد ثقتها عبر/hooksلبدء العمل.
08 تدريب عملي: كتابة خطاف وتسجيل مخرجاته
نطبق معاً تدريباً عملياً متكاملاً: كتابة سكربت لتسجيل أوامر Bash المستدعاة ← تسجيل السكربت في ملف الخطافات للمشروع ← الموافقة عليه ← وتشغيل أمر للتحقق من كتابة السجلات تلقائياً.
سندمج سكربت بسيطاً يقوم بتسجيل أي أمر يكتبه Codex في ملف نصي على جهازك للرجوع إليه وتتبع العمليات.
الخطوة الأولى: إنشاء مجلد السكربت وكتابة كود التسجيل
أنشأ مجلداً للاستخدام الحسابي في بيئة عملك، وأنشأ سكربت بايثون في المسار .codex/hooks/log-bash.py:
#!/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 في نفس المجلد:
{
"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:
codexاكتب الأمر المائل التالي لمراجعة والموافقة على الخطاف الجديد:
/hooksالمتوقع: ظهور الخطاف الجديد في قائمة المراجعة كـ "تحت المراجعة review"، قم باختياره وتأكيد الموافقة عليه لتتحول حالته لـ "موثوق trusted".
الخطوة الثالثة: الطلب من Codex تشغيل أمر Bash
اطلب منه استعراض الملفات للتأكد من تفعيل الخطاف:
اعرض لي قائمة الملفات الحالية في المجلد باستخدام أمر lsسيقوم Codex باستدعاء أداة Bash وتشغيل أمر استعراض الملفات ls. ويتم تشغيل خطاف PostToolUse المسجل تلقائياً بعد اكتمال التنفيذ وبشكل صامت.
الخطوة الرابعة: مراجعة سجل الأوامر للتأكد من نجاح العملية
افتح نافذة طرفية أخرى واقرأ محتويات الملف النصي:
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؟ |
تعذر ظهور الخطاف في قائمة /hooks | 1. وجود خطأ في بنية ملف 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 ومراجعة رمز الخروج:
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 العام:
[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 من العمل بالتوازي ودون تداخل، لتسريع العمل وتنسيق المهام الكبيرة.