skailabinfo/claude-video-harness

Configuration initiale d'un projet pour un nouvel utilisateur — vérification de l'environnement et entretien détaillé (qui es-tu ; ~10 Reels de référence et analyse du style ; transcription ; connexion des services avec vérification d'accès ; palette ; polices ; sous-titres, graphiques, mouvement, son), avec affichage des variantes par images prêtes ; écriture de harness.config.json, brand-kit.md, editing-taste.md, exemplars.md. Lance-le quand 'configured' est false dans harness.config.json, ou quand l'utilisateur demande de reconfigurer le projet / changer de style / refaire l'analyse des références.

Qu'est-ce que claude-video-harness ?

Ce skill pour Claude Code configure automatiquement un nouveau projet de montage vidéo vertical (type « tête parlante » pour Reels, TikTok, Shorts) en menant un entretien structuré avec l'utilisateur. Il couvre l'installation de l'environnement (Node.js, FFmpeg, Python, yt-dlp, Remotion), l'analyse de 10 Reels de référence via des scripts dédiés, la transcription vocale (whisper.cpp ou ElevenLabs Scribe), et la connexion de services comme ElevenLabs, Higgsfield, 21st.dev ou Buffer. L'utilisateur définit son identité de marque, sa palette de couleurs, ses polices, le style des sous-titres et le graphisme général, le tout affiché visuellement par des rendus Remotion. Le skill évite toute supposition et base chaque décision sur les réponses et références explicites de l'utilisateur, enregistrant le tout dans des fichiers de configuration (harness.config.json, brand-kit.md, editing-taste.md, exemplars.md). Il est idéal pour démarrer un pipeline personnalisé sans style par défaut, garantissant que le rendu final reflète exactement les goûts de l'utilisateur.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/skailabinfo/claude-video-harness/tree/HEAD/.claude/skills/setup

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Configuration du projet

Objectif : transformer un clone vierge en pipeline qui monte dans le style de cette personne — comprendre ce qu'il/elle aime, connecter ses services et montrer des images de sa future vidéo. Parle dans la langue de l'utilisateur, de manière courte et humaine.

Le projet n'a pas son propre style. Tout ce qui concerne l'apparence de la vidéo — palette, polices, sous-titres, cartes, stickers, poster, tempo, punch-ins, grading, son — est choisi par l'utilisateur ou tiré de ses références. Tu ne proposes pas d'option « standard » ou « populaire », tu ne substitues pas tes préférences et rien de ce qui se trouve déjà dans le projet (les espaces réservés dans harness.config.json et la démo ne sont pas un style, mais un espace vide).

Règles de l'entretien

  • Un bloc = un message, les blocs ne sont jamais fusionnés. Ne mets pas deux blocs dans un seul formulaire AskUserQuestion : les gens cliquent sur la première option d'une série de questions. Les blocs 4 (services), 6 (palette), 7 (polices), 8 (style de montage) sont des conversations en plusieurs messages.
  • Pas de « (je recommande) » sur le goût. La mention n'est autorisée que pour un choix purement technique — méthode de transcription (bloc 3). Pour les couleurs, polices, style, services et questions sur la personne, elle n'existe pas ; décris les options de manière neutre, en précisant ce que chacune apporte.
  • Les options viennent des réponses et des références de la personne. S'il n'y a ni réponses ni références, rassemble 2–3 options sensiblement différentes adaptées à son sujet et ton, et montre-les par des images ; c'est à lui/elle de choisir.
  • Montre, ne décris pas : la palette, les polices et le style de montage par des images prêtes via video/scripts/variants.py.
  • Sauter un bloc (« passe ») — seulement sur le mot de l'utilisateur. Dans ce cas, il reste un espace réservé neutre dans le profil, et dis-le clairement : « tu pourras configurer plus tard — dis "configure les sous-titres" ».
  • Ne devine rien sur la personne. La marque, le nom, le sujet, l'audience et le ton — seulement à partir de ses réponses, pas de l'email du compte, du nom dans le système, du nom du dossier ou du lien vers le dépôt. Le nom du compte dans le lien du dépôt est celui de l'auteur du modèle, pas de l'utilisateur.
  • La technique ne fait pas partie de l'entretien : les zones de sécurité, le montage sans queues coupées, le loudnorm en deux passes, la mécanique des punch-ins sur les collures — ce n'est pas du goût, c'est la façon dont le pipeline fonctionne (CLAUDE.md, « Mécanique »).
  • Les clés ne passent jamais par le chat. L'utilisateur les saisit lui-même dans video/.env ; tu vérifies l'accès via doctor.sh, sans rien imprimer. S'il envoie une clé dans le chat, ne l'utilise pas, conseille de la révoquer et d'en créer une nouvelle.
  • Tout ce qui s'installe via brew / pip ou qui pèse lourd — d'abord « quoi et combien », ensuite « oui ».

Étape 0. Salutation (un seul message)

Deux ou trois lignes : ceci est un montage de vidéos verticales « tête parlante » via Claude Code + Remotion ; le projet n'a pas son propre style — configurons tout maintenant en fonction de toi : parle de toi, envoie ~10 Reels que tu aimes, choisis les couleurs, les polices et le style de montage (je montrerai les options par images), connectons les services nécessaires. Passe immédiatement à l'étape 1.

Étape 1. Environnement

cd video && ( [ -d node_modules ] || npm install ) && bash scripts/doctor.sh

Affiche le résultat dans un court tableau. Pour chaque MISSING, propose une commande tirée de la sortie et, une fois l'accord obtenu, exécute-la :

  • Skills Remotion (obligatoire) : npx -y skills add remotion-dev/skills --skill '*' --agent claude-code -y depuis la racine du projet.
  • ffmpeg, node, python3, yt-dlp (pour les références) — brew install … (macOS) ; Linux — gestionnaire de paquets ; Windows — WSL.
  • whisper / rembg — quand ils seront nécessaires selon les réponses (étape 3).

Pas de brew — donne le lien https://brew.sh et attends (l'installation demande un mot de passe, c'est à l'utilisateur de la faire).

Étape 2. Entretien

Bloc 1 — qui es-tu

Marque / nom de la chaîne ; qui apparaît à l'écran ; de quoi parlent les vidéos ; plateformes et handles (Reels, TikTok, Shorts, Telegram…) ; audience ; ton ; langue des vidéos ; appel à l'action final.

Demande de manière ouverte — laisse-le/la répondre dans ses propres mots, même en un seul message. Si tu donnes des options (pour le ton ou l'appel à l'action), elles sont neutres et identiques pour n'importe qui, sans sujet ou niche pré-remplie.

Bloc 2 — références (~10 Reels)

Demande : « Envoie environ 10 liens vers des Reels que tu aimes en termes de montage — Instagram, TikTok ou Shorts. De préférence ceux auxquels tu aimerais ressembler. Grâce à eux, je comprendrai ton goût : tempo, sous-titres, graphiques, couleurs, polices. » Moins de 5 — demande encore : impossible de dégager un goût commun à partir de 3 vidéos. Explique que sans références, il faudra poser plus de questions dans les blocs 6–8.

Une fois les liens reçus — lance immédiatement l'analyse en arrière-plan et passe au bloc 3 :

cd video && python3 scripts/refs.py "URL1" "URL2" … > ../takes/refs.log 2>&1     # run_in_background

Le script télécharge dans takes/refs/ (ne va pas dans git) et mesure : durée, fréquence de changement d'image, changements dans le hook, volume, tempo de parole, première phrase, couleurs vives (palette.png) ; dessine NN-sheet.jpg (24 images par vidéo) et NN-hook.jpg (les 3 premières secondes). Si une partie des liens échoue avec une demande de connexion — options dans SERVICES.md → « Instagram » : relance avec COOKIES_FROM=chrome (uniquement avec un « oui » explicite) ou laisse-le/la télécharger lui/elle-même et placer les mp4 dans takes/refs/ (dans ce cas, passe les chemins au lieu des liens).

Bloc 3 — transcription de la parole

  • whisper.cpp en local (je recommande sur Mac) : gratuit, hors ligne ; brew install whisper-cpp + modèle large-v3-turbo 1,6 Go.
  • ElevenLabs Scribe : payant (crédits), rien à installer, fonctionne sur n'importe quel système ; nécessite une clé (bloc 4).

Bloc 4 — services (un message par service)

Ne demande pas d'un seul coup « quoi connecter ». Parcours les services un par un — un message par service : ce qu'il apporte au montage (1–2 lignes avec un exemple), combien ça coûte, ce dont l'utilisateur a besoin et combien de temps ça prend. Question : « on connecte maintenant / plus tard / pas besoin ».

servicece qu'il apporte au montageaccèstemps
ElevenLabstranscription Scribe ; accents sonores selon ton goût ; voix offclé API~3 min
Higgsfieldcourtes insertions vidéo (b-roll), quand tu parles de quelque chose qu'on peut montrerconnexion via navigateur~2 min + après redémarrage
21st.devcomposants React prêts à l'emploi comme base pour de nouveaux graphiquesclé API~3 min
Bufferbrouillons de posts pour Reels / TikTok / Shortsconnexion via navigateur + canaux dans Buffer~5 min

Ordre : ElevenLabs → Higgsfield → 21st.dev → Buffer. Si Scribe a été choisi au bloc 3, ElevenLabs est obligatoire, dis-le. « Plus tard » et « pas besoin » sont des réponses normales.

Pour chaque service où la réponse est « maintenant », suis la section correspondante de SERVICES.md : liens et étapes dans tes propres mots, attends le « prêt », configure ta partie et vérifie :

  • Clés (ElevenLabs, 21st.dev) : si video/.env n'existe pas — cp video/.env.example video/.env ; l'utilisateur saisit la clé lui-même (open -e video/.env). Vérification — bash video/scripts/doctor.sh, section access. Refusé — probablement copié incomplètement ou sans les droits nécessaires ; qu'il en crée une nouvelle.
  • 21st.dev : après vérification de la clé, ajoute le serveur localement (la clé est lue depuis .env directement dans le shell) :
    cd video && set -a && . ./.env && set +a && cd .. && claude mcp add --transport http 21st https://21st.dev/api/mcp --header "x-api-key: $TWENTYFIRST_API_KEY" --scope local
    
    Si claude n'est pas dans le PATH — donne cette commande à l'utilisateur pour qu'il l'exécute dans le terminal.
  • OAuth (Higgsfield, Buffer, facultatif ElevenLabs MCP) : ajoute les serveurs choisis dans le fichier racine .mcp.json :
    {
      "mcpServers": {
        "higgsfield": { "type": "http", "url": "https://mcp.higgsfield.ai/mcp" },
        "buffer": { "type": "http", "url": "https://mcp.buffer.com/mcp" },
        "elevenlabs": { "type": "http", "url": "https://api.elevenlabs.io/v1/mcp" }
      }
    }
    
    Connexion via navigateur — après le redémarrage de Claude Code (/mcp → serveur → Authenticate) : dis-le maintenant et rappelle-le à l'étape 5. Pour Buffer, demande de connecter les canaux à l'avance dans Buffer lui-même (Instagram — compte professionnel).

Marque les services connectés dans integrations. Si tu es bloqué sur un service pendant 15 minutes ou plus — propose de le reporter : « on connectera plus tard — dis "connecte Buffer" ».

Bloc 5 — ce que tu aimes (selon les références)

Attends la fin de l'analyse (ps -axo command | grep "[r]efs.py"), lis takes/refs/refs.json, regarde chaque NN-hook.jpg et NN-sheet.jpg et palette.png. Pour chaque vidéo, note ce que les chiffres ne voient pas : sous-titres (position, taille, casse, graisse, couleur, surbrillance des mots, fond), graphiques (cartes et leur apparence, stickers, captures d'écran, b-roll, emojis), plan et punch-ins, proportion de visage nu, palette des graphiques, polices, ce qu'il y a dans le hook (texte-poster, question, action), fin.

Résume en un « profil de goût » : 5–7 tendances qui sont présentes dans au moins la moitié des vidéos, avec des chiffres (médianes de refs.py). Affiche-le en un seul message et demande : « c'est toi ? qu'est-ce que tu veux garder chez toi, et qu'est-ce que tu ne veux pas ? ». Ce qui est accepté deviendra des propositions dans les blocs 6–8 — tu le montreras par des images à côté d'autres options, sans l'appliquer en silence. Ce qui ne correspond pas aux réglages (stickers emoji, écran vert…) — note-le comme souhait dans le profil.

Bloc 6 — palette (2–3 messages)

6.1 Questions — en un seul message, en texte libre :

  • As-tu des couleurs de marque — logo, site web, habillage de la chaîne, couvertures ? Envoie des codes hexadécimaux, un lien vers le site ou place le logo / une capture d'écran dans takes/brand/.
  • Qu'est-ce qui doit ressortir en couleur dans les vidéos : chiffres, mots-clés, appels à l'action ?
  • Quelle sensation veux-tu : stricte, chaleureuse, vive, calme ?
  • Quelles couleurs ne veux-tu surtout pas ?

S'il envoie une image, extrais les couleurs principales :

python3 -c "
from PIL import Image; import sys
im = Image.open(sys.argv[1]).convert('RGB').resize((200, 200)).quantize(6)
pal = im.getpalette(); cnt = sorted(im.getcolors(), reverse=True)
print([('#%02X%02X%02X' % tuple(pal[i*3:i*3+3]), round(100*n/40000)) for n, i in cnt])
" takes/brand/logo.png

S'il envoie un lien vers un site — ouvre-le et trouve les couleurs principales (logo, boutons, variables CSS).

6.2 Candidats — 2–3 palettes selon quatre rôles : dark (plaques, écrans), light (texte), accent (surbrillance), pain (carte « pas comme ça », s'il en a besoin) :

  • depuis les références — recurring_colours dans refs.json et palette.png ; vérifie avec les storyboards que la couleur est un graphique ou du texte, pas un mur, un objet à l'écran ou de la peau ;
  • depuis les couleurs de marque, si elles existent ;
  • selon les réponses 6.1 — sensation et quoi mettre en évidence.

Lisibilité (technique, pas goût) : le texte sur la plaque et par-dessus le footage doit être lisible — vérifie le contraste de chaque candidat (light sur dark ≥ 7:1, accent sur dark ≥ 3:1) ; si un candidat ne passe pas, dis-le et propose le plus proche qui passe :

python3 -c "
import sys
def L(h):
    c=[int(h[i:i+2],16)/255 for i in (1,3,5)]
    c=[x/12.92 if x<=0.03928 else ((x+0.055)/1.055)**2.4 for x in c]
    return 0.2126*c[0]+0.7152*c[1]+0.0722*c[2]
a,b=sorted([L(sys.argv[1]),L(sys.argv[2])]); print(round((b+0.05)/(a+0.05),1))
" '#FFFFFF' '#141414'

6.3 Montre par images :

cd video && python3 scripts/variants.py out/palette-options.png 70,368 \
  '{"label":"A","colors":{"dark":"#…","light":"#…","accent":"#…","pain":"#…"}}' \
  '{"label":"B","colors":{…}}' '{"label":"C","colors":{…}}'

Affiche la feuille (SendUserFile), légende : « A — d'après tes références, B — d'après le logo, C — d'après la sensation ». Modifications (« A, mais l'accent plus foncé ») — nouveau passage. Ce qui est choisi — dans colors.

Bloc 7 — polices (2–3 messages)

Deux polices : texte (sous-titres et cartes, graisses 500 / 600 / 700) et poster (titre au début de la vidéo, s'il y en a un). Les deux doivent prendre en charge l'alphabet de la langue des vidéos.

7.1 Questions — en un seul message : as-tu des polices de marque (noms ou fichiers dans takes/brand/) ; quel caractère — strict, amical, technologique, éditorial ; sous-titres légers ou denses.

S'il y a eu un bloc 2 — regarde les sous-titres et les titres sur les storyboards et dis ce que tu vois : type (grotesque géométrique, néo-grotesque, étroit, arrondi, avec empattements), graisse, casse. Ne devine pas le nom exact d'après l'image — cherche une police libre similaire.

7.2 Candidats — 2–3 paires « texte + poster » issues de @fontsource avec l'alphabet nécessaire, de caractères différents, adaptés à ses réponses et à ses références. Pour le russe, vérifie le cyrillique ; Bebas Neue — seulement latin. Police de marque achetée — dans video/src/fonts/ + @font-face avec font-display: block manuellement ; rappelle la licence si le dépôt est public.

7.3 Montre par images :

cd video && npm i @fontsource/<a> @fontsource/<b>                  # candidats
ls node_modules/@fontsource/<a>/ | grep -c cyrillic                # pour ru > 0
ls node_modules/@fontsource/<a>/ | grep -E '^[0-9]+\.css$'         # graisses disponibles
grep -m1 font-family node_modules/@fontsource/<a>/400.css          # nom exact de la famille

Ajoute dans video/src/index.css les imports des graisses des candidats (@import "@fontsource/<a>/600.css"; …), puis :

python3 scripts/variants.py out/font-options.png 70,368 \
  '{"label":"A","fonts":{"text":"…","poster":"…","posterWeight":700}}' '{"label":"B","fonts":{…}}'

Affiche, légende. Après le choix, ne laisse dans index.css que les imports choisis et supprime les paquets inutiles (npm un …).

Bloc 8 — style de montage (un message par sujet)

Quatre sujets, chacun dans un message séparé : question, ce qui est visible dans les références (« dans 7 vidéos sur 10, les sous-titres sont centrés, grands »), puis 2–3 options par images via variants.py (clés style.*, images 70,270,368). Sans « je recommande ».

8.1 Sous-titres (style.captions) :

  • position : cycle — les phrases se déplacent dans le cadre (haut-gauche → haut-droite → bas) ; rail — toujours en bas ; center — centré ;
  • taille size: [mot normal, mot surligné] en px (≈ 48 petit, 60 moyen, 76 grand) ;
  • graisse weight (500–800) ; casse case : lower / asis / upper ;
  • surbrillance highlight : color (mots-clés en couleur d'accent) / size (plus grand) / both / none ;
  • fond box : true — plaque sous la ligne, false — ombre.

8.2 Graphiques :

  • cartes style.cards : glass (verre semi-transparent) / solid (plaque pleine) / none ; fréquence — en mots dans editing-taste.md §3 ;
  • stickers-pictogrammes dans les pauses style.stickers : true / false ;
  • poster-titre derrière la tête au début style.poster : enabled, casse case (upper / asis), petit sous-titre kicker. Activé — besoin de rembg (~30 min en arrière-plan par vidéo, modèle ~1 Go une fois) ;
  • b-roll (si Higgsfield est connecté) : nécessaire ou non, combien — en mots dans brand-kit.md §5.

8.3 Mouvement et image :

  • tempo style.tempo : punchy (coupes rapides, beaucoup de punch-ins) / calm (poses, plans larges) ;
  • punch-ins style.punchIns : frequent (toutes les 4–7 secondes si le sujet change) / sparse ;
  • zoom style.zoom : subtle (zoom lent 1.0→1.05 en 3 sec) / pronounced (1.0→1.15) / none ;
  • grade style.grading : warm (chaud) / cool (froid) / neutral (neutre) — par mots et exemples ; correction des couleurs technique (courbes, balances) — dans le fichier editing-taste.md §1, pas ici.

8.4 Son :

  • niveaux style.audio.levels : voice, music en pourcentage (moyenne : parole 12 dB, musique -18 dB) ;
  • audio accent style.audio.accents : true (si ElevenLabs connecté) — effets sonores aux moments clés (ding, swipe, pop) ;
  • loudness style.audio.loudnorm : true (normalisation à -14 LUFS, deux passes). Si l'utilisateur veut plus fort — dans le profil, mais note qu'il dépassera la norme ;
  • suppression du bruit style.audio.noiseReduction : light / medium / heavy / none.

Bloc 9 — film d'échantillons (un message)

cd video && python3 scripts/variants.py out/style-preview.png 70,368 \
  '{"label":"A","style":{"captions":{…},"cards":"…","tempo":"…",…}}' \
  '{"label":"B","style":{…}}' \
  '{"label":"C","style":{…}}'

Affiche la feuille d'images de la vidéo d'échantillons (chiffre de l'étape 9). Pas de sélection — les touches des blocs 8.1–8.4 constituent le choix final.

Étape 3. Sauvegarde du profil

cd video && python3 scripts/save_profile.py

Écrit dans les fichiers racine :

  • harness.config.json — paramètres techniques (services, couleurs, polices, style) — utilise le JSON directement depuis les blocs 2–8 ;
  • brand-kit.md — marque, audience, ton, mots-clés ;
  • editing-taste.md — la partie technique du goût (grading, ratio de punch-ins, mécanique des sous-titres) ;
  • exemplars.md — liens vers les références et ce qui a été appris d'elles.

Les fichiers ne sont pas en git, ils sont créés dans le dossier racine. Tout est prêt. Dis : « Le projet est configuré. Tu peux commencer la première vidéo — écris "fais la première vidéo" ». Et c'est tout.

Spécifique au système de fichiers et au code

  • Tous les chemins depuis la racine du projet. Les appels aux scripts utilisent cd video && ….
  • doctor.sh est un script bash dans video/scripts/ qui vérifie Node, Python, le son, l'accès aux clés (sans imprimer les clés).
  • variants.py génère une grille d'images (70×368 px par cellule) avec des légendes. Appel : python3 scripts/variants.py <chemin_sortie> <dimensions_cellule> <json1> [json2 …].
  • Le profil après l'entretien se trouve dans harness.config.json — un format technique (services, palettes, polices, style). Ne le modifie pas après la sauvegarde sauf demande explicite.
  • Un fichier /mcp sert à redémarrer le serveur Claude Code (après ajout de serveurs OAuth).
  • yt-dlp télécharge les références. Cookies pour Instagram — via SERVICES.md.
  • rembg — modèle pour l'incrustation du portrait (fond).
  • Les clés dans .env sont strictement locales, ne les imprime pas et ne les utilise pas dans le chat.
  • SERVICES.md — instructions pour connecter chaque service. Ne contient pas de clés.
  • CLAUDE.md — mécanique du pipeline, règles de montage.

Comportement dans les cas particuliers

  • L'utilisateur interrompt l'entretien au milieu : ne devine pas la suite. Demande : « On continue la configuration ? On en était à … » (cite le bloc en cours).
  • L'utilisateur a déjà un fichier de profil (configured: true dans harness.config.json) : ne relance pas l'entretien. Demande : « Le projet est déjà configuré. Tu veux changer quelque chose ? Dis "reconfigure" pour tout refaire, ou "change la palette" pour un bloc spécifique. »
  • L'utilisateur envoie une clé dans le chat : « Ne partage jamais la clé dans le chat. Révoke-la et crée-en une nouvelle, puis inscris-la dans le fichier .env. »
  • L'utilisateur refuse les références : passe les blocs 5, 6, 7, 8 en mode questions (sans carry-over des références). Propose des options génériques.
  • Moins de 5 références : idem, sauf si l'utilisateur insiste pour continuer avec ce qu'il a.
  • Le script refs.py échoue pour tous les liens : « Les liens ne sont pas téléchargeables. Tu peux télécharger les vidéos toi-même et les mettre dans takes/refs/, ou on continue sans analyse et on choisira les options manuellement. »
  • L'utilisateur change d'avis en cours de route : on peut revenir en arrière. « Dis "retour au bloc palette" et on y retourne. »
  • L'utilisateur a déjà un .env avec des clés : vérifie via doctor.sh. Si l'accès est bon, passe le bloc 4 en mode confirmation (tout est bon).
  • L'utilisateur veut un style « comme ce reel spécifique » : exécute refs.py sur celui-ci (même si ce n'est pas le bloc 2). Utilise-le comme référence unique.
  • L'utilisateur dit « c'est trop long » : propose un mode rapide — uniquement les blocs 1, 4, 6, 8 (sans analyse des références ni comparaisons). « On peut raccourcir — juste la palette, les polices et le style. Les détails plus tard. »
  • Système d'exploitation non supporté : demande quel OS l'utilisateur utilise. Sur Windows sans WSL, propose WSL. Sur Linux, vérifie la disponibilité de ffmpeg, Python, Node.
  • Conflit de dépendances : dis exactement quelle dépendance et quel conflit. « Le package X nécessite la version Y, mais Z est installé. Peut-on mettre à jour ou supprimer Z ? »
  • L'utilisateur fournit un lien de référence qui nécessite une connexion (Instagram) : propose d'utiliser les cookies du navigateur (COOKIES_FROM=chrome) ou de télécharger manuellement.
  • Après la configuration, l'utilisateur veut ajouter un service : « Dis "connecte [nom du service]" et je t'aiderai. »
  • Le script save_profile.py échoue : vérifie les permissions d'écriture dans le dossier racine. « Tu n'as pas les droits d'écriture. Corrige ça ou change de dossier. »

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Skills associés