Une commande a suffi pour donner à mon agent de code un projet où il savait se repérer

Publié le  · Mis à jour le  · Igor Tkachenko

Une commande dans le terminal qui mène à trois workspaces : common, api et web

En juin, j’ai ajouté une commande create-app à OwlMeans Common. Je voulais un petit projet à confier à un agent de code sans devoir d’abord lui expliquer le framework de A à Z.

Common, c’est la fondation TypeScript sur laquelle reposent les projets OwlMeans. La commande te donne un point de départ qui tourne et les consignes qui décrivent ses conventions. C’est toujours toi qui diriges l’agent et qui relis ce qu’il modifie.

Ce pas-à-pas reprend l’exemple de juin, avec les versions épinglées du texte tenu à jour sur le site. L’organisation des consignes décrite plus bas tient compte du passage ultérieur à .agents/.

Le projet de départ

Choisis une commande :

bun create @owlmeans/app my-app
# or
npm create @owlmeans/app@latest my-app
# or
npx @owlmeans/create-app@^0.1.18-rc.65 my-app

Lance ensuite les serveurs de développement :

cd my-app
bun run dev          # API on :3000, web on :3001

Ouvre l’app web et essaie d’ajouter et de supprimer des éléments sur l’écran Session. La démo relie un frontend à une API par un contrat partagé. Ses données sont stockées en mémoire : un redémarrage du processus suffit à te rappeler pourquoi ça compte.

Le squelette comprend trois workspaces :

  • common contient les déclarations de routes partagées, les schémas de validation et les types.
  • api fait tourner le backend sur @owlmeans/server-app.
  • web fournit le frontend sur @owlmeans/web-panel.

C’est le squelette minimal de la CLI. Les projets générés dans OwlMeans peuvent aussi comprendre une bibliothèque backend partagée et un worker. L’exemple de la CLI ne les provisionne pas pour toi, pas plus qu’une base de données.

Le contrat de l’application

Je veux qu’un agent trouve une déclaration de route en cherchant son alias. Moi aussi, je veux pouvoir suivre cette même déclaration.

Common s’appuie sur des entrypoints pour ce contrat. Un entrypoint relie un alias, un chemin, une méthode et une validation :

entrypoint(
  route(session.add, '/:sid/items', { parent: session.base, method: RouteMethod.POST }),
  filter(params(SessionParamsSchema), body(AddItemSchema)),
)

Le backend y rattache un handler avec elevate. Le frontend y rattache le comportement de son écran et appelle l’entrypoint via ctx.entrypoint(session.add).call({ params, body }).

La route et le schéma sont du code source partagé. Avec ce modèle, il n’y a pas de client d’API généré à part. Modifier la déclaration oblige toujours à vérifier les appelants et le handler. Des types partagés ne peuvent pas décider si l’opération aurait dû être autorisée.

Les services suivent un chemin tout aussi visible. Une factory crée le service, l’application l’enregistre sous un alias, et le code le résout avec context.service('alias').

Je préfère ce câblage parce que je peux le lire. Je n’ai pas mesuré de ratio d’économie de tokens par rapport à un autre framework, et cet exemple n’en établit aucun.

Une illustration qui oppose un câblage implicite à des déclarations TypeScript explicites

Les données persistantes

La ressource de démo a des méthodes comme create, list et delete. Les ressources adossées à une base de données utilisent la même interface, ce qui permet aux handlers de garder cette forme familière.

Une migration vers une base de données ne se règle pas pour autant avec un seul package. Il te faut encore la configuration de connexion, les index, la validation et une décision sur les données existantes. Il faut aussi tester les règles d’accès.

Pour une nouvelle fonctionnalité de notes, voici une demande utile à soumettre à l’agent :

Ajoute des notes persistantes stockées dans MongoDB. Utilise @owlmeans/mongo et @owlmeans/mongo-resource. Déclare le schéma et les entrypoints dans sources/common, enregistre la ressource et les handlers dans sources/api, et ajoute un écran dans sources/web. Suis les consignes installées sur les ressources et sur la réutilisation du code.

Les appels à la ressource peuvent alors ressembler à ceci :

const notes = context.resource<NotesResource>(RES_NOTES)
await notes.create({ id, text, createdAt })
const { items } = await notes.list({ criteria: { ... } })

Ce sont des extraits de l’interface, pas une application complète. Il faut enregistrer dans le projet l’alias de la ressource, son schéma et sa connexion.

Après la modification, redémarre l’app et vérifie que la note est toujours là. Essaie aussi une saisie invalide et une connexion qui échoue. Si les notes appartiennent à différents utilisateurs, teste qu’un utilisateur ne peut pas lire celles d’un autre.

La couche web utilise shadcn UI et Tailwind. La documentation de shadcn explique que son approche consiste à te donner le code source des composants pour que tu travailles dessus. Dans ce projet, l’agent peut examiner et modifier ce code source. C’est toujours à toi de vérifier l’interaction qui en résulte.

Les consignes des packages

La version de juin copiait les consignes dans des répertoires séparés pour chaque agent. On a ensuite supprimé ces sources parallèles. Les consignes de référence du projet se trouvent dans .agents/, avec AGENTS.md à la racine et un pont vers Claude là où c’est nécessaire.

Les packages OwlMeans distribuent leurs consignes via agent-meta/. L’installateur lit ces métadonnées et écrit les skills des packages présents dans le projet. Une skill sur les ressources peut expliquer le framework ; c’est aux instructions de ton projet d’expliquer à quoi servent tes notes.

Une fois les packages concernés mis à niveau, la commande à jour pour ce pas-à-pas est :

npx @owlmeans/agent-skills@^0.1.18-rc.56

Relis la sortie de l’installateur. Des fichiers gérés que tu as modifiés localement peuvent entrer en conflit, et forcer l’écrasement revient à décider du sort de tes propres modifications. L’installateur est destiné aux projets consommateurs ; les monorepos liés du framework ont leur propre workflow de maintenance.

L’illustration originale de juin, avec des fichiers de consignes séparés pour chaque agent

Cette illustration montre l’organisation des répertoires en juin. Pour le workflow révisé, utilise l’organisation partagée sous .agents décrite plus haut.

Ni AGENTS.md ni le format Agent Skills ne garantissent que chaque outil charge automatiquement chaque fichier. Vérifie l’intégration de l’agent avant de compter sur les instructions.

Ce qui reste à ta charge

create-app te donne le squelette Common. OwlMeans ajoute autour de cette fondation un pipeline de rôles de développement. Ce sont deux façons différentes de commencer à travailler avec le même framework.

La commande ne décide pas de ton modèle de données, ne teste pas les permissions et ne fait pas tourner ton service en production. Un build qui passe reste un résultat limité : dans cette configuration, lance bun run typecheck séparément de bun run build.

J’ai construit ce squelette pour ne plus refaire le câblage initial. Il me laisse la partie qui demande réflexion : savoir si la fonctionnalité a sa place là, et si elle marche.

Initialement publié le 17 juin 2026. Révisé le 15 octobre 2026 pour reprendre les versions épinglées à jour des commandes et l’organisation partagée des consignes d’agent.

OwlMeans