สรุปย่อ
แปลงไฟล์เอไอเอเจนต์หนึ่งไฟล์เป็น 10 IDEs ใน 3 ขั้นตอน: (1) แยก YAML frontmatter ด้วยฟังก์ชัน bash `get_field()`, `get_body()` และ `to_kebab()` (2) แปลงเป็นรูปแบบเฉพาะของเครื่องมือโดยใช้ `convert.sh` (Claude Code `.md`, Cursor `.mdc`, Aider `CONVENTIONS.md`, Windsurf `.windsurfrules`) (3) ติดตั้งไปยังพาธที่ถูกต้องด้วย `install.sh` เขียนครั้งเดียว แปลงอัตโนมัติ ใช้งานได้ทุกที่
ไฟล์เอเจนต์หนึ่งไฟล์ สิบ IDEs เรียนรู้ว่าโปรเจกต์ The Agency แปลงไฟล์ Markdown ไฟล์เดียวให้ทำงานได้กับ Claude Code, Cursor, Aider, Windsurf, GitHub Copilot และเครื่องมืออื่นๆ อีก 6+ ตัวได้อย่างไร
คุณเขียนเอไอเอเจนต์ตัวหนึ่ง ตอนนี้คุณต้องการให้มันใช้งานได้ใน:
- Claude Code (ไฟล์ `.md` ใน `~/.claude/agents/`)
- Cursor (ไฟล์ `.mdc` ใน `.cursor/rules/`)
- Aider (ไฟล์ `CONVENTIONS.md` ไฟล์เดียวใน root ของโปรเจกต์)
- Windsurf (ไฟล์ `.windsurfrules` ไฟล์เดียว)
- GitHub Copilot (ไฟล์ `.md` ใน `~/.github/agents/`)
- และเครื่องมืออื่นๆ อีก 5+ ตัว
คุณจะเขียน 10 เวอร์ชันหรือไม่? ไม่ คุณเขียนครั้งเดียว แล้วแปลงโดยอัตโนมัติ
โปรเจกต์ The Agency แก้ปัญหานี้ด้วยสคริปต์ bash สองตัว:
- `convert.sh` — แปลงไฟล์เอเจนต์เป็นรูปแบบเฉพาะของเครื่องมือ
- `install.sh` — คัดลอกไฟล์ที่แปลงแล้วไปยังพาธที่ถูกต้อง
ในบทช่วยสอนนี้ คุณจะได้ทำวิศวกรรมย้อนกลับสคริปต์ทั้งสองตัวนี้ คุณจะได้เรียนรู้วิธีแยก YAML frontmatter, แยกเนื้อหาหลัก และสร้างไปป์ไลน์การแปลงสำหรับเครื่องมือใดๆ
รูปแบบของเอเจนต์
เอเจนต์ทุกตัวใน 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 — เนื้อหา Markdown หลังตัวคั่น `---` ตัวที่สอง
การแปลงหมายถึง: แยกฟิลด์ frontmatter, แปลงเนื้อหาหลักเป็นรูปแบบเป้าหมาย, เขียนไปยังพาธที่ถูกต้อง
ขั้นตอนที่ 1: แยกวิเคราะห์ YAML Frontmatter
สร้าง `parse-frontmatter.sh`:
#!/usr/bin/env bash
#
# parse-frontmatter.sh — แยกฟิลด์ YAML frontmatter จากไฟล์เอเจนต์
#
set -euo pipefail
# แยกค่าฟิลด์เดียวจาก YAML frontmatter
# การใช้งาน: get_field <field> <file>
get_field() {
local field="$1" file="$2"
awk -v f="$field" '
/^---$/ { fm++; next }
fm == 1 && $0 ~ "^" f ": " {
sub("^" f ": ", "");
print;
exit
}
' "$file"
}
# ลบ frontmatter, ส่งคืนเฉพาะเนื้อหาหลัก
# การใช้งาน: get_body <file>
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
# แปลงชื่อเป็น kebab-case slug
# การใช้งาน: to_kebab "API Tester" → api-tester
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 "ไฟล์: $AGENT_FILE"
echo "ชื่อ: $(get_field 'name' "$AGENT_FILE")"
echo "คำอธิบาย: $(get_field 'description' "$AGENT_FILE")"
echo "สลัก: $(to_kebab "$(get_field 'name' "$AGENT_FILE")")"
echo "---"
echo "ตัวอย่างเนื้อหา:"
get_body "$AGENT_FILE" | head -10
fi
ทดสอบ:
chmod +x parse-frontmatter.sh
./parse-frontmatter.sh --demo engineering-backend-architect.md
ผลลัพธ์:
ไฟล์: engineering-backend-architect.md
ชื่อ: Backend Architect
คำอธิบาย: สถาปนิกแบ็คเอนด์อาวุโสที่เชี่ยวชาญด้านการออกแบบระบบที่ปรับขนาดได้...
สลัก: backend-architect
---
ตัวอย่างเนื้อหา:
# บุคลิกของเอเจนต์ Backend Architect
คุณคือ **Backend Architect** สถาปนิกแบ็คเอนด์อาวุโส...
ขั้นตอนที่ 2: แปลงเป็นรูปแบบ Claude Code
Claude Code ใช้ไฟล์ `.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: แปลงเป็นรูปแบบ Cursor
Cursor ใช้ไฟล์ `.mdc` ที่มีฟิลด์ `description` ใน frontmatter:
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: $description
---
$body
EOF
echo " Cursor: agency-${slug}.mdc"
}
ข้อมูลนำเข้า:
---
name: API Tester
description: Specialized in API testing...
---
# API Tester Agent...
ข้อมูลส่งออก (`.mdc`):
---
description: เอเจนต์ของ Agency: Specialized in API testing...
---
# API Tester Agent...
ขั้นตอนที่ 4: แปลงเป็นรูปแบบ Aider
Aider ใช้ไฟล์ `CONVENTIONS.md` ไฟล์เดียวที่มีเอเจนต์ทั้งหมด:
convert_aider() {
local agent_file="$1"
local output="CONVENTIONS.md"
# เพิ่มด้วยตัวคั่น
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Aider: เพิ่มลงใน $output"
}
สร้างไฟล์ทั้งหมด:
build_aider() {
local output="CONVENTIONS.md"
echo "# เอเจนต์ของ Agency สำหรับ Aider" > "$output"
echo "" >> "$output"
echo "ไฟล์นี้มีเอเจนต์ของ Agency ทั้งหมดสำหรับการรวม Aider" >> "$output"
echo "" >> "$output"
for agent_file in engineering/*.md design/*.md testing/*.md; do
convert_aider "$agent_file"
done
}
ขั้นตอนที่ 5: แปลงเป็นรูปแบบ Windsurf
Windsurf ใช้ไฟล์ `.windsurfrules` ไฟล์เดียว (คล้ายกับ Aider):
convert_windsurf() {
local agent_file="$1"
local output=".windsurfrules"
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Windsurf: เพิ่มลงใน $output"
}
ขั้นตอนที่ 6: แปลงเป็นรูปแบบ Antigravity
Antigravity (Gemini) ใช้ไฟล์ `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: $name
$(get_body "$agent_file")
EOF
echo " Antigravity: agency-${slug}/SKILL.md"
}
ขั้นตอนที่ 7: แปลงเป็นรูปแบบ OpenClaw
OpenClaw ใช้สามไฟล์ต่อเอเจนต์ ( `SOUL.md`, `AGENTS.md`, `IDENTITY.md`):
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
# ความสามารถของเอเจนต์: $name
- ความเชี่ยวชาญเฉพาะด้าน
- ผลลัพธ์ที่เน้นการส่งมอบ
- มีการกำหนดตัวชี้วัดความสำเร็จ
ดู SOUL.md สำหรับคำจำกัดความฉบับเต็ม
EOF
# IDENTITY.md - ข้อมูลระบุตัวตนของเอเจนต์
cat > "$output_dir/IDENTITY.md" << EOF
# ข้อมูลระบุตัวตน: $name
- ชื่อ: $name
- คำอธิบาย: $description
- แหล่งที่มา: The Agency (agency-agents repo)
EOF
echo " OpenClaw: agency-${slug}/"
}
ขั้นตอนที่ 8: สคริปต์ convert.sh ฉบับเต็ม
นี่คือสคริปต์การแปลงที่สมบูรณ์ (แบบง่าย):
#!/usr/bin/env bash
#
# convert.sh — แปลงเอเจนต์ของ Agency ทั้งหมดเป็นรูปแบบเฉพาะของเครื่องมือ
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
OUT_DIR="$REPO_ROOT/integrations"
# ตัวช่วยสำหรับ Frontmatter
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: $(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 "กำลังแปลงเอเจนต์ของ Agency..."
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 "กำลังประมวลผล: $name"
convert_claude_code "$agent_file"
convert_cursor "$agent_file"
done
done
# สร้างไฟล์ที่รวมกัน
echo "# เอเจนต์ของ Agency สำหรับ 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 สำหรับ 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 "การแปลงเสร็จสมบูรณ์!"
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) ตัว"
}
# 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) ข้อ"
}
# Aider
install_aider() {
local src="$REPO_ROOT/integrations/aider/CONVENTIONS.md"
local dest="./CONVENTIONS.md"
cp "$src" "$dest"
echo "Aider: ติดตั้ง CONVENTIONS.md แล้ว"
}
# Windsurf
install_windsurf() {
local src="$REPO_ROOT/integrations/windsurf/.windsurfrules"
local dest="./.windsurfrules"
cp "$src" "$dest"
echo "Windsurf: ติดตั้ง .windsurfrules แล้ว"
}
# ติดตั้งเครื่องมือที่ตรวจพบทั้งหมด
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
การเปรียบเทียบรูปแบบ
| เครื่องมือ | รูปแบบ | ขอบเขต | การแปลง |
|---|---|---|---|
| Claude Code | .md |
ทั่วทั้งผู้ใช้ (~/.claude/agents/) |
คัดลอกตามเดิม |
| Cursor | .mdc |
โปรเจกต์ (.cursor/rules/) |
เพิ่ม description frontmatter |
| Aider | CONVENTIONS.md |
root ของโปรเจกต์ | รวมเอเจนต์ทั้งหมดเข้าด้วยกัน |
| Windsurf | .windsurfrules |
root ของโปรเจกต์ | รวมเอเจนต์ทั้งหมดเข้าด้วยกัน |
| GitHub Copilot | .md |
ทั่วทั้งผู้ใช้ (~/.github/agents/) |
คัดลอกตามเดิม |
| Antigravity | SKILL.md |
ทั่วทั้งผู้ใช้ (~/.gemini/antigravity/) |
ห่อในไดเรกทอรีสกิล |
| OpenClaw | SOUL.md + อื่นๆ |
ทั่วทั้งผู้ใช้ (~/.openclaw/) |
แบ่งเป็น 3 ไฟล์ |
| Gemini CLI | ส่วนเสริม | ทั่วทั้งผู้ใช้ (~/.gemini/extensions/) |
สร้าง manifest + skills |
| OpenCode | .md |
โปรเจกต์ (.opencode/agents/) |
คัดลอกตามเดิม |
| Qwen Code | .md |
โปรเจกต์ (.qwen/agents/) |
คัดลอกเป็น 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
# รูปแบบเฉพาะของเครื่องมือของคุณ
# ใช้: $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 frontmatter |
get_body() |
ลบ frontmatter, ส่งคืนเนื้อหา markdown |
to_kebab() |
แปลงชื่อเป็น slug ที่ปลอดภัยสำหรับ URL |
convert_cursor() |
แปลงเป็นรูปแบบ .mdc |
convert_aider() |
รวมเข้าเป็นไฟล์เดียว |
convert_windsurf() |
รวมเข้าเป็นไฟล์เดียว |
convert_antigravity() |
สร้างไดเรกทอรีสกิล |
convert_openclaw() |
แยกเป็น 3 ไฟล์ต่อเอเจนต์ |
install.sh |
คัดลอกไปยังพาธเฉพาะของเครื่องมือ |
ขั้นตอนถัดไป
ขยายสคริปต์:
- เพิ่มการแปลงแบบขนานด้วย `xargs -P` หรือ GNU parallel
- เพิ่มการตรวจสอบ (ตรวจสอบฟิลด์ frontmatter ที่จำเป็น)
- เพิ่มโหมด dry-run (แฟล็ก `--dry-run`)
เพิ่มเครื่องมือเพิ่มเติม:
- ส่วนเสริม VS Code
- JetBrains IDEs
- เครื่องมือภายในแบบกำหนดเอง
เพิ่มประสิทธิภาพสำหรับ repos ขนาดใหญ่:
- แคช frontmatter ที่แยกวิเคราะห์แล้ว
- ใช้ `find` กับ `-print0` สำหรับการจัดการไฟล์ที่ปลอดภัย
- เพิ่มแถบความคืบหน้าสำหรับเอเจนต์ 100+ ตัว
การแก้ไขปัญหาทั่วไป
สคริปต์การแปลงล้มเหลวด้วย "bad substitution":
- ตรวจสอบให้แน่ใจว่าคุณกำลังรัน bash ไม่ใช่ sh: `#!/usr/bin/env bash`
- ตรวจสอบเวอร์ชัน bash: `bash --version` (ควรเป็น 4.0+)
- รันอย่างชัดเจนด้วย bash: `bash convert.sh`
- มองหาการขึ้นบรรทัดใหม่ของ Windows: `sed -i 's/\r$//' convert.sh`
ฟิลด์ Frontmatter ไม่ถูกแยก:
- ตรวจสอบว่ารูปแบบ YAML ใช้ `: ` (โคลอน เว้นวรรค) ไม่ใช่แค่ `:`
- ตรวจสอบช่องว่างพิเศษหน้าชื่อฟิลด์
- ตรวจสอบให้แน่ใจว่าตัวคั่น frontmatter เป็น `---` (3 ขีด) อย่างถูกต้อง
- ทดสอบการแยกวิเคราะห์ด้วยตนเอง: `./parse-frontmatter.sh --demo agent.md`
การสร้าง Slug สร้างชื่อที่เสีย:
- ทดสอบฟังก์ชัน `to_kebab()` ด้วยกรณีสุดขีด
- จัดการอักขระพิเศษ: `to_kebab() { echo "$1" | iconv -f utf8 -t ascii//translit | ... }`
- เพิ่มค่าสำรองสำหรับ slug ที่ว่างเปล่า: `[[ -z "$slug" ]] && slug="unknown-agent"`
- บันทึกชื่อเดิมสำหรับการดีบัก
กฎของ Cursor ไม่โหลด:
- ตรวจสอบว่าไฟล์ `.mdc` มี frontmatter ที่ถูกต้องพร้อม `description`
- ตรวจสอบการกำหนดค่า MCP ของ Cursor: `.cursor/mcp.json`
- ตรวจสอบให้แน่ใจว่าไฟล์อยู่ใน `.cursor/rules/` ไม่ใช่ `.cursor/agents/`
- รีสตาร์ท Cursor หลังจากเพิ่มกฎใหม่
Aider CONVENTIONS.md มีขนาดใหญ่เกินไป:
- แบ่งตามหมวดหมู่: `CONVENTIONS-engineering.md`, `CONVENTIONS-design.md`
- ใช้การลบอัตโนมัติสำหรับเอเจนต์ที่เลิกใช้แล้ว
- เพิ่มสารบัญที่ด้านบน
- พิจารณาไฟล์ต่อเอเจนต์พร้อมคำสั่ง include
การเพิ่มประสิทธิภาพสำหรับงานแปลงขนาดใหญ่
การประมวลผลแบบขนาน:
สำหรับ repositories ที่มีเอเจนต์มากกว่า 100 ตัว ให้ใช้ 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 "กำลังแปลง: $name"
convert_cursor "{}"
convert_claude_code "{}"
'
echo "การแปลงแบบขนานเสร็จสมบูรณ์!"
การแปลงแบบเพิ่มขึ้น:
แปลงเฉพาะไฟล์ที่เปลี่ยนแปลง:
#!/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 "เปลี่ยนแปลง: $agent_file"
convert_cursor "$agent_file"
convert_claude_code "$agent_file"
NEW_HASHES["$agent_file"]="$CURRENT_HASH"
else
echo "ไม่เปลี่ยนแปลง: $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"
# ตรวจสอบฟิลด์ frontmatter ที่จำเป็น
local name=$(get_field 'name' "$file")
local description=$(get_field 'description' "$file")
if [[ -z "$name" ]]; then
echo "ข้อผิดพลาด: ไม่มีฟิลด์ 'name' ใน $file"
return 1
fi
if [[ -z "$description" ]]; then
echo "คำเตือน: ไม่มีฟิลด์ 'description' ใน $file"
fi
# ตรวจสอบรูปแบบที่เป็นอันตรายในเนื้อหาหลัก
local body=$(get_body "$file")
if echo "$body" | grep -q 'rm -rf\|curl.*\|wget.*\|eval\|exec'; then
echo "คำเตือน: รูปแบบที่อาจเป็นอันตรายใน $file"
return 1
fi
echo "ถูกต้อง: $name"
return 0
}
การแยกการทำงานของเอเจนต์ใน Sandbox:
สำหรับเอเจนต์ที่ไม่น่าเชื่อถือ ให้รันในสภาพแวดล้อมที่แยกต่างหาก:
- ใช้ Docker containers สำหรับการทำงานของเอเจนต์
- จำกัดการเข้าถึงระบบไฟล์ด้วย read-only mounts
- จำกัดการเข้าถึงเครือข่ายไปยังโดเมนที่เฉพาะเจาะจง
- บันทึกการกระทำทั้งหมดของเอเจนต์สำหรับการตรวจสอบ
ไฟล์เอเจนต์หนึ่งไฟล์ สิบ IDEs สคริปต์ bash สองตัว
นี่คือพลังของระบบอัตโนมัติในการแปลง เขียนครั้งเดียว แปลงอัตโนมัติ ติดตั้งได้ทุกที่
ถึงตาคุณแล้ว: เพิ่มการรองรับการแปลงสำหรับเครื่องมือ AI ที่คุณชื่นชอบ แชร์สคริปต์ ทำให้เอเจนต์สามารถเคลื่อนย้ายได้
ประเด็นสำคัญ
- เขียนครั้งเดียว แปลงเป็น 10+ รูปแบบ — ไฟล์ Markdown ไฟล์เดียวที่มี YAML frontmatter แปลงเป็น Claude Code, Cursor, Aider, Windsurf และเครื่องมืออื่นๆ อีก 6+ ตัว
- การแยกวิเคราะห์ Bash จัดการการแยก frontmatter — `get_field()` แยกค่า YAML, `get_body()` ลบ frontmatter, `to_kebab()` สร้าง slug ที่ปลอดภัยสำหรับ URL
- รูปแบบเฉพาะของเครื่องมือต้องการการแปลงที่แตกต่างกัน — Claude Code คัดลอกตามเดิม, Cursor เพิ่ม description frontmatter, Aider/Windsurf รวมเอเจนต์ทั้งหมดเข้าด้วยกัน
- สคริปต์ติดตั้งคัดลอกไปยังพาธที่ถูกต้อง — เครื่องมือทั่วทั้งผู้ใช้ใช้ `~/.claude/agents/`, เครื่องมือโปรเจกต์ใช้ `.cursor/rules/` หรือไฟล์ root ของโปรเจกต์
- ขยายด้วยเทมเพลตสำหรับเครื่องมือใหม่ — กำหนดฟังก์ชัน `convert_your_tool()`, เพิ่มลงในลูปหลัก, บันทึกข้อกำหนดรูปแบบ
คำถามที่พบบ่อย
`convert.sh` คืออะไรและทำงานอย่างไร? `convert.sh` คือสคริปต์ bash ที่แยกวิเคราะห์ YAML frontmatter จากไฟล์ Markdown ของเอเจนต์, ดึงเนื้อหาหลัก, และแปลงเอเจนต์แต่ละตัวเป็นรูปแบบเฉพาะของเครื่องมือ มันใช้ awk สำหรับการแยกวิเคราะห์, sed สำหรับการแปลง slug, และ heredocs สำหรับการสร้างเอาต์พุต
การแยกวิเคราะห์ frontmatter ใน bash ทำงานอย่างไร? ฟังก์ชัน `get_field()` ใช้ awk เพื่อติดตามตัวคั่น frontmatter (`---`), ค้นหาบรรทัดที่ตรงกับชื่อฟิลด์, และดึงค่าออกมา `get_body()` จะพิมพ์บรรทัดทั้งหมดหลังจากตัวคั่น `---` ตัวที่สอง
รองรับ IDEs และเครื่องมือใดบ้าง? Claude Code (`.md`), Cursor (`.mdc`), Aider (`CONVENTIONS.md`), Windsurf (`.windsurfrules`), GitHub Copilot (`.md`), Antigravity (`SKILL.md`), OpenClaw (`SOUL.md` + 2 ไฟล์), ส่วนเสริม Gemini CLI, OpenCode, และ Qwen Code
ฉันจะเพิ่มการรองรับการแปลงสำหรับเครื่องมือใหม่ได้อย่างไร? สร้างฟังก์ชัน `convert_yourtool()` ที่ดึงฟิลด์ frontmatter, แปลงเนื้อหาหลักเป็นรูปแบบของเครื่องมือของคุณ, และเขียนไปยังพาธที่ถูกต้อง เพิ่มการเรียกใช้ฟังก์ชันนั้นในลูปการแปลงหลัก
ฉันสามารถเรียกใช้การแปลงแบบขนานเพื่อให้ประมวลผลเร็วขึ้นได้หรือไม่? ได้ ใช้ `xargs -P` หรือ GNU parallel เพื่อประมวลผลไฟล์เอเจนต์หลายไฟล์พร้อมกัน สำหรับเอเจนต์มากกว่า 100 ตัว การแปลงแบบขนานสามารถลดเวลาทำงานจากนาทีเป็นวินาที
ฉันจะตรวจสอบได้อย่างไรว่ามีฟิลด์ frontmatter อยู่? เพิ่มการตรวจสอบในฟังก์ชันการแปลงของคุณ: `[[ -z "$name" ]] && echo "Missing name field" && exit 1` เรียกใช้การตรวจสอบก่อนเขียนไฟล์เอาต์พุต
จะเกิดอะไรขึ้นหากการแปลงล้มเหลวสำหรับเอเจนต์บางตัว? ใช้ `set -euo pipefail` เพื่อให้หยุดทำงานทันทีเมื่อเกิดข้อผิดพลาด เพิ่มการจัดการข้อผิดพลาดด้วย `|| continue` เพื่อข้ามไฟล์ที่เสียหาย บันทึกข้อผิดพลาดไปยังไฟล์แยกต่างหากสำหรับการดีบัก
