Back to thales
thales

Cockpit : le petit CLI qui a corrigé mon workflow IA

Il y a cinq mois, j'ai partagé le workflow qui a construit six produits en production avec zéro ingénieur. Voici la pièce qui me manquait et le petit CLI open-source qui la corrige. Licence MIT, source sur GitHub aujourd'hui, paquet npm disponible : npx @justethales/cockpit init.

Juste A. Gnimavo (Thales) | May 30, 2026 19 min thales
EN/ FR/ ES
workflowai-ctoclaudemethodologycockpitsession-architectureopen-sourceafrica-tech

Par Thales (Juste Gnimavo) — CEO & fondateur, ZeroSuite, Inc.


En mars, j'ai publié un long article expliquant le workflow que j'utilise pour piloter six produits en production avec Claude comme CTO et zéro ingénieur humain. C'est l'article le plus lu que j'aie jamais écrit. Il décrivait cinq piliers : la constitution CLAUDE.md, l'architecture des sessions, le développement par phases, la boucle d'audit multi-agents, et la structure d'autorité qui autorise Claude à me dire non.

Je maintiens cet article. Ces cinq piliers ont construit sh0, FLIN, Déblo, 0fee, 0cron et 0diff. Ils continuent à livrer du code qui tourne aujourd'hui.

Mais l'article avait un trou que je ne voyais pas à l'époque. Il expliquait comment bien mener une session unique. Il ne disait rien sur la façon de garder des dizaines de sessions cohérentes sur plusieurs mois de travail.

C'est un problème distinct. C'est aussi le problème qui a failli faire échouer une session vendredi après-midi dernier.


Le bug qui a failli gâcher une session

Le contexte. J'étais en pleine Phase 4.6 de Conductor, notre espace de travail IA interne. La session du jour était la Section C de cette phase, une surface d'API conversationnelle. La session précédente, deux jours plus tôt, avait livré la Section B (le schéma de base de données). J'ai ouvert une nouvelle session Claude Code, tapé /next, et regardé l'agent commencer à exécuter.

Environ 90 secondes plus tard, l'agent a marqué une pause. Il avait lu le cockpit (le fichier d'état que je vais expliquer dans un instant) et remarqué quelque chose qui m'avait échappé.

state.json.next_prompt pointe vers le parent PHASE-4.6-WORKSPACE-V1.md, mais le sous-prompt rédigé dans le commit le plus récent est PHASE-4.6C-CONVERSATION-API.md et next_phase nomme la Section C. Exécuter le sous-prompt C est la vraie tranche suivante.

Le cockpit avait dérivé. Les métadonnées que j'avais mises à jour à la fin de la session B pointaient vers le mauvais fichier. L'agent l'a repéré en croisant deux champs. Sans cela, si l'agent avait exécuté aveuglément ce que next_prompt désignait, j'aurais gâché la session à refaire un périmètre de prompt parent qui n'était même pas en file d'attente.

C'est le mode de défaillance que mon article des cinq piliers ne décrivait jamais. Chaque session prise isolément était solide. La passation entre sessions était un copier-coller manuel et fragile qui marchait 95 % du temps et cassait silencieusement les 5 % restants. Le coût de ces 5 % n'était pas une erreur de syntaxe. C'étaient trente minutes de confusion, une mauvaise direction prise, et une érosion silencieuse de la confiance dans le cockpit lui-même.

Je suis resté sur le problème pendant une heure. Puis j'ai construit la correction. Je la livre ce soir sous licence MIT, en open source. Quiconque lit ces lignes peut l'installer en 30 secondes et l'utiliser sur n'importe quel projet.

Il s'appelle Cockpit. Voici ce que c'est, pourquoi ça marche, et pourquoi je pense que chaque développeur qui mène des sessions pilotées par IA a besoin de quelque chose de similaire.


Ce qu'est réellement un cockpit

J'utilise le mot « cockpit » informellement dans nos dépôts depuis environ trois mois. L'idée est simple : un dossier à la racine de chaque projet qui répond à la question « où suis-je, qu'est-ce que je fais, qu'est-ce qui vient ensuite » sans obliger l'agent à relire la codebase.

Un cockpit contient six fichiers markdown, un fichier JSON et un dossier de templates :

state.json est la source de vérité unique lisible par machine. current_phase, next_phase, next_prompt, last_session_id, last_commit, phases_shipped, migrations_applied. Chaque champ est un fait. Les agents le lisent avant de faire quoi que ce soit.

now.md est le focus lisible par un humain. Un paragraphe décrivant ce qui vient d'être livré, ce qu'il faut faire ensuite, ce qu'il NE faut PAS faire. Mis à jour à chaque clôture de session. Le moi futur lit ce paragraphe et reconstruit son état de travail sans lire une ligne de code.

roadmap.md est la surface avant : Next-3, en cours, bloqué, en file, livré-cette-semaine, scoreboard des phases. Référence les prompts sous docs/plan/sessions/ et les logs sous session-logs/.

architecture.md numérote les segments de la codebase (R1, A2, T3 et ainsi de suite) pour qu'une session puisse déléguer par ID (« audite T3 », « étends A2 ») au lieu de par dossier.

carte.md est un aperçu ASCII de la façon dont routes, libs et BDD s'articulent. Vision d'un seul coup d'œil, sans scroll.

README.md contient les protocoles de début et de fin de session, écrits pour l'agent qui va agir sur ce cockpit.

templates/ héberge trois squelettes canoniques : session-prompt.md, session-log.md, audit-brief.md. Toute nouvelle ébauche de session démarre depuis là.

Peut-être 1 000 lignes de markdown sur la durée de vie du projet. Coûte entre 3 et 5 mille tokens à charger (environ 1k via le nouveau CLI status). Coûte quatre-vingt-dix secondes à mettre à jour à la clôture de session.

C'était la forme depuis trois mois. Ça marchait.

Ce qui manquait, et que le bug de vendredi dernier a fait remonter, c'était une porte vérifiable par machine. La discipline du cockpit était 100 % manuelle. Si j'oubliais de bumper un champ, rien ne me rattrapait. L'agent en début de session faisait confiance à ce que disait state.json, et state.json disait ce que mon moi précédent avait tapé, et ce moi précédent avait été distrait.

La correction est aussi modeste dans l'esprit, sinon en nombre de lignes : un validateur TypeScript en un seul fichier (environ 500 lignes aujourd'hui) qui compare state.json au système de fichiers et à git, sort en 1 à la moindre incohérence, et affiche un indice → fix pour chaque trouvaille. À lancer avant chaque push. Le jour où vous le sautez est le jour où vous livrez un fichier d'état qui ment.


Ce que le validateur attrape

Je l'ai construit un vendredi après-midi. Il attrape neuf modes de défaillance que j'ai observés en trois mois de dérive de cockpit à travers ZeroSuite :

  1. state.json.next_prompt pointe vers un fichier inexistant. La session a oublié de rédiger le prompt suivant.
  2. state.json.next_prompt pointe vers un prompt avec status: shipped. Le bug exact qui m'a coûté une demi-heure. Le cockpit n'a jamais été bumpé après la session précédente.
  3. state.json.last_session_id ne correspond à aucun fichier de session-log. Le log n'a jamais été écrit.
  4. state.json.last_commit introuvable dans git log. SHA bidon, branche supprimée, faute de frappe.
  5. state.json.phases_shipped[] contient des doublons. Le protocole de clôture a tourné deux fois.
  6. state.json.migrations_applied[] ne correspond pas à drizzle/*.sql. Une migration a été livrée sans bump de l'état, ou l'état liste un fantôme.
  7. Un prompt de session a status: shipped mais session_log: pending. La bascule à la clôture a été faite avec négligence.
  8. Le session_log: d'un prompt livré pointe vers un fichier manquant. Faute de frappe ou renommage.
  9. Changements non commités dans cockpit/, docs/plan/sessions/ ou session-logs/. Une session précédente a oublié l'étape commit.

Chaque trouvaille affiche une ligne → fix pour que la session suivante puisse la résoudre sans relire la documentation :

cockpit:check · 22 PASS · 1 WARN · 1 FAIL
──────────────────────────────────────────────────────────────────────
  FAIL  next_prompt is already SHIPPED · docs/plan/sessions/PHASE-4.6C-CONVERSATION-API.md has status: shipped — cockpit was not bumped after that session
        → either (a) update state.json.next_prompt to the real next slice, or (b) re-execute the shipped prompt explicitly
  WARN  last_commit is in history but not at HEAD · state=81a5138 HEAD=e8795b1
        → bump state.last_commit to e8795b1 if the new commits are uncockpitted work

✗ 1 drift detected. Fix before push.

C'est toute la surface d'interaction. Pas de tableau de bord. Pas de SaaS. Pas de login. Branchez-le sur un hook pre-push, sur de la CI, sur une cible Makefile, ce qui colle à votre projet. Code de sortie 1 si dérive, 0 sinon.


Test terrain : deux projets en production, 90 secondes chacun

Avant de livrer la 0.1.0 sur npm, j'ai lancé npx @justethales/cockpit init sur deux projets ZeroSuite vivants que je n'avais pas rouverts depuis des semaines. Même commande, deux formes très différentes. Les deux ont fait remonter des bugs concrets en moins de deux minutes.

Test 1 — 0seat.dev (SvelteKit + Prisma, un projet que j'avais mis en pause six semaines plus tôt)

Le projet est une appli SvelteKit 2 + Prisma 6 + Stripe + Anthropic SDK, originellement extraite d'un monorepo Solid.js + Bun + InstantDB en mars. Dernier commit 2eaf2dd le 31 mars. Je n'y avais pas touché depuis.

J'ai lancé :

bashcd ~/ZeroSuite/0seat.dev
npx @justethales/cockpit@latest init
npx @justethales/cockpit@latest status
npx @justethales/cockpit@latest check

Trois trouvailles en 90 secondes, toutes que j'avais oubliées :

  1. REFACTORING-PLAN.md traînait non commité dans l'arbre de travail depuis deux mois. Le plan appelait à migrer depuis InstantDB vers Prisma. Le message du commit le plus récent disait "going to start added real instantdb client". Le plan et le travail étaient en désaccord. Aucun fichier du projet ne vous disait lequel faisait foi. Le champ next_prompt du cockpit m'a forcé à choisir. (J'ai choisi Prisma — le plan a gagné.)
  2. Huit fichiers non suivis (.auth-keys/, _logs/, 0seat.zip, .nx/, .vscode/, et trois autres) pourrissaient silencieusement. cockpit status les a fait remonter sur un seul écran.
  3. Le CLAUDE.md faisait 17 Ko de prose marketing (« The Four-Engine AI-Mesh System »), zéro règle d'ingénierie. Le décalage est devenu évident dès que cockpit/now.md m'a demandé d'écrire un paragraphe de focus et que j'ai réalisé que je n'avais nulle part où le mettre.

Le check est passé de 8 PASS · 2 FAIL (squelette frais) à 14 PASS · 0 FAIL · 1 WARN après que j'ai câblé le vrai last_commit, rédigé un vrai prompt PHASE-1-PRISMA-AUTH-MAGIC-LINK.md, et rétro-rempli un session log pour le travail de mars. Temps total écoulé : moins de cinq minutes.

Test 2 — Poponi (Rust + React Native + SvelteKit + Python, sans git)

Poponi est l'application de moto-taxi vocale d'Abidjan. Multi-stack : microservices Rust côté backend, client et applis pro React Native, dashboard SvelteKit, serveur vocal Python (Pipecat + Ultravox), infra. Dernier mtime de fichier : 15 avril. Six semaines de silence.

J'ai lancé les trois mêmes commandes. Cockpit a immédiatement affiché branch (no git) · HEAD (no git) — et j'ai réalisé l'état le pire possible. Le projet local n'avait aucun dossier .git, ni à la racine, ni dans aucun des six sous-dossiers. Le dépôt GitHub privé à github.com/zerosuite-inc/poponi-source-code existait bien — je l'avais créé il y a des mois avec cette intention — mais il n'avait jamais été initialisé localement et rien n'avait jamais été poussé. La page du remote affichait encore les instructions par défaut de mise en route rapide git init / git add / git commit / git push. Six semaines de microservices Rust, de client et d'applis pro React Native, de dashboard SvelteKit, et de serveur vocal Python vivaient exclusivement sur ce portable. Un café renversé et le projet disparaissait.

Cockpit n'a pas réparé ça automatiquement. Mais à l'instant où son en-tête de status a dit (no git), j'ai remarqué quelque chose qui m'avait échappé pendant des semaines. Le remote était créé, le local n'avait jamais existé, rien de chaque côté ne levait de drapeau.

J'ai corrigé sur-le-champ. Même session, dix minutes après la découverte : audit des secrets (.env était déjà dans .gitignore, aucune clé en dur dans le source, aucun JSON de service-account dans l'arbre), git init -b main, 151 fichiers stagés, commit monolithique unique cf1b77c intitulé « initial commit — 6 weeks of multi-stack scaffolding », remote ajouté, git push -u origin main. Le dépôt n'est plus un point de défaillance unique. Le coût a été de dix minutes que j'évitais depuis des semaines parce que rien ne me rappelait de les passer.

La deuxième trouvaille, c'est que le claude.md du projet impose un dossier work-sessions/ avec un cycle d'audit en quatre phases pour chaque fonctionnalité. Le dossier n'existe pas. La discipline est documentée dans la constitution mais jamais appliquée. La forme session-logs/ du cockpit est le correctif à 90 % de chevauchement ; pointer vers elle a forcé la question évidente — est-ce que j'écris les rapports ou non ?

check --no-git a correctement écarté les quatre assertions dépendantes de git et a fait tourner celles sur les métadonnées. Les deux véritables échecs (pas de prompt rédigé, pas de log écrit) étaient tous deux légitimes. Le CLI dégrade gracieusement quand git est absent.

Le motif que les deux tests ont révélé

La valeur du cockpit n'est pas dans les lignes de TypeScript. Elle est dans les questions que le squelette vous force à répondre :

  • Quelle est la prochaine tranche concrète ? → rédige le fichier ou échoue.
  • Où est le dernier session log ? → l'attend sur disque ou échoue.
  • Sur quel commit êtes-vous ancré ? → correspond à git log ou échoue.
  • L'arbre de travail est-il assez propre pour pousser ? → avertit sinon.

Dans les deux tests, les questions étaient la valeur. Le validateur n'était que la partie qui refusait de me laisser les sauter.


Les deux autres pièces

Une fois le validateur en place, j'ai réalisé qu'il résolvait un second problème que je n'avais pas encore nommé : les templates comme savoir implicite.

Chaque session produit trois artefacts : le prompt de session (rédigé à la fin de la session précédente), le session log (écrit à la fin de cette session), et l'audit brief (utilisé pour faire émerger l'agent d'audit post-implémentation). Les trois avaient une forme (format de frontmatter, ordre des sections, blocs obligatoires comme « Observed divergence ») que j'avais raffinée sur onze sessions. Les nouvelles sessions découvraient la forme en se calquant sur le fichier antérieur le plus récent. Ce qui voulait dire que les bizarreries de ce fichier se propageaient. Ce qui voulait dire que la forme dérivait.

Le cockpit livre désormais ces trois squelettes sous cockpit/templates/. Copiez-les quand vous rédigez un nouvel artefact. La forme reste stable parce que plus personne ne se calque. Tout le monde copie depuis la même source canonique.

La troisième pièce est pnpm cockpit:status : une capture sur un écran de l'état du projet, imprimable en environ 300 ms, qui remplace les quatre ou cinq commandes cat que je lançais en début de session. Elle affiche le nom et la version du package, la branche git et HEAD, la phase courante et suivante, le statut et un aperçu du prompt suivant, les 10 derniers commits, le focus courant depuis now.md, et le Next-3 depuis roadmap.md. Conscient des couleurs, conscient du TTY, se comporte bien dans une session Claude Code ou un terminal classique.

C'est toute la surface CLI aujourd'hui : cockpit init (squelette), cockpit status (lecture), cockpit check (validation), cockpit new prompt|log (template). Quatre verbes. Chacun fait une seule chose. Aucun ne fait rien de magique.


Pourquoi je l'open-source

Trois raisons.

D'abord, c'est assez petit pour être lu. Les deux scripts TypeScript font environ 700 lignes ensemble, plus trois templates et un README. Vous pouvez lire le tout en trente minutes et comprendre exactement ce qu'il fait. Pas d'algorithme propriétaire, pas d'indexation rusée, pas de complexité cachée. S'il cessait d'exister demain, vous pourriez le réécrire en un après-midi.

Deuxièmement, la valeur réside dans la discipline, pas dans l'outil. L'outil rend simplement la discipline vérifiable par machine. Séparer l'état de session de l'état de projet, rédiger le prompt suivant à chaque clôture de session, valider avant push : ces règles fonctionnent quel que soit l'outil qui les fait respecter. Prenez la discipline et utilisez mon outil ou construisez le vôtre. Les deux issues sont bonnes. La mauvaise issue, c'est de mener des sessions pilotées par IA sans aucune discipline, ce que je vois faire la plupart des équipes aujourd'hui.

Troisièmement, le motif est absent du paysage. Je lis des articles sur les workflows IA chaque semaine. J'en ai vu exactement zéro qui décrivent la gestion d'état de session. Ils décrivent les prompts, les outils, les sous-agents, les system messages, le choix de modèle : chaque couche sauf celle qui compte quand vous menez la session 47 d'un projet démarré en février. Le cockpit comble ce vide.

Où le trouver :

Zéro appel réseau, zéro télémétrie, zéro authentification.


Ce que ça change pour les cinq piliers

L'article original décrivait cinq piliers : CLAUDE.md, architecture des sessions, développement par phases, boucle d'audit multi-agents, et structure d'autorité. Ces piliers sont toujours justes. Cockpit n'est pas un sixième pilier. Il se loge en dessous comme le tissu conjonctif entre les sessions.

Le CLAUDE.md dit à Claude comment être un CTO. L'architecture des sessions dit à Claude comment travailler sur une fonctionnalité. Le développement par phases dit à Claude comment décomposer un problème. La boucle d'audit dit à Claude comment vérifier sa propre sortie. La structure d'autorité dit à Claude quand refuser.

Le cockpit dit à Claude quel jour on est dans la vie du projet, ce qui a été fait hier, ce qui est aujourd'hui, et si la passation depuis la session d'hier est intacte. Sans le cockpit, les cinq piliers fonctionnent pour une session. Avec le cockpit, ils fonctionnent pour des mois de sessions enchaînées.

Si vous avez lu l'article original et construit votre propre version du workflow, vous avez sans doute une version informelle du cockpit déjà : un STATUS.md, un NEXT.md, l'habitude d'écrire des session logs. Ce que je sors aujourd'hui, c'est cette version informelle formalisée, validée, et rendue partageable.


Comment l'adopter

Trois chemins, selon où vous en êtes.

Si vous n'avez pas encore de workflow IA : lisez d'abord l'article des cinq piliers. Le cockpit est une couche au-dessus des piliers. Sans les piliers, le cockpit n'est qu'un state.json sans sessions à gérer. Construisez d'abord le workflow.

Si vous avez un workflow mais pas de cockpit : lancez npx @justethales/cockpit init à la racine de votre projet. Il génère le dossier cockpit/ avec les templates pré-remplis, dépose les deux scripts CLI à leur place, et vous indique les quatre lignes à ajouter à votre package.json. Éditez cockpit/now.md et cockpit/state.json pour décrire où vous en êtes vraiment. Commencez votre prochaine session avec npx @justethales/cockpit status au lieu de coller le message de fin de la session précédente. Vous sentirez la différence dès la session trois.

Si vous avez déjà une discipline de type cockpit : générez un squelette dans un dossier temporaire avec npx @justethales/cockpit init, comparez ce qu'il livre à ce que vous avez, prenez les pièces qui vous manquent, ignorez celles que vous avez améliorées. Le validateur est la pièce la plus portable. Boulonnez-le sur la forme que vous avez déjà bâtie.


Ce qui reste ouvert

La revue honnête de mon propre travail, la même revue qui a fait remonter le bug de vendredi dernier, a identifié quatre faiblesses que je n'ai pas encore traitées :

Le cockpit pollue git log avec des commits chore(cockpit):. Chaque bump de state.json est son propre commit. Sur une année de sessions, ça fait du bruit dans le changelog. Je n'ai pas encore résolu ça. Les deux chemins sont : déplacer le cockpit vers une branche orpheline, ou accepter le bruit.

Le validateur attrape la dérive de métadonnées, pas la dérive d'intention. Si now.md ment sur ce qui a été construit, le validateur ne le verra pas. Rien ne le verra, sauf des humains et l'audit post-implémentation. Je pense que c'est fondamental.

Le CLI est Node-only. Les projets Python, Rust, Go peuvent le lancer via npx mais paient une dépendance à Node qu'ils ne voudraient pas autrement. Une distribution binaire est un portage d'une journée si la demande existe. Pour l'instant elle n'existe pas.

Pas de chemin de rollback. Si une session livre une phase qui se révèle cassée en production, le cockpit n'a pas de concept de « Section C dé-livrée, revert et retry ». state.json recule à la main. Je n'en ai pas eu besoin pour l'instant. Le jour où ça arrive, je devrai l'inventer.

Je livre ces limitations connues parce que les cacher serait malhonnête. Le cockpit est bon. Il n'est pas fini.


Le point plus large

J'écris ceci un vendredi soir au lieu de livrer plus de code parce que je pense que le motif compte plus que l'outil.

Le développement logiciel entre dans une phase où le goulot n'est plus la vitesse de frappe, l'intuition architecturale, ou la capacité à lire une stack trace. Le nouveau goulot est la capacité à maintenir un état cohérent à travers des workflows pilotés par IA qui s'étalent dans le temps. Les développeurs qui trouvent comment garder des dizaines de sessions alignées, sans brûler des heures par semaine à reconstruire le contexte, livreront plus et se feront moins de souci que ceux qui continuent à traiter chaque session comme un démarrage à zéro.

Le cockpit est une réponse à ce problème. Il y en a sans doute de meilleures. Le problème lui-même ne fait pas débat.

Il y a cinq mois j'écrivais que la façon dont vous utilisez Claude est la raison pour laquelle vous n'en obtenez pas ce que vous voulez. Je modifierais ça aujourd'hui : la façon dont vous gérez l'état entre les sessions est la raison pour laquelle vous ne livrez pas. Réglez le problème de gestion d'état et le reste devient plus facile.

Le cockpit est gratuit. La discipline est le prix.


Ressources

Si ça vous épargne une demi-heure par semaine, c'est déjà bien. Si ça vous en épargne plus, dites-le-moi. Je veux savoir quels modes de défaillance ça attrape que je n'avais pas anticipés.

— Thales Abidjan, Côte d'Ivoire 2026-05-30

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles