Skip to main content

Plugins لوكلاء الذكاء الاصطناعي: حزمة واحدة، وفريقك كله

13 مفهوماً، 80% من الاستخدام الحقيقي · قراءة مفاهيمية تقارب 90 دقيقة · يوم مركّز لأول plugin حقيقي · من مجلد فارغ إلى plugin يثبّته زميل بأمر واحد

أولاً: ما هو plugin فعلاً؟ افتراضياً، يكون وكيل برمجة مثل Claude Code أو OpenCode عاماً وقادراً. يستطيع العمل في أي مشروع، لكنه لا يعرف طريقتك في العمل. Plugin هو الحزمة التي تصلح ذلك بتثبيت واحد: يجمع playbooks التي يتبعها الوكيل (skills)، والمتخصصين الذين يفوّض إليهم (subagents)، والأنظمة التي يستطيع الوصول إليها (MCP servers)، وتعليماتك الدائمة، والقواعد التي لا يستطيع تجاوزها (hooks). أعطِ هذه الحزمة لوكيل عام فيصبح وكيلك، والزميل الذي يثبتها يحصل على الشيء نفسه بالضبط.

والآن اجعل ذلك ملموساً. تشحن Anthropic marketplaces كاملة لهذه الحزم. أمران، claude plugin marketplace add anthropics/knowledge-work-plugins ثم claude plugin install finance@knowledge-work-plugins، فيتحول Claude الفارغ إلى متخصص مالي: skills تعمل من تلقاء نفسها، وأوامر مثل /finance:reconciliation، وconnectors إلى الأنظمة التي يعيش فيها فريق المالية. بدّل finance ب sales أو legal فتحصل على ذلك المتخصص. هذا هو plugin: تثبيت واحد يحوّل generalist إلى الخبير الدقيق الذي تحتاجه. بنهاية هذه الدورة ستكون قد بنيت واحداً لنفسك، ورأيت إلى أين يقود: marketplaces نطاقية قابلة للبيع مثل agentfactory-business (banking وlegal-ops وIslamic finance)، تضيف عمق المجالات المنظمة فوق Anthropic.

الحزمة خاصة بالمضيف؛ معظم ما بداخلها ليس كذلك. يغلّف plugin ل Claude Code وplugin ل OpenCode القطع نفسها بتنسيقات مختلفة لا يحمّل أحدها الآخر (يفسر المفهوم 2 السبب). لكن القطع نفسها غالباً تسافر: skill هي ملف SKILL.md نفسه في كل مكان، وتعليماتك هي markdown نفسه، وخادم MCP هو URL يمكن لأي host أن يشير إليه. وحده hook خاص فعلاً بكل host، لأنه يتصل بآلية مختلفة داخل كل مضيف (سترى ذلك بدقة في المفهوم 7). لذلك تبني للمضيف الذي تستخدمه، ومعظم ما في الداخل يبقى قادراً على الوصول إلى claude.ai وCodex وCursor، وحتى وكيل شخصي مثل OpenClaw.

وهذا هو ما جئت لتتعلمه فعلاً. يعرف وكيلك الصياغة التقنية مسبقاً؛ يستطيع كتابة hook أو manifest عند الطلب. لو كان هذا كل ما تعلّمه الدورة، لجعلها الوكيل بلا قيمة. النادر هو الحكم الذي لا يملكه: أي رافعة تحتاجها وظيفة ما، ومتى يجب أن تصبح القاعدة ضماناً لا أملاً، وكيف تثبت أن plugin يفعل ما تزعم. لذلك توجّه بلغة إنجليزية واضحة، وتبني كل رافعة من مجلد فارغ، وتقارن بما بُني وثبت بجانبك، ثم تشحن plugin حقيقياً يثبّته زميل بأمر واحد. القرار لك؛ والكتابة للوكيل.

كل شيء يتبع حقيقة واحدة: أنت توسّع وكيلاً لا تملكه. المضيف يملك الحلقة والنموذج والآلة. لا يدير plugin العرض؛ بل يسلّم المضيف قطعاً ليحمّلها. تنتج من ذلك أربعة أمور غير قابلة للتفاوض، والدورة كلها تبنيها:

  1. حزمة للمشاركة. plugin هو الشكل القابل للمشاركة والمُصدَر للتخصيص. إن كان الأمر لك وحدك في repo واحد، فأنت تحتاج إلى مجلد .claude/ لا إلى plugin. استخدم plugin عندما ينبغي أن يحصل الآخرون عليه أيضاً.
  2. الرافعة الصحيحة للوظيفة. Skill معرفة يستخدمها الوكيل باختياره؛ subagent عمل يفوّضه؛ MCP server أدوات وبيانات يصل إليها؛ hook كود يعمل من تلقاء نفسه في لحظات ثابتة. طابق الوظيفة مع الرافعة.
  3. ما يجب دائماً هو hook، لا تعليمة. أي شيء في skill أو CLAUDE.md نصيحة قد يتجاوزها النموذج. hook كود يعمل كل مرة. إن كان الشيء لا بد أن يحدث، مثل formatter أو بوابة أمان، فهو hook.
  4. plugin يعمل داخل ثقة المستخدم. ينفذ كوداً على جهاز من يثبّته. ابنِ بأقل صلاحية، واذكر ما يلمسه بوضوح، وتعامل مع تثبيته أو شحنه كقرار ثقة.

الثوابت الأربعة ل plugin لوكيل برمجة: حزمة للمشاركة، أي الشكل المصدّر والقابل للمشاركة للتخصيص؛ الرافعة الصحيحة للوظيفة، أي skill أو subagent أو MCP server أو hook؛ السلوك الذي يجب أن يحدث دائماً مكانه hook لا تعليمة، لأن hooks حتمية والتعليمات إرشادية؛ وplugin يعمل داخل ثقة المستخدم لأنه ينفّذ كوداً على جهازه. القاعدة المنظمة فوقها: أنت توسّع وكيلاً لا تملكه.

اقرأ كل مفهوم وأنت تسأل: أي ثابت يمثّل هذا؟

note

المتطلبات السابقة. تفترض هذه الصفحة ثلاثة أشياء.

  1. أنت تقود وكيل برمجة. أنهيت الدورة المكثفة في البرمجة الوكيلة: Claude Code أو OpenCode، نمط التخطيط، وملف قواعد. نحن نبني من خلال ذلك المنضد.
  2. تستطيع قراءة كود مكتوب: shell وقليل من JSON وTypeScript، مباشرة أو بلصق المقاطع في وكيلك ليشرحها بلغة واضحة.
  3. موصى به: Connector-Native Apps. علّمتك تلك الدورة العادة نفسها، اعرف الطبقة التي تقف عليها، وبنت خادم MCP. يستطيع plugin أن يشير إلى واحد (المفهوم 6)، لذلك تتصل الدورتان.

لا تحتاج إلى Build AI Agents أو AI Identity أولاً. كلاهما يأتي لاحقاً في المسار، وهذه الدورة تشير إليهما.

note

أين يقع هذا؟ في Mode 2، مباشرة بعد Connector-Native Apps. المسار هو: Connector-Native Apps → هذه الدورة → AI Identity (تسجيل الدخول ووصول الوكيل)Build AI Agents. تطبيقات connector-native توسّع تطبيق المحادثة للمستخدمين النهائيين؛ أما plugins فتوسّع وكيل البرمجة للبناة. الحركة نفسها، والمضيف الآخر.

الإعداد (بضع دقائق)

لن تشغّل أوامر shell يدوياً هنا. توجّه وكيل البرمجة بلغة إنجليزية واضحة وتراجع ما يبلّغك به؛ وهذه هي الحلقة نفسها التي ستستخدمها لبناء plugin. الإعداد هو أول تمرين عليها.

  1. نزّل القاعدة (plugins-crash-course-base.zip)، وفك ضغطها، ثم افتح مجلد plugins-crash-course في Claude Code (أو OpenCode). عند الفتح، يقرأ الوكيل AGENTS.md: brief لما تبنيه وأين توجد النسخة المثبتة.

  2. اطلب منه إعداد نفسه. الصق:

Set up my base environment, then tell me what you did and what passed.

خلف هذا السطر يتبع وكيلك brief في AGENTS.md: في Claude Code يثبّت skill الرسمية لبنية plugins حتى يعمل من المواصفة الحالية؛ وفي OpenCode يقرأ وثائق plugins؛ ثم يشغل فحوص build المرجعية.

  1. الآن اجعله يشرح لك التخطيط. الصق:

Walk me through, in plain English, how a plugin is laid out on my host.

ينتهي عندما يبلّغك الوكيل أن build المرجعية خضراء (يحظر guard ملفات .env وrm -rf، وتنجح skill النموذجية وخادم MCP)، ويستطيع شرح تخطيط plugin في مضيفك.

ما الموجود في الصندوق. تقريباً لا شيء لك بعد، وهذا هو المقصود. أنت تبني plugin؛ starter يعطيك brief وbuild مثبتاً تقيس عملك عليه.

plugins-crash-course/           ← you build YOUR marketplace + plugin here, from blank
AGENTS.md your brief + how each host lays out a plugin
CLAUDE.md points Claude Code at the same brief (@AGENTS.md)
reference/ a COMPLETE, PROVEN build — read it, diff against it, don't copy it
plugins/agent-factory/ the finished plugin: proven guard, a model skill, a model reviewer
server/ a runnable MCP server you point your plugin at
verify.sh one command that proves the reference is sound

ستبني كل رافعة بنفسك: guard hook، وskill لعمل تفعله فعلاً، وsubagent للمراجعة، وتوصيل MCP، وmarketplace. توجّه وكيلك بإنجليزية واضحة. عندما تعود قطعة خاطئة، تقارنها ب reference/، النسخة المعروفة بصحتها. أنت توجّه؛ الوكيل يكتب؛ أنت تراجع؛ أنت تقارن.


شاهد واحداً يعمل قبل أن تبني واحداً (5 دقائق)

قرأت للتو ما يفعله plugin. الآن اشعر به. قبل المفاهيم، ثبّت plugin المكتمل الذي يأتي في starter وشاهد كيف يفرض شيئاً. رؤيته أولاً تجعل بقية الدورة تستقر.

حمّل plugin المرجعي في جلسة:

claude --plugin-dir reference/plugins/agent-factory

افتح reference/plugins/agent-factory في OpenCode. يحمّل guard من .opencode/plugins/ في ذلك المجلد، وskill من skills/.

ثم اجعله يعمل. الصق:

Try to read a file called .env, then use your loop-engineering skill to explain an agent loop in four moves.

ما ينبغي أن تراه:

  • يُحظر الوكيل من قراءة .env، ويخبرك بالسبب. (hook يعمل على tool call لا يستطيع النموذج تجاوزه)
  • تجيب skill بصوتها الخاص، من غير أن تسميها. (skill اختارها النموذج)
  • (Claude Code) اطلب منه إصلاح ملف فوضوي، فيعود مهيأ تلقائياً من غير طلب إضافي. (hook ثانٍ)

ذلك الحظر الصلب على .env هو ما لا تستطيع تعليمة "من فضلك لا تقرأ الأسرار" ضمانه أبداً، وتعلّم بنائه هو قلب هذه الدورة. لم تضبط شيئاً لكل ملف؛ plugin حمل السلوك معه. الآن لدى المفاهيم شيء حقيقي تتعلق به.


الجزء 1: الشكل

المفهوم 1: توسّع الوكيل، ولا تملكه

plugin ليس برنامجاً تشغّله. إنه مجموعة قطع يحمّلها مضيف ويشغّلها نيابةً عنك. المضيف، Claude Code أو OpenCode، يملك حلقة الوكيل، أي دورة قرّر-افعل-كرّر، ويجلب النموذج، ويعمل على جهاز المستخدم. يضيف plugin قدرات وقواعد يلتقطها المضيف. إذا صحّت هذه الصورة، فالباقي تفاصيل؛ وإذا أخطأت، ستظل تحاول جعل plugin "يفعل" أشياء لم تكن يوماً تحت مسؤوليته.

هنا لمسة جميلة تستحق التسمية: أنت توجّه وكيل برمجة ليبني plugin لوكلاء البرمجة. ستطلب من Claude Code أن يكتب النوع نفسه من التوسعة الذي يحمّله Claude Code. الأداة التي تبنيه والأداة التي يوسّعها من العائلة نفسها. ليست حيلة؛ إنها أسرع طريقة لبناء واحد، وهي الطريقة التي تعمل بها كل دورة في Manufacturing: أنت توجّه، والوكيل يكتب، وأنت تتحقق.

المفهوم 2: مضيفان، وفكرة واحدة

تغطي هذه الدورة مضيفين. يغلّفان التوسعات بشكل مختلف، لكن الفكرة متطابقة: وحدة يحمّلها المضيف.

  • Claude Code يأخذ حزمة تصريحية: مجلد مكوّنات (skills، subagents، hooks، MCP servers) يصفه manifest صغير. تكتب غالباً إعدادات وسكربتات؛ وClaude Code يربطها.
  • OpenCode يأخذ وحدة كود: ملف JavaScript/TypeScript يتصل بأحداث الوكيل ويمكنه إضافة أدوات. تكتب دوالاً؛ وOpenCode يستدعيها.
Plugin في Claude CodePlugin في OpenCode
الشكلمجلد + manifest باسم plugin.jsonوحدة .ts/.js تصدّر دوالاً
ما تكتبهskills، subagents، إعدادات hooks، .mcp.jsonevent handlers، أدوات مخصصة
يُحمّل منmarketplace، أو --plugin-dir.opencode/plugins/ أو حزمة npm

لا يوسّعان أفضل أو أسوأ؛ يوسّعان بشكل مختلف، وهذا الفرق يستحق أن تعرفه قبل أن تختار هدفاً. Claude Code أداة Anthropic، مرتبطة بنماذج Claude، مع تنسيق حزمة تصريحية ونظام marketplace للتوزيع. أما OpenCode فمفتوح المصدر ومحايد تجاه النموذج: أحضر مفتاح API الخاص بك، أو شغّل نماذج مجانية أو محلية (Gemini، GPT، محلية). وplugins فيه كود، وهذا يشتري تحكماً أدق مقابل أن تكتب أكثر بنفسك. بالنسبة إلى المتعلمين الحسّاسين للتكلفة، حرية النموذج هي العنوان: المهارة نفسها التي تكتبها يمكن أن تعمل على نموذج مجاني في OpenCode. (ويتداخل الاثنان أيضاً: المهارات تنتقل مباشرة، وplugins من المجتمع تصل الاعتمادات والواجهات الخلفية بينهما، لكن هذا استخدام للأدوات معاً، لا تأليف plugins، لذلك هو خارج النطاق هنا.)

معظم هذه الدورة هو النموذج الذهني المشترك وشكل Claude Code، لأنه الحزمة الأغنى؛ أما الجزء 5 فيعرض شكل OpenCode للوظيفة نفسها. اختر المضيف الذي تستخدمه فعلاً؛ الثوابت الأربعة لا تتغير.

رافعة واحدة تنتقل مجاناً؛ وواحدة لا تنتقل. المهارة هي فقط ملف SKILL.md، وكل وكلاء البرمجة الثلاثة في هذه الدورة يقرأون ذلك التنسيق أصلاً: Claude Code وOpenCode وCodex. يكتشف OpenCode المهارات وحده من .opencode/skills/ و.claude/skills/ و.agents/skills/، ولا يحتاج إلى plugin للمهارات أصلاً. لذلك يمكن لمجلد مهارة واحد أن يخدم كل أداة. hooks هي العكس: hooks في Claude Code إعدادات JSON، وhooks في OpenCode وحدة JavaScript؛ لا يوجد تنسيق مشترك، لذلك تكتب hook مرة لكل مضيف. احتفظ بهذا الفصل في ذهنك؛ فهو يحدد كيف ترتّب plugin عابراً للأدوات (المفهوم 4).

ذلك الفصل يكبر إلى عائلتين. plugin الذي تبنيه ل Claude Code يحمّل أيضاً في Claude Cowork وclaude.ai، فهي تشارك تنسيق plugin من Anthropic. وplugin الذي تبنيه ل OpenCode يحمّل أيضاً في OpenWork، وهو وكيل سطح مكتب مبني على OpenCode، بنفس تنسيق OpenCode. المهارات تعبر العائلتين (كل شيء يقرأ SKILL.md)؛ أما الحزم فلا تعبر (حزمة Claude ليست وحدة OpenCode). لذلك يحدد المضيف الذي تستهدفه مدى سفر الحزمة، لكن مهارة عادية تسافر إلى كل مكان. نبقى هنا على وكيلي البرمجة؛ أما مضيفو العمل المعرفي فلهم دورتهم الخاصة (انظر السقف).

عائلتان من مضيفي وكلاء البرمجة. عائلة Anthropic، وهي Claude Code وClaude Cowork وclaude.ai، تشارك تنسيق حزمة واحداً هو .claude-plugin. وعائلة OpenCode، وهي OpenCode وOpenWork، تشارك Plugin OpenCode، وهو وحدة JS/TS. تبقى الحزمة داخل عائلتها؛ ولا تعبر العائلتان. تحت الاثنين يوجد SKILL.md، الرافعة المحمولة: ملف واحد يقرأه كل مضيف في العائلتين، إضافة إلى Codex. اجعل جسم المهارة محايداً تجاه الأداة فتسافر إلى كل مكان؛ أما الحزمة الكاملة فتسافر داخل عائلتها فقط.

المفهوم 3: اجمع للمشاركة، لا تضبط لتحتفظ

يسمح لك المضيفان بالتخصيص من دون plugin: يقرأ Claude Code مجلد .claude/ في مشروعك؛ ويقرأ OpenCode مجلد .opencode/. هذه هي الأداة الصحيحة عندما يكون التخصيص شخصياً ويعيش في مستودع واحد. أما plugin فتستخدمه عندما ينبغي للتخصيص أن يسافر: إلى زملائك، وبين مشاريعك، وإلى المجتمع، مع إصدارات وتحديثات.

لذلك اختبار "هل ينبغي أن يكون هذا plugin؟" ليس ماذا يفعل، بل من يحتاج إليه غيري؟ مطوّر واحد، مشروع واحد: مجلد .claude/. فريق، مشاريع كثيرة، أو غرباء: plugin (الثابت 1).

نتيجة مبكرة يجب معرفتها: مهارات وأوامر plugin لها namespace باسم plugin. مهارة hello داخل plugin اسمه repo-tools تُستدعى باسم /repo-tools:hello. يمنع ذلك اصطدام pluginين مثبتين على الاسم نفسه.

Checkpoint: الشكل واضح. تعرف أن plugin وحدة يحمّلها المضيف، وأن مضيفين يغلّفانها بشكل مختلف، وأن "plugin" يعني "تخصيصاً صُنع للمشاركة". الآن الروافع الأربع.


الجزء 2: روافع القدرة

ثلاث من الروافع الأربع تضيف إلى ما يستطيع الوكيل فعله. (الرابعة، hooks، مختلفة بما يكفي لتأخذ جزءاً خاصاً بها.)

الروافع الأربع التي يستخدمها plugin لتوسيع وكيل. ثلاث تضيف قدرة: skill معرفة يستخدمها الوكيل باختياره؛ subagent عمل يكلّفه لسياق جديد؛ MCP server أدوات وبيانات يصل إليها. أما الرابعة فهي تحكم: hook كود يعمل حتمياً في لحظات ثابتة. skills وsubagents وMCP servers إرشادية، أي يقرر النموذج هل يستخدمها؛ أما hooks فمفروضة، تعمل كل مرة.

المفهوم 4: المهارات، معرفة يستخدمها الوكيل باختياره

المهارة مجلد فيه ملف SKILL.md: وصف وتعليمات. يقرأ Claude الوصف، وعندما تطابق المهمة، يسحب المهارة بنفسه. إنها يستدعيها النموذج. المهارة هي طريقة تعليم الوكيل كيف يفعل فريقك شيئاً: قائمة مراجعة الكود، صيغة رسائل commit، خطوات عملية release.

---
description: Review a diff for our team's standards. Use when reviewing code or a PR.
---

When reviewing, check in this order:

1. Does it match the existing patterns in the file?
2. Error handling and edge cases.
3. Tests for the new behavior.
4. Security: secrets, input validation, injection.

الوصف هو أهم سطر: إنه ما يقرأه النموذج ليقرر هل المهارة ذات صلة، لذلك اكتبه عن متى تُستخدم هذه، لا عمّا تكون فقط. لا يحمّل الجسم إلا عندما تعمل المهارة، لذلك يمكن أن يكون بطول ما يحتاج.

ولأن المهارة نصيحة يختار النموذج اتباعها، فهي الرافعة الصحيحة للإرشاد، والرافعة الخاطئة لأي شيء يجب أن يحدث بلا فشل. لذلك hook هو المفهوم 8.

اكتب مهارة مرة واحدة، وكل أداة تقرؤها. هذه قوة المهارة كرافعة: تنسيق SKILL.md مشترك بين Claude Code وOpenCode وCodex. لتبقى المهارة قابلة للنقل، اجعل جسمها محايداً تجاه الأداة: اعتمد فقط على name وdescription في frontmatter، ولا تستخدم تراكيب خاصة بأداة مثل $ARGUMENTS أو allowed-tools أو disable-model-invocation. عندها يعمل الملف نفسه في كل مكان: يحمّله Claude Code من skills/ داخل plugin؛ ويجده OpenCode أصلاً في .opencode/skills/ أو .claude/skills/; وCodex في .agents/skills/. ملف skills/loop-engineering/SKILL.md في starter مثال كامل وقابل للنقل؛ اقرأه.

لماذا frontmatter فقط؟

يشتق كل مضيف اسم المهارة ويقرر متى يستدعيها من description. بعد هذين الحقلين، تختلف المضيفات: ما يدعمه أحدها قد يتجاهله آخر أو يتعطل عليه. لذلك أي شيء تضعه في الجسم ويخص أداة واحدة يكسر المهارة بصمت في غيرها. تعليمات عادية في الجسم، وحقلان في frontmatter، وتصبح المهارة عامة.

المفهوم 5: الوكلاء الفرعيون، تفويض بسياق جديد

الوكيل الفرعي مساعد يستطيع الوكيل الرئيسي تسليمه عملاً، مع نافذة سياق نظيفة خاصة به وتعليماته الخاصة. تعرّفه كملف markdown داخل مجلد agents/: frontmatter لاسمه ووصفه، والجسم لموجزه:

---
name: reviewer
description: Reviews a diff against our standards. Use after a change is written.
---

You review code in your own context. Check, in order: matches existing patterns,
error handling, tests, security. Report findings as a short ordered list.
Do not edit files — only review and report.

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

استخدم وكيلاً فرعياً عندما تكون المهمة مستقلة وقابلة للتحقق: "راجع هذا diff"، "اعثر على كل مكان تُستدعى فيه هذه الدالة"، "اكتب اختبارات لهذا الملف". يبقى الوكيل الرئيسي على الخط العام؛ ويدخل الوكيل الفرعي في العمق ثم يقدّم تقريراً.

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

المفهوم 6: خوادم MCP، المدى الخارجي الذي يمكن أن يشحنه plugin

تعطي الرافعة الرابعة الوكيل مدى لم يكن لديه: API داخلي، أو database، أو service. يحدث ذلك بالإشارة إلى خادم MCP، وقد بنيت واحداً بالفعل في Connector-Native Apps. لا تبني آخر هنا. وظيفة plugin كلها هي توصيله.

يتصل plugin عبر ملف .mcp.json في جذره: سمّ الخادم، وأعطه URL، واحمل مفتاح المستخدم في header. عندما يكون plugin مفعّلاً، يتصل host وتظهر أدوات الخادم للوكيل.

{
"mcpServers": {
"my-api": {
"type": "http",
"url": "https://api.yourdomain.com/mcp",
"headers": { "Authorization": "Bearer ${MY_API_KEY}" }
}
}
}

الخادم بعيد بالتصميم: تبقى المنطق والبيانات والأسرار على بنية تتحكم فيها، ولا يشحن plugin إلا ذلك المؤشر. هذا ما يجعل المدى ثابتاً، وفي المفهوم 10 قابلاً للضبط والبيع. plugin عميل رقيق؛ القيمة خلف URL. المفتاح في ذلك header هو أبسط بوابة: يفحصه خادمك، ويتوقف المفتاح الملغى عن العمل. أما ما هو أقوى فهو sign-in، وقد رأيته في دورة connector، والدورة التالية AI Identity كلها عن منح الوكلاء وصولاً محدوداً. لا تحتاجه هنا.

إذن من أين يأتي الخادم؟ من الخادم الذي بنيته بالفعل. افتح connector من الدورة السابقة، واطلب من وكيلك تشغيله، وانسخ URL الذي يطبعه إلى .mcp.json أعلاه. الخادم نفسه، باب أمامي ثانٍ: خدم connector تطبيق المحادثة؛ ويخدم هذا plugin وكيل البرمجة. أليس لديك connector جاهز؟ يشحن starter خادماً صغيراً قابلاً للتشغيل في reference/server/ لتوصيله. في الحالتين أنت تشير إلى خادم؛ لا تكتب خادماً داخل plugin.

لماذا لا نستخدم خادماً محلياً؟

يدعم Claude Code أيضاً خوادم MCP محلية، أي command يشغله host كعملية على جهاز المستخدم. نتجاوزها عمداً. يشحن الخادم المحلي كوده مع plugin ويعمل على حاسوب شخص آخر، فيكون قابلاً للنسخ مثل skill وب runtime لا تملكه. بالنسبة إلى plugin، يكون الخادم البعيد هو القرار الصحيح غالباً: ابنِه واستضفه مرة واحدة، ثم أشر إليه من أي عدد من plugins عبر URL.

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

Checkpoint: غُطّيت روافع القدرة. تضيف skills معرفة، وتضيف subagents مساعدة مركّزة، وتضيف MCP servers مدى؛ والثلاثة إرشادية: النموذج يقرر متى يستخدمها. الآن الرافعة التي ليست اختيارية.


الجزء 3: الرافعة الحتمية

المفهوم 7: hooks، كود يعمل كل مرة

hook أمر يشغّله المضيف تلقائياً عند نقطة ثابتة في دورة حياة الوكيل. ليس اقتراحاً للنموذج؛ إنه كودك، ينفّذه المضيف، وفق جدول لا يستطيع النموذج تغييره. هذه الخاصية وحدها هي سبب أهمية hooks أكثر مما تبدو أولاً.

تقع نقاط دورة الحياة (events) في ثلاث إيقاعات:

  • مرة في الجلسة: SessionStart، SessionEnd.
  • مرة في الدور: UserPromptSubmit قبل أن يرى الوكيل prompt جديداً، وStop عندما ينتهي الوكيل.
  • عند كل استدعاء أداة: PreToolUse قبل تشغيل الأداة، وهي النقطة الوحيدة التي تستطيع حظرها، وPostToolUse بعدها.

يعمل hook من نوع command بالطريقة نفسها كل مرة: يرسل المضيف له وصفاً JSON للحدث عبر standard input؛ يقرأ script ذلك، ويفعل عمله، ويعود ب exit code.

  • Exit 0: اسمح / انتهى.
  • Exit 2 عند PreToolUse: احظر استدعاء الأداة. أي شيء تطبعه إلى standard error يُسلّم للنموذج كسبب، حتى يعدّل.
  • أي non-zero آخر: خطأ غير حاجب؛ يُسجل، لكن الإجراء يستمر.

بطاقة مرجعية لل hooks في نصفين. متى يمكن أن يعمل hook: مرة في الجلسة (SessionStart، SessionEnd)؛ مرة في الدور (UserPromptSubmit، Stop)؛ وعند كل tool call (PreToolUse، الذي يستطيع الحظر، وPostToolUse). كيف يجيب command hook: exit 0 يسمح والأداة تعمل طبيعياً؛ exit 2 يحظر tool call عند PreToolUse ويسلّم stderr للنموذج كسبب؛ exit 1 يحذّر فقط، يُسجل لكن الإجراء يستمر، وهو خطأ شائع في الحواجز.

قاعدة exit-2 هي اللعبة كلها في guardrails، وهي أكثر ما يخطئه الناس (exit 1 لا يحظر). داخل plugin، تعيش hooks في hooks/hooks.json:

{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/format.sh"
}
]
}
],
"PreToolUse": [
{
"matcher": "Read|Edit|Write|Bash",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/block-secrets.sh"
}
]
}
]
}
}

matcher نمط يحدد الأدوات التي يعمل عليها hook (Write|Edit = كتابة ملفات؛ Bash = أوامر shell). متغير مسار جذر plugin يشير إلى مجلد plugin حتى يجد المضيف scripts الخاصة بك؛ تحقق من اسمه الدقيق مقابل إصدار Claude Code لديك، لأن SDK ومسارات plugin تتحرك.

المفهوم 8: ما يجب دائماً هو hook، لا تعليمة

هذه أهم فكرة في الدورة. كل ما تكتبه كتعليمات، في skill أو سطر CLAUDE.md، إرشادي. غالباً ما يتبعه النموذج، لكنه قد ينساه، أو ينفد سياقه، أو يقرر أن المحادثة انتقلت. معظم الإرشاد لا بأس به هكذا. أما أي شيء يجب أن يثبت كل مرة، فالنصيحة لا تكفي. hook يكفي.

نموذجان يحملان معظم القيمة العملية:

تهيئة عند الكتابة: PostToolUse. بعد كل تعديل ملف، شغّل المهيّئ. لم يعد على خرج النموذج أن يكون مثالياً في الأسلوب، لأن المهيّئ يطبّعه كل مرة:

#!/usr/bin/env bash
# hooks/format.sh — runs after every Write/Edit
path=$(jq -r '.tool_input.file_path // empty') # read the edited file's path from the event
[[ -n "$path" ]] && npx --yes prettier --write "$path" 2>/dev/null
exit 0

احظر ما لا يجوز أبداً: PreToolUse، exit 2. افحص tool call؛ فإذا تجاوزت خطاً، احظرها وأخبر النموذج لماذا. يغطي هذا الحاجز ملفات الأسرار و_الأوامر_ التدميرية، لذلك يقرأ حقلين من الحدث:

#!/usr/bin/env bash
# hooks/block-secrets.sh — runs before Read/Edit/Write/Bash
input=$(cat) # read the event ONCE (see note)
path=$(printf '%s' "$input" | jq -r '.tool_input.file_path // empty')
cmd=$(printf '%s' "$input" | jq -r '.tool_input.command // empty')

if [[ "$path" == *.env* || "$path" == */secrets/* ]]; then
echo "Blocked: $path is a secret file. Do not read or edit it." >&2 # stderr → the model
exit 2 # exit 2 → blocked
fi
if [[ "$cmd" == *"rm -rf"* || "$cmd" == *"git push --force"* ]]; then
echo "Blocked: refusing to run a destructive command ($cmd)." >&2
exit 2
fi
exit 0
الفخ ذو السطر الواحد: اقرأ الحدث مرة واحدة

يرسل المضيف الحدث عبر standard input، وstandard input هو stream: أول شيء يقرأه يستنزفه. إذا استدعيت jq مرتين مباشرة (path=$(jq …) ثم cmd=$(jq …))، تستهلك الدعوة الأولى الحدث كله ولا يصل للثانية شيء، فيصبح cmd فارغاً بصمت ولا يعمل حاجز الأوامر أبداً. التقطه مرة واحدة ب input=$(cat) وحلّل ذلك المتغير، كما في الأعلى. هذا هو الخطأ نفسه الذي يمسكه اختبار starter: كان سيشحن حاجزاً يبدو صحيحاً ويفشل بصمت عند rm -rf.

مهارة تقول "لا تقرأ .env أبداً" هي أمل. هذا hook ضمان.

شغّله. الصق هذا في وكيل البرمجة:

add a PostToolUse hook that formats files after Write/Edit, and a PreToolUse hook (matched on Read|Edit|Write|Bash) that blocks reads/edits of .env/secrets/ and blocks rm -rf in Bash, all with exit 2. Read the event once with input=$(cat). Then try to read my .env and run rm -rf and show me both are blocked, and edit a file and show me it got formatted.

(تبني واحداً هنا كي ترى الآلية. في المثال العملي ستستخدم نسخة starter المثبتة مسبقاً بدلاً من إعادة كتابتها؛ بناؤه مرة بنفسك هو طريقة الثقة به.)

شغّله بنفسك في طرفية (أوامر خام). اختبر hook كما يستدعيه المضيف: مرر له حدثاً مزيفاً عبر pipe وافحص exit code:

echo '{"tool_input":{"file_path":"/app/.env"}}' | ./hooks/block-secrets.sh; echo "exit: $?"   # expect: exit 2
echo '{"tool_input":{"command":"rm -rf /"}}' | ./hooks/block-secrets.sh; echo "exit: $?" # expect: exit 2
echo '{"tool_input":{"file_path":"/app/main.ts"}}' | ./hooks/block-secrets.sh; echo "exit: $?" # expect: exit 0

تحقق. تتطابق رموز الخروج الثلاثة: .env محظور (2)، وrm -rf محظور (2)، والملف العادي مسموح (0). إذا مرّت قراءة السر، ف hook يخرج ب 1 بدلاً من 2، وهذا أكثر خطأ شيوعاً. وإذا مرّ rm -rf بينما التقط .env، فأنت تقرأ stdin مرتين (انظر الفخ أعلاه). Exit 2، واقرأ مرة واحدة، وإلا فهو لا يحظر.

Checkpoint: الرافعة الحتمية تعمل. تستطيع جعل شيء يحدث عند كل تعديل، وإيقاف شيء عند كل tool call. هذا هو الفرق بين plugin يقترح وplugin يفرض.

عندما يسيء hook التصرف (الجزء الذي تتجاوزه الأدلة)

تعمل hooks عند كل tool call مطابق، لذلك يظهر أثر السيئ منها فوراً. أربع قواعد تبقيها خارج طريقك:

  • اجعلها سريعة. hook من نوع PreToolUse يوقف كل استدعاء مطابق، لذلك المنطق البطيء، مثل round-trip شبكي أو suite اختبارات كاملة عند كل تعديل، يعلّق الوكيل. استهدف أقل بكثير من ثانية؛ وضع العمل الثقيل في Stop، لا في كل call.
  • افشل بأمان، عن قصد. قرر ماذا يحدث عندما يفشل hook نفسه. المهيّئ الذي لا يستطيع العمل ينبغي أن يخرج ب 0 (دع التعديل قائماً)، لذلك ينتهي format.sh ب exit 0 ويبتلع أخطاء prettier. أما الحاجز فالعكس: إذا لم يستطع أن يقرر، فالأفضل أن يحظر. لا تدع حاجزاً ينهار ثم يسقط بصمت إلى exit 0.
  • قل لماذا، كل مرة تحظر. exit 2 بلا رسالة لا يعطي النموذج شيئاً يتصرف بناءً عليه، وسيعيد المحاولة نفسها. سطر stderr هو تعليمة الإصلاح؛ اجعله محدداً ("عدّل المصدر لا الملف المولّد").
  • صححه كما يستدعيه المضيف. مرر حدثاً مزيفاً عبر pipe واقرأ exit code (اختبار الأوامر الخام أعلاه). إذا بدا أن hook يعمل كثيراً، افحص matcher: ‏Write|Edit ضيق؛ أما matcher فارغ أو واسع فيعمل على كل شيء.

الجزء 4: الشحن

المفهوم 9: manifest والبنية

plugin في Claude Code مجلد يصفه manifest باسم .claude-plugin/plugin.json. (يمكن ل Claude Code أن يكتشف مجلدات المكوّنات القياسية تلقائياً حتى من دونه، لكن اشحن manifest، فهو يحمل الاسم والإصدار والوصف.)

{
"name": "agent-factory",
"description": "A portable skill, guard hooks, and a reviewer subagent.",
"version": "1.0.0",
"author": { "name": "Your Name" }
}

كل شيء آخر يقف عند جذر plugin، لا داخل .claude-plugin/، فهذا هو الخطأ البنيوي الذي يقع فيه الناس:

agent-factory/
├── .claude-plugin/
│ └── plugin.json # the manifest (this, and only this, goes here)
├── skills/ # skills as <name>/SKILL.md
├── agents/ # subagent definitions
├── hooks/
│ └── hooks.json # event → command wiring
└── .mcp.json # optional: MCP servers to load

version مهم للتحديثات: عندما ترفعه، يحصل المثبّتون على الإصدار الجديد؛ وإذا حذفته ووزّعت عبر git، فكل commit يُعد إصداراً جديداً. شغّل claude plugin validate قبل المشاركة، فهو الاختبار نفسه الذي يعمل في مراجعة marketplace.

الشجرة أعلاه هي plugin نفسه أينما وُضع. في starter يعيش داخل plugins/agent-factory/ ضمن مستودع marketplace، وهذا هو المفهوم التالي.

المفهوم 10: marketplaces، كيف يحصل عليه زميل

marketplace ليس إلا مستودع git فيه ملف كتالوج (marketplace.json) يسرد واحداً أو أكثر من plugins. هذه هي قصة التوزيع كلها: لا تنشر حزمة في registry؛ بل توجّه الناس إلى repo.

{
"name": "agent-factory",
"owner": { "name": "Your Name" },
"plugins": [
{
"name": "agent-factory",
"source": "./plugins/agent-factory",
"description": "A portable skill, guard hooks, and a reviewer."
}
]
}

بعدها يشغّل الزميل أمرين داخل Claude Code:

/plugin marketplace add your-org/agent-factory   # the git repo with marketplace.json
/plugin install agent-factory@agent-factory # plugin@marketplace
tip

أثناء التطوير، تجاوز marketplace. لديك حلقتان أسرع على جهازك: حمّل plugin مباشرةً من القرص باستخدام claude --plugin-dir ./plugins/agent-factory (ويقبل أيضاً ملف .zip)، أو أنشئ واحداً ب claude plugin init <name>، فيضعه داخل ~/.claude/skills/<name>/ ويحمّله تلقائياً في الجلسة التالية باسم <name>@skills-dir، بلا marketplace ولا install. marketplace للمشاركة؛ لا تحتاج إليه للبناء والاختبار.

note

لا تخلط بين manifestين. لدى plugin ملف .claude-plugin/plugin.json; ولدى marketplace ملف .claude-plugin/marketplace.json. يبقي التخطيط الموثق الاثنين منفصلين: يجلس marketplace.json في جذر المستودع، ويعيش كل plugin في مجلده الفرعي (./plugins/<name>/) ومعه plugin.json الخاص به. يستخدم starter هذا بالضبط: plugins/agent-factory/. (يمكن أن يكون مستودع واحد marketplace ويستضيف plugin واحداً، لكن إبقاء plugin داخل مجلد ./plugins/<name> هو نمط كل الأمثلة الرسمية؛ فضّله.)

التثبيت على ref وsources: كيف تعمل التحديثات فعلاً. يمكن أن يكون source في plugin مساراً نسبياً (كما في الأعلى)، أو كائناً يشير إلى مستودع آخر بالكامل؛ يستطيع marketplace سرد plugins من مستودعات كثيرة، وكل واحد منها مثبت مستقلاً:

{
"name": "code-formatter",
"source": { "source": "github", "repo": "acme/formatter", "ref": "v2.1.0" }
}

يثبّت ref فرعاً أو tag، ويثبّت sha commit بعينه، وعندما يوجدان معاً يفوز sha. هذا، لا ملف الكتالوج نفسه، هو كيف يحصل الزميل على إصدار محدد وكيف تشحن التحديثات. (يغطي source من نوع url GitLab ومضيفي git الآخرين؛ والمسار المحلي مفيد للاختبار.)

اعرف هذين الفخين قبل النشر:

  • لا تُحلّ المسارات النسبية إلا عندما يُضاف marketplace عبر Git (GitHub/GitLab/git URL). إذا أضافه شخص عبر URL مباشر إلى ملف marketplace.json، فلن يُحل ./plugins/...; استخدم حينها source من نوع github أو url.
  • تُنسخ plugins المثبتة إلى cache، لذلك لا يستطيع plugin الوصول إلى ملفات خارج مجلده ب ../. ضع كل ما يحتاجه plugin داخله؛ تتبع عملية النسخ symlinks ما دامت تشير إلى داخل plugin، ولهذا يستهدف رابطا starter ملفات داخل plugin نفسه.

تدير Anthropic كتالوجاتها الرسمية: claude-plugins-official (منسّق) والمجتمع claude-community، إذ تضيف مستودعه anthropics/claude-plugins-community وتثبّت منه باسم @claude-community. لذلك اختر اسماً مميزاً ل marketplace الخاص بك بدلاً من أن يطغى على تلك الأسماء. (قواعد التسمية والإرسال لا تزال فتية؛ تحقق من سياسة الأسماء المحجوزة الحالية مقابل مرجع plugins قبل النشر.)

التوزيع إلى فريق، أو إلى غير المبرمجين. في خطط Team وEnterprise، ينشر المالكون marketplace من Organization settings → Plugins؛ يضاف marketplace خاص ب Knowledge Work افتراضياً، وتظهر plugins التي توزعها في chat وفي Claude Cowork، أي أن الحزمة نفسها تصل إلى knowledge workers لا إلى البناة فقط (انظر السقف ودورة Cowork and OpenWork).

شغّل claude plugin validate قبل المشاركة. المخطط أعلاه هو الحالي حتى منتصف 2026؛ أعد التحقق من أسماء الحقول في مرجع plugins ل Claude Code قبل النشر، لأن هذه السطحية حديثة وتتحرك.

هل يمكنك أن تتقاضى ثمناً؟ نعم، لكن ليس على الملفات. marketplace كتالوج لا متجر: لا طبقة دفع، ولا فحص ترخيص، ولا primitive اشتراك في التنسيق. تبني الفوترة وفرض الوصول خارج نظام plugins. وهناك حافة حادة: skill ملف SKILL.md نصي بلا DRM. في اللحظة التي يثبّتها العميل، يمسك المصدر، لذلك وضع ملفات ثابتة خلف اشتراك يدعو إلى churn واحد لكل عميل: يدفع مرة، يستنسخ، يلغي. وبالنسبة إلى منهج تكون قيمته النص المقروء، تسلّم الملكية الفكرية عند أول تنزيل.

لذلك النموذج الوحيد الذي يدعم اشتراكاً حقيقياً هو الوصول المستضاف: أبقِ المنطق القيّم على خادم تملكه، وبِع الدخول إلى الخادم لا إلى الملفات. plugin المثبت عميل رقيق مجاني، يشير ملف .mcp.json فيه إلى خادم MCP المستضاف لديك مع مفتاح المستخدم في header (توصيل المفهوم 6)؛ المفتاح هو بوابة الاشتراك، وإبطاله يقطع الوصول فوراً. SKILL.md المجاني هو funnel؛ والخندق المدفوع هو ما لا ينسخه clone: الخادم المستضاف، وجودة retrieval، والبيانات الحية خلف URL.

هذه نسخة plugins من نمط بنيته بالفعل. تطبيق connector-native لا يواجه مشكلة الملفات القابلة للنسخ، لأنه خادم مستضاف خالص لا يضع شيئاً على قرص المستخدم. الشكل النظيف هو الاثنان معاً: plugin المجاني هو العميل والقمع، والاشتراك يركب على خادم connector-native خلفه. الخادم نفسه، باب أمامي ثانٍ. لكنه يقطع في الاتجاهين: يثق المستخدمون الآن بخادمك في طلباتهم، لذلك يعمل عقد الثقة في الجانبين (المفهوم 11).

تحذيران قبل أن تفوتر
  • لا تكسر سياسات استخدام Anthropic. إذا استهلك الطلاب Claude عبر خدمتك المستضافة، فيجب أن تكون رخصة ذلك الاستخدام وفوترته شرعيتين؛ المنطق نفسه الذي يجعل تمرير اشتراك Pro/Max شخصي إلى أدوات طرف ثالث مشكلة. إذا تحول هذا إلى دخل حقيقي، فاقرأ شروط Anthropic التجارية مباشرةً، لا مدونة، وتحقق من مسار الفوترة لاستخدام Claude الذي يطلقه خادمك.
  • الاستضافة تعني أنك تملك سطح الأمان. خادم MCP مدفوع ومحجوب بمفتاح هدف للهجوم، والعملاء الذين يدفعون يتوقعون الاستقرار. لذلك لا تعود أذونات الأدوات والتأكيدات لأي فعل كتابة أو حذف أو شبكة اختيارية. هذا هو الثابت 4، لكن المال فوقه الآن.
note

خطوة بشرية فقط. إنشاء repo git وإرساله إلى marketplace عملك أنت؛ يكتب وكيل البرمجة الملفات، لكنه لا يستطيع فتح حسابات أو الدفع باسمك. وكذلك /plugin install الذي يشغّله زميلك: هذا قرار ثقته (المفهوم التالي).

المفهوم 11: plugin يعمل داخل ثقة المستخدم

تراجع خطوة وانظر ماذا يستطيع plugin أن يفعل على الجهاز الذي يثبّته: تشغّل hooks أوامر shell، ويضاف bin/ الخاص به إلى path، وتعمل خوادم MCP لديه وتصل إلى الخارج. تثبيت plugin يعني تشغيل كود شخص آخر. هذا يقطع في الاتجاهين، وكلاهما عملك:

  • بصفتك مؤلفاً: أقل صلاحيات. فقط hooks التي تحتاج إليها، وب matchers أضيق ما يمكن. لا تصل إلى الشبكة أو نظام الملفات خارج الوظيفة. واجعل الثقة مقروءة: اشحن README يذكر، بكلمات واضحة، ماذا يفعل plugin على جهاز المثبّت:

    README.md — the trust contract
    What this plugin installs (skills, subagents, hooks, MCP servers)
    What hooks run, and when (e.g. PostToolUse formatter on Write/Edit)
    What files they inspect (e.g. reads tool_input.file_path; never opens .env)
    What commands they execute (e.g. prettier; no network calls)
    What network access they use (ideally: none)

    يستطيع مثبّت يقرأ ذلك في عشر ثوان أن يثق بك في عشر ثوان.

  • بصفتك مثبّتاً: راجع قبل التثبيت كما تراجع dependency. فضّل marketplaces التي تثق بها؛ واقرأ ماذا تفعل hooks؛ وتذكّر أن hook باسم PreToolUse يرى كل tool call. قبل أن تثق بواحد، شغّل claude plugin details <plugin>: يطبع inventory المكوّنات، أي skills وsubagents وhooks وMCP servers التي يشحنها، والكلفة المتوقعة بال tokens، من دون تفعيل أي شيء. hooks هي السطر الذي يجب أن تقرأه أولاً.

هذا هو الثابت 4، وليس عملاً ورقياً: hook للتهيئة يرفع ملفاتك بصمت سيكون غير مرئي حتى تقرأه. اشحن plugins تستطيع أنت تثبيتها براحة.

Checkpoint: تستطيع الشحن. manifest وبنية وmarketplace يثبّت منه زميل، ورؤية واضحة للثقة التي تشحنها. مضيف آخر، ثم البناء الكامل.


الجزء 5: Plugins في OpenCode

المفهوم 12: Plugins في OpenCode، hooks ككود

يأخذ OpenCode الأفكار نفسها بشكل مختلف: plugin هو وحدة JavaScript/TypeScript تصدّر دالة. يستدعي المضيف دالتك مع كائن context وتعيد أنت hooks، أي handlers لأحداث الوكيل. لا يوجد manifest منفصل؛ تضع الملف في .opencode/plugins/ أو تثبّت حزمة npm.

warning

تحقق من هذا القسم مقابل إصدارك. واجهة plugins في OpenCode أحدث وأكثر قرباً من الكود من الشكل التصريحي في Claude Code، لذلك تتحرك أسماء الأحداث والتواقيع الدقيقة أدناه (tool.execute.before، وsession.idle، وhelper باسم tool) أسرع من بقية الدورة. هي صحيحة حتى منتصف 2026، لكن راجعها مقابل @opencode-ai/plugin المثبت لديك قبل أن تعلّم أو تشحن من هذا القسم.

فرق مهم عن Claude Code: في OpenCode، plugin مخصص ل hooks والأدوات، لا للمهارات. يكتشف OpenCode المهارات أصلاً من مجلدات (.opencode/skills/ و.claude/skills/ و.agents/skills/)، لذلك لا تحتاج ملفات SKILL.md المحمولة إلى plugin ولا shim هنا إطلاقاً. يوجد plugin للجزء الذي لا ينتقل: hooks.

// .opencode/plugins/block-secrets.ts
import type { Plugin } from "@opencode-ai/plugin";

export const BlockSecrets: Plugin = async ({
project,
client,
$,
directory,
}) => {
return {
// runs before any tool — throw to block it (the OpenCode equivalent of exit 2)
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath?.includes(".env")) {
throw new Error("Blocked: .env files are off-limits.");
}
},
};
};

ينتقل النموذج الذهني مباشرة من Claude Code: ‏tool.execute.before هو PreToolUse، وtool.execute.after هو PostToolUse، ورمي خطأ يحظر الاستدعاء كما يفعل exit 2. يشغّل OpenCode أيضاً أحداث جلسة وملفات (session.idle وfile.edited وغيرها)، ويمكن ل plugin إضافة أداة مخصصة عبر helper باسم tool: فكرة "إضافة مدى" نفسها كما في خادم MCP، لكنها مكتوبة inline.

يعطيك كائن context ما تحتاج إليه: project وdirectory (أين أنت)، و$ (تشغيل أوامر shell)، وclient (التحدث إلى الوكيل والتسجيل). الشكل يختلف؛ الثوابت الأربعة لا تختلف. قاعدة must-always تظل hook هنا، لكنها دالة ترمي خطأ بدلاً من script يخرج ب 2.


الجزء 6: مثال عملي كامل: ابنِ plugin باسم agent-factory

لقد شغّلت agent-factory المكتمل في Quick Win. الآن تبنيه أنت، من الفراغ، رافعة بعد رافعة، موجهاً وكيلك بإنجليزية واضحة. عندما تعود قطعة خاطئة، تفرقها مقابل reference/، أي build المثبت الذي ثبّته للتو. أنت لا تملأ stubs؛ بل تتخذ قرارات (أي رافعة، أمل أم ضمان، ما الذي يسافر) وتثبت كل واحدة. الإيقاع هو الذي تعرفه: خطّط → راجع → نفّذ → تحقق.

عندما تنتهي، يعرض agent-factory الروافع الأربع: skill محمولة لعمل حقيقي لديك، وreviewer subagent، وguard hook مع format-on-write hook، وخادم MCP موصول عبر URL، وmarketplace يثبّته زميل. يأتي guard must-always أولاً، لأنه الجزء الذي يجب أن يكون صحيحاً.

1. ابنِ scaffold ل plugin فارغ. يوجّه prompt وكيلك إلى التخطيط المعتمد لمضيفك. الصق ما يخص مضيفك:

Using the Plugin Structure skill you installed in setup, scaffold an empty plugin called agent-factory, set up the right way for Claude Code. Show me the layout.

Read the OpenCode plugin docs at https://opencode.ai/docs/plugins, then scaffold an empty OpenCode plugin called agent-factory the way they describe. Show me the layout.

ينتهي عندما: يطابق shell تخطيط مضيفك (يمكن للوكيل المقارنة بالنسخة المرجعية إن شك). في Claude Code، ينجح claude plugin validate على plugin الفارغ.

2. ابنِ guard hook أولاً، رافعة must-always، وأثبت أنه يحظر. هذا هو الجزء الذي يجب أن يكون صحيحاً، لذلك تبنيه وتثبته ثم تفحصه مقابل النسخة المثبتة. الصق:

Add two house rules my agent can't skip: auto-format any file right after it's changed, and hard-block anything that reads my secrets or runs a destructive command. Prove both live: have it try a secret read and a destructive command and show me they're stopped, then edit a file and show me it came back formatted.

ثم افحص عملك مقابل build المثبت بدلاً من الثقة به:

Compare my guard against the proven one and tell me if I missed anything that would keep it from actually blocking.

ينتهي عندما: يحظر guard قراءة .env وأمراً تدميرياً مباشرة، ولا تكشف المقارنة مع المرجع فجوة مهمة. (يتخذ guard شكلاً مختلفاً في كل host: script shell في Claude Code، ودالة ترمي خطأ في OpenCode، والمرجع يحوي الاثنين. يبني وكيلك الشكل الذي يستخدمه مضيفك.)

3. ابنِ skill لعمل تفعله فعلاً. ليست لعبة: اختر شيئاً متكرراً حقيقياً، مثل checklist المراجعة، أو تنسيق commit messages، أو خطوات release. الصق:

Look at the model skill in the reference build first. Then write me a skill for [a real, repetitive job you do]: a clear description of when to use it and the steps to follow. Keep it portable so it works in any agent, not just this one. Show it firing on a real example.

ينتهي عندما: تعمل skill من تلقاء نفسها عندما تلائمها المهمة، ويكون جسمها محمولاً (أبقاها الوكيل تعليمات واضحة بلا constructs خاصة بأداة معينة).

4. أضف reviewer subagent. الصق:

Add a subagent that reviews a change in its own context and only reports, never edits. Run it on a real diff, show me what it finds, then compare it to the model reviewer.

ينتهي عندما: يراجع subagent داخل سياق نظيف ويبلغ قائمة مرتبة؛ ولا تظهر المقارنة مع المرجع شيئاً مهماً مفقوداً.

5. وصّل خادم MCP، واجعل plugin يشير إلى خادم يعمل. لا تكتب الخادم. تشير إلى واحد لديك بالفعل: connector الذي بنيته في الدورة السابقة، أو sample القابل للتشغيل في starter. الصق:

Start the sample MCP server in the starter and wire my plugin to it, then show me the agent can call one of its tools.

(تفضل خادمك؟ اطلب من وكيلك تشغيل connector من الدورة السابقة واستخدام ذلك URL.) التوصيل الذي يكتبه وكيلك هو المكان الوحيد الذي يختلف فيه المضيفان فعلاً؛ هذا هو الشكل في كل واحد:

اشحن .mcp.json في جذر plugin (يسافر مع plugin):

{
"mcpServers": {
"agent-factory": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": { "Authorization": "Bearer ${AGENT_FACTORY_KEY}" }
}
}
}

تأكد عبر /mcp: يظهر الخادم متصلاً ويمكن استدعاء أداته.

أضف remote block إلى opencode.json:

{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"agent-factory": {
"type": "remote",
"url": "http://localhost:3000/mcp",
"enabled": true
}
}
}

ينتهي عندما: يعرض مضيفك الخادم متصلاً ويمكن استدعاء أداته.

6. اجعله قابلاً للتثبيت، وأثبت أنه يسافر. الصق:

Make this installable from a marketplace. Then prove it travels: install it into a different project and show the guard blocks a secret read there too, with no extra setup.

ينتهي عندما: يحمي hook نفسه مشروعاً ثانياً من خلال تثبيت واحد. هذه هي فكرة plugin كلها: القاعدة تسافر.

لاحظ الإيقاع: خطّط → راجع → نفّذ → تحقق، مع بناء guard must-always وإثباته أولاً لأنه الجزء الذي يجب أن يكون صحيحاً، وفحص كل قطعة مقابل المرجع المثبت. كان الحكم لك طوال الوقت؛ والكتابة للوكيل.


الجزء 7: السقف، وأين ينمو

المفهوم 13: السقف، والجسور إلى الخارج

اشعر بحافة ما يكونه plugin. يحسّن plugin وكيل الباني: أذكى، أكثر أماناً، وأقرب إليك. لكن ثلاثة أشياء لا تزال ليست لك، وكل واحد منها يسمّي الدورة التالية.

الحلقة ليست لك. تعمل hooks حول حلقة host؛ لكنها لا تشغّل حلقة خاصة بها. لا يستطيع plugin أن يستيقظ، أو يلاحق هدفاً عبر خطوات كثيرة وحده، أو ينجز عملاً وأنت نائم. عندما تريد worker يملك حلقته، تكتب agent، وهذا هو Build AI Agents لاحقاً في المسار.

الهوية ليست لك. يعمل plugin بوصف الشخص الذي يشغّل host. لا يملك credential خاصاً به ولا طريقة للعمل نيابة عن شخص بسلطة محدودة وقابلة للإلغاء. عندما يحتاج agent إلى هويته الخاصة، ويحتاج شخص إلى تفويضه بسلام، فذلك هو AI Identity (مبني على Better Auth): امتلك sign-in، ثم امنح agent وصولاً scoped ومحدود الزمن وبموافقة بشرية.

المدى مستعار. يستطيع plugin توصيل خادم MCP بعيد، لكن الخادم نفسه، الشيء الدائم المواجه للمستخدم الذي يلصقه غريب في تطبيق المحادثة، بحالته وsign-in الخاصين به، هو تطبيق connector-native الذي بنيته في الدورة السابقة. تشير plugins وconnectors إلى الخادم نفسه من مضيفين؛ ومعاً يغطيان الاثنين.

لكن لاحظ اتجاه الحدود، وأين ينمو هذا. ما بنيته يصل إلى ما بعد وكيل البرمجة. داخل عائلة Anthropic، تُحمّل حزمة .claude-plugin نفسها في Claude Cowork وclaude.ai chat؛ ويُحمّل plugin ل OpenCode في OpenWork أيضاً. والقطعة المحمولة، أي skill، تسافر أبعد، إلى وكيل شخصي مثل OpenClaw وما بعده. لذلك تستطيع skill كتبتها لوكيل الباني أن تنتقل بلا تغيير إلى وكيل عامل معرفة: المحامي، والمحلل، وقائد العمليات. (الاستثناء هو hook shell. يحتاج إلى shell حقيقي، لذلك يبقى guard في جهة البرمجة بينما تعبر skill إلى مضيفي chat.) عندما تكون مضيفات knowledge work هي القصة كلها لا مجرد bonus، فذلك له دورة خاصة: Cowork and OpenWork.

لم تهدر خطوة. تعلمت أن توسّع وكيلاً بشكل حتمي وأن تشحنه إلى فريق؛ وهي المهارات نفسها التي ستعيد استخدامها عندما يصبح agent، وهويته، ملكك.

الهيكل نفسه، وplugins أخرى

agent-factory شكل واحد. لا تتغير الروافع؛ تتغير الوظيفة فقط:

  • Plugin لأسلوب الفريق: skill تحمل قواعد الكتابة أو الكود لديك، وformatter PostToolUse، وreviewer subagent. (لفريق يريد صوتاً متسقاً واحداً.)
  • Plugin أمان: guards من نوع PreToolUse لأهداف الإنتاج، والأسرار، والأوامر التدميرية؛ ولا شيء غير ذلك. (أقل صلاحية، الثابت 4.)
  • Plugin خدمة: خادم MCP بعيد (.mcp.json) ل API المستضاف لديك، مع skill تعلّم الوكيل كيف يستخدمه.
  • Plugin سير عمل: hook من نوع Stop يشغل test suite عندما ينتهي الوكيل، وskill لخطوات release.

اختر الأقرب إلى ألم حقيقي لدى فريقك؛ البناء هو نفسه في المثال العملي.

المشروع الختامي

اشحن plugin خاصاً بك. اختر احتكاكاً حقيقياً في طريقة عمل فريقك مع وكيل برمجة. ابنِ plugin يصلحه بالروافع الصحيحة: hook واحد على الأقل يفرض قاعدة must-always (exit 2 أو thrown error)، ورافعة قدرة واحدة على الأقل (skill أو subagent أو MCP server). انشره إلى marketplace واجعل شخصاً آخر يثبّته. تأكد أن hook يعمل لديه، في مشروعه، بلا إعداد إضافي.

1Your Work
2Get Your Score

Discuss with an AI. Question your scores.
Come back when you have your BEST evaluation.