TL;DR
Converta um arquivo de agente de IA para 10 IDEs em 3 etapas:
(1) Analise o frontmatter YAML com as funções bash get_field(), get_body() e to_kebab()
(2) Transforme para formatos específicos de ferramentas usando convert.sh (Claude Code .md, Cursor .mdc, Aider CONVENTIONS.md, Windsurf .windsurfrules)
(3) Instale nos caminhos corretos com install.sh.
Escreva uma vez, converta automaticamente, implante em todo lugar.
Um arquivo de agente. Dez IDEs. Aprenda como o projeto The Agency converte um único arquivo Markdown para funcionar com Claude Code, Cursor, Aider, Windsurf, GitHub Copilot e mais de 6 outras ferramentas.
Você escreve um agente de IA. Agora você quer ele disponível em:
- Claude Code (arquivos
.mdem~/.claude/agents/) - Cursor (arquivos
.mdcem.cursor/rules/) - Aider (um único
CONVENTIONS.mdna raiz do projeto) - Windsurf (um único arquivo
.windsurfrules) - GitHub Copilot (arquivos
.mdem~/.github/agents/) - E mais de 5 outras ferramentas
Você escreve 10 versões? Não. Você escreve uma vez, converte automaticamente.
O projeto The Agency resolve isso com dois scripts bash:
-
convert.sh— Transforma arquivos de agente em formatos específicos de ferramentas -
install.sh— Copia arquivos convertidos para os caminhos corretos
Neste tutorial, você fará engenharia reversa de ambos os scripts. Você aprenderá como analisar frontmatter YAML, extrair conteúdo do corpo e construir pipelines de conversão para qualquer ferramenta.
💡 Seja você implantando agentes para fluxos de trabalho de desenvolvimento de API com integração Apidog ou criando agentes de teste especializados, o sistema de conversão garante que eles funcionem em todas as IDEs preferidas da sua equipe.
O Formato do Agente
Cada agente na The Agency usa a mesma estrutura:
---
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
...
O arquivo tem duas partes:
-
Frontmatter — Metadados YAML entre delimitadores
--- -
Corpo — Conteúdo Markdown após o segundo
---
O que converter significa: extrair campos do frontmatter, transformar o corpo para o formato alvo, escrever no caminho correto.
Etapa 1: Analisar o Frontmatter YAML
Crie parse-frontmatter.sh:
#!/usr/bin/env bash
#
# parse-frontmatter.sh — Extract YAML frontmatter fields from agent files
#
set -euo pipefail
# Extrai um campo do frontmatter YAML
get_field() {
local field="$1" file="$2"
awk -v f="$field" '
/^---$/ { fm++; next }
fm == 1 && $0 ~ "^" f ": " {
sub("^" f ": ", "");
print;
exit
}
' "$file"
}
# Remove o frontmatter, retorna só o corpo
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
# Converte nome para 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
Teste:
chmod +x parse-frontmatter.sh
./parse-frontmatter.sh --demo engineering-backend-architect.md
Saída esperada:
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...
Etapa 2: Converter para o Formato Claude Code
Claude Code usa arquivos .md brutos. Não precisa converter, só copiar:
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")"
}
Etapa 3: Converter para o Formato Cursor
Cursor exige arquivos .mdc com description no 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"
}
Exemplo de entrada:
---
name: API Tester
description: Specialized in API testing...
---
# API Tester Agent...
Exemplo de saída (.mdc):
---
description: Agency agent: Specialized in API testing...
---
# API Tester Agent...
Etapa 4: Converter para o Formato Aider
Aider usa um único arquivo CONVENTIONS.md com todos os agentes:
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"
}
Crie o arquivo com todos os agentes:
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
}
Etapa 5: Converter para o Formato Windsurf
Windsurf usa um único arquivo .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"
}
Etapa 6: Converter para o Formato Antigravity
Antigravity (Gemini) usa arquivos SKILL.md em subdiretórios próprios:
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"
}
Etapa 7: Converter para o Formato OpenClaw
OpenClaw usa três arquivos por agente:
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 - Definição principal
cat > "$output_dir/SOUL.md" << EOF
# $name
$description
---
$body
EOF
# AGENTS.md - Capacidades do agente
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 - Identidade do agente
cat > "$output_dir/IDENTITY.md" << EOF
# Identity: $name
- Name: $name
- Description: $description
- Source: The Agency (agency-agents repo)
EOF
echo " OpenClaw: agency-${slug}/"
}
Etapa 8: O Script convert.sh Completo
Script de conversão completo para todos os formatos principais:
#!/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
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"
Execute:
chmod +x convert.sh
./convert.sh
Etapa 9: Instalar em Cada Ferramenta
Após converter, copie os arquivos para os locais de cada ferramenta:
#!/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"
}
# Instala em todas as ferramentas detectadas
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
Comparação de Formatos
| Ferramenta | Formato | Escopo | Conversão |
|---|---|---|---|
| Claude Code | .md |
Global (~/.claude/agents/) |
Copia como está |
| Cursor | .mdc |
Projeto (.cursor/rules/) |
Adiciona frontmatter de descrição |
| Aider | CONVENTIONS.md |
Raiz do projeto | Concatena todos os agentes |
| Windsurf | .windsurfrules |
Raiz do projeto | Concatena todos os agentes |
| GitHub Copilot | .md |
Global (~/.github/agents/) |
Copia como está |
| Antigravity | SKILL.md |
Global (~/.gemini/antigravity/) |
Empacota em diretório da skill |
| OpenClaw |
SOUL.md + outros |
Global (~/.openclaw/) |
Divide em 3 arquivos |
| Gemini CLI | Extensão | Global (~/.gemini/extensions/) |
Gera manifesto + habilidades |
| OpenCode | .md |
Projeto (.opencode/agents/) |
Copia como está |
| Qwen Code | .md |
Projeto (.qwen/agents/) |
Copia como SubAgente |
Crie Seu Próprio Script de Conversão
Modelo para adicionar uma nova ferramenta:
#!/usr/bin/env bash
# 1. Defina a função de conversão
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. Crie o caminho de saída
local output="path/to/your/tool/agency-${slug}.ext"
mkdir -p "$(dirname "$output")"
# 3. Escreva o conteúdo convertido
cat > "$output" << EOF
# Seu formato específico da ferramenta
# Use: $name, $description, $body
EOF
echo " YourTool: agency-${slug}.ext"
}
# 4. Adicione ao loop principal
for agent_file in engineering/*.md; do
convert_your_tool "$agent_file"
done
O Que Você Construiu
| Componente | Propósito |
|---|---|
get_field() |
Extrair valores do frontmatter YAML |
get_body() |
Remover frontmatter, retorna corpo markdown |
to_kebab() |
Converter nomes para slugs seguros para URL |
convert_cursor() |
Transformar para formato .mdc
|
convert_aider() |
Concatenar em um único arquivo |
convert_windsurf() |
Concatenar em um único arquivo |
convert_antigravity() |
Criar diretórios de habilidades |
convert_openclaw() |
Dividir em 3 arquivos por agente |
install.sh |
Copiar para caminhos específicos da ferramenta |
Próximos Passos
Estenda os scripts:
- Adicione conversão paralela com
xargs -Pou GNU parallel - Adicione validação (verifique campos de frontmatter obrigatórios)
- Adicione modo de simulação (
--dry-runflag)
Adicione mais ferramentas:
- Extensões do VS Code
- IDEs JetBrains
- Ferramentas internas personalizadas
Otimize para grandes repositórios:
- Armazene em cache o frontmatter analisado
- Use
findcom-print0para manipulação segura de arquivos - Adicione barras de progresso para mais de 100 agentes
Solução de Problemas Comuns
O script de conversão falha com "bad substitution":
- Certifique-se de usar bash:
#!/usr/bin/env bash - Verifique a versão do bash:
bash --version(4.0+) - Execute explicitamente:
bash convert.sh - Remova quebras de linha do Windows:
sed -i 's/\r$//' convert.sh
Campos do frontmatter não extraem:
- Use
:(dois pontos + espaço) no YAML - Verifique espaços extras antes dos campos
- Delimitadores do frontmatter devem ser
--- - Teste manualmente:
./parse-frontmatter.sh --demo agent.md
Slugs quebrados:
- Teste
to_kebab()com vários nomes - Lide com caracteres especiais:
to_kebab() { echo "$1" | iconv -f utf8 -t ascii//translit | ... } - Adicione fallback:
[[ -z "$slug" ]] && slug="unknown-agent" - Logue nomes originais para debug
Regras do Cursor não carregam:
- Arquivos
.mdcprecisam de frontmatter válido comdescription - Verifique
.cursor/mcp.json - Certifique-se de que os arquivos estão em
.cursor/rules/ - Reinicie o Cursor após adicionar regras
CONVENTIONS.md do Aider fica grande:
- Divida por categoria:
CONVENTIONS-engineering.md, etc - Implemente poda de agentes obsoletos
- Adicione índice no topo
- Considere arquivos por agente com diretivas de inclusão
Otimização de Desempenho para Grandes Conversões
Processamento Paralelo (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!"
Conversão 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"
Barra de Progresso:
#!/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"
Considerações de Segurança para Agentes Compartilhados
Valide agentes baixados:
#!/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"
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
}
Execução em Sandbox:
- Use Docker para isolar agentes não confiáveis
- Monte diretórios como somente leitura
- Restrinja a rede a domínios específicos
- Logue todas as ações do agente
Um arquivo de agente. Dez IDEs. Dois scripts bash.
Automatize: escreva uma vez, converta automaticamente, instale em todo lugar.
Sua vez: adicione suporte para sua ferramenta de IA favorita. Compartilhe o script. Torne agentes portáteis.
Principais Conclusões
- Escreva uma vez, converta para 10+ formatos — Um único arquivo Markdown com frontmatter YAML se transforma em Claude Code, Cursor, Aider, Windsurf e mais de 6 outras ferramentas
-
Parsing Bash cobre extração de frontmatter —
get_field()extrai valores YAML,get_body()remove o frontmatter,to_kebab()cria slugs seguros - Formatos diferentes exigem transformações específicas — Claude Code copia, Cursor adiciona descrição, Aider/Windsurf concatenam tudo
-
Scripts de instalação copiam para os locais certos — Ferramentas globais usam
~/.claude/agents/, ferramentas de projeto usam.cursor/rules/ou arquivos raiz -
Extensível para novas ferramentas — Defina a função
convert_your_tool(), adicione ao loop, documente o formato
FAQ
O que é convert.sh e como ele funciona?
convert.sh é um script bash que analisa o frontmatter YAML de arquivos Markdown de agente, extrai o corpo e converte cada agente para formatos específicos de ferramenta. Usa awk para parsing, sed para slugs e heredocs para geração.
Como funciona a análise de frontmatter em bash?
get_field() usa awk para encontrar o campo pelo nome entre delimitadores ---. get_body() retorna tudo depois do segundo ---.
Quais IDEs e ferramentas são suportadas?
Claude Code (.md), Cursor (.mdc), Aider (CONVENTIONS.md), Windsurf (.windsurfrules), GitHub Copilot (.md), Antigravity (SKILL.md), OpenClaw (SOUL.md + outros), Gemini CLI, OpenCode, Qwen Code.
Como adiciono suporte para uma nova ferramenta?
Crie convert_yourtool() que extrai campos do frontmatter, converte o corpo e grava no local correto. Adicione ao loop principal.
Posso rodar conversão em paralelo?
Sim, use xargs -P ou GNU parallel para processar vários arquivos ao mesmo tempo.
Como valido campos do frontmatter?
Adicione checagens na função de conversão:
[[ -z "$name" ]] && echo "Missing name field" && exit 1
E se a conversão falhar para alguns agentes?
Use set -euo pipefail. Adicione || continue para pular arquivos com erro. Logue falhas para depuração.
Top comments (0)