ملخص سريع
حوّل ملف وكيل ذكاء اصطناعي واحدًا إلى 10 بيئات تطوير متكاملة (IDEs) بثلاث خطوات عملية: (1) تحليل مقدمة YAML بدوال باش (get_field()، get_body()، to_kebab()), (2) تحويل الملف إلى تنسيقات الأدوات المختلفة عبر convert.sh, (3) تثبيت النتائج في المسارات الصحيحة باستخدام install.sh. اكتب ملفًا واحدًا فقط ووزعه تلقائيًا على جميع بيئات التطوير.
ملف وكيل واحد يكفي ليعمل عبر كلود كود، كيرسور، آيدر، ويندسيرف، جيت هاب كوبايلوت، وأكثر من 6 أدوات أخرى، بفضل مشروع "The Agency" ونصوصه البرمجية التلقائية.
لماذا تحتاج إلى أتمتة التحويل؟
كتبت وكيل ذكاء اصطناعي وتريد نشره في:
- كلود كود (
.mdفي~/.claude/agents/) - كيرسور (
.mdcفي.cursor/rules/) - آيدر (
CONVENTIONS.mdفي جذر المشروع) - ويندسيرف (
.windsurfrules) - جيت هاب كوبايلوت (
.mdفي~/.github/agents/) - وغيرها الكثير...
هل ستكتب 10 نسخ يدوياً؟ لا! الحل: اكتب مرة واحدة، ودع نصوص التحويل تقوم بالباقي.
بنية ملف الوكيل
كل وكيل في "The Agency" يتبع بنية ثابتة:
---
name: API Tester
description: Specialized in API testing with Apidog, Postman, and automated validation
color: purple
emoji: 🧪
vibe: Breaks APIs before users do.
---
# API Tester Agent Personality
You are **API Tester**, an expert in API validation...
## Identity & Memory
- Role: API testing specialist
- Personality: Thorough, skeptical, evidence-focused
...
-
المقدمة (Frontmatter): بيانات YAML بين
--- - النص الأساسي (Body): كل المحتوى بعد المقدمة
التحويل: استخرج الحقول من المقدمة، حوّل النص الأساسي حسب متطلبات كل أداة، ثم اكتب النتيجة في المسار المناسب.
الخطوة 1: تحليل مقدمة YAML
أنشئ ملف parse-frontmatter.sh بهذا المحتوى:
#!/usr/bin/env bash
#
# parse-frontmatter.sh — استخراج بيانات المقدمة من ملفات الوكلاء
#
set -euo pipefail
# استخراج قيمة حقل من YAML
get_field() {
local field="$1" file="$2"
awk -v f="$field" '
/^---$/ { fm++; next }
fm == 1 && $0 ~ "^" f ": " {
sub("^" f ": ", "");
print;
exit
}
' "$file"
}
# إرجاع النص الأساسي بدون المقدمة
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
# تحويل الاسم إلى slug بصيغة kebab-case
to_kebab() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g'
}
# اختبار سريع
if [[ "${1:-}" == "--demo" ]]; then
AGENT_FILE="${2:-test-agent.md}"
echo "File: $AGENT_FILE"
echo "Name: $(get_field 'name' "$AGENT_FILE")"
echo "Description: $(get_field 'description' "$AGENT_FILE")"
echo "Slug: $(to_kebab "$(get_field 'name' "$AGENT_FILE")")"
echo "---"
echo "Body preview:"
get_body "$AGENT_FILE" | head -10
fi
جرّب السكريبت:
chmod +x parse-frontmatter.sh
./parse-frontmatter.sh --demo engineering-backend-architect.md
الناتج المتوقع:
File: engineering-backend-architect.md
Name: Backend Architect
Description: Senior backend architect specializing in scalable system design...
Slug: backend-architect
---
Body preview:
# Backend Architect Agent Personality
You are **Backend Architect**, a senior backend architect...
الخطوة 2: تحويل إلى تنسيق كلود كود
كلود كود يقبل ملفات .md كما هي. فقط انسخ الملف:
convert_claude_code() {
local agent_file="$1"
local dest="$HOME/.claude/agents/"
mkdir -p "$dest"
cp "$agent_file" "$dest/"
echo " Claude Code: $(basename "$agent_file")"
}
الخطوة 3: تحويل إلى تنسيق كيرسور
كيرسور يحتاج ملف .mdc مع حقل وصف في المقدمة:
convert_cursor() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local description=$(get_field 'description' "$agent_file")
local slug=$(to_kebab "$name")
local body=$(get_body "$agent_file")
local output=".cursor/rules/agency-${slug}.mdc"
mkdir -p "$(dirname "$output")"
cat > "$output" << EOF
---
description: Agency agent: $description
---
$body
EOF
echo " Cursor: agency-${slug}.mdc"
}
الخطوة 4: تحويل إلى آيدر
آيدر يجمع جميع الوكلاء في ملف CONVENTIONS.md واحد:
convert_aider() {
local agent_file="$1"
local output="CONVENTIONS.md"
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Aider: appended to $output"
}
لبناء الملف بالكامل:
build_aider() {
local output="CONVENTIONS.md"
echo "# Agency Agents for Aider" > "$output"
echo "" >> "$output"
echo "This file contains all Agency agents for Aider integration." >> "$output"
echo "" >> "$output"
for agent_file in engineering/*.md design/*.md testing/*.md; do
convert_aider "$agent_file"
done
}
الخطوة 5: تحويل إلى تنسيق ويندسيرف
نفس فكرة آيدر، ولكن في .windsurfrules:
convert_windsurf() {
local agent_file="$1"
local output=".windsurfrules"
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Windsurf: appended to $output"
}
الخطوة 6: تحويل إلى أنتيجرافيتي (جيميني)
ينشئ ملف SKILL.md في مجلد خاص:
convert_antigravity() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local slug=$(to_kebab "$name")
local output="integrations/antigravity/skills/agency-${slug}/SKILL.md"
mkdir -p "$(dirname "$output")"
cat > "$output" << EOF
# Agency Agent: $name
$(get_body "$agent_file")
EOF
echo " Antigravity: agency-${slug}/SKILL.md"
}
الخطوة 7: تحويل إلى أوبن كلو
ينشئ ثلاثة ملفات لكل وكيل:
convert_openclaw() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local description=$(get_field 'description' "$agent_file")
local slug=$(to_kebab "$name")
local body=$(get_body "$agent_file")
local output_dir="integrations/openclaw/agency-${slug}"
mkdir -p "$output_dir"
# SOUL.md
cat > "$output_dir/SOUL.md" << EOF
# $name
$description
---
$body
EOF
# AGENTS.md
cat > "$output_dir/AGENTS.md" << EOF
# Agent Capabilities: $name
- Specialized expertise in domain
- Deliverable-focused output
- Success metrics defined
See SOUL.md for full definition.
EOF
# IDENTITY.md
cat > "$output_dir/IDENTITY.md" << EOF
# Identity: $name
- Name: $name
- Description: $description
- Source: The Agency (agency-agents repo)
EOF
echo " OpenClaw: agency-${slug}/"
}
الخطوة 8: سكريبت convert.sh الكامل
سكريبت شامل لتحويل جميع الوكلاء:
#!/usr/bin/env bash
#
# convert.sh — تحويل جميع وكلاء The Agency إلى تنسيقات الأدوات المختلفة
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
OUT_DIR="$REPO_ROOT/integrations"
# دوال المساعدة
get_field() {
local field="$1" file="$2"
awk -v f="$field" '
/^---$/ { fm++; next }
fm == 1 && $0 ~ "^" f ": " { sub("^" f ": ", ""); print; exit }
' "$file"
}
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
to_kebab() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g'
}
# دوال التحويل
convert_claude_code() {
local agent_file="$1"
local dest="$OUT_DIR/claude-code/"
mkdir -p "$dest"
cp "$agent_file" "$dest/"
}
convert_cursor() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local slug=$(to_kebab "$name")
local body=$(get_body "$agent_file")
mkdir -p "$OUT_DIR/cursor/.cursor/rules/"
cat > "$OUT_DIR/cursor/.cursor/rules/agency-${slug}.mdc" << EOF
---
description: Agency agent: $(get_field 'description' "$agent_file")
---
$body
EOF
}
convert_aider() {
local output="$OUT_DIR/aider/CONVENTIONS.md"
echo "" >> "$output"
echo "---" >> "$output"
cat "$agent_file" >> "$output"
}
convert_windsurf() {
local output="$OUT_DIR/windsurf/.windsurfrules"
echo "" >> "$output"
echo "---" >> "$output"
cat "$agent_file" >> "$output"
}
# التحويل لجميع الأدوات
echo "Converting Agency agents..."
AGENT_DIRS=(engineering design testing marketing sales)
for dir in "${AGENT_DIRS[@]}"; do
for agent_file in "$REPO_ROOT/$dir"/*.md; do
[[ -f "$agent_file" ]] || continue
name=$(get_field 'name' "$agent_file")
echo "Processing: $name"
convert_claude_code "$agent_file"
convert_cursor "$agent_file"
done
done
# بناء الملفات المجمعة
echo "# Agency Agents for Aider" > "$OUT_DIR/aider/CONVENTIONS.md"
for dir in "${AGENT_DIRS[@]}"; do
for agent_file in "$REPO_ROOT/$dir"/*.md; do
[[ -f "$agent_file" ]] || continue
convert_aider "$agent_file"
done
done
echo "# Agency Agents for Windsurf" > "$OUT_DIR/windsurf/.windsurfrules"
for dir in "${AGENT_DIRS[@]}"; do
for agent_file in "$REPO_ROOT/$dir"/*.md; do
[[ -f "$agent_file" ]] || continue
convert_windsurf "$agent_file"
done
done
echo "Conversion complete!"
echo " Claude Code: $OUT_DIR/claude-code/"
echo " Cursor: $OUT_DIR/cursor/.cursor/rules/"
echo " Aider: $OUT_DIR/aider/CONVENTIONS.md"
echo " Windsurf: $OUT_DIR/windsurf/.windsurfrules"
شغل السكريبت:
chmod +x convert.sh
./convert.sh
الخطوة 9: التثبيت لكل أداة
بعد التحويل، انسخ الملفات إلى المسارات الصحيحة:
#!/usr/bin/env bash
#
# install.sh — تثبيت الوكلاء المحولين للأدوات المحلية
#
set -euo pipefail
# Claude Code
install_claude_code() {
local src="$REPO_ROOT/integrations/claude-code/"
local dest="$HOME/.claude/agents/"
mkdir -p "$dest"
cp "$src"/*.md "$dest/"
echo "Claude Code: $(find "$dest" -name '*.md' | wc -l) agents installed"
}
# Cursor
install_cursor() {
local src="$REPO_ROOT/integrations/cursor/.cursor/rules/"
local dest="./.cursor/rules/"
mkdir -p "$dest"
cp "$src"/*.mdc "$dest/"
echo "Cursor: $(find "$dest" -name '*.mdc' | wc -l) rules installed"
}
# Aider
install_aider() {
local src="$REPO_ROOT/integrations/aider/CONVENTIONS.md"
local dest="./CONVENTIONS.md"
cp "$src" "$dest"
echo "Aider: CONVENTIONS.md installed"
}
# Windsurf
install_windsurf() {
local src="$REPO_ROOT/integrations/windsurf/.windsurfrules"
local dest="./.windsurfrules"
cp "$src" "$dest"
echo "Windsurf: .windsurfrules installed"
}
# تثبيت جميع الأدوات المتوفرة
install_all() {
if [[ -d "$HOME/.claude/agents/" ]]; then
install_claude_code
fi
if command -v cursor &>/dev/null || [[ -d "./.cursor/" ]]; then
install_cursor
fi
if command -v aider &>/dev/null; then
install_aider
fi
}
install_all
مقارنة التنسيقات
| الأداة | التنسيق | النطاق | التحويل |
|---|---|---|---|
| كلود كود | .md |
على مستوى المستخدم | نسخ كما هو |
| كيرسور | .mdc |
على مستوى المشروع | إضافة وصف في المقدمة |
| آيدر | CONVENTIONS.md |
جذر المشروع | تجميع جميع الوكلاء |
| ويندسيرف | .windsurfrules |
جذر المشروع | تجميع جميع الوكلاء |
| جيت هاب كوبايلوت | .md |
على مستوى المستخدم | نسخ كما هو |
| أنتيجرافيتي | SKILL.md |
على مستوى المستخدم | تغليف في مجلد المهارة |
| أوبن كلو |
SOUL.md + أخرى |
على مستوى المستخدم | تقسيم إلى 3 ملفات |
| جيميني CLI | امتداد | على مستوى المستخدم | إنشاء بيان + مهارات |
| أوبن كود | .md |
على مستوى المشروع | نسخ كما هو |
| كوين كود | .md |
على مستوى المشروع | النسخ كوكيل فرعي (SubAgent) |
ابنِ نص التحويل الخاص بك لأي أداة
قالب جاهز لإضافة دعم أداة جديدة:
#!/usr/bin/env bash
# 1. عرف دالة التحويل
convert_your_tool() {
local agent_file="$1"
local name=$(get_field 'name' "$agent_file")
local description=$(get_field 'description' "$agent_file")
local slug=$(to_kebab "$name")
local body=$(get_body "$agent_file")
# 2. أنشئ المسار الناتج
local output="path/to/your/tool/agency-${slug}.ext"
mkdir -p "$(dirname "$output")"
# 3. اكتب المحتوى المحوّل
cat > "$output" << EOF
# Your tool-specific format
# Use: $name, $description, $body
EOF
echo " YourTool: agency-${slug}.ext"
}
# 4. أضفها إلى الحلقة الرئيسية
for agent_file in engineering/*.md; do
convert_your_tool "$agent_file"
done
ما الذي قمت ببنائه؟
| المكون | الغرض |
|---|---|
get_field() |
استخراج قيم المقدمة من YAML |
get_body() |
تجريد المقدمة وإرجاع نص Markdown |
to_kebab() |
تحويل الأسماء إلى slugs آمنة لروابط URL |
convert_cursor() |
التحويل إلى تنسيق .mdc
|
convert_aider() |
التجميع في ملف واحد |
convert_windsurf() |
التجميع في ملف واحد |
convert_antigravity() |
إنشاء أدلة المهارات |
convert_openclaw() |
التقسيم إلى 3 ملفات لكل وكيل |
install.sh |
النسخ إلى المسارات الخاصة بالأداة |
الخطوات التالية
توسيع السكريبتات:
- استخدم التحويل المتوازي بـ
xargs -Pأو GNU parallel - أضف تحقق من المقدمة (الحقول المطلوبة)
- أضف وضع التشغيل التجريبي (
--dry-run)
دعم أدوات جديدة:
- ملحقات VS Code
- JetBrains IDEs
- أدوات داخلية
تحسين الأداء للمستودعات الكبيرة:
- تخزين المقدمة المحللة مؤقتًا (Cache)
- استخدم
find -print0للتعامل مع الملفات بأمان - أضف أشرطة تقدم لأكثر من 100 وكيل
استكشاف المشكلات الشائعة
مشكلة "bad substitution":
- تأكد من أنك تستخدم bash (
#!/usr/bin/env bash) - تحقق من إصدار bash (
bash --version، يجب أن يكون 4.0+) - شغل السكريبت بصيغة
bash convert.sh - أزل نهايات أسطر Windows:
sed -i 's/\r$//' convert.sh
عدم استخراج حقول المقدمة:
- استخدم
:(نقطتين ومسافة) في YAML - لا تضف مسافات زائدة قبل اسم الحقل
- تأكد من وجود
---بالضبط - اختبر التحليل يدويًا:
./parse-frontmatter.sh --demo agent.md
مشاكل في إنشاء slug:
- اختبر الدالة
to_kebab()على الحالات القصوى - عالج الأحرف الخاصة بـ
iconv - عالج الحالات الفارغة:
[[ -z "$slug" ]] && slug="unknown-agent" - سجل الأسماء الأصلية لتصحيح الأخطاء
عدم تحميل قواعد كيرسور:
- تحقق من وجود وصف المقدمة في
.mdc - تحقق من تكوين
.cursor/mcp.json - ضع الملفات في
.cursor/rules/ - أعد تشغيل كيرسور بعد إضافة قواعد جديدة
ملف آيدر كبير جدًا:
- قسم بالتصنيفات (
CONVENTIONS-engineering.md) - نفذ تقليم تلقائي للوكلاء المهملين
- أضف جدول محتويات
- فكر في التضمين التلقائي
تحسين الأداء للتحويلات الكبيرة
المعالجة المتوازية:
استخدم GNU parallel لمئات الوكلاء:
#!/usr/bin/env bash
# convert-parallel.sh
export OUT_DIR="$REPO_ROOT/integrations"
# دوال قابلة للتصدير
export -f get_field get_body to_kebab convert_cursor convert_claude_code
# معالجة متوازية
find "$REPO_ROOT" -name "*.md" -type f | \
parallel -j 8 --progress '
name=$(get_field "name" {})
slug=$(to_kebab "$name")
echo "Converting: $name"
convert_cursor "{}"
convert_claude_code "{}"
'
echo "Parallel conversion complete!"
التحويل التزايدي (Incremental):
حوّل فقط الملفات التي تغيرت:
#!/usr/bin/env bash
# convert-incremental.sh
CACHE_FILE="$REPO_ROOT/.conversion-cache"
declare -A PREV_HASHES
if [[ -f "$CACHE_FILE" ]]; then
while IFS='=' read -r file hash; do
PREV_HASHES["$file"]="$hash"
done < "$CACHE_FILE"
fi
for agent_file in engineering/*.md; do
CURRENT_HASH=$(md5sum "$agent_file" | cut -d' ' -f1)
PREV_HASH="${PREV_HASHES[$agent_file]:-}"
if [[ "$CURRENT_HASH" != "$PREV_HASH" ]]; then
echo "Changed: $agent_file"
convert_cursor "$agent_file"
convert_claude_code "$agent_file"
NEW_HASHES["$agent_file"]="$CURRENT_HASH"
else
echo "Unchanged: $agent_file"
fi
done
for file in "${!NEW_HASHES[@]}"; do
echo "$file=${NEW_HASHES[$file]}"
done > "$CACHE_FILE"
تتبع التقدم:
#!/usr/bin/env bash
total_files=$(find "$REPO_ROOT" -name "*.md" -type f | wc -l)
current=0
for agent_file in "$REPO_ROOT"/**/*.md; do
((current++))
percent=$((current * 100 / total_files))
# شريط التقدم
filled=$((percent / 5))
empty=$((20 - filled))
bar=$(printf '%*s' "$filled" | tr ' ' '#')
spaces=$(printf '%*s' "$empty" | tr ' ' ' ')
name=$(get_field 'name' "$agent_file")
echo -ne "\r[${bar}${spaces}] ${percent}% - $name"
convert_cursor "$agent_file"
done
echo -ne "\n"
اعتبارات الأمان للوكلاء المشتركين
تحقق من مصادر الوكيل:
#!/usr/bin/env bash
# validate-agent.sh
validate_agent() {
local file="$1"
local name=$(get_field 'name' "$file")
local description=$(get_field 'description' "$file")
if [[ -z "$name" ]]; then
echo "ERROR: Missing 'name' field in $file"
return 1
fi
if [[ -z "$description" ]]; then
echo "WARNING: Missing 'description' field in $file"
return 1
fi
local body=$(get_body "$file")
if echo "$body" | grep -q 'rm -rf\|curl.*\|wget.*\|eval\|exec'; then
echo "WARNING: Potentially dangerous patterns in $file"
return 1
fi
echo "VALID: $name"
return 0
}
عزل التنفيذ (Sandboxing):
- استخدم حاويات Docker
- حدد الصلاحيات والقراءة فقط
- قيد الشبكة للنطاقات المطلوبة فقط
- سجل كل نشاطات الوكلاء لأغراض التدقيق
النقاط الرئيسية
- اكتب مرة واحدة وحوّل لأكثر من 10 تنسيقات — ملف Markdown واحد مع YAML يتحول لجميع الأدوات
-
باش لتحليل المقدمة —
get_field()وget_body()وto_kebab()أدوات استخراج وتحويل مرنة - كل أداة تتطلب تحويلًا خاصًا — بعض الأدوات تحتاج فقط نسخ، وبعضها يحتاج تجميع أو تقسيم
- سكريبتات التثبيت — تثبيت تلقائي في المسارات الصحيحة للأدوات
- قابلية التوسيع — أضف أي أداة جديدة خلال دقائق مع دوال التحويل الجاهزة
الأسئلة الشائعة
ما هو convert.sh? وكيف يعمل؟
هو نص باش يقوم بتحليل YAML من ملفات Markdown للوكلاء، استخراج النص الأساسي، وتحويل المحتوى لتنسيق كل أداة عبر دوال منفصلة لكل تحويل.
كيف يتم تحليل المقدمة في باش؟
باستخدام دالة get_field() مع awk للبحث عن الحقول بين محددات ---، ودالة get_body() لطباعة النص بعد المقدمة مباشرة.
ما هي الأدوات المدعومة؟
كلود كود، كيرسور، آيدر، ويندسيرف، جيت هاب كوبايلوت، أنتيجرافيتي، أوبن كلو، جيميني CLI، أوبن كود، كوين كود.
كيف أضيف دعم أداة جديدة؟
أنشئ دالة convert_yourtool()، استخرج الحقول وحوّل النص، واكتب إلى المسار الخاص بالأداة. أضفها للسكريبت الرئيسي.
هل يمكن التحويل بشكل متوازي؟
نعم، استخدم xargs -P أو GNU parallel لتقليل وقت التحويل.
كيف أتحقق من وجود الحقول المطلوبة؟
اختبر في دوال التحويل: [[ -z "$name" ]] && echo "Missing name" && exit 1
ماذا لو فشل التحويل؟
استخدم set -euo pipefail للفشل السريع، أو أضف معالجة أخطاء مخصصة وسجّل المشاكل.
Top comments (0)