Mon coach de course était un script

Dix semaines, un plan YAML, cinq scripts Python et une Garmin branchée dessus. Un coach IA construit en quelques échanges, qui m'a envoyé un mail chaque matin à 10h et m'a mené sans casse au bout d'un semi-marathon.

Chaussures de running et montre GPS posées sur un chemin au lever du jour

Pendant dix semaines, j'ai reçu chaque matin à 10h un mail de mon coach. Personne ne l'écrivait. Un script l'envoyait, après avoir lu ma montre.

Pour préparer une course, je me suis construit un coach qui n'existe pas. Pas une appli, pas un abonnement. Un dossier sur mon ordinateur, quelques scripts Python, un plan dans un fichier texte, et ma Garmin branchée dessus. Je n'ai pas écrit une ligne de code moi-même : c'est un agent IA qui a tout construit.

La course est passée depuis quelques mois. J'ai laissé retomber avant d'écrire : comment c'était fait, ce que ça valait vraiment, et ce que je ne referais pas.

Le point de départ : une allure cible et deux points faibles

L'objectif : tenir 5:41 au kilomètre le jour de la course, pendant 21 km. Dix semaines de préparation pour y arriver.

Le problème, ce n'est pas le chrono. C'est le corps. Une tendinite d'Achille qui revient quand je change brutalement de charge, et un genou fragile côté fascia lata. Un plan trouvé sur Internet ne connaît ni l'un ni l'autre. Une appli de course non plus, ou alors elle me demande comment je me sens et n'en fait pas grand-chose.

Ce que je voulais : un plan qui s'adapte à ce que mon corps dit vraiment, chaque jour, sans que j'aie à y penser. Un coach qui me connaît, qui ne dort pas, et qui ne me pousse pas à me casser.

Comment c'est construit

Un dossier dédié dans OpenClaw, l'agent IA que j'utilise, jouait le rôle de coach. Il contenait le plan, cinq scripts Python, un journal des séances envoyées et un log quotidien. C'est l'agent qui a écrit les scripts ; mon rôle a été de dire ce que je voulais, de vérifier, de corriger.

Le plan alimente la montre, la montre alimente Garmin Connect, et le script du matin referme la boucle en réécrivant la semaine à venir.

Mon plan semi-marathon est un fichier texte

Tout le programme tenait dans un fichier YAML : 10 semaines, 70 séances, chacune avec sa date, sa durée, son détail, sa fréquence cardiaque cible et ses notes. Un fichier lisible, modifiable, versionnable. Comme du code.

Ce n'est pas un template générique. Il est calé sur mes données :

  • Zones cardiaques recalibrées : FC max fixée à 193 (189 observés sur mes sorties, plus une marge), cinq zones de la récupération au VO2max.
  • Allures chiffrées par type d'effort : endurance fondamentale 6:10 à 6:25/km, tempo 5:35 à 5:45, seuil 5:20 à 5:30, allure course 5:41.
  • Une semaine construite autour des blessures : la sortie longue le samedi, la qualité le jeudi, le renforcement le mercredi pour le genou.
  • Des interdits écrits noir sur blanc : pas de 30-30, pas de sprint en descente, 15 minutes d'échauffement minimum.

Ce dernier point change tout. Mes contraintes ne sont plus dans ma tête, où je les oublie un jour de forme. Elles sont dans le plan, et le plan les applique.

Garmin Connect devient un backend

La partie qui m'a le plus surpris. Un script parle directement à Garmin Connect, via une bibliothèque Python communautaire (garminconnect). Il ne se contente pas de lire mes données : il écrit sur ma montre.

Concrètement, pour chaque séance du plan, il :

  1. construit l'entraînement au format natif Garmin, avec échauffement, intervalles, récupération et retour au calme, et des cibles cardiaques en bpm ;
  2. le planifie à la date prévue dans le calendrier Garmin ;
  3. le synchronise sur la montre.

Le jour J, je lançais la séance et la montre me guidait étape par étape : 15 minutes d'échauffement, 4 fois 5 minutes au seuil avec 1:30 de récupération, 10 minutes de retour au calme. Je ne regardais plus mon téléphone en courant. Chaque envoi était tracé dans un journal.

Le vrai coach, ce sont les règles d'adaptation

Pousser un plan sur une montre, c'est pratique. Mais un plan figé reste un plan figé. Ce qui fait un coach, c'est qu'il change le programme quand le corps ne suit pas.

Chaque matin à 10h, une tâche planifiée lance le script quotidien. Il récupère mes 7 derniers jours sur Garmin (courses, fréquence cardiaque, charge d'entraînement, VFC, sommeil), les compare à ce que le plan prévoyait, recalcule les 7 jours suivants et m'envoie le tout par mail.

Les adaptations sont des règles simples, écrites à l'avance :

Si…Alors…
VFC déséquilibrée 2 jours de suitela séance de qualité devient de l'endurance fondamentale
Douleur à l'Achille au-dessus de 3/10le fractionné saute
Moins de 6h de sommeil sur 3 nuitsla qualité redevient de la récupération
Charge cumulée au-delà de 130 % du planalerte, et proposition d'endurance fondamentale

Il n'y a pas d'intelligence magique là-dedans. Ce sont des « Si… Alors… » qu'un bon entraîneur appliquerait de tête. La différence, c'est qu'ils sont appliqués tous les matins, sans exception, même quand j'ai envie de forcer. Pour quelqu'un qui a un tendon qui réagit aux changements brusques de charge, c'est exactement ce qui manquait.

C'est là que je vois la différence entre une appli gadget et un coach : pas dans la quantité de données, dans la qualité des décisions qu'on en tire.

Les chiffres bruts

IndicateurValeur
Semaines de préparation10
Séances dans le plan70
Sorties réelles par semaine2 à 3
Mail du coachtous les matins, sans interruption
Lignes de code écrites par moi0
Allure cible5:41/km
Résultat20 km courus sans trop de problème

Ce qui coince

Le système a marché. Il a aussi ses angles morts, et je préfère les poser ici.

  • Le plan était plus ambitieux que ma vraie vie. 70 séances prévues, 2 à 3 sorties par semaine en pratique. Le coach constatait l'écart tous les matins, mais il ne courait pas à ma place.
  • L'accès Garmin n'est pas officiel. La bibliothèque utilisée est maintenue par la communauté, pas par Garmin. Une mise à jour côté Garmin peut tout casser du jour au lendemain, et il faut stocker ses identifiants pour que ça tourne.
  • Mes données de santé circulent. Sommeil, VFC, fréquence cardiaque : ce sont des données sensibles. Savoir exactement où elles passent fait partie du travail, pas d'un détail technique.
  • Une règle n'est pas un kiné. Le seuil de douleur à 3/10 protège d'une erreur grossière. Il ne remplace pas un avis médical si le tendon se réveille vraiment.
  • Le ressenti reste une saisie. La montre ne mesure pas ma douleur à l'Achille. Une partie de l'intelligence du coach dépend de ce que je lui déclare.

Au final : 20 km, sans casse

J'ai couru les 20 km sans trop de problème. Le mail est arrivé tous les matins jusqu'au bout, et la montre a toujours su quoi faire.

Avec quelques mois de recul, ce test m'a surtout appris une chose : l'IA ne m'a pas donné un coach. Elle m'a permis de construire le mien, avec mes données, mes contraintes et mes règles, en quelques échanges plutôt qu'en quelques semaines de code. Le vrai travail a été de dire clairement ce que je voulais protéger.

Ce que j'en garde : un plan, tout le monde peut en trouver un. Ce qui m'a amené au bout sans casse, ce sont les règles écrites à l'avance et appliquées sans exception.

Sous le capot : comment c'est fait, pour qui veut savoir

Cette section s'adresse à ceux qui veulent comprendre l'implémentation. Les autres peuvent sauter directement à la newsletter.

Architecture

Tout tient dans un workspace OpenClaw local, exécuté en ligne de commande. Pas de serveur, pas de base de données : des fichiers texte et cinq scripts Python.

~/.openclaw/workspace-coach-run/
├── plans/semi-2026-11-08.yaml   # 10 semaines, 70 séances
├── scripts/
│   ├── coach_daily.py           # cerveau quotidien, lancé à 10h
│   ├── push_workouts.py         # pousse les séances sur la montre
│   ├── analyze_today.py         # analyse la dernière course
│   ├── baseline.py              # calibrage sur 30 jours d'historique
│   └── send_plan.py             # récap initial du plan par e-mail
├── data/pushed_workouts.jsonl   # traçabilité des séances poussées
└── memory/coach_daily.log       # journal quotidien
ScriptRôleDéclenchement
baseline.pyCalcule FC max observée et zones sur 30 joursUne fois, au démarrage
send_plan.pyEnvoie le plan complet par e-mailUne fois, au démarrage
push_workouts.pyConvertit YAML → format Garmin, planifie, traceÀ la demande ou par lot
coach_daily.pyLit 7 jours, compare au plan, applique les règles, mailCron, 10h
analyze_today.pyAnalyse détaillée de la dernière sortieÀ la demande

Stack

ComposantRôleStatut
OpenClawAgent IA local, cron intégréOpen source, auto-hébergé
Python 3Langage des cinq scripts—
garminconnectClient Garmin : lecture santé/activités + écriture de séancesMIT, non officiel
PyYAMLLecture du planMIT
cronDéclenchement quotidien à 10hSystème
SMTPEnvoi du récap quotidien—

Accès Garmin Connect

Le projet parle à Garmin Connect via garminconnect, un client non officiel : il s'authentifie comme l'app mobile et appelle les mêmes services web. C'est ce qui permet d'écrire sur le compte — donc de pousser des séances — ce que l'API personnelle officielle, en lecture seule, ne permet pas.

Trois voies possibles en octobre 2026 :

VoieLectureÉcritureConditions
garminconnect (non officiel)OuiOuiAucune validation ; peut casser à tout changement côté Garmin
API personnelle Garmin (officielle)OuiNonClé générée depuis les réglages Connect
Programme développeurs (Starter / Enterprise)OuiOui (Training API)Validation business, site public, politique de confidentialité

Point d'attention, octobre 2026 : Garmin a durci ses conditions pour les tiers et fermé plusieurs apps intermédiaires (Intervals Pro, 12 octobre). Ce projet lit Garmin directement, sans plateforme intermédiaire : il n'est pas visé par cette restriction. Il reste exposé à un durcissement de l'accès non officiel. Évolution naturelle : lire par l'API personnelle, et ne garder garminconnect que pour l'écriture.

Séances structurées : du YAML à la montre

Une séance Garmin est un objet workout découpé en segments et étapes typées — échauffement, intervalle, récupération, retour au calme — chacune avec une condition de fin (durée ou distance) et une cible facultative (allure, FC, puissance, cadence).

push_workouts.py enchaîne trois opérations :

ÉtapeMéthodeEffet
1. Créerupload_running_workout(workout)Ajoute la séance à la bibliothèque Garmin, renvoie un workoutId
2. Planifierschedule_workout(workout_id, "AAAA-MM-JJ")Place la séance à la date du plan dans le calendrier Connect
3. Envoyersynchronisation de la montreLa séance apparaît sur la montre

Le plan en YAML

Le programme est une donnée, pas un document. Il se versionne avec Git, se relit à l'œil, se modifie sans outil.

athlete:
  fc_max: 193
  allures:
    ef:     ["6:25", "6:10"]
    tempo:  ["5:45", "5:35"]
    seuil:  ["5:30", "5:20"]
    course: "5:41"

contraintes:
  - pas de 30-30
  - pas de sprint en descente
  - echauffement_min: 15

semaines:
  - numero: 7
    seances:
      - date: 2026-10-15
        type: seuil
        duree_min: 45
        detail: "15' échauffement, 4 x 5' seuil r=1'30, 10' retour au calme"
        fc_cible: z4
        notes: "stop si Achille > 3/10"

Fondement scientifique des règles

Trois des quatre règles s'appuient sur une littérature solide ; aucune n'est une prescription médicale.

RègleFondementÉcart avec la littérature
VFC déséquilibrée 2 jours de suiteEntraînement guidé par la VFCCohérent ; bénéfice modeste mais réel
Douleur Achille > 3/10Modèle de surveillance de la douleur (Silbernagel 2007)Plus prudent que le seuil étudié (< 5/10)
Sommeil < 6h sur 3 nuitsAssociation manque de sommeil / blessurePreuves surtout chez l'adolescent ; prudence raisonnable chez l'adulte
Charge cumulée > 130 % du planRatio aigu/chronique (Gabbett 2016)Le projet compare au plan, pas à la charge chronique réelle

Deux méta-analyses de 2021 montrent que l'entraînement guidé par la VFC améliore surtout les marqueurs physiologiques sous-maximaux, avec un gain de performance faible mais moins de « non-répondeurs ». L'essai de Silbernagel et al. (AJSM 2007) montre que continuer à courir avec un modèle de surveillance de la douleur n'a pas d'effet négatif par rapport au repos, tant que la douleur reste sous 5/10. Gabbett a précisé en 2019 que son ratio charge aiguë/chronique montre une association, pas une prédiction : il ne doit jamais être lu isolément.

Sécurité

VFC, FC, sommeil et douleur déclarée sont des données de santé au sens du RGPD. Pour un usage strictement personnel, le RGPD ne s'applique pas. Il s'applique dès que le montage est proposé à d'autres.

PointMesure
Jetons Garmin (garmin_tokens.json)Droits 0600, jamais dans Git, révocation côté compte en cas de doute
Mot de passe GarminSaisie interactive au premier login ; MFA activé
Envoi aux modèles d'IASavoir quel modèle OpenClaw appelle, limiter aux agrégats
Mail de récapContenu minimal, boîte personnelle
Journal et .jsonlChiffrement du disque, rétention limitée

Un livre blanc technique complet (architecture, bibliothèques, extraits de code, références scientifiques et sources) est disponible sur demande.

---

Vous voulez recevoir mes prochains tests de ce genre ? Inscrivez-vous à la newsletter Because Friday. Chaque semaine, un test vécu, ce qui a marché et ce qui a coincé.

Transparence : les scripts ont été écrits par un agent IA (OpenClaw), cet article a été rédigé avec l'aide de Claude à partir de mes notes. Le plan, les choix et les kilomètres sont à moi.