mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-04-06 13:31:43 +02:00
190 lines
4.6 KiB
Bash
Executable File
190 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# sync-ai-instructions.sh
|
|
# Génère ~/.claude/CLAUDE.md et ~/.codex/AGENTS.md (symlink) depuis _AI_INSTRUCTIONS.md
|
|
# Ces fichiers sont globaux à la machine — ils ne vivent PAS dans le repo Lead_tech
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
SOURCE="$REPO_ROOT/_AI_INSTRUCTIONS.md"
|
|
|
|
# --- Détection machine ---
|
|
OS="$(uname -s)"
|
|
CHANGED=0
|
|
SKILLS_SOURCE_DIR="$REPO_ROOT/skills"
|
|
|
|
generate_repo_claude() {
|
|
local header="$1"
|
|
local dest="$2"
|
|
local tmp
|
|
|
|
tmp="$(mktemp)"
|
|
|
|
mkdir -p "$(dirname "$dest")"
|
|
|
|
{
|
|
echo "$header"
|
|
echo ""
|
|
sed "s|{{LEADTECH}}|$REPO_ROOT|g" "$SOURCE"
|
|
} > "$tmp"
|
|
|
|
if [ ! -f "$dest" ] || ! cmp -s "$tmp" "$dest"; then
|
|
mv "$tmp" "$dest"
|
|
CHANGED=1
|
|
else
|
|
rm -f "$tmp"
|
|
fi
|
|
}
|
|
|
|
ensure_symlink() {
|
|
local target="$1"
|
|
local link_path="$2"
|
|
|
|
mkdir -p "$(dirname "$link_path")"
|
|
|
|
if [ -L "$link_path" ]; then
|
|
local current_target
|
|
current_target="$(readlink "$link_path")"
|
|
if [ "$current_target" = "$target" ] && [ -e "$link_path" ]; then
|
|
return 0
|
|
fi
|
|
rm -f "$link_path"
|
|
elif [ -e "$link_path" ]; then
|
|
rm -f "$link_path"
|
|
fi
|
|
|
|
ln -s "$target" "$link_path"
|
|
CHANGED=1
|
|
}
|
|
|
|
sync_skills_for_target() {
|
|
local target_root="$1"
|
|
local source_dir="$2"
|
|
local skill_dir
|
|
local skill_name
|
|
local target_link
|
|
|
|
mkdir -p "$target_root"
|
|
[ -d "$source_dir" ] || return 0
|
|
|
|
for skill_dir in "$source_dir"/*; do
|
|
[ -d "$skill_dir" ] || continue
|
|
[ -f "$skill_dir/SKILL.md" ] || continue
|
|
|
|
skill_name="$(basename "$skill_dir")"
|
|
target_link="$target_root/$skill_name"
|
|
|
|
if [ -L "$target_link" ]; then
|
|
local current_target
|
|
current_target="$(readlink "$target_link")"
|
|
if [ "$current_target" = "$skill_dir" ] && [ -e "$target_link" ]; then
|
|
continue
|
|
fi
|
|
rm -f "$target_link"
|
|
elif [ -e "$target_link" ]; then
|
|
echo "WARN: skill déjà présent et non symlink, conservé: $target_link" >&2
|
|
continue
|
|
fi
|
|
|
|
ln -s "$skill_dir" "$target_link"
|
|
CHANGED=1
|
|
done
|
|
}
|
|
|
|
sync_codex_prompt_wrappers() {
|
|
local target_dir="$1"
|
|
local source_dir="$2"
|
|
local skill_dir
|
|
local skill_name
|
|
local dest
|
|
local tmp
|
|
|
|
mkdir -p "$target_dir"
|
|
[ -d "$source_dir" ] || return 0
|
|
|
|
for skill_dir in "$source_dir"/*; do
|
|
[ -d "$skill_dir" ] || continue
|
|
[ -f "$skill_dir/SKILL.md" ] || continue
|
|
skill_name="$(basename "$skill_dir")"
|
|
dest="$target_dir/leadtech-$skill_name.md"
|
|
tmp="$(mktemp)"
|
|
|
|
cat > "$tmp" <<EOF
|
|
---
|
|
description: 'Lead_tech: exécuter le skill $skill_name.'
|
|
---
|
|
|
|
Utilise le skill \`$skill_name\` depuis \`$skill_dir/SKILL.md\`.
|
|
|
|
Contrainte:
|
|
- Respecter strictement le workflow et les règles du skill.
|
|
- Si une information manque, le signaler explicitement avant d'agir.
|
|
EOF
|
|
|
|
if [ ! -f "$dest" ] || ! cmp -s "$tmp" "$dest"; then
|
|
mv "$tmp" "$dest"
|
|
CHANGED=1
|
|
else
|
|
rm -f "$tmp"
|
|
fi
|
|
done
|
|
}
|
|
|
|
sync_claude_command_wrappers() {
|
|
local target_dir="$1"
|
|
local source_dir="$2"
|
|
local skill_dir
|
|
local skill_name
|
|
local dest
|
|
local tmp
|
|
|
|
mkdir -p "$target_dir"
|
|
[ -d "$source_dir" ] || return 0
|
|
|
|
for skill_dir in "$source_dir"/*; do
|
|
[ -d "$skill_dir" ] || continue
|
|
[ -f "$skill_dir/SKILL.md" ] || continue
|
|
skill_name="$(basename "$skill_dir")"
|
|
dest="$target_dir/leadtech-$skill_name.md"
|
|
tmp="$(mktemp)"
|
|
|
|
cat > "$tmp" <<EOF
|
|
---
|
|
description: 'Lead_tech: exécuter le skill $skill_name.'
|
|
---
|
|
|
|
Utilise le skill \`$skill_name\` depuis \`$skill_dir/SKILL.md\`.
|
|
|
|
Contrainte:
|
|
- Respecter strictement le workflow et les règles du skill.
|
|
- Si une information manque, le signaler explicitement avant d'agir.
|
|
EOF
|
|
|
|
if [ ! -f "$dest" ] || ! cmp -s "$tmp" "$dest"; then
|
|
mv "$tmp" "$dest"
|
|
CHANGED=1
|
|
else
|
|
rm -f "$tmp"
|
|
fi
|
|
done
|
|
}
|
|
|
|
CLAUDE_HEADER="# Instructions globales — Lead Tech Copilote
|
|
|
|
Ce fichier est chargé automatiquement par Claude Code ou Codex à chaque session.
|
|
Il constitue la porte d'entrée principale de la base de connaissance Lead_tech et oriente vers les fichiers spécialisés utilisés par tous les projets."
|
|
|
|
generate_repo_claude "$CLAUDE_HEADER" "$HOME/.claude/CLAUDE.md"
|
|
|
|
ensure_symlink "$HOME/.claude/CLAUDE.md" "$HOME/.codex/AGENTS.md"
|
|
sync_skills_for_target "$HOME/.claude/skills" "$SKILLS_SOURCE_DIR"
|
|
sync_skills_for_target "$HOME/.codex/skills" "$SKILLS_SOURCE_DIR"
|
|
sync_claude_command_wrappers "$HOME/.claude/commands" "$SKILLS_SOURCE_DIR"
|
|
sync_codex_prompt_wrappers "$HOME/.codex/prompts" "$SKILLS_SOURCE_DIR"
|
|
|
|
if [ "$CHANGED" -eq 1 ]; then
|
|
echo "Sync AI instructions (OS: $OS)"
|
|
echo "Sync terminée."
|
|
fi
|