TÓM LƯỢC
Chuyển đổi một tệp tác nhân AI sang 10 IDE chỉ với 3 bước: (1) Phân tích YAML frontmatter bằng bash (get_field(), get_body(), to_kebab()), (2) Chuyển đổi sang định dạng dành riêng cho từng công cụ với convert.sh (Claude Code .md, Cursor .mdc, Aider CONVENTIONS.md, Windsurf .windsurfrules...), (3) Cài đặt vào đúng đường dẫn với install.sh. Viết một lần, tự động chuyển đổi, triển khai khắp nơi.
Một tệp tác nhân. Mười IDE. Dưới đây là cách dự án The Agency tự động chuyển đổi một tệp Markdown tác nhân để sử dụng cho Claude Code, Cursor, Aider, Windsurf, GitHub Copilot và hơn 6 công cụ khác.
Bạn viết một tác nhân AI. Giờ bạn muốn nó hoạt động trên:
- Claude Code (
.mdtrong~/.claude/agents/) - Cursor (
.mdctrong.cursor/rules/) - Aider (
CONVENTIONS.mdtại gốc dự án) - Windsurf (
.windsurfrules) - GitHub Copilot (
.mdtrong~/.github/agents/) - Và hơn 5 công cụ khác
Bạn không cần viết 10 phiên bản. Chỉ cần một bản, tự động chuyển đổi.
The Agency giải quyết bằng 2 script bash:
-
convert.sh— Chuyển đổi tệp tác nhân sang từng định dạng công cụ -
install.sh— Sao chép các tệp đã chuyển đổi đến đúng vị trí
Hướng dẫn này giúp bạn từng bước xây dựng bộ chuyển đổi, từ phân tích YAML frontmatter, trích xuất phần thân, tới các hàm chuyển đổi cho bất kỳ công cụ nào.
💡 Cho dù bạn tích hợp tác nhân vào workflow phát triển API với Apidog hoặc xây dựng các agent kiểm thử chuyên biệt, hệ thống chuyển đổi này đảm bảo tác nhân hoạt động đồng nhất trên mọi IDE nhóm sử dụng.
Định dạng Tác nhân
Tất cả tác nhân đều dùng chung một cấu trúc:
---
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
...
Tệp gồm 2 phần:
-
Frontmatter — Siêu dữ liệu YAML giữa các dấu
--- -
Body — Nội dung Markdown sau dấu
---thứ hai
Chuyển đổi = trích xuất trường frontmatter, chuyển đổi phần thân, ghi ra đúng định dạng và vị trí.
Bước 1: Phân tích YAML Frontmatter
Tạo file parse-frontmatter.sh để trích xuất trường YAML:
#!/usr/bin/env bash
#
# parse-frontmatter.sh — Extract YAML frontmatter fields from agent files
#
set -euo pipefail
# Trích xuất một trường từ YAML frontmatter
get_field() {
local field="$1" file="$2"
awk -v f="$field" '
/^---$/ { fm++; next }
fm == 1 && $0 ~ "^" f ": " {
sub("^" f ": ", "");
print;
exit
}
' "$file"
}
# Trả về phần body (bỏ frontmatter)
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
# Đổi tên thành slug (kebab-case)
to_kebab() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g'
}
# Demo
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
Chạy thử:
chmod +x parse-frontmatter.sh
./parse-frontmatter.sh --demo engineering-backend-architect.md
Đầu ra mẫu:
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...
Bước 2: Chuyển đổi sang Định dạng Claude Code
Claude Code chỉ cần copy nguyên trạng .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")"
}
Bước 3: Chuyển đổi sang Định dạng Cursor
Cursor yêu cầu .mdc với frontmatter description:
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"
}
Đầu vào:
---
name: API Tester
description: Specialized in API testing...
---
# API Tester Agent...
Đầu ra (.mdc):
---
description: Agency agent: Specialized in API testing...
---
# API Tester Agent...
Bước 4: Chuyển đổi sang Định dạng Aider
Aider dùng một file CONVENTIONS.md chứa nhiều agent:
convert_aider() {
local agent_file="$1"
local output="CONVENTIONS.md"
# Thêm vào cuối file với separator
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Aider: appended to $output"
}
Để build file hoàn chỉnh:
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
}
Bước 5: Chuyển đổi sang Định dạng Windsurf
Windsurf dùng file .windsurfrules tương tự Aider:
convert_windsurf() {
local agent_file="$1"
local output=".windsurfrules"
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Windsurf: appended to $output"
}
Bước 6: Chuyển đổi sang Định dạng Antigravity
Antigravity (Gemini) cần mỗi agent là một thư mục 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"
}
Bước 7: Chuyển đổi sang Định dạng OpenClaw
OpenClaw tách mỗi agent thành 3 file:
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}/"
}
Bước 8: Tập lệnh convert.sh hoàn chỉnh
Tập lệnh chuyển đổi toàn bộ agent:
#!/usr/bin/env bash
#
# convert.sh — Convert all Agency agents to tool-specific formats
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
OUT_DIR="$REPO_ROOT/integrations"
# Helper functions
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'
}
# Chuyển đổi cho từng công cụ
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"
}
# Main
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
# Build gộp cho Aider/Windsurf
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"
Chạy chuyển đổi:
chmod +x convert.sh
./convert.sh
Bước 9: Cài đặt vào từng công cụ
Sau khi chuyển đổi, dùng script để copy vào đúng vị trí:
#!/usr/bin/env bash
#
# install.sh — Install converted agents to your local tools
#
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 detected tools
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
So sánh Định dạng
| Công cụ | Định dạng | Phạm vi | Chuyển đổi |
|---|---|---|---|
| Claude Code | .md |
Toàn hệ thống người dùng (~/.claude/agents/) |
Sao chép nguyên trạng |
| Cursor | .mdc |
Dự án (.cursor/rules/) |
Thêm description frontmatter |
| Aider | CONVENTIONS.md |
Thư mục gốc dự án | Nối tất cả tác nhân |
| Windsurf | .windsurfrules |
Thư mục gốc dự án | Nối tất cả tác nhân |
| GitHub Copilot | .md |
Toàn hệ thống người dùng (~/.github/agents/) |
Sao chép nguyên trạng |
| Antigravity | SKILL.md |
Toàn hệ thống người dùng (~/.gemini/antigravity/) |
Đóng gói trong thư mục kỹ năng |
| OpenClaw |
SOUL.md + khác |
Toàn hệ thống người dùng (~/.openclaw/) |
Chia thành 3 tệp |
| Gemini CLI | Tiện ích mở rộng | Toàn hệ thống người dùng (~/.gemini/extensions/) |
Tạo manifest + kỹ năng |
| OpenCode | .md |
Dự án (.opencode/agents/) |
Sao chép nguyên trạng |
| Qwen Code | .md |
Dự án (.qwen/agents/) |
Sao chép dưới dạng SubAgent |
Xây dựng Tập lệnh Chuyển đổi của riêng bạn
Mẫu thêm công cụ mới:
#!/usr/bin/env bash
# 1. Định nghĩa hàm chuyển đổi
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. Tạo đường dẫn output
local output="path/to/your/tool/agency-${slug}.ext"
mkdir -p "$(dirname "$output")"
# 3. Ghi nội dung chuyển đổi
cat > "$output" << EOF
# Your tool-specific format
# Use: $name, $description, $body
EOF
echo " YourTool: agency-${slug}.ext"
}
# 4. Thêm vào vòng lặp chính
for agent_file in engineering/*.md; do
convert_your_tool "$agent_file"
done
Những gì bạn đã xây dựng
| Thành phần | Mục đích |
|---|---|
get_field() |
Trích xuất giá trị YAML frontmatter |
get_body() |
Loại bỏ frontmatter, trả về phần thân |
to_kebab() |
Chuyển tên thành slug cho URL |
convert_cursor() |
Chuyển đổi sang định dạng .mdc
|
convert_aider() |
Nối vào một tệp duy nhất |
convert_windsurf() |
Nối vào một tệp duy nhất |
convert_antigravity() |
Tạo thư mục kỹ năng |
convert_openclaw() |
Chia thành 3 tệp cho mỗi tác nhân |
install.sh |
Sao chép vào đúng đường dẫn từng công cụ |
Các bước tiếp theo
Mở rộng script:
- Thêm chuyển đổi song song với
xargs -Phoặc GNU parallel - Thêm xác thực frontmatter bắt buộc
- Thêm chế độ
--dry-runđể kiểm thử
Thêm nhiều công cụ hơn:
- Extension VS Code
- JetBrains IDE
- Công cụ nội bộ tùy chỉnh
Tối ưu cho repo lớn:
- Cache frontmatter đã phân tích
- Dùng
find ... -print0để xử lý tệp an toàn - Thêm thanh tiến độ nếu agent >100
Khắc phục các sự cố thường gặp
Lỗi “bad substitution” khi chạy script:
- Đảm bảo dùng bash:
#!/usr/bin/env bash - Kiểm tra bash version:
bash --version(>=4.0) - Chạy script bằng bash:
bash convert.sh - Loại bỏ ký tự xuống dòng Windows:
sed -i 's/\r$//' convert.sh
Không trích xuất được trường frontmatter:
- Đảm bảo YAML dùng
:(có dấu cách) - Không có thừa khoảng trắng đầu dòng
- Dấu phân cách frontmatter đúng là
--- - Thử demo:
./parse-frontmatter.sh --demo agent.md
Tạo slug bị lỗi:
- Test
to_kebab()với tên đặc biệt - Xử lý ký tự đặc biệt:
iconv -f utf8 -t ascii//translit - Dự phòng slug trống:
[[ -z "$slug" ]] && slug="unknown-agent" - Log lại tên gốc để debug
Cursor không nhận rule:
- File
.mdccó frontmatter hợp lệ vớidescription - Kiểm tra
.cursor/mcp.json - File đúng vị trí
.cursor/rules/ - Khởi động lại Cursor
Aider CONVENTIONS.md quá lớn:
- Chia nhỏ theo nhóm:
CONVENTIONS-engineering.md, ... - Cắt tỉa agent không dùng nữa tự động
- Thêm mục lục đầu file
- Cân nhắc tách từng agent thành file riêng rồi include
Tối ưu hóa hiệu suất cho chuyển đổi lớn
Chạy song song:
Dùng GNU parallel cho repo >100 agent:
#!/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!"
Chuyển đổi tăng dần (incremental):
Chỉ convert file thay đổi:
#!/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"
Theo dõi tiến độ:
Hiển thị progress bar khi chuyển đổi nhiều 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"
Các cân nhắc bảo mật cho tác nhân được chia sẻ
Xác thực nguồn agent:
Kiểm tra nội dung agent trước khi chuyển đổi:
#!/usr/bin/env bash
# validate-agent.sh
validate_agent() {
local file="$1"
# Kiểm tra trường bắt buộc
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"
fi
# Kiểm tra lệnh nguy hiểm trong body
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
}
Chạy agent trong sandbox:
- Dùng Docker để cô lập agent
- Mount file hệ thống chỉ đọc
- Giới hạn truy cập mạng
- Log toàn bộ hành động agent
Một tệp tác nhân. Mười IDE. Hai script bash.
Đó là sức mạnh của tự động hóa chuyển đổi: Viết một lần, chuyển đổi tự động, cài đặt khắp nơi.
Hãy thêm hỗ trợ cho công cụ AI yêu thích của bạn, chia sẻ script, giúp agent di động và dễ tích hợp hơn.
Những điểm chính
- Viết một lần, chuyển đổi hơn 10 định dạng — Một file Markdown với YAML frontmatter, chuyển đổi sang Claude Code, Cursor, Aider, Windsurf,... và các công cụ khác
-
Bash xử lý parsing frontmatter —
get_field()trích xuất YAML,get_body()lấy body,to_kebab()tạo slug - Chuyển đổi đặc thù cho từng công cụ — Claude Code chỉ copy, Cursor thêm description, Aider/Windsurf gộp agent
-
Script cài đặt copy ra đúng đường dẫn — Hệ thống người dùng:
~/.claude/agents/, dự án:.cursor/rules/hoặc gốc dự án -
Mở rộng dễ dàng với mẫu — Định nghĩa
convert_your_tool(), thêm vào vòng lặp chính, ghi chú yêu cầu định dạng
Câu hỏi thường gặp
convert.sh là gì?
Script bash này phân tích YAML frontmatter từ Markdown agent, trích xuất body, chuyển đổi sang từng định dạng công cụ bằng awk, sed, heredoc.
Phân tích frontmatter trong bash hoạt động ra sao?
get_field() dùng awk xác định block YAML, tìm trường, lấy giá trị. get_body() in tất cả sau dấu --- thứ hai.
Hỗ trợ IDE/công cụ nào?
Claude Code (.md), Cursor (.mdc), Aider (CONVENTIONS.md), Windsurf (.windsurfrules), GitHub Copilot (.md), Antigravity (SKILL.md), OpenClaw (SOUL.md + 2 file), Gemini CLI extension, OpenCode, Qwen Code.
Thêm công cụ mới thế nào?
Tạo hàm convert_<tool>() trích xuất trường, chuyển đổi body, ghi đúng định dạng/đường dẫn. Thêm vào vòng lặp chính.
Chuyển đổi song song để nhanh hơn được không?
Có. Dùng xargs -P hoặc GNU parallel để convert nhiều file cùng lúc, giảm thời gian cho repo lớn.
Làm sao xác thực trường frontmatter?
Kiểm tra trong hàm: [[ -z "$name" ]] && echo "Thiếu trường tên" && exit 1. Validate trước khi ghi file output.
Nếu chuyển đổi lỗi với một số agent thì sao?
Dùng set -euo pipefail để fail fast. Hoặc thêm || continue để bỏ qua file lỗi, ghi log riêng để debug.
Top comments (0)