30 حدث خطاف ينطلق في جلسة Claude Code. ثلاثة فقط يمكنها الرد.
القائمة الكاملة لأحداث خطافات Claude Code، ومتى ينطلق كل منها، وأي 15 منها يمكنه الحظر، وقاعدة stdout التي تبتلع بصمت مخرجات معظم الخطافات. مرجع ميداني بُني من تشغيل الخطافات في الإنتاج عبر آلاف جلسات الوكلاء.
يتكرر عطلان مرارا حين يربط الناس الخطافات بـ Claude Code، وهما لا يشبهان بعضهما في شيء.
الأول: تضيف خطافا، فلا يحدث شيء. لا خطأ، ولا تحذير، ولا سطر في السجل. الخطاف ببساطة لا ينفَّذ أبدا.
الثاني: الخطاف ينفَّذ بوضوح، وترى آثاره الجانبية على القرص، لكن الرسالة التي يطبعها للوكيل لا تصل أبدا. يتصرف الوكيل كأن الخطاف لم يقل شيئا.
كلاهما يأتي من المكان نفسه. نظام الخطافات أكبر وأقل انتظاما من حفنة الأحداث التي تغطيها معظم المقالات، والقواعد التي تحدد من يستطيع مخاطبة الوكيل ليست تلك التي قد تخمّنها. هذا هو المرجع الذي كنا نتمنى لو توفر لنا. نحن نبني AgentsRoom فوق هذه الخطافات، وكل ما يلي إما منقول عن المرجع الرسمي وإما مقيس في الإنتاج.
هناك 30 حدثا، لا ستة
تغطي معظم الأدلة PreToolUse وPostToolUse وUserPromptSubmit وStop وNotification وSubagentStop. هذه الستة حقيقية، وهي تحمل معظم العمل المفيد. وهي أيضا خُمس ما هو موجود.
القائمة الكاملة، مجمّعة بحسب ما تراقبه:
| المجموعة | الأحداث |
|---|---|
| الجلسة | SessionStart، SessionEnd، Setup |
| المطالبة | UserPromptSubmit، UserPromptExpansion |
| الأدوات | PreToolUse، PostToolUse، PostToolUseFailure، PostToolBatch |
| الأذونات | PermissionRequest، PermissionDenied |
| الدور | Stop، StopFailure |
| الوكلاء الفرعيون والمهام | SubagentStart، SubagentStop، TaskCreated، TaskCompleted، TeammateIdle |
| السياق | PreCompact، PostCompact، InstructionsLoaded |
| البيئة | FileChanged، CwdChanged، ConfigChange |
| أشجار العمل (worktrees) | WorktreeCreate، WorktreeRemove |
| الواجهة | Notification، MessageDisplay |
| استدراج MCP | Elicitation، ElicitationResult |

ترتيب انطلاق الأحداث في جلسة واحدة. تتكرر كتلة الأدوات مرة عند كل استدعاء أداة، وتتكرر كتلة المطالبة كاملة مرة عند كل دور.
بعض هذه الأحداث يغيّر طريقة تفكيرك في النظام. PostToolUseFailure موجود، أي أن مسار "هل نجحت الأداة" حدث قائم بذاته، لا شيء تستنتجه من الحمولة. ينطلق PostToolBatch مرة واحدة بعد انتهاء دفعة من استدعاءات الأدوات المتوازية، وهو المكان الصحيح لتشغيل مدقق الشيفرة مرة واحدة بدل مرة عند كل تعديل. ينطلق InstructionsLoaded عند قراءة CLAUDE.md، ما يمنحك نقطة خطاف للتحقق من أن الوكيل حمّل فعلا القواعد التي تظن أنه حمّلها.
قاعدة stdout التي تبتلع معظم مخرجات الخطافات
هذه أنفع معلومة في هذه الصفحة.
عند رمز الخروج 0، يحلل Claude Code محتوى stdout بحثا عن حقول إخراج JSON. لكن ما إذا كان هذا الـ stdout سيُعرض على الوكيل يوما فذلك يتوقف على الحدث، والاستثناءات قائمة قصيرة. من المرجع:
بالنسبة لمعظم الأحداث، يُكتب stdout في سجل التصحيح لكنه لا يظهر في سجل المحادثة. الاستثناءات هي
UserPromptSubmitوUserPromptExpansionوSessionStart، حيث يُضاف stdout بوصفه سياقا يستطيع Claude رؤيته والتصرف بناء عليه.
ثلاثة أحداث من ثلاثين. إن نفّذت echo "warning: this migration is destructive" من خطاف PostToolUse وتوقعت أن يقرأها الوكيل، فلن يقرأها أبدا. نصك ذهب إلى سجل التصحيح.
هناك طريقتان اثنتان بالضبط لوضع نص أمام الوكيل انطلاقا من أي حدث آخر:
- اخرج برمز 2 واكتب على stderr. عند الخروج برمز 2، يتجاهل Claude Code محتوى stdout وأي JSON فيه، ويمرر stderr إلى الوكيل بوصفه رسالة خطأ.
- اخرج برمز 0 واطبع كائن JSON يحمل
hookSpecificOutput.additionalContext.
لاحظ اللاتناظر في الأولى. الخروج برمز 0 يعني أن stdout مهم وأن stderr غير مهم. والخروج برمز 2 يعني أن stderr مهم وأن stdout يُهمل تماما. عكس هذين هو سبب أن يبدو خطاف صحيحا تماما ويظل أخرس مع ذلك.
أي رمز خروج آخر هو خطأ غير حاجب. يعرض سجل المحادثة إشعار <hook name> hook error مع أول سطر من stderr، ويستمر التنفيذ، ويحط stderr كاملا في سجل التصحيح.

أي قناة تصل إلى الوكيل، بحسب رمز الخروج. المسار المتقطع هو المسار الذي يفترض الناس وجوده وهو غير موجود.
نصفها بالضبط يمكنه الحظر
خمسة عشر حدثا توقف الإجراء عند الخروج برمز 2. وخمسة عشر تتجاهله وتمضي.
يمكنها الحظر: PreToolUse، PermissionRequest، UserPromptSubmit، UserPromptExpansion، Stop، SubagentStop، TeammateIdle، TaskCreated، TaskCompleted، ConfigChange، PostToolBatch، PreCompact، Elicitation، ElicitationResult، WorktreeCreate.
لا يمكنها الحظر: PostToolUse، PostToolUseFailure، PermissionDenied، StopFailure، Notification، SubagentStart، SessionStart، Setup، SessionEnd، CwdChanged، FileChanged، PostCompact، WorktreeRemove، InstructionsLoaded، MessageDisplay.
النتيجة العملية: حاجز الحماية مكانه PreToolUse، لا PostToolUse أبدا. ينطلق PostToolUse بعد نجاح الأداة. الخروج برمز 2 هناك لا يتراجع عن الكتابة، بل يطبع خطأ فقط بينما الضرر قابع على القرص. إن أردت إيقاف rm -rf فلديك مكان واحد بالضبط لفعل ذلك.
كون PostToolBatch قادرا على الحظر بينما PostToolUse غير قادر يستحق نظرة ثانية. معناه أن فحصا على مستوى الدفعة ما زال بإمكانه إيقاف الدور بعد نزول التعديلات المتوازية، وهو أقرب شيء إلى نقض بعد الكتابة يقدمه النظام.
مطابقات matcher تامة، إلى أن تكفّ فجأة عن ذلك
يبدّل حقل matcher استراتيجية التقييم بناء على محارفه هو، ولا شيء يخبرك أي مسار سلك.
| matcher | يُقيَّم بوصفه |
|---|---|
"*" أو "" أو محذوف | يطابق كل شيء |
حروف وأرقام و_ و- ومسافات و, و| فقط | سلسلة تامة، أو قائمة سلاسل تامة مقسّمة على | أو , |
| أي شيء آخر | تعبير نمطي JavaScript غير مثبّت الطرفين |
عدم تثبيت الطرفين هو الفخ. المرجع صريح في أن التعبير النمطي يُختبر بـ RegExp.prototype.test، وهو ينجح عند وجود تطابق في أي موضع من القيمة. لذا فإن Edit.* يطابق Edit وNotebookEdit. إن كنت تقصد أداة واحدة، فاكتب ^Edit$.
سلوكان يعتمدان على الإصدار، يحسن معرفتهما قبل أن تصحّح المشكلة الخطأ:
- الفواصل بوصفها فواصل فصل والتسامح مع المسافات البيضاء يحتاجان Claude Code v2.1.191 أو أحدث.
- انضمت الواصلة إلى مجموعة محارف المطابقة التامة في v2.1.195. قبل ذلك، كان مطابق مثل
code-reviewerيُعامل كتعبير نمطي غير مثبّت الطرفين، فينطلق أيضا معsenior-code-reviewer.
في AgentsRoom نحصر خطاف نسبة الملفات الخاص بنا بـ Write|Edit|MultiEdit|NotebookEdit، وهو يبقى على مسار السلسلة التامة ويطابق تلك الأدوات الأربع ولا شيء غيرها. أما خطافات دورة الحياة التي نثبّتها فلا تحمل أي مطابق، لأنها تعنينا دائما.
ستة أماكن يمكنها تعريف الخطافات، وهي تندمج
الغريزة هي البحث عن ترتيب أولوية. لا وجود له، وهذا هو الجزء المثير للاهتمام.
| الموقع | النطاق |
|---|---|
~/.claude/settings.json | كل مشاريعك، محلي على جهازك |
.claude/settings.json | مشروع واحد، قابل للإيداع في git |
.claude/settings.local.json | مشروع واحد، يستثنيه Claude Code من git |
| Managed policy settings | على مستوى المؤسسة، يتحكم فيه المسؤول |
hooks/hooks.json الخاص بالإضافة | طالما كانت الإضافة مفعّلة |
| ترويسة مهارة أو وكيل | طالما كان المكوّن نشطا |
من المرجع:
تندمج مدخلات الخطافات عبر مستويات الإعدادات بدل أن يحل بعضها محل بعض: إعدادات المستخدم وإعدادات المشروع والإعدادات المحلية تضيف خطافاتها الخاصة دون إزالة الخطافات المُدارة، ولا يستطيع إعداد
disableAllHooksتعطيل الخطافات المُدارة من خارج الإعدادات المُدارة.
إذن لا يتجاوز خطاف المشروع خطافا عاما أبدا، بل يتراكم فوقه. ستة مصادر، كلها تراكمية. منسّق PostToolUse معرّف في إعدادات المستخدم ثم معرّف مرة أخرى في المشروع ينفَّذ مرتين عند كل تعديل، والعرض الوحيد لذلك هو الإحساس بالبطء.

ستة مصادر، مجموعة واحدة مدمجة. لا شيء هنا يتجاوز شيئا.
هذا يفسر أيضا لماذا .claude/settings.local.json هو المكان الصحيح لأداة تريد تثبيت خطاف داخل مشروع شخص آخر. نطاقه هو المشروع، ويستثنيه Claude Code من git، ويُحمَّل من دون أي راية في سطر الأوامر. هناك يكتب AgentsRoom مدخلاته، فلا يُمَس أبدا ملف .claude/settings.json المُودع لدى المستخدم، ولا يرث زملاؤه أبدا مسارا خاصا بجهاز بعينه.
ما علّمنا إياه تشغيل الخطافات في الإنتاج
يثبّت AgentsRoom خطافات في كل مشروع يفتحه، ليتتبع حالة الوكلاء بشكل حتمي وينسب الملفات المعدَّلة إلى الوكيل الصحيح. بعض الأمور لا تظهر إلا على هذا المقياس.
أسماء الأحداث غير المعروفة تُتجاهل بصمت. هذا غير موجود في التوثيق، ونحن نعتمد عليه. حين نضيف حدث دورة حياة جديدا إلى مثبّتنا، يحصل المستخدمون العاملون على إصدار أقدم من الـ CLI على settings.local.json يحتوي اسم حدث لم يسمع به ملفهم التنفيذي قط. لا شيء ينكسر، ولا شيء يحذّر، ويُتخطى المدخل ببساطة. هذا ما يجعل شحن المثبّت قبل إصدار الـ CLI آمنا. وهو أيضا، حتما، سبب أن يُنتج خطأ إملائي صمتا تاما بدل رسالة خطأ.
agent_id هو ما يخبرك أنك داخل وكيل فرعي. الحقل موجود فقط حين ينطلق الخطاف داخل استدعاء وكيل فرعي. وهذا أهم مما يبدو: ينطلق Stop حين ينهي وكيل فرعي دوره، لا عند الوكيل الرئيسي فقط. قاعدة ساذجة من نوع "علّم الجلسة منتهية عند Stop" تعلّم الجلسة كلها منتهية أول مرة يعود فيها أي وكيل فرعي. نحن نتخطى أحداث الدور التي تحمل agent_id لهذا السبب بالضبط.
لا تقرأ transcript_path للدور الحالي. يحذّر المرجع من أن سجل المحادثة يُكتب بشكل غير متزامن وقد يتأخر عن المحادثة الموجودة في الذاكرة، فقد لا تكون أحدث الرسائل موجودة فيه بعد حين ينطلق خطافك. يتلقى Stop وSubagentStop الحقل last_assistant_message تحديدا حتى لا تضطر أبدا إلى مسابقة الملف.
الخطافات هي إشارة الحالة الموثوقة الوحيدة. قبل الخطافات، كنا نكشط الـ PTY لنعرف ما إذا كان الوكيل يفكر أو ينتظر أو انتهى. ينكسر ذلك في اللحظة التي يعرض فيها الـ CLI عبر شاشة الطرفية البديلة، وهو ما يفعله /tui fullscreen. تنطلق الخطافات بالطريقة نفسها تحت كل محرك عرض. إن كنت تبني أي شيء يراقب وكيلا من الخارج، فهذه هي الطبقة التي تُبنى عليها، ويبقى الكشط حلا احتياطيا في أحسن الأحوال.
async: true لا يكلف شيئا. يستطيع أمر الخطاف أن يعلن async: true، فلا ينتظره الوكيل. خطافنا يرسل POST إلى نقطة نهاية محلية بسقف قدره ثانيتان ثم يعود، وزمن استجابة دور الوكيل لا يتأثر حتى حين يكون التطبيق المستقبِل مغلقا. إن كان خطافك يراقب فقط ولا يقرر أبدا، فاجعله غير متزامن وتوقف عن دفع ثمنه.
لا تدع خطافا يكتب نفايات في الطرفية أبدا. سكربتنا يبتلع كل استثناء، بما في ذلك على المستوى الأعلى. تتبّع استدعاءات Python غير معالَج قادم من خطاف لا يفشل بهدوء فحسب، بل يطبع مكدس التتبّع داخل جلسة طرفية المستخدم في وسط عمله.
المهل الزمنية
القيم الافتراضية سخية، مع ثلاثة استثناءات ليست كذلك:
| نوع الخطاف | المهلة الافتراضية |
|---|---|
command، http، mcp_tool | 600 s |
prompt | 30 s |
agent | 60 s |
UserPromptSubmit (command, http, mcp_tool) | 30 s |
MessageDisplay (command, http, mcp_tool) | 10 s |
SessionEnd | 1.5 s مشتركة بين كل الخطافات، تُرفع لتطابق timeout أطول محدد لخطاف بعينه، حتى 60 s |
ميزانية SessionEnd هي التي تفاجئ الناس. إنها ميزانية مشتركة، لا مخصص لكل خطاف على حدة، فثلاثة خطافات تنظيف تتقاسم 1.5 ثانية بينها ما لم ترفعها صراحة.
النسخة المختصرة
- 30 حدثا موجودة. ستة منها مشهورة.
- يصل stdout إلى الوكيل في
UserPromptSubmitوUserPromptExpansionوSessionStartفقط. في كل مكان آخر، استخدم الخروج برمز 2 مع stderr، أوadditionalContextداخل JSON. - 15 حدثا تحظر عند الخروج برمز 2، و15 تتجاهله. حواجز الحماية مكانها
PreToolUse. - مطابقات matcher سلاسل تامة إلى أن يحوّلها محرف خاص إلى تعبير نمطي غير مثبّت الطرفين.
- ستة مصادر إعدادات تندمج تراكميا. لا شيء يتجاوز شيئا.
- اسم حدث مكتوب بشكل خاطئ يفشل بصمت تام.
إن أردت أن تشاهد هذه الأحداث وهي تنطلق بدل أن تستنتجها بالتفكير، فهذا ما بنيناه: يعرض AgentsRoom كل إطلاق خطاف، لكل وكيل، ولكل مشروع، ولكل تشغيل، عبر عشرات الوكلاء المتوازيين وجلسات الوكلاء الفرعيين. الخطافات التي تضبطها في إعداداتك الخاصة تظل تعمل تماما كما كُتبت، لأنه يشغّل الـ CLI الحقيقي.
تابع القراءة
كيفية توسيع وكلاء البرمجة الذكية عبر فريق التطوير
مطور واحد مع وكيل برمجة هو قصة إنتاجية. خمسة مطورين مع عشرين وكيلًا هي مشكلة تنسيق. إليك ما ينكسر أولاً عندما يتوسع الفريق، والإعداد الذي ينجح: ملفات السياق الملتزمة، ملكية الملفات الواضحة، المراجعة حسب نطاق الانفجار، والتكاليف التي يمكنك رؤيتها بالفعل.
اقرأ المقالAgentsRoom يدعم الآن Kimi Code
أصبح Kimi Code، وكيل البرمجة في الطرفية من Moonshot AI، مزودًا كامل الصلاحيات داخل AgentsRoom. شغّله إلى جانب Claude وCodex وAntigravity CLI وOpenCode وAider وGrok Build وMistral Vibe، وبدّل بينها في منتصف المحادثة.
اقرأ المقالهل يجب عليك مراجعة كود وكيل الذكاء الاصطناعي الخاص بك؟
وكلاؤك يكتبون كودًا أفضل من نصف طلبات السحب التي كنت تدمجها. فهل لا تزال تقرأ كل سطر؟ الحالة الصادقة لكلا الجانبين، والعلامات العشر التي تخبرك أن الوكيل ارتكب خطأ، وكم من المراجعة يستحق كل تغيير فعليًا.
اقرأ المقال
تحميل AgentsRoom
شغّل وكلاء الذكاء الاصطناعي (Claude، Codex، Antigravity CLI، OpenCode، Aider، Grok Build، Mistral Vibe، Kimi Code) على جميع مشاريعك من نافذة واحدة.
التطبيق المرافق: تابع وكلاءك أينما كنت
استخدم Claude أو Codex أو Antigravity CLI أو أي مزود AI آخر.
أرسل الأخطاء والطلبات مباشرة إلى قائمة المهام العامة.
لمحة عن AgentsRoom أثناء العمل.