TL;DR
Convertissez un fichier d'agent IA en 10 IDE en 3 étapes :
- Analysez le frontmatter YAML avec les fonctions bash
get_field(),get_body()etto_kebab() - Transformez vers les formats spécifiques aux outils avec
convert.sh(Claude Code.md, Cursor.mdc, AiderCONVENTIONS.md, Windsurf.windsurfrules) - Installez dans les chemins cibles avec
install.sh. Écrivez une fois, convertissez automatiquement, déployez partout.
Un fichier d'agent. Dix IDE. Voici comment le projet The Agency convertit un seul fichier Markdown pour fonctionner avec Claude Code, Cursor, Aider, Windsurf, GitHub Copilot et plus de 6 autres outils.
Essayez Apidog dès aujourd'hui
Vous écrivez un agent IA. Maintenant, vous voulez qu'il soit disponible dans :
- Claude Code (
.mddans~/.claude/agents/) - Cursor (
.mdcdans.cursor/rules/) - Aider (un seul
CONVENTIONS.mdà la racine du projet) - Windsurf (un seul fichier
.windsurfrules) - GitHub Copilot (
.mddans~/.github/agents/) - Et 5+ autres outils
Écrivez-vous 10 versions ? Non. Vous écrivez une fois, convertissez automatiquement.
Le projet The Agency résout ce problème avec deux scripts bash :
-
convert.sh— Transforme les fichiers d'agent en formats spécifiques aux outils -
install.sh— Copie les fichiers convertis vers les chemins corrects
Dans ce tutoriel, vous allez rétro-ingénier les deux scripts. Vous apprendrez à analyser le frontmatter YAML, extraire le contenu du corps, et construire des pipelines de conversion pour n'importe quel outil.
💡 Que vous déployiez des agents pour des workflows de développement d'API avec l'intégration Apidog ou que vous créiez des agents de test spécialisés, le système de conversion garantit leur compatibilité sur tous les IDE de votre équipe.
Le format d'agent
Chaque agent de The Agency utilise la structure suivante :
---
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
...
Le fichier a deux parties :
-
Frontmatter — Métadonnées YAML entre des délimiteurs
--- -
Corps — Contenu Markdown après le second
---
La conversion consiste à : extraire les champs du frontmatter, transformer le corps au format cible, écrire dans le bon chemin.
Étape 1 : Analyser le frontmatter YAML
Créez parse-frontmatter.sh :
#!/usr/bin/env bash
#
# parse-frontmatter.sh — Extraire les champs YAML frontmatter des fichiers agent
#
set -euo pipefail
# Extraire la valeur d'un champ du frontmatter
# Usage: get_field <champ> <fichier>
get_field() {
local field="$1" file="$2"
awk -v f="$field" '
/^---$/ { fm++; next }
fm == 1 && $0 ~ "^" f ": " {
sub("^" f ": ", "");
print;
exit
}
' "$file"
}
# Supprimer le frontmatter et retourner seulement le corps
# Usage: get_body <fichier>
get_body() {
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm>=2{print}' "$1"
}
# Convertir le nom en slug kebab-case
# Usage: to_kebab "API Tester" → api-tester
to_kebab() {
echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g'
}
# Démo
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
Testez-le :
chmod +x parse-frontmatter.sh
./parse-frontmatter.sh --demo engineering-backend-architect.md
Exemple de sortie :
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...
Étape 2 : Convertir au format Claude Code
Claude Code utilise des fichiers .md bruts. Il suffit de copier le fichier :
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")"
}
Étape 3 : Convertir au format Cursor
Cursor attend des fichiers .mdc avec un champ description dans le 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"
}
Entrée :
---
name: API Tester
description: Specialized in API testing...
---
# API Tester Agent...
Sortie (.mdc) :
---
description: Agency agent: Specialized in API testing...
---
# API Tester Agent...
Étape 4 : Convertir au format Aider
Aider utilise un seul fichier CONVENTIONS.md qui contient tous les agents :
convert_aider() {
local agent_file="$1"
local output="CONVENTIONS.md"
# Ajout avec séparateur
echo "" >> "$output"
echo "---" >> "$output"
echo "" >> "$output"
cat "$agent_file" >> "$output"
echo " Aider: appended to $output"
}
Pour construire le fichier complet :
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
}
Étape 5 : Convertir au format Windsurf
Windsurf fonctionne comme Aider, mais avec .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"
}
Étape 6 : Convertir au format Antigravity
Antigravity (Gemini) utilise des fichiers SKILL.md dans des sous-répertoires :
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"
}
Étape 7 : Convertir au format OpenClaw
OpenClaw attend trois fichiers par agent (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
# 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}/"
}
Étape 8 : Le script convert.sh complet
Voici un script de conversion simplifié :
#!/usr/bin/env bash
#
# convert.sh — Convertir tous les agents Agency vers les formats spécifiques outils
#
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"
}
# 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"
Exécution :
chmod +x convert.sh
./convert.sh
Étape 9 : Installer vers chaque outil
Copiez les fichiers convertis dans les chemins requis :
#!/usr/bin/env bash
#
# install.sh — Installer les agents convertis dans vos outils locaux
#
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"
}
# Installer pour tous les outils détectés
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
Comparaison des formats
| Outil | Format | Portée | Conversion |
|---|---|---|---|
| Claude Code | .md |
Utilisateur (~/.claude/agents/) |
Copie telle quelle |
| Cursor | .mdc |
Projet (.cursor/rules/) |
Ajout description du frontmatter |
| Aider | CONVENTIONS.md |
Racine du projet | Concaténer tous les agents |
| Windsurf | .windsurfrules |
Racine du projet | Concaténer tous les agents |
| GitHub Copilot | .md |
Utilisateur (~/.github/agents/) |
Copie telle quelle |
| Antigravity | SKILL.md |
Utilisateur (~/.gemini/antigravity/) |
Encapsuler dans un répertoire de compétences |
| OpenClaw |
SOUL.md + autres |
Utilisateur (~/.openclaw/) |
Diviser en 3 fichiers |
| Gemini CLI | Extension | Utilisateur (~/.gemini/extensions/) |
Générer manifeste + compétences |
| OpenCode | .md |
Projet (.opencode/agents/) |
Copie telle quelle |
| Qwen Code | .md |
Projet (.qwen/agents/) |
Copier en sous-agent |
Créez votre propre script de conversion
Modèle pour ajouter un nouvel outil :
#!/usr/bin/env bash
# 1. Définir la fonction de conversion
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. Créer le chemin de sortie
local output="path/to/your/tool/agency-${slug}.ext"
mkdir -p "$(dirname "$output")"
# 3. Écrire le contenu converti
cat > "$output" << EOF
# Format spécifique à votre outil
# Utilisez: $name, $description, $body
EOF
echo " YourTool: agency-${slug}.ext"
}
# 4. Ajouter à la boucle principale
for agent_file in engineering/*.md; do
convert_your_tool "$agent_file"
done
Ce que vous avez construit
| Composant | Objectif |
|---|---|
get_field() |
Extraire les valeurs du frontmatter YAML |
get_body() |
Supprimer le frontmatter, retourner le corps markdown |
to_kebab() |
Convertir les noms en slugs URL-compatibles |
convert_cursor() |
Transformer au format .mdc
|
convert_aider() |
Concaténer en un seul fichier |
convert_windsurf() |
Concaténer en un seul fichier |
convert_antigravity() |
Créer des répertoires de compétences |
convert_openclaw() |
Diviser en 3 fichiers par agent |
install.sh |
Copier vers les chemins spécifiques outils |
Prochaines étapes
Étendez les scripts :
- Ajoutez la conversion parallèle avec
xargs -Pou GNU parallel - Ajoutez la validation (champs frontmatter requis)
- Ajoutez un mode dry-run (
--dry-run)
Ajoutez plus d'outils :
- Extensions VS Code
- IDE JetBrains
- Outils internes personnalisés
Optimisez pour les grands dépôts :
- Mettez en cache le frontmatter analysé
- Utilisez
findavec-print0pour une gestion sûre des fichiers - Ajoutez des barres de progression pour plus de 100 agents
Dépannage des problèmes courants
Le script échoue avec "mauvaise substitution" :
- Exécutez avec bash, pas sh :
#!/usr/bin/env bash - Vérifiez la version de bash :
bash --version(>= 4.0) - Lancez explicitement avec bash :
bash convert.sh - Corrigez les fins de ligne Windows :
sed -i 's/\r$//' convert.sh
Les champs du frontmatter ne sont pas extraits :
- Format YAML :
:(deux-points espace) - Pas d'espaces superflus avant les champs
- Délimiteurs de frontmatter : exactement
--- - Testez :
./parse-frontmatter.sh --demo agent.md
La génération de slugs crée des noms corrompus :
- Testez
to_kebab()avec des cas limites - Gérez les caractères spéciaux :
to_kebab() { echo "$1" | iconv -f utf8 -t ascii//translit | ... } - Valeur de secours :
[[ -z "$slug" ]] && slug="unknown-agent" - Logguez les noms originaux pour debug
Les règles Cursor ne se chargent pas :
- Les fichiers
.mdcdoivent avoir un frontmatter valide avecdescription - Vérifiez
.cursor/mcp.json - Les fichiers doivent être dans
.cursor/rules/ - Redémarrez Cursor après ajout
Le fichier Aider CONVENTIONS.md devient trop volumineux :
- Divisez par catégorie :
CONVENTIONS-engineering.md, etc. - Ajoutez suppression automatique des agents obsolètes
- Ajoutez une table des matières
- Ou fichiers par agent + directives d'inclusion
Optimisation des performances pour les conversions massives
Traitement parallèle :
Pour >100 agents, utilisez 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!"
Conversion incrémentielle :
Ne convertissez que les fichiers modifiés :
#!/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"
Suivi de la progression :
Ajoutez une barre de progression :
#!/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"
Considérations de sécurité pour les agents partagés
Validation des sources d'agents :
#!/usr/bin/env bash
# validate-agent.sh
validate_agent() {
local file="$1"
# Champs frontmatter requis
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
# Recherche de patterns dangereux dans le corps
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
}
Exécution d'agents en sandbox :
- Utilisez des conteneurs Docker pour exécuter les agents
- Limitez l'accès au filesystem (montages read-only)
- Restreignez l'accès réseau à des domaines spécifiques
- Enregistrez toutes les actions des agents pour audit
Un fichier d'agent. Dix IDE. Deux scripts bash.
C'est le pouvoir de l’automatisation de la conversion.
Écrivez une fois, convertissez automatiquement, installez partout.
À vous de jouer : ajoutez la compatibilité conversion pour votre outil IA préféré.
Partagez votre script. Rendez les agents portables.
Points clés à retenir
- Écrivez une fois, convertissez vers plus de 10 formats — Un seul fichier Markdown avec frontmatter YAML se transforme pour Claude Code, Cursor, Aider, Windsurf et plus de 6 autres outils
-
L'analyse bash gère l'extraction du frontmatter —
get_field()extrait les valeurs YAML,get_body()supprime le frontmatter,to_kebab()crée des slugs URL-compatibles - Les formats spécifiques outils nécessitent des transformations différentes — Claude Code copie tel quel, Cursor ajoute la description frontmatter, Aider/Windsurf concatènent tous les agents
-
Les scripts d'installation copient vers les bons chemins — Outils utilisateur :
~/.claude/agents/, outils projet :.cursor/rules/ou fichiers à la racine projet -
Étendez avec des modèles pour de nouveaux outils — Définissez la fonction
convert_your_tool(), ajoutez-la à la boucle principale, documentez les exigences du format
FAQ
Qu'est-ce que convert.sh et comment ça marche ?
convert.sh est un script bash qui analyse le frontmatter YAML des fichiers Markdown d'agent, extrait le corps, et transforme chaque agent en formats spécifiques outils. Utilise awk pour l’analyse, sed pour les slugs, heredocs pour la génération.
Comment fonctionne l’analyse du frontmatter en bash ?
get_field() utilise awk pour repérer les délimiteurs frontmatter (---), trouve la ligne du champ et extrait la valeur. get_body() affiche tout après le second ---.
Quels IDE et outils sont pris en charge ?
Claude Code (.md), Cursor (.mdc), Aider (CONVENTIONS.md), Windsurf (.windsurfrules), GitHub Copilot (.md), Antigravity (SKILL.md), OpenClaw (SOUL.md et 2 fichiers), extensions Gemini CLI, OpenCode, Qwen Code.
Comment ajouter la conversion pour un nouvel outil ?
Créez une fonction convert_yourtool() qui extrait les champs frontmatter, transforme le corps au format de l’outil, écrit dans le bon chemin. Ajoutez l’appel à la boucle principale.
Peut-on faire des conversions en parallèle ?
Oui, utilisez xargs -P ou GNU parallel pour traiter plusieurs fichiers d’agent simultanément. Pour >100 agents, la conversion parallèle réduit le temps d’exécution.
Comment valider l’existence des champs frontmatter ?
Ajoutez des vérifications dans votre fonction de conversion :
[[ -z "$name" ]] && echo "Missing name field" && exit 1
Validez avant d’écrire les fichiers de sortie.
Que faire si la conversion échoue pour certains agents ?
Utilisez set -euo pipefail pour échouer vite. Ajoutez || continue pour ignorer les fichiers corrompus. Logguez les échecs dans un fichier séparé pour le debug.
Top comments (0)