---
title: 'تعديلات Claude Code: ١٠ حالات استخدام مُجربة (٢٠٢٦)'
description: 'شرح إضافات Claude Code مع ١٠ حالات استخدام مُجربة: حماية الأوامر الخطيرة، إخفاء الأسرار، إضافة أوامر، وألواح وأدوات. كل مثال يجتاز اختبار claude plugin.'
url: https://nerdleveltech.com/ar/claude-code-mods-use-cases-examples
language: ar
date: '2026-10-09'
category: tooling
tags:
  - claude code
  - claude code mods
  - claude code plugins
  - agentic coding
  - ai agent safety
  - typescript
  - developer tools
markdown_url: https://nerdleveltech.com/ar/claude-code-mods-use-cases-examples.md
attribution: 'Source: NerdLevelTech — https://nerdleveltech.com/ar/claude-code-mods-use-cases-examples'
terms: https://nerdleveltech.com/llms.txt
---

# تعديلات Claude Code: ١٠ حالات استخدام مُجربة (٢٠٢٦)

تعد إضافات Claude Code (المعروفة بـ mods) عبارة عن ملحقات تعمل وظائف الـ JavaScript أو TypeScript الخاصة بها داخل Claude Code عند وقوع حدث معين: استدعاء أداة، أو مطالبة (prompt)، أو دورة (turn)، أو إعادة رسم. أدناه يوجد 10 إضافات تعمل لمهام شائعة، بدءاً من حماية الأوامر الخطيرة وصولاً إلى رسم الأجزاء (panes)، وكل واحدة منها تجتاز `claude plugin test`.

## ملخص

أضافت Anthropic الإضافات (mods) إلى Claude Code في 1 أكتوبر 2026، في الإصدار 2.1.287.[^1][^2] تقوم الإضافة بربط حدث معين ويمكنها مراقبته، أو إعادة كتابته، أو الرد عليه بدلاً من Claude Code، كما يمكنها رسم أجزاء (panes)، وأشرطة (bands)، وخطوط حالة خاصة بها.[^3]

لقد كتبنا 10 إضافات للمهام اليومية وتحققنا منها على Claude Code 2.1.295. جميع الإضافات العشر تجتاز `claude plugin validate`، وجميع اختبارات الوحدة الـ 25 تجتاز بنجاح، كما أن ستة منها عملت كما هو متوقع في عمليات تشغيل `claude -p` حية. الكود أدناه منسوخ من الملفات التي تم اختبارها.

تعمل الإضافات بصلاحياتك وليست معزولة (sandboxed)، لذا اقرأ الإضافة قبل تثبيتها.[^3]

## ما ستتعلمه

- ما هي إضافة Claude Code، ومتى تختارها بدلاً من خطافات الإعدادات (settings hooks)، أو المهارات (skills)، أو خادم MCP
- الملفات الثلاثة التي تحتاجها كل إضافة، وكيفية تحميلها والتحقق منها واختبارها
- 10 حالات استخدام مختبرة مع الكود الكامل: حواجز الأمان، سياق المطالبة، الأوامر، الأجزاء، أداة مخصصة ومراقب خلفي
- ما الذي تغير في الأسبوع الأول بعد الإطلاق، والقيود التي قد تسبب ارتباكاً للمستخدمين
- كيف تتحكم الفرق والمؤسسات في الإضافات التي يتم تشغيلها

## ما هي إضافة Claude Code؟

إضافة Claude Code هي ملحق يقوم الكود الخاص به بتسجيل معالجات للأحداث، تسمى خطافات (hooks).

توضح وثائق Anthropic الأمر كالتالي: "الإضافة هي ملحق يغير مظهر وسلوك Claude Code. وهي تتكون من معالجات أحداث JavaScript أو TypeScript."[^3] ويصفها الإعلان بأنها "وظائف TypeScript صغيرة" يمكنها إعادة كتابة مطالبة، أو إضافة واجهة مستخدم جديدة، أو استبدال ميزة مدمجة، أو إضافة وظائف جديدة.[^1]

يحصل كل خطاف على نفس الوسائط الثلاثة:[^4]

- **`$`**، وهو API الخاص بالإضافات: كل طريقة يمكن للإضافة استدعاؤها، مجمعة في مساحات أسماء مثل `$.ui` و `$.fs` و `$.process`
- **`e`**، وهو الحدث: بيانات بسيطة ومجمدة مثل اسم استدعاء الأداة ووسائطها
- **`next`**، وهو المعالج التالي: يقوم بتمرير الحدث إلى الإضافات الأخرى ثم إلى سلوك Claude Code نفسه

ما يفعله الخطاف بـ `next` هو ما يحدد نوع الخطاف. إذا قمت بإرجاع `next(e)` فهو يقوم فقط بـ **المراقبة**. وإذا مررت لـ `next` نسخة معدلة فهو يقوم بـ **إعادة كتابة** الحدث. أما إذا أرجعت نتيجة دون استدعاء `next` فهو يقوم بـ **الرد** على الحدث بنفسه، وبالتالي لا يتم تشغيل سلوك Claude Code الأصلي أبداً.[^5]

### الإضافات مقابل خطافات الإعدادات، المهارات وخوادم MCP

كان Claude Code يحتوي بالفعل على خطافات إعدادات، ومهارات، وخوادم MCP، وتقارن الوثائق بين الأربعة. باختصار: الإضافة هي الوحيدة التي تعمل داخل عملية (process) Claude Code والوحيدة التي يمكنها الرسم في واجهة المستخدم.[^3]

|                           | Mod                                                                                | Settings hook                                                                                         | Skill                                 | MCP server                             |
| ------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------- | -------------------------------------- |
| ما هو                     | وظائف في إضافة (plugin) يستدعيها Claude Code في عمليته الخاصة                      | أمر shell، أو طلب HTTP، أو prompt يقوم Claude Code بتشغيله عند حدث في دورة الحياة (lifecycle event)   | ملف تعليمات `SKILL.md` يقرأه Claude   | عملية أو خدمة خارجية تمنح Claude أدوات |
| ما الذي يمكنه تغييره      | استدعاءات الأدوات، الـ prompts، الأوامر، الأدوار (turns)، وما ترسمه الواجهة        | ما إذا كان استدعاء الأداة أو الـ prompt سيستمر، وسائط ونتيجة استدعاء الأداة، والسياق المضاف لـ Claude | ما يعرفه Claude وما يفعله             | الأدوات التي يمتلكها Claude            |
| هل يمكنه الرسم في الواجهة | نعم                                                                                | لا                                                                                                    | لا                                    | لا                                     |
| ما الذي تكتبه             | JavaScript أو TypeScript                                                           | سكربت بالإضافة إلى إدخال في `settings.json`                                                           | Markdown                              | سيرفر بأي لغة برمجة                    |
| اختره عندما               | تريد لوحة (pane)، أو شريطاً فوق الـ prompt، أو أمراً مخصصاً، أو إعادة كتابة حدث ما | تريد حظر أو السماح أو تسجيل حدث باستخدام سكربت لديك بالفعل                                            | تستمر في لصق نفس التعليمات في الدردشة | يحتاج Claude للوصول إلى نظام خارجي     |

مقتبس من وثائق Claude Code، "Mods overview".[^3] يمكن للإضافة أن تحتوي على العناصر الأربعة معاً، لذا يمكن شحن mod بجانب skill و MCP server.

## كيف تقوم ببناء واختبار Claude Code mod؟

تحتاج إلى Claude Code 2.1.287 أو إصدار أحدث في الـ terminal. علامة تبويب Code في تطبيق Desktop تشغل الـ mods من إصدار 2.1.286.[^3] لا تحتاج إلى Node.js أو خطوة بناء (build step)، لأن Claude Code يحمل ملفات `.js` و `.ts` مباشرة.[^4]

يتكون الـ mod من ثلاثة ملفات:[^4][^9]

```text
my-mod/
├── .claude-plugin/
│   └── plugin.json      # the plugin manifest: name, version, description
└── hooks/
    ├── hooks.json       # {"modules": ["./register.js"]} points at your code
    └── register.js      # your hooks module, which exports register(on)
```

كل mod في هذا المنشور يستخدم نفس ملفي JSON، مع تغيير الاسم والوصف فقط. إليك الملفات الخاصة بالأول:

```json
{
  "name": "confirm-risky",
  "version": "0.1.0",
  "description": "Asks before Claude runs a destructive shell command",
  "author": { "name": "NerdLevelTech" }
}
```

```json
{
  "modules": ["./register.js"]
}
```

ثلاثة أوامر تغطي الدورة الكاملة:[^4][^8][^9]

```bash
# Load the mod for one session; Claude Code hot-reloads it when you save
claude --plugin-dir ./confirm-risky

# See what Claude Code reads from the mod: the events it hooks and the API calls it makes
claude plugin validate ./confirm-risky

# Run the mod's *.test.ts files with no session, sign-in or network
cd confirm-risky && claude plugin test
```

يمكنك أيضاً وصف الـ mod الذي تريده في جلسة Claude Code وتترك Claude يكتبه. يستخدم Claude مهارة (skill) مدمجة تسمى `plugin-authoring` لهذا الغرض، ولا يعمل الـ mod إلا بعد موافقتك عليه.[^4]

### كيف اختبرنا هذه الـ 10 mods

كتبنا كل mod يدوياً من الوثائق الرسمية وتصريحات الأنواع (type declarations) التي يشحنها Claude Code لإصداره، ثم أجرينا ثلاثة فحوصات في 9 أكتوبر 2026 باستخدام Claude Code 2.1.295:

1. `claude plugin validate` على كل mod. اجتازت جميع الـ 10 الفحص.
2. `claude plugin test` مع 2 إلى 4 اختبارات لكل mod، بإجمالي 25 اختباراً. اجتازت جميع الـ 25 الفحص.
3. تشغيل مباشر لـ `claude -p` باستخدام نموذج Haiku في مستودع git مؤقت، لسبعة mods. ستة منها عملت كما هو متوقع. السابع، وهو turn receipt، اجتاز اختباراته، ولكن `claude -p` يطبع الإجابة فقط، لذا لا يظهر السطر الخاص به هناك وقد تحققنا منه عبر الاختبارات فقط.

تظهر الـ Mods التي تقوم بالرسم فقط في الطرفية (terminal) التفاعلية أو تطبيق سطح المكتب.[^3] لقد قمنا برسم الشريط واللوحة باستخدام `$.ui.mount` الخاصة بمجموعة أدوات الاختبار، والتي تقوم بتصيير موقع بدون جلسة، وتحققنا من سطر الحالة عن طريق عمل stub لـ `$.ui.status`.[^8]

الاختبار هو ملف TypeScript يقوم بإثارة الأحداث وعمل stub لأي شيء قد يجيب عليه Claude Code. هذا هو الاختبار الخاص بـ push guard في حالة الاستخدام 2. يقوم بالرد على `$.process.run` باسم فرع وهمي، لذا لا يتم تشغيل أي `git`:[^8]

```typescript
import { expect, test } from 'claude-code/testing'

// Stubs what the permission rules decided and what git says the current branch is,
// and counts how often the mod ran git
function stubs(on, branch: string, rules = 'allow') {
  const runs = { git: 0 }
  on('tool.check', () => ({ decision: rules }))
  on('process.run', () => {
    runs.git += 1
    return { value: { exitCode: 0, stdout: branch + '\n', stderr: '' } }
  })
  return runs
}

test('git push while main is checked out is denied', async ($, on) => {
  stubs(on, 'main')
  const out = await $.tool.check({ tool: 'Bash', input: { command: 'git push' } })
  expect(out.decision).toBe('deny')
})

test('a push that targets main from another branch is denied', async ($, on) => {
  stubs(on, 'feature/login')
  for (const command of ['git push origin main', 'git push origin HEAD:main', 'git push origin +main', 'git push origin feature/login:refs/heads/main', 'git push --force origin main;', 'git push origin "main"']) {
    const out = await $.tool.check({ tool: 'Bash', input: { command } })
    expect(out.decision).toBe('deny')
  }
})

test('a feature branch push keeps the rules decision', async ($, on) => {
  stubs(on, 'feature/login')
  const out = await $.tool.check({ tool: 'Bash', input: { command: 'git push origin feature/login' } })
  expect(out.decision).toBe('allow')
})

test('other commands never run git', async ($, on) => {
  const runs = stubs(on, 'main', 'ask')
  const out = await $.tool.check({ tool: 'Bash', input: { command: 'npm test' } })
  expect(out.decision).toBe('ask')
  expect(runs.git).toBe(0)
})
```

![مخرجات الطرفية من Claude Code 2.1.295 تظهر نجاح claude plugin validate لـ push-guard mod، ونجاح اختباراته الأربعة، وعدد مرات النجاح والفشل للتسعة mods الأخرى. تم إزالة التوقيتات واختصار المسارات.](https://nerdleveltech.com/images/claude-code-mods-use-cases-examples-test-run.png)

![جدول يوضح الـ 10 Claude Code mods التي تم بناؤها لهذا الدليل، مع الأحداث التي يستخدمها كل منها، وما يفعله الـ hook الخاص بها، وأين تظهر، وعدد اختباراتها، وما إذا كان قد تم التحقق منها أيضاً في تشغيل claude -p مباشر.](https://nerdleveltech.com/images/claude-code-mods-use-cases-examples-matrix.png)

## 1. السؤال قبل أن يقوم Claude بتشغيل أمر shell تدميري

استخدم هذا إذا كنت تسمح لـ Claude بتشغيل أوامر shell ولكنك تريد مراجعة بشرية للأوامر التي لا يمكن التراجع عنها.

يمكن لـ hook من نوع `tool.call` إيقاف استدعاء الأداة بينما يطرح عليك سؤالاً. يقوم `$.ui.ask` بإظهار السؤال في الحوار الذي يستخدمه Claude للأسئلة وينتهي بالوصول إلى التسمية (label) التي تختارها. يتم رفض الطلب عندما تغلقه، وفي تشغيل `claude -p` حيث لا يمكن لأحد الإجابة.[^5] لذا يبدأ الـ hook من "الرفض" (Refuse) ولا يشغل الأمر إلا عند اختيار "تشغيله" (Run it) بشكل صريح.

```javascript
// Commands worth a second look: recursive deletes (rm -r, -R, -rf, -f -r, rm dir -rf, --recursive),
// hard resets, and force pushes (--force, -f, or a +branch refspec)
const RISKY = [
  /\brm\b.*\s-[a-zA-Z]*[rR][a-zA-Z]*(?=\s|$)/,
  /\brm\b.*\s--recursive\b/,
  /\bgit\s+reset\s+--hard\b/,
  /\bgit\s+push\b.*(?:\s--force\b|\s-f\b|\s\+\S)/,
]

export function register(on) {
  on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
    // Everything else runs as usual
    if (!RISKY.some((pattern) => pattern.test(e.command))) return next(e)
    // Start from the safe answer, so a question nobody answers refuses the command
    let answer = 'Refuse'
    try {
      // The tool call waits here until you pick an option; Refuse is listed first
      answer = await $.ui.ask('Run this command? ' + e.command, ['Refuse', 'Run it'])
    } catch {
      // Dismissed, or a claude -p run with nobody to ask
    }
    if (answer !== 'Run it') {
      return { deny: 'The user declined this command. Ask before trying another approach.' }
    }
    return next(e)
  }).catch(async ($, e, next) => {
    // If the guard itself fails before the command ran, refuse instead of failing open
    return next.called ? next(e) : { deny: 'The confirm-risky guard failed, so this command was not run.' }
  })
}
```

تعتبر `.catch` مهمة هنا. أي hook يتسبب في خطأ (throw) أو ينتهي وقته قبل استدعاء `next` يتم تخطيه، وسيعمل الأمر. يقوم معالج `.catch` بالرد بدلاً منه، لذا فإن هذا الحارس يفشل في حالة الإغلاق (fails closed).[^5]

تغطي ثلاثة اختبارات ستة أوامر آمنة يجب ألا تثير سؤالاً (من بينها `rm notes.txt` و `docker rm -f web` و `npm run build -- --force-color`)، وثمانية أوامر خطيرة يجب رفضها (`rm -rf` و `rm -Rf` و `rm -R` و `rm -f -r` و `rm build -rf` و `rm --recursive` و `git reset --hard` و force push لـ `+main`)، وأمر `git push -f` معتمد.

في تجربة حية، طلبنا من Claude تشغيل `rm build -rf` مع تحميل الـ mod. رد Claude قائلاً "تم رفض الأمر، لذا لم يتم تشغيل أي شيء و `build` لم يمس". وكان مجلد `build` لا يزال موجوداً.

تنبيه واحد: الأنماط تعتمد على مطابقة النصوص. فهي تغفل الأوامر التدميرية التي لا تشبه هذه الأنماط، مثل `find . -delete` أو سكربت يقوم بحذف الملفات، لذا تعامل مع الـ mod كمطب للسرعة وليس كبيئة معزولة (sandbox). يمكنه أيضاً السؤال عن أوامر غير ضارة، مثل تشغيل `grep -r` بعد `git rm`. تم وضع "الرفض" (Refuse) أولاً عن قصد، حتى لا يؤدي الضغط غير المقصود على Enter إلى تشغيل الأمر.

## 2. منع الـ pushes إلى main، بغض النظر عما تقوله القواعد

هذا مخصص للفرق التي تريد من Claude أن يقوم بعمل push لفروع الميزات (feature branches) ولكن ليس لـ `main` أبداً.

يتم إطلاق `tool.check` بعد أن تقرر قواعد الأذونات و hooks الإعدادات ما إذا كان الاستدعاء يمكن أن يعمل، وينتهي `next(e)` بهذا القرار: `allow` (سماح)، أو `ask` (سؤال)، أو `deny` (رفض). يمكن للـ hook أن يعيد قراراً مختلفاً.[^5]

وهذا يجعلها الحدث المناسب لفحص يعتمد على ما هو صحيح في الوقت الحالي، مثل الفرع الحالي. يرفض هذا التعديل (mod) أي عملية push تحدد `main` كهدف لها (`origin main`، أو `HEAD:main`، أو `+main`، أو `refs/heads/main` أو `"main"` بين علامتي تنصيص)، وأي عملية push بينما يكون `main` هو الفرع النشط (checked out).

```javascript
export function register(on) {
  // tool.check fires after your permission rules and settings hooks have decided
  on('tool.check', { tool: 'Bash' }, async ($, e, next) => {
    // What the rules decided: allow, ask, or deny
    const decided = await next(e)
    const command = e.input.command
    if (!/\bgit\s+push\b/.test(command)) return decided
    // A push that names main as its target: "origin main", "HEAD:main", "+main", "refs/heads/main", "'main'"
    const namesMain = /\bgit\s+push\b.*(?:[\s:+'"]|refs\/heads\/)main(?=$|[\s;&|'"])/.test(command)
    // Or any push while main is checked out
    const branch = await $.process.run(['git', 'branch', '--show-current'])
    const onMain = branch.exitCode === 0 && branch.stdout.trim() === 'main'
    if (!namesMain && !onMain) return decided
    return { decision: 'deny', reason: 'Pushing to main is blocked here. Push a feature branch and open a pull request instead.' }
  }).catch(async ($, e, next) => {
    // If the check fails, for example git can't run, refuse the push rather than let it through
    return { decision: 'deny', reason: 'push-guard could not check this push (' + next.error.kind + '), so it was refused.' }
  })
}
```

هناك أربعة اختبارات تحاكي اسم الفرع وقرار القواعد، واختبار واحد يحسب عدد مرات تشغيل `git` لإثبات أن الأوامر الأخرى لا تقوم بتشغيله أبداً.

في التجربة الحية، ومع السماح بـ `Bash(git push:*)`، أدى تنفيذ `git push origin main` على فرع `main` إلى ظهور رسالة "Permission to use Bash denied by plugin push-guard: Pushing to main is blocked here. Push a feature branch and open a pull request instead."

ومن فرع يسمى `feature/demo`، حصلت أوامر `git push origin HEAD:main` و `git push origin +main` على نفس الرفض، ولم يحتوي المستودع البعيد (remote) إلا على فرع `feature/demo`.

أما عملية push لفرع `feature/demo` نفسه فقد كانت مسموحة وأبلغت بأن "Everything up-to-date".

ترفض `.catch` عملية الـ push إذا فشل الفحص نفسه، على سبيل المثال عندما لا يمكن تشغيل `git`. ومع ذلك، تقول الوثائق بوضوح أن الـ hook الذي يطابق نص الأمر هو مجرد تذكير لـ Claude. فأي صيغة لا يتوقعها النمط، مثل `git -C . push`، ستمر. كما يمكن رفض أمر غير ضار أيضاً، مثل `git push origin feature/login && git log main`. لمنع عمليات الـ push إلى `main` للجميع، قم بحماية الفرع على مستضيف Git الخاص بك.[^5]

## 3. إخفاء الأسرار في مخرجات الأوامر قبل أن يقرأها Claude

استخدم هذا الحل عندما يمكن أن تحتوي مخرجات الـ shell على بيانات اعتماد، مثل ملفات تكوين السحابة أو تفريغ لبيانات البيئة (environment dumps).

يسمح هذا الـ hook بتشغيل الأمر، ثم يعيد كتابة ما نتج عنه. تذكر الإعلانات أن تنقيح الأسرار من مخرجات الأدوات هو أحد الأشياء التي يمكن للتعديل (mod) القيام بها باستخدام دالة واحدة.[^1] إن إرجاع كائن `result` جديد، بدلاً من الكائن الذي قدمه لك `next`، هو ما يجعل Claude يقرأ نسختك أنت.

الأمر الفاشل يحتاج إلى مسار معالجة خاص به. تعود مخرجاته مع تعيين `isError` والنص الذي يقرأه Claude يكون في `text`، وليس في `stdout`.[^12] يقوم التعديل بإخفاء هذا النص وإرجاعه كـ `deny`، بحيث لا يقرأ Claude إلا النص المخفي.

```javascript
// Common credentials: AWS key ids (AKIA, ASIA), AWS secret keys and session tokens,
// GitHub tokens, Slack tokens, and private key blocks
const SECRETS = [
  [/\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g, '[REDACTED]'],
  [/\b(aws_secret_access_key|aws_session_token)(\s*[=:]\s*)\S+/gi, '$1$2[REDACTED]'],
  [/\bgh[pousr]_[A-Za-z0-9]{36,}\b/g, '[REDACTED]'],
  [/\bgithub_pat_[A-Za-z0-9_]{22,}\b/g, '[REDACTED]'],
  [/\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g, '[REDACTED]'],
  [/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g, '[REDACTED]'],
]

function redact(text) {
  return SECRETS.reduce((out, [pattern, replacement]) => out.replace(pattern, replacement), text)
}

export function register(on) {
  on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
    // Let the command run, then look at what it printed
    const ran = await next(e)
    // A refused call has nothing to clean
    if (ran.deny !== undefined) return ran
    if (ran.isError) {
      // A failed command's output reaches Claude as error text
      const text = typeof ran.text === 'string' ? ran.text : typeof ran.result === 'string' ? ran.result : ''
      const masked = redact(text)
      if (masked === text) return ran
      $.ui.log('masked a credential in the error output of: ' + e.command.slice(0, 60))
      // An error result can't be rewritten in place, so withhold it and pass on the masked text
      return { deny: masked }
    }
    // Another mod may have answered with a plain string; leave that alone
    if (typeof ran.result !== 'object' || ran.result === null) return ran
    const stdout = redact(ran.result.stdout ?? '')
    const stderr = redact(ran.result.stderr ?? '')
    if (stdout === ran.result.stdout && stderr === ran.result.stderr) return ran
    $.ui.log('masked a credential in the output of: ' + e.command.slice(0, 60))
    // Return a new result, so Claude reads the masked text and not the original
    return { result: { ...ran.result, stdout, stderr } }
  }).catch(async () => {
    // If masking itself fails, withhold the output rather than pass it on unmasked
    return { deny: 'mask-secrets could not check this output, so it was withheld.' }
  })
}
```

تتحقق أربعة اختبارات من إخفاء معرف مفتاح AWS والمفتاح السري، ومن مرور المخرجات النظيفة والأخطاء النظيفة دون تغيير، ومن إخفاء المفتاح في الأمر الفاشل، ومن قيام `.catch` بحجب المخرجات إذا فشلت عملية الإخفاء.

في التجربة الحية، وضعنا ملف بيانات اعتماد AWS وهمي في `creds.txt` وطلبنا من Claude اقتباس `cat creds.txt`\_\_PRESERSEVERE\_\_ حرفياً. مع وجود التعديل، اقتبس Claude `aws_access_key_id = [REDACTED]` و `aws_secret_access_key = [REDACTED]`. وبدونه، اقتبست محاولة سابقة لنفس الأمر معرف المفتاح الوهمي كاملاً. كما أن الأمر الفاشل، `cat creds.txt; exit 3`، عاد مخفياً أيضاً.

هذا يغطي مخرجات Bash والأنماط المدرجة فقط. لا يزال بإمكان Claude فتح نفس الملف باستخدام أداة Read، لذا قم بدمج هذا الحل مع حماية لعمليات القراءة. يوضح منشورنا السابق أحد هذه الحلول: [تعديل لـ Claude Code يمنع قراءة ملفات .env](https://nerdleveltech.com/claude-code-mod-block-env-secrets-tested).

## 4. إضافة فرع git الحالي إلى المطالبات المتعلقة بطلبات السحب (pull requests)

هذا يوفر عليك كتابة حقائق المستودع في كل مطالبة.

ترى هوك `prompt.submit` كل أمر (prompt) قبل بدء الدور. تمرير حدث يحتوي على إدخال `context` إضافي إلى `next` يضيف نصاً يقرأه Claude بعد الأمر الخاص بك، بينما يظل السجل (transcript) يعرض ما كتبته فقط.[^5]

```javascript
export function register(on) {
  on('prompt.submit', async ($, e, next) => {
    // Leave prompts that don't mention a pull request alone
    if (!/\bPR\b|pull request/i.test(e.text)) return next(e)
    let git
    try {
      git = await $.process.run(['git', 'branch', '--show-current'])
    } catch {
      // git isn't installed, so send the prompt as it is
      return next(e)
    }
    // Outside a git repository there is no branch to add
    if (git.exitCode !== 0) return next(e)
    // Claude reads this line after your prompt; the transcript still shows what you typed
    return next({ ...e, context: [...(e.context ?? []), 'Current branch: ' + git.stdout.trim()] })
  })
}
```

يتحقق اختباران من أن الأمر الذي يشير إلى PR يحصل على `Current branch: feature/auth`، ويقومان بعد مرات تشغيل `git` لإثبات أن الأوامر الأخرى لا تشغله أبداً. في الواقع، ومع تعطيل Bash حتى لا يتمكن Claude من البحث عنها، حصل أمر يشير إلى PR على الإجابة `feature/demo`. أما السؤال الذي لا يشير إلى PR فقد حصل على "Unknown"، لأنه لم يتم إضافة أي فرع (branch).

يقرأ Claude السطر المضاف مع كل أمر مطابق، لذا اجعله قصيراً وأضفه فقط عندما يكون مفيداً، كما يفعل هذا التعديل (mod).

## 5. إضافة أمر "slash" فوري يتجاوز النموذج

بعض عمليات البحث لا تحتاج إلى تفكير Claude على الإطلاق.

الأمر المسجل بواسطة mod يقوم بتشغيل الدالة الخاصة بك على الفور، دون أي دور لـ Claude.[^3] قم بتسجيله في `session.start`، وأجب عليه في `command.run`، وأضف `immediate: true` ليعمل أيضاً بينما يكون Claude مشغولاً.[^6]

```javascript
export function register(on) {
  on('session.start', async ($, e, next) => {
    // immediate: true lets /todos run even while Claude is working
    await $.command.register({ name: 'todos', description: 'List TODO and FIXME lines in tracked files', immediate: true })
    return next(e)
  })

  on('command.run', { command: 'todos' }, async ($) => {
    let out
    try {
      // git grep searches tracked files only and needs no shell
      out = await $.process.run(['git', 'grep', '-n', '-I', '-E', 'TODO|FIXME'])
    } catch {
      return { text: 'Could not run git grep.' }
    }
    // git grep exits 1 when nothing matches
    if (out.exitCode === 1) return { text: 'No TODO or FIXME lines found.' }
    if (out.exitCode !== 0) return { text: 'git grep failed: ' + out.stderr.trim() }
    const lines = out.stdout.trim().split('\n')
    const shown = lines.slice(0, 20).join('\n')
    const more = lines.length > 20 ? '\n... and ' + (lines.length - 20) + ' more' : ''
    return { text: lines.length + ' TODO/FIXME lines:\n' + shown + more }
  })
}
```

يغطي اختباران حالة المطابقة وعدم المطابقة. في الواقع، في مستودع (repository) يحتوي على سطرين محددين، قام الأمر `claude -p "/todos" --plugin-dir ./todo-scan` بطباعة:

```text
todo-scan: 2 TODO/FIXME lines:
app.js:2:// TODO handle empty input
app.js:3:// FIXME flaky retry
```

لم تكن هناك حاجة لاستدعاء النموذج. يضع Claude Code اسم الإضافة (plugin) أمام نص الأمر.[^4]

انتبه للاسم الذي تختاره: تطلق `$.command.register` خطأً إذا كان هناك أمر مدمج يستخدم الاسم بالفعل، وأي هوك يطلق خطأً يتم تخطيه، لذا قم بتسجيل الأوامر في نهاية `session.start` أو غلفها بـ `try`.[^6]

## 6. إظهار "إيصال" تحت كل إجابة: الوقت المستغرق والتوكنز المستخدمة

هذا مفيد إذا كنت تراقب المدة التي تستغرقها الأدوار أو تكلفة التوكنز.

يتم إطلاق `turn.complete` عند انتهاء الدور. يحمل الحدث `durationMs`، و`usage` للتوكنز في الدور، و`isAborted`، ويمكن للهوك إرجاع حقل `text` يظهر كسطر تحت الإجابة.[^5]

```javascript
export function register(on) {
  on('turn.complete', async ($, e, next) => {
    const result = await next(e)
    // Subagent turns and interrupted turns get no receipt
    if (e.agentId || e.isAborted) return result
    const seconds = (e.durationMs / 1000).toFixed(1)
    const tokens = e.usage ? ' · ' + e.usage.output_tokens + ' output tokens' : ''
    // A text other than the answer itself is shown under the answer
    return { ...result, text: 'Done in ' + seconds + 's' + tokens }
  })
}
```

يتحقق اختباران من السطر لدور استغرق 12,345 مللي ثانية مع 420 توكن مخرجات (`Done in 12.3s · 420 output tokens`) ومن أن الدور المقطوع لا يحصل على شيء. في تشغيل `claude -p` يتم طباعة الإجابة فقط، لذا يظهر هذا السطر في الجلسات التفاعلية.

يتخطى الهوك أدوار الوكلاء الفرعيين (subagent turns)، والتي تطلق أيضاً `turn.complete` مع تعيين `agentId`.[^5]

## 7. رسم مقياس للسياق فوق الأمر

هذا مفيد عندما تريد رؤية نافذة السياق وهي تمتلئ قبل أن تكتمل.

الشريط الموجود فوق الأمر هو موقع رندر (render site) يتشاركه كل mod. يقوم هوك `ui.render` المفلتر إلى `{ component: 'AbovePrompt' }` بإرجاع ما يجب رسمه هناك، أو `next(e)` لعدم رسم شيء.[^7] ترجع `$.session.usage()` توكنز نافذة السياق `tokens`، و`window` و`percent`، من بين أرقام أخرى.[^9]

```javascript
// A 20-cell bar, filled in proportion to the percent used
function bar(percent) {
  const filled = Math.round(percent / 5)
  return '█'.repeat(filled) + '░'.repeat(20 - filled)
}

export function register(on) {
  // After each turn the context has grown, so ask for a redraw of the band
  on('turn.complete', async ($, e, next) => {
    const result = await next(e)
    $.ui.invalidate('ui.render')
    return result
  })

  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
    // Give way to a survey that wants the band
    if (e.props.hasSurvey) return next(e)
    const { context } = await $.session.usage()
    // No reading yet, before the first response
    if (context.percent === undefined) return next(e)
    const { Text } = $.ui.resolve(e)
    const color = context.percent >= 80 ? 'red' : context.percent >= 60 ? 'yellow' : 'green'
    const used = Math.round((context.tokens ?? 0) / 1000) + 'k of ' + Math.round(context.window / 1000) + 'k'
    return Text({ color, children: ['context ' + bar(context.percent) + ' ' + context.percent + '% (' + used + ')'] })
  })
}
```

الرسم يتغير فقط عندما يتم تشغيل الـ hook الخاص به مرة أخرى، لذا يقوم الـ mod باستدعاء `$.ui.invalidate('ui.render')` بعد كل دور.[^7]

يقوم الاختبار الأول برسم الشريط باستخدام `$.ui.mount` على كل من أسطح الـ terminal والـ desktop. مع استخدام 84,000 من أصل 200,000 توكن، يقوم برسم `context ████████░░░░░░░░░░░░ 42% (84k of 200k)`. أما الاختبار الثاني فيتحقق من عدم رسم أي شيء قبل القراءة الأولى.

يقوم Claude Code بتقليل سرعة إعادة الرسم إلى 10 مرات في الثانية، أو 30 في الـ terminal لبعض المواقع، وهو أكثر بكثير مما يحتاجه هذا المقياس.[^9]

## 8. احتفظ بملاحظاتك المسودة في لوحة تصمد أمام إعادة التشغيل

إذا كنت تحتفظ بقائمة جارية من الأشياء التي يجب التحقق منها أثناء عمل Claude، فضعها في لوحة (pane).

يفتح `/notes` لوحة تحتوي على حقل نصي. تحصل كل ملاحظة على زر `x` لحذفها، ويتم حفظ القائمة في `$.store`، وهو مخزن مفتاح-قيمة (key-value store) يستمر بين الجلسات.[^7] يتبع هذا مثال الملاحظات الموجود في الوثائق، مع إضافة خاصية التحميل.

```javascript
const PANE = 'scratch-notes'

// The notes the pane draws, loaded from the store when the session starts
let notes = []

export function register(on) {
  on('session.start', async ($, e, next) => {
    const saved = await $.store.get('notes')
    if (Array.isArray(saved)) notes = saved
    await $.command.register({ name: 'notes', description: 'Open your scratch notes pane' })
    return next(e)
  })

  on('command.run', { command: 'notes' }, async ($) => {
    await $.ui.open({ id: PANE, title: 'Notes', focus: true, closeOnEscape: true })
    // Print nothing in the transcript
    return {}
  })

  on('ui.render', { component: 'Pane' }, async ($, e, next) => {
    // Leave other mods' panes alone
    if (e.requestId !== PANE) return next(e)
    const { Box, Text, Button, Input } = $.ui.resolve(e)
    const save = async () => {
      $.ui.invalidate('ui.render')
      await $.store.set('notes', notes)
    }
    return Box({
      flexDirection: 'column',
      children: [
        Input({
          key: 'new-note',
          label: 'Note',
          placeholder: 'Type a note and press Enter',
          value: '',
          submitLabel: 'add',
          autoFocus: true,
          onSubmit: async (value) => {
            if (!value.trim()) return
            notes = [...notes, value.trim()]
            await save()
          },
        }),
        ...notes.map((note, i) =>
          Box({
            flexDirection: 'row',
            columnGap: 1,
            children: [
              Button({
                key: 'delete-' + i,
                label: 'x',
                plain: true,
                onPress: async () => {
                  notes = notes.filter((_, j) => j !== i)
                  await save()
                },
              }),
              Text({ children: [note] }),
            ],
          }),
        ),
      ],
    })
  })
}
```

يقوم الاختبار الأول بكتابة ملاحظة، والتحقق من رسمها، ثم حذفها، والتحقق من القائمة المحفوظة على كل من أسطح الـ terminal والـ desktop. ويتحقق اختبار ثانٍ من أن الملاحظات المحفوظة مسبقاً تعود بعد `session.start`.

ضع في اعتبارك أن `$.store` مشترك بين كل جلسة على جهازك، وعملية `get` متبوعة بـ `set` ليست ذرية (atomic)، لذا يمكن لجلساتين أن تمسح تغييرات بعضهما البعض.[^7] يتسع المخزن لما يصل إلى 4 ميجابايت من JSON.[^9]

## 9. امنح Claude أداة مخصصة دون تشغيل خادم MCP

غالباً ما ترغب الفرق في أن يقوم Claude بالبحث عن شيء ما في أحد أنظمتهم الخاصة.

يضيف `$.tool.register` أداة يمكن لـ Claude استدعاؤها. يراها Claude تحت اسم أطول، `mcp__<plugin>__<tool>`، ويقوم الـ `tool.call` hook الخاص بك لهذا الاسم الكامل بالرد عليه.[^6]

هذه الأداة تجلب مشكلة (issue) من GitHub. تقول وثائق REST الخاصة بـ GitHub إن الطلبات التي لا تحتوي على ترويسة `User-Agent` يتم رفضها، ولهذا السبب يرسل الـ mod واحدة.[^10] هناك متغير بيئة اختياري `TICKET_API_BASE`، يتم قراءته بواسطة `$.env.get`، يوجه الأداة نحو GitHub Enterprise أو خادم اختبار.[^6]

```javascript
export function register(on) {
  on('session.start', async ($, e, next) => {
    await $.tool.register({
      name: 'github_issue',
      // Claude decides when to call the tool from this description
      description: 'Look up a GitHub issue or pull request and return its title, state, labels and first 1,500 characters',
      inputSchema: {
        type: 'object',
        properties: {
          repo: { type: 'string', description: 'owner/name, such as anthropics/claude-code' },
          number: { type: 'integer' },
        },
        required: ['repo', 'number'],
      },
    })
    return next(e)
  })

  // The full name is mcp__, the plugin's name, two underscores, and the tool's name
  on('tool.call', { tool: 'mcp__ticket-tool__github_issue' }, async ($, e) => {
    if (!/^[\w.-]+\/[\w.-]+$/.test(e.repo)) return { result: 'repo must look like owner/name' }
    // GitHub by default; set TICKET_API_BASE to point at GitHub Enterprise or a test server
    const base = (await $.env.get('TICKET_API_BASE')) ?? 'https://api.github.com'
    const url = base + '/repos/' + e.repo + '/issues/' + Number(e.number)
    const response = await $.http.fetch(url, { headers: { accept: 'application/vnd.github+json', 'user-agent': 'ticket-tool-mod' } })
    if (!response.ok) return { result: 'Lookup failed with status ' + response.status }
    let issue
    try {
      issue = JSON.parse(response.text)
    } catch {
      return { result: 'The lookup returned something that is not JSON' }
    }
    const labels = (issue.labels ?? []).map((l) => l.name).join(', ') || 'none'
    return {
      result: '#' + issue.number + ' ' + issue.title + '\nstate: ' + issue.state + '\nlabels: ' + labels + '\n\n' + (issue.body ?? '').slice(0, 1500),
    }
  }).catch(async ($, e, next) => {
    // A network error or a timeout becomes a result Claude can read
    return { result: 'The issue lookup failed: ' + next.error.kind }
  })
}
```

يقوم اختباران بعمل stub لـ `$.http.fetch`: أحدهما يتحقق من رابط GitHub والملخص لمشكلة تم العثور عليها، والآخر يتحقق من أن `TICKET_API_BASE` يغير الرابط وأنه يتم الإبلاغ عن خطأ 404.

أول تشغيل حي لنا ضد `api.github.com` أعطى HTTP 403، لأن بروكسي الشبكة الخاص بالـ sandbox يسمح فقط باستدعاءات GitHub API للمستودعات المرتبطة بالجلسة.

لذا قمنا بتشغيله حياً ضد خادم محلي صغير يستجيب مثل نقطة نهاية المشكلات (issues endpoint) في GitHub. استدعى Claude الأداة ورد بالعنوان والحالة والتصنيفات التي أرسلها الخادم (`Export button does nothing`, `open`, `bug, p1`)، وأظهر سجل الخادم الطلب مع `User-Agent` الخاص بالـ mod.

يسمح GitHub بمزيد من الطلبات في الساعة عند المصادقة.[^10] بالنسبة للمستودعات الخاصة، اقرأ رمز الوصول (token) باستخدام `$.env.get` وأرسله كـ header.[^6]

## 10. مراقبة CI وعرض النتيجة أسفل الأمر (prompt)

تساعد هذه الإضافة أثناء انتظارك لعمليات التحقق من الـ pull request مع الاستمرار في العمل.

العمل الذي يستمر لأكثر من حدث واحد يعمل على مؤقت يبدأ في `session.start`. ويحل `$.clock.every` محل `setInterval`، بينما يقوم `$.ui.status` بتعيين سطر واحد أسفل الأمر يظل موجوداً حتى تقوم بتغييره.[^6]

تطلب هذه الإضافة من GitHub CLI التحقق من حالة الـ pull request الحالية مرة كل دقيقة. يتضمن `gh pr checks --json` حقلاً باسم `bucket` يصنف كل عملية تحقق إلى `pass`، أو `fail`، أو `pending`، أو `skipping` أو `cancel`.[^11]

```javascript
// Turn gh's JSON into a short line such as "3 pass · 1 fail · 2 pending"
function summarize(json) {
  const counts = {}
  for (const check of JSON.parse(json)) counts[check.bucket] = (counts[check.bucket] ?? 0) + 1
  const parts = ['pass', 'fail', 'pending'].filter((b) => counts[b]).map((b) => counts[b] + ' ' + b)
  return parts.length > 0 ? parts.join(' · ') : 'no checks'
}

async function refresh($) {
  let out
  try {
    out = await $.process.run(['gh', 'pr', 'checks', '--json', 'bucket,name'])
  } catch {
    $.ui.status(undefined)
    return
  }
  // gh exits 8 while checks are pending and 1 when the command fails,
  // so read the JSON instead of the exit code
  let line
  try {
    line = 'CI: ' + summarize(out.stdout)
  } catch {
    line = undefined
  }
  // undefined clears the line
  $.ui.status(line)
}

export function register(on) {
  on('session.start', async ($, e, next) => {
    // Check once a minute; the timer stops when the mod reloads
    $.clock.every(60_000, () => refresh($))
    return next(e)
  })
}
```

يستخدم اختباران `mock.clock` الخاص بالمجموعة، لذا تمر الدقيقة فوراً. بعد 59 ثانية لا يظهر شيء. وعند 60 ثانية يقرأ السطر `CI: 2 pass · 1 pending`. وعندما لا يكون هناك pull request، يتم مسح السطر.

تتوقف المؤقتات عند إعادة تحميل الإضافة، ويبدأ مثيل (instance) جديد مؤقته الخاص.[^6][^7] يبدأ سطر الحالة بعلامة تحذير واسم الإضافة، لذا اجعل النص قصيراً.[^6]

## ما الذي تغير في الأسبوع الأول

وصلت الإضافات (Mods) في الإصدار 2.1.287 في 1 أكتوبر 2026، وتبع ذلك ثمانية إصدارات أخرى بحلول 8 أكتوبر.[^2] هناك بعض التغييرات التي تهم مؤلفي الإضافات:

| الإصدار | التاريخ       | التغيير                                                                                          |
| ------- | ------------- | ------------------------------------------------------------------------------------------------ |
| 2.1.287 | 1 أكتوبر 2026 | "إضافة Claude Mods: يمكن للإضافات الآن تعديل سلوكيات أعمق"                                       |
| 2.1.288 | 2 أكتوبر 2026 | إضافة `$.ui.selection()`، والتي تعيد النص الذي حددته مؤخراً في وضع ملء الشاشة                    |
| 2.1.290 | 5 أكتوبر 2026 | يقوم `claude plugin validate` بسرد كل hook مسجل في موقع gating، وما إذا كان يحتوي على `.catch`   |
| 2.1.292 | 6 أكتوبر 2026 | تخزين مؤقت للأوامر (Prompt caching) لـ `$.model.complete`، وحدث `prompt.autocomplete` جديد       |
| 2.1.293 | 7 أكتوبر 2026 | إضافة `isDeferred` في `$.tool.register`، لسرد مخطط الأداة (tool's schema) في الأمر منذ البداية   |
| 2.1.295 | 8 أكتوبر 2026 | إضافة `$.ui.notify`؛ الرفض بعد تشغيل الأداة يقول الآن "تم تشغيل الأداة وقامت إضافة بحجب نتيجتها" |

المصدر: سجل تغييرات Claude Code.[^2] تغيير الإصدار 2.1.290 هو السبب في أن مخرجات validate لدينا تتضمن أسطراً مثل `gating hook with .catch: tool.call{tool=Bash}`، وهو ما لا تظهره مخرجات الأمثلة في التوثيق بعد. يحذر التوثيق من أن الأحداث والطرق قد تتغير بين الإصدارات، وأن تعريفات الأنواع التي يكتبها Claude Code لإصدارك هي المرجع الأدق في حال وجود تعارض مع أي صفحة توثيق.[^4]

## الأخطاء الشائعة والقيود

`claude plugin validate` يقرأ الكود المصدري الخاص بك بنفس الطريقة التي يقوم بها Claude Code، ومعظم الأخطاء الأولى تأتي من قواعده:[^4]

- **اكتب كل استدعاء API بالكامل**، كما في `$.store.get('notes')`. استدعاء `const ui = $.ui` سيفشل مع خطأ `$.ui is used as a value`.
- **استخدم نصاً صريحاً (string literal) لاسم الحدث.** استخدام متغير أو حلقة تكرارية (loop) على الأسماء سيؤدي لفشل التحقق.
- **سجل كل حدث مرة واحدة لكل matcher.** وجود اثنين من خطافات (hooks) `session.start` بدون matcher يمنع تحميل الموديول.[^5]
- **استخدم ES modules.** لا تستخدم `require`، ولا استدعاءات `import()`.[^4]

القيود الأكثر شيوعاً:[^9]

| القيد                             | القيمة                                |
| --------------------------------- | ------------------------------------- |
| وقت تشغيل الخطاف (hook) لحدث واحد | 10 ثوانٍ                              |
| معالج `.catch`                    | ثانية واحدة                           |
| مهلة `$.process.run`              | 30 ثانية افتراضياً، 10 دقائق كحد أقصى |
| `maxTokens` في `$.model.complete` | 1,024 افتراضياً                       |
| `$.fs.read` و `$.fs.write`        | 4 ميجابايت لكل ملف                    |
| `$.store`                         | 4 ميجابايت من JSON إجمالاً            |
| اختبار `claude plugin test` واحد  | 5 ثوانٍ ما لم يتم تعيين `timeoutMs`   |

الوقت الذي يتم قضاؤه في الانتظار داخل `next` أو استدعاء API للمودز لا يُحتسب ضمن الـ 10 ثوانٍ، باستثناء `$.clock.sleep`.[^9] وهذا هو السبب في أن حارس confirm-risky يمكنه الانتظار على `$.ui.ask` دون تجاوز الحد.[^5]

## هل مودز Claude Code آمنة؟

المودز تكون آمنة بقدر أمان مؤلفها. تقول الوثائق أن المود "يعمل بصلاحياتك": يمكنه قراءة وكتابة ملفاتك، وبدء البرامج، وإجراء طلبات الشبكة، وقراءة متغيرات البيئة الخاصة بك، ورؤية كل أمر (prompt) واستدعاء أداة، والموافقة على استدعاء أداة قبل أن يُطلب منك ذلك، واستدعاء نموذج (model) ضمن خطتك. "المودز ليست معزولة (sandboxed)". وحتى مع تفعيل العزل، فإن أي عملية يبدأها المود تعمل خارج نطاق العزل.[^3]

هناك شيئان لا يمكن للمود القيام بهما: تغيير ما يظهر في مطالبة الصلاحيات، أو تجاوز حظر من خطاف `PreToolUse` في إعدادات الإدارة الخاصة بمؤسستك، والتي تعمل قبل أي مود.[^3][^5]

قبل تثبيت مود خاص بشخص آخر، قم بتشغيل `claude plugin validate` على المجلد الخاص به. ستعرض أسطر `hooks:` و `calls:` الأحداث التي يتعامل معها وكل استدعاء API يقوم به، دون تشغيله.[^3] يغطي تحليلنا في [Plugin4Shell](https://nerdleveltech.com/plugin4shell-ai-coding-agent-plugin-security) سبب أهمية الثقة في الإضافات بالنسبة لوكلاء البرمجة.

لإيقاف تشغيل الـ mods: قم بتعطيل أحدها في `/plugin`، أو ابدأ جلسة باستخدام `--safe-mode`، أو قم بتعيين `"disableAllHooks": true` في `~/.claude/settings.json`.[^3]

### عناصر التحكم للفرق والمؤسسات

في خطط Team و Enterprise، وعلى الأجهزة ذات الإعدادات المدارة، يتم تحميل حارس مدمج يسمى `sec-default` قبل الـ mods التي يثبتها المستخدم، لمنعهم من القيام بأشياء خطيرة مثل تجاوز قواعد رفض الأذونات.[^1][^9] يمكن للمسؤولين أيضاً:[^9]

- تشغيل الـ mods الخاصة بهم أولاً أو أخيراً باستخدام `prependPlugins` و `appendPlugins`
- السماح فقط بـ mods المؤسسة باستخدام `allowManagedModsOnly`
- رفض `--plugin-dir` و `--plugin-url` عند بدء التشغيل باستخدام `disableSideloadFlags`

تتضمن أمثلة فريق الإعلان نفسها حالة CI/CD في لوحة جانبية، وتأكيداً قبل أن تؤثر الأوامر على إعدادات الإنتاج (production config)، وسجلاً تدقيقياً لكل استدعاءات الـ mod.[^1]

## أين تعمل الـ mods؟

ترتبط الـ mods بالأحداث في كل مكان يتم فيه تحميل الإضافة، لكنها ترسم فقط في بعض الأماكن.[^3]

| مكان تشغيل Claude Code                      | تشغيل الـ Hooks             | ظهور الرسومات                        |
| ------------------------------------------- | --------------------------- | ------------------------------------ |
| `claude` في Terminal                        | نعم                         | نعم                                  |
| تبويب Code في تطبيق Desktop (ليس جلسات WSL) | نعم                         | نعم، باستثناء عناصر الـ terminal فقط |
| لوحة الدردشة في إضافة VS Code               | نعم                         | لا                                   |
| `claude -p` و Agent SDK                     | نعم                         | لا                                   |
| جلسة سحابية (cloud session)                 | نعم، إذا وصلت الإضافة إليها | لا                                   |

لهذا السبب أمكن اختبار ستة من الـ mods الخاصة بنا مباشرة في `claude -p` بينما لم يكن ذلك ممكناً للـ mods التي تعتمد على الرسم.

## أماكن إضافية للبدء

- **الـ mods المدمجة.** بعض ميزات Claude Code نفسها هي عبارة عن mods، مثل `/diff`، ويمكنك رؤيتها تحت قسم **Built-in** في `/plugin`. يوجد مصدر العديد منها في مجلد `mods` الخاص بمستودع Claude Code.[^3]
- **نماذج Anthropic.** يحتوي مستودع `claude-code-playground` على `token-weather` (توقعات للسياق فوق المطالبة)، و `blast-radius` (يحتجز الأمر الخطير ويظهر ما سيقوم بتغييره)، و `replay-theater` (أمر `/replay` لتعديلات الدورة الأخيرة). تشارك Anthropic هذه النماذج كما هي، بدون دعم.[^3]
- **اسأل Claude.** صف الـ mod الذي تريده، وسيقوم Claude بكتابته باستخدام مهارة `plugin-authoring`. سيعمل بمجرد موافقتك عليه.[^4]

## الأسئلة الشائعة

### ما هي الـ Claude Code mods؟

تعد إضافات (mods) Claude Code بمثابة ملحقات تحتوي على وظائف JavaScript أو TypeScript يستدعيها Claude Code عند وقوع حدث ما، مثل استدعاء أداة، أو مطالبة (prompt)، أو إعادة رسم الواجهة. يمكن للإضافة مراقبة الحدث، أو إعادة كتابته، أو الرد عليه، كما يمكنها رسم ألواح (panes)، وأشرطة (bands)، وخطوط حالة. أضافتها Anthropic في الإصدار 2.1.287 في 1 أكتوبر 2026.[^1][^2][^3]

### كيف أقوم بإنشاء إضافة لـ Claude Code؟

قم بإنشاء مجلد للملحق يحتوي على `.claude-plugin/plugin.json`، وملف `hooks/hooks.json` يشير مفتاح `modules` فيه إلى الكود الخاص بك، ووحدة hooks تقوم بتصدير `register(on)`. قم بتحميلها باستخدام `claude --plugin-dir ./my-mod`، وتحقق منها عبر `claude plugin validate`، واختبرها باستخدام `claude plugin test`.[^4]

### كيف أختبر إضافة Claude Code؟

اكتب ملفات تنتهي بـ `.test.ts` تستورد `claude-code/testing`، ثم قم بتشغيل `claude plugin test`. تقوم الاختبارات بإثارة الأحداث، ومحاكاة ما سيرد به Claude Code، ويمكنها رسم لوح أو شريط باستخدام `$.ui.mount`. لا يلزم وجود جلسة أو تسجيل دخول أو شبكة، والاختبار الفاشل يخرج بحالة 1، لذا فهو يعمل في بيئات CI.[^8]

### هل إضافات Claude Code معزولة (sandboxed)؟

لا. تعمل الإضافة بصلاحياتك ويمكنها قراءة الملفات، وتشغيل البرامج، وإجراء طلبات الشبكة، والموافقة على استدعاءات الأدوات. قم بتثبيت الإضافات فقط من المؤلفين الذين تثق بهم، وقم بتشغيل `claude plugin validate` أولاً لسرد ما تقوم الإضافة بربطه واستدعائه.[^3]

### ما الفرق بين الإضافة (mod) وخطاف (hook) Claude Code؟

خطاف الإعدادات هو أمر shell أو طلب HTTP أو مطالبة تعمل عند حدث في دورة الحياة من ملف إعدادات. كلاهما يمكنه منع استدعاء أداة أو مطالبة من المضي قدماً، ويمكن لخطاف الإعدادات أيضاً تغيير وسائط ونتيجة استدعاء الأداة وإضافة سياق لـ Claude. أما الإضافة فهي كود يعمل داخل Claude Code، وبخلاف خطاف الإعدادات، يمكنها الرسم في الواجهة، وإضافة أوامر وأدوات، وإعادة كتابة مطالبة، وإرسال طلب إلى نموذج مختلف.[^3]

### هل تعمل الإضافات في VS Code؟

تعمل الخطافات في لوحة الدردشة الخاصة بإضافة VS Code، ولكن ما ترسمه الإضافة لا يظهر هناك. تظهر الألواح والأشرطة والصفوف المستبدلة في الطرفية (terminal) وفي تبويب Code الخاص بتطبيق سطح المكتب.[^3]

## الخلاصة

يمكنك الآن تغيير طريقة سلوك Claude Code ببضع عشرات من أسطر JavaScript. تغطي الأمثلة العشرة هنا المهام الشائعة: حماية أمر ما، تغيير ما يقرأه Claude، إضافة أمر أو أداة، ورسم حالة خاصة بك. كل مثال منها قصير، ويسمح لك `claude plugin test` بإثبات عمله قبل أن يلمس جلسة حقيقية. اقرأ أي إضافة لم تكتبها بنفسك قبل تحميلها، لأنها تعمل بصلاحياتك.

## قراءات ذات صلة

- [تعديل Claude Code لمنع قراءة ملفات .env: تم الاختبار (2026)](https://nerdleveltech.com/claude-code-mod-block-env-secrets-tested) يقوم ببناء حماية للملفات السرية وقياس أماكن تسريب مطابقة النصوص.
- [Plugin4Shell: ترقيع وتحصين وكيل البرمجة الخاص بك (2026)](https://nerdleveltech.com/plugin4shell-ai-coding-agent-plugin-security) يشرح مخاطر تثبيت الإضافات في وكيل البرمجة.
- [إضافات الوكلاء 1.0: إضافة واحدة، تسعة عملاء في 2026](https://nerdleveltech.com/agent-plugins-open-standard-skills-mcp) يغطي كيفية تعبئة المهارات وخوادم MCP كإضافات.
- [خطافات استنتاج Claude: بوابة DLP لعام 2026 وثغراتها](https://nerdleveltech.com/claude-inference-hooks-enterprise-dlp) ينظر في طبقة أخرى لمنع وصول البيانات إلى المطالبات (prompts).

## المراجع

[^1]: [Customize Claude Code with mods](https://claude.com/resources/articles/claude-code-mods), Anthropic, October 1, 2026. Source for "small TypeScript functions", what a mod can do with one function including redacting secrets from tool output, `/diff` shipping as a mod, `sec-default` on Team and Enterprise plans, the team examples, and the warning that mods aren't sandboxed.

[^2]: [Claude Code changelog](https://code.claude.com/docs/en/changelog), Anthropic, versions 2.1.287 (October 1, 2026) to 2.1.295 (October 8, 2026), read October 9, 2026.

[^3]: [Mods overview](https://code.claude.com/docs/en/plugins/mods/overview), Claude Code docs, read October 9, 2026. Source for the definition, version requirements, the comparison table, what a mod can reach, the permission prompt, where mods run, turning mods off, built-in mods and the sample mods.

[^4]: [Create a mod](https://code.claude.com/docs/en/plugins/mods/create), Claude Code docs, read October 9, 2026. Source for the three files, no build step, `--plugin-dir`, the `plugin-authoring` skill, `claude plugin validate` and its rules, and the advice to trust the type declarations for your version.

[^5]: [React to events with a mod](https://code.claude.com/docs/en/plugins/mods/events), Claude Code docs, read October 9, 2026. Source for observe, rewrite and answer, `tool.call`, `$.ui.ask`, `tool.check`, `prompt.submit` context, `turn.complete`, managed `PreToolUse` hooks running first, failing hooks and `.catch`.

[^9]: [Mods reference](https://code.claude.com/docs/en/plugins/mods/reference), Claude Code docs, read October 9, 2026. Source for files, `$.session.usage()`, limits, render sites and organization settings.

[^8]: [Test a mod](https://code.claude.com/docs/en/plugins/mods/test), Claude Code docs, read October 9, 2026. Source for `claude plugin test`, stubs, `mock.clock`, `$.ui.mount` and the exit status.

[^12]: Claude Code 2.1.295 type declarations for mods, `ToolCallResult`, the file Claude Code writes beside a mod as `.claude-plugin/types/claude-code/index.d.ts`. A published copy lives at [mods/types/claude-code.d.ts](https://github.com/anthropics/claude-code/blob/main/mods/types/claude-code.d.ts) in the Claude Code repository and can be older than your version.

[^6]: [Use the mods API](https://code.claude.com/docs/en/plugins/mods/api), Claude Code docs, read October 9, 2026. Source for commands, `immediate`, tools and their `mcp__` names, `$.clock`, `$.ui.status`, `$.ui.log` and `$.env`.

[^7]: [Draw in the interface with a mod](https://code.claude.com/docs/en/plugins/mods/interface), Claude Code docs, read October 9, 2026. Source for render sites, the band above the prompt, panes, the notes example, redraws and `$.store`.

[^10]: [Getting started with the REST API](https://docs.github.com/en/rest/using-the-rest-api/getting-started-with-the-rest-api), GitHub Docs, read October 9, 2026. Source for the required `User-Agent` header and higher hourly limits for authenticated requests.

[^11]: [gh pr checks](https://cli.github.com/manual/gh_pr_checks), GitHub CLI manual, read October 9, 2026. Source for the `--json` fields and the `bucket` values.
