TL;DR
Convierta un archivo de agente de IA a 10 IDEs en 3 pasos: (1) Analice el frontmatter YAML con las funciones bash get_field(), get_body() y to_kebab(), (2) Transforme a formatos específicos de la herramienta usando convert.sh (Claude Code .md, Cursor .mdc, Aider CONVENTIONS.md, Windsurf .windsurfrules), (3) Instale en las rutas correctas con install.sh. Escriba una vez, convierta automáticamente, despliegue en todas partes.
Un archivo de agente. Diez IDEs. Aprenda cómo el proyecto The Agency convierte un solo archivo Markdown para que funcione en Claude Code, Cursor, Aider, Windsurf, GitHub Copilot y más de 6 herramientas adicionales.
Usted escribe un agente de IA. Ahora quiere que esté disponible en:
- Claude Code (archivos
.mden~/.claude/agents/) - Cursor (archivos
.mdcen.cursor/rules/) - Aider (un solo
CONVENTIONS.mden la raíz del proyecto) - Windsurf (un solo archivo
.windsurfrules) - GitHub Copilot (archivos
.mden~/.github/agents/) - Y más de 5 herramientas adicionales
¿Escribe 10 versiones? No. Escribe una vez, convierte automáticamente.
El proyecto The Agency resuelve esto con dos scripts bash:
convert.sh— Transforma los archivos del agente a formatos específicos de la herramientainstall.sh— Copia los archivos convertidos a las rutas correctas
En este tutorial, realizará ingeniería inversa de ambos scripts. Aprenderá cómo analizar el frontmatter YAML, extraer el contenido del cuerpo y construir tuberías de conversión para cualquier herramienta.
El formato del agente
Cada agente en The Agency usa la misma estructura:
---
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
...
El archivo tiene dos partes:
- Frontmatter — Metadatos YAML entre delimitadores
--- - Cuerpo — Contenido Markdown después del segundo
---
La conversión significa: extraer campos del frontmatter, transformar el cuerpo al formato objetivo, escribir a la ruta correcta.
Paso 1: Analizar el Frontmatter YAML
Cree parse-frontmatter.sh:
#!/usr/bin/env bash
#
# parse-frontmatter.sh — Extract YAML frontmatter fields from agent files
#
set -euo pipefail
# Extract a single field value from YAML frontmatter
# Usage: 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"
}
# Strip frontmatter, return only body
# Usage: get_body <file>
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
# Convert name to kebab-case slug
# Usage: to_kebab "API Tester" → api-tester
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
Pruébelo:
chmod +x parse-frontmatter.sh
./parse-frontmatter.sh --demo engineering-backend-architect.md
Salida:
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...
Paso 2: Convertir al formato Claude Code
Claude Code usa archivos .md sin procesar. No se necesita conversión, solo copie:
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")"
}
Paso 3: Convertir al formato Cursor
Cursor usa archivos .mdc con un campo description en el 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 agent: $description
---
$body
EOF
echo " Cursor: agency-${slug}.mdc"
}
Entrada:
---
name: API Tester
description: Specialized in API testing...
---
# API Tester Agent...
Salida (.mdc):
---
description: Agency agent: Specialized in API testing...
---
# API Tester Agent...
Paso 4: Convertir al formato Aider
Aider usa un único archivo CONVENTIONS.md que contiene todos los agentes:
convert_aider() {
local agent_file="$1"
local output="CONVENTIONS.md"
# Append with separator
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Aider: appended to $output"
}
Construya el archivo completo:
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
}
Paso 5: Convertir al formato Windsurf
Windsurf usa un único archivo .windsurfrules (similar a 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"
}
Paso 6: Convertir al formato Antigravity
Antigravity (Gemini) usa archivos SKILL.md en subdirectorios:
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"
}
Paso 7: Convertir al formato OpenClaw
OpenClaw usa tres archivos por agente (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 - Main agent definition
cat > "$output_dir/SOUL.md" << EOF
# $name
$description
---
$body
EOF
# AGENTS.md - Agent capabilities
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 - Agent identity
cat > "$output_dir/IDENTITY.md" << EOF
# Identity: $name
- Name: $name
- Description: $description
- Source: The Agency (agency-agents repo)
EOF
echo " OpenClaw: agency-${slug}/"
}
Paso 8: El script completo convert.sh
Aquí está el script de conversión completo (simplificado):
#!/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"
# Frontmatter helpers
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'
}
# Conversion functions
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 conversion loop
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
# Build combined files
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"
Ejecútelo:
chmod +x convert.sh
./convert.sh
Paso 9: Instalar en cada herramienta
Después de la conversión, copie los archivos a las rutas específicas de cada herramienta:
#!/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
Comparación de formatos
| Herramienta | Formato | Alcance | Conversión |
|---|---|---|---|
| Claude Code | .md |
De usuario (~/.claude/agents/) |
Copiar tal cual |
| Cursor | .mdc |
Proyecto (.cursor/rules/) |
Añadir frontmatter de descripción |
| Aider | CONVENTIONS.md |
Raíz del proyecto | Concatenar todos los agentes |
| Windsurf | .windsurfrules |
Raíz del proyecto | Concatenar todos los agentes |
| GitHub Copilot | .md |
De usuario (~/.github/agents/) |
Copiar tal cual |
| Antigravity | SKILL.md |
De usuario (~/.gemini/antigravity/) |
Envolver en directorio de habilidad |
| OpenClaw | SOUL.md + otros |
De usuario (~/.openclaw/) |
Dividir en 3 archivos |
| Gemini CLI | Extensión | De usuario (~/.gemini/extensions/) |
Generar manifiesto + habilidades |
| OpenCode | .md |
Proyecto (.opencode/agents/) |
Copiar tal cual |
| Qwen Code | .md |
Proyecto (.qwen/agents/) |
Copiar como SubAgente |
Construya su propio script de conversión
Plantilla para añadir una nueva herramienta:
#!/usr/bin/env bash
# 1. Define conversion function
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. Create output path
local output="path/to/your/tool/agency-${slug}.ext"
mkdir -p "$(dirname "$output")"
# 3. Write converted content
cat > "$output" << EOF
# Your tool-specific format
# Use: $name, $description, $body
EOF
echo " YourTool: agency-${slug}.ext"
}
# 4. Add to main loop
for agent_file in engineering/*.md; do
convert_your_tool "$agent_file"
done
Lo que ha construido
| Componente | Propósito |
|---|---|
get_field() |
Extraer valores del frontmatter YAML |
get_body() |
Quitar el frontmatter, devolver el cuerpo markdown |
to_kebab() |
Convertir nombres a slugs URL-seguros |
convert_cursor() |
Transformar al formato .mdc |
convert_aider() |
Concatenar en un solo archivo |
convert_windsurf() |
Concatenar en un solo archivo |
convert_antigravity() |
Crear directorios de habilidad |
convert_openclaw() |
Dividir en 3 archivos por agente |
install.sh |
Copiar a rutas específicas de la herramienta |
Próximos pasos
Extender los scripts:
- Añadir conversión paralela con
xargs -Po GNU parallel - Añadir validación (comprobar campos de frontmatter requeridos)
- Añadir modo de prueba (
--dry-runflag)
Añadir más herramientas:
- Extensiones de VS Code
- IDEs de JetBrains
- Herramientas internas personalizadas
Optimizar para grandes repositorios:
- Cachear frontmatter analizado
- Usar
findcon-print0para un manejo seguro de archivos - Añadir barras de progreso para más de 100 agentes
Solución de problemas comunes
El script de conversión falla con "bad substitution":
- Asegúrese de estar ejecutando bash, no sh:
#!/usr/bin/env bash - Compruebe la versión de bash:
bash --version(debería ser 4.0+) - Ejecute explícitamente con bash:
bash convert.sh - Busque finales de línea de Windows:
sed -i 's/\r$//' convert.sh
Los campos del frontmatter no se extraen:
- Verifique que el formato YAML use
:(dos puntos espacio) y no solo: - Compruebe si hay espacios extra antes de los nombres de los campos
- Asegúrese de que los delimitadores del frontmatter sean exactamente
---(3 guiones) - Pruebe el análisis manualmente:
./parse-frontmatter.sh --demo agent.md
La generación de slugs crea nombres rotos:
- Pruebe la función
to_kebab()con casos extremos - Maneje caracteres especiales:
to_kebab() { echo "$1" | iconv -f utf8 -t ascii//translit | ... } - Añada un fallback para slugs vacíos:
[[ -z "$slug" ]] && slug="unknown-agent" - Registre los nombres originales para depuración
Las reglas del cursor no se cargan:
- Verifique que los archivos
.mdctengan un frontmatter válido condescription - Compruebe la configuración MCP de Cursor:
.cursor/mcp.json - Asegúrese de que los archivos estén en
.cursor/rules/y no en.cursor/agents/ - Reinicie Cursor después de añadir nuevas reglas
El archivo CONVENTIONS.md de Aider se vuelve demasiado grande:
- Divida por categoría:
CONVENTIONS-engineering.md,CONVENTIONS-design.md - Implemente una poda automática para agentes obsoletos
- Añada una tabla de contenidos en la parte superior
- Considere archivos por agente con directivas de inclusión
Optimización del rendimiento para grandes conversiones
Procesamiento paralelo:
Para repositorios con más de 100 agentes, use GNU parallel:
#!/usr/bin/env bash
# convert-parallel.sh
export OUT_DIR="$REPO_ROOT/integrations"
# Export functions for parallel use
export -f get_field get_body to_kebab convert_cursor convert_claude_code
# Find all agent files and process in parallel
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!"
Conversión incremental:
Convierta solo los archivos modificados:
#!/usr/bin/env bash
# convert-incremental.sh
CACHE_FILE="$REPO_ROOT/.conversion-cache"
# Load previous state
declare -A PREV_HASHES
if [[ -f "$CACHE_FILE" ]]; then
while IFS='=' read -r file hash; do
PREV_HASHES["$file"]="$hash"
done < "$CACHE_FILE"
fi
# Process each agent
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
# Save cache
for file in "${!NEW_HASHES[@]}"; do
echo "$file=${NEW_HASHES[$file]}"
done > "$CACHE_FILE"
Seguimiento de progreso:
Añada una barra de progreso visual para conversiones largas:
#!/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))
# Progress bar
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"
Consideraciones de seguridad para agentes compartidos
Validación de fuentes de agentes:
Al descargar agentes de fuentes externas:
#!/usr/bin/env bash
# validate-agent.sh
validate_agent() {
local file="$1"
# Check required frontmatter fields
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
# Check for malicious patterns in 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
}
Ejecución de agentes en sandbox:
Para agentes no confiables, ejecute en entornos aislados:
- Use contenedores Docker para la ejecución de agentes
- Limite el acceso al sistema de archivos con montajes de solo lectura
- Restrinja el acceso a la red a dominios específicos
- Registre todas las acciones del agente para pistas de auditoría
Un archivo de agente. Diez IDEs. Dos scripts bash.
Ese es el poder de la automatización de la conversión. Escriba una vez, convierta automáticamente, instale en todas partes.
Ahora es su turno: añada soporte de conversión para su herramienta de IA favorita. Comparta el script. Haga que los agentes sean portátiles.
Puntos clave
- Escriba una vez, convierta a más de 10 formatos — Un solo archivo Markdown con frontmatter YAML se transforma a Claude Code, Cursor, Aider, Windsurf y más de 6 herramientas adicionales
- El análisis de Bash maneja la extracción del frontmatter —
get_field()extrae valores YAML,get_body()quita el frontmatter,to_kebab()crea slugs seguros para URL - Los formatos específicos de la herramienta requieren diferentes transformaciones — Claude Code copia tal cual, Cursor añade frontmatter de descripción, Aider/Windsurf concatenan todos los agentes
- Los scripts de instalación copian a las rutas correctas — Las herramientas de usuario usan
~/.claude/agents/, las herramientas de proyecto usan.cursor/rules/o archivos en la raíz del proyecto - Extienda con plantillas para nuevas herramientas — Defina la función
convert_your_tool(), añádala al bucle principal, documente los requisitos del formato
Preguntas frecuentes
¿Qué es convert.sh y cómo funciona? convert.sh es un script bash que analiza el frontmatter YAML de los archivos Markdown de los agentes, extrae el contenido del cuerpo y transforma cada agente a formatos específicos de la herramienta. Utiliza awk para el análisis, sed para la conversión de slugs y heredocs para la generación de salida.
¿Cómo funciona el análisis del frontmatter en bash? La función get_field() utiliza awk para rastrear los delimitadores del frontmatter (---), encuentra la línea que coincide con el nombre del campo y extrae el valor. get_body() imprime todas las líneas después del segundo delimitador ---.
¿Qué IDEs y herramientas son compatibles? Claude Code (.md), Cursor (.mdc), Aider (CONVENTIONS.md), Windsurf (.windsurfrules), GitHub Copilot (.md), Antigravity (SKILL.md), OpenClaw (SOUL.md + 2 archivos), extensiones de Gemini CLI, OpenCode y Qwen Code.
¿Cómo añado soporte de conversión para una nueva herramienta? Cree una función convert_yourtool() que extraiga los campos del frontmatter, transforme el cuerpo al formato de su herramienta y escriba en la ruta correcta. Añada la llamada a la función al bucle de conversión principal.
¿Puedo ejecutar conversiones en paralelo para un procesamiento más rápido? Sí. Utilice xargs -P o GNU parallel para procesar varios archivos de agentes simultáneamente. Para más de 100 agentes, la conversión en paralelo puede reducir el tiempo de ejecución de minutos a segundos.
¿Cómo valido que los campos del frontmatter existen? Añada comprobaciones de validación en su función de conversión: [[ -z "$name" ]] && echo "Missing name field" && exit 1. Ejecute la validación antes de escribir los archivos de salida.
¿Qué pasa si la conversión falla para algunos agentes? Use set -euo pipefail para fallar rápidamente en caso de errores. Añada manejo de errores con || continue para omitir archivos dañados. Registre los fallos en un archivo separado para depuración.
