J’ai configuré Pi comme agent de code : LSP, MCP, skills et extensions
Ma configuration complète et reproductible de Pi : modèles locaux, LSP, RAG, MCP, codemode, extensions, commandes de session, skills et sécurité.
On me demande régulièrement comment j’ai configuré mon agent de code. La réponse courte tient en une phrase : j’utilise Pi, puis j’ajoute seulement les pièces dont j’ai réellement besoin. La réponse utile, elle, demande un article entier.
Pi n’est pas l’agent le plus spectaculaire à montrer dans une vidéo. Il n’arrive pas avec une salle de contrôle, douze personnages numériques et un bouton censé remplacer une équipe. Il ressemble d’abord à une interface dans un terminal. C’est précisément ce qui m’a plu : au lieu de m’imposer une usine, il me donne un noyau petit, compréhensible et extensible.
Pourquoi le minimalisme compte plus qu’une longue liste de fonctions
J’ai déjà connu ce scénario avec beaucoup de logiciels. Au début, un programme accomplit très bien une tâche. Puis chaque version ajoute un lecteur, un convertisseur, un synchroniseur, un assistant, un magasin et trois panneaux dont personne ne se souvient. Le logiciel finit par démarrer comme un petit système d’exploitation alors que je voulais seulement graver un disque, éditer un fichier ou lancer une commande.
Pi adopte la logique inverse. Cela me rappelle ce que j’aime dans une distribution Linux minimale : la base ne prétend pas deviner mon environnement idéal. Je construis progressivement celui qui me convient. Cette sobriété n’est pas une coquetterie esthétique. Moins l’agent charge de règles, d’outils et de serveurs inutiles, plus je comprends ce qu’il fait, moins je gaspille de tokens et plus il est facile de trouver la cause d’un comportement étrange.
Il faut cependant être honnête : « minimal » ne signifie pas « magiquement simple ». Un outil extensible me laisse aussi choisir, installer et maintenir ses extensions. Pi me convient parce que j’aime connaître la mécanique. Si vous cherchez un produit entièrement préconfiguré, cette liberté peut ressembler à du travail supplémentaire.
Installation et espace de travail
L’installation officielle tient dans une commande sous macOS ou Linux. Comme toujours avec un script distant, je conseille de consulter sa provenance avant de l’exécuter :
curl -fsSL https://pi.dev/install.sh | sh
On peut aussi passer par npm — avec une version récente de Node.js — et une procédure séparée existe pour Windows natif. Une fois installé, je vérifie immédiatement la version, je me place dans le répertoire du projet, puis je lance Pi depuis cet endroit. Le dossier de départ compte : il sert à découvrir les instructions et à regrouper les sessions.
pi --version
cd /chemin/vers/le-projet
pi
La configuration montrée ici correspond à Pi 1.0.4, la version employée pendant mon essai. Le projet évolue vite : la commande pi update met à jour une installation effectuée avec le script, alors qu’une installation npm ou Nix se met à jour avec son propre gestionnaire. C’est un petit détail, mais il évite de croire qu’une fonction manque alors qu’on lance simplement une vieille version.
Pi fonctionne dans le terminal, mais le terminal n’est pas un détail. J’utilise Kitty et ses onglets pour séparer mes projets, puis Zellij à l’intérieur de chaque onglet. Je garde souvent le code dans un panneau, Pi dans un deuxième, le processus de développement dans un troisième, puis les tests, les logs ou un environnement distant dans un quatrième. Je vois ainsi immédiatement si la modification compile, si le serveur redémarre et si les erreurs changent pendant que l’agent travaille.
Ce n’est pas une obligation : tmux, un terminal classique ou celui de l’éditeur font très bien l’affaire. L’idée n’est pas de reproduire mon écran au pixel près, mais d’éviter le terminal unique où Pi, le serveur et les tests s’écrasent mutuellement. Un agent devient beaucoup plus agréable lorsque son travail reste observable.
La configuration utilisateur se trouve dans ~/.pi/agent/. Pi peut aussi lire une configuration propre au projet. Cette séparation est saine : mes préférences personnelles et mes identifiants ne doivent pas finir dans le dépôt, tandis que les règles d’architecture et les commandes de test doivent pouvoir être partagées avec l’équipe.
| Élément | Rôle | Ma règle |
|---|---|---|
auth.json | Identifiants et tokens d’accès des fournisseurs | Privé, permissions strictes, jamais dans Git |
models.json | Points d’accès compatibles et modèles personnalisés ou locaux | Seulement si les fournisseurs intégrés ne suffisent pas |
settings.json | Réglages généraux de l’interface et du comportement | Peu de changements à la fois |
keybindings.json | Raccourcis de l’interface terminal | Utile seulement après avoir identifié mes gestes fréquents |
mcp.json | Serveurs MCP disponibles | Un serveur doit répondre à un besoin identifié |
SYSTEM.md | Remplacement complet du prompt système | Je n’y touche presque jamais |
APPEND_SYSTEM.md | Complément au prompt système | Pour un comportement général réellement transversal |
AGENTS.md | Contexte, règles et commandes du projet | Mon point de départ habituel |
extensions/, skills/, prompts/, themes/ | Capacités, procédures, modèles de prompt et apparence | Je les ajoute après avoir rencontré le besoin plusieurs fois |
Au niveau du projet, les réglages exécutables vivent plutôt dans .pi/ : .pi/settings.json, .pi/mcp.json, les extensions, skills, prompts et thèmes locaux. Pi ne charge cette configuration qu’après la décision de confiance du projet. Les fichiers de contexte, eux, sont découverts dans le répertoire courant et ses parents. Après une modification manuelle, /reload recharge les ressources sans imposer un redémarrage complet.
L’arborescence exacte peut évoluer avec Pi. Je vérifie donc toujours la documentation de la version installée au lieu de recopier aveuglément une configuration trouvée six mois plus tôt.
Le modèle d’abord, les accessoires ensuite
Un agent sans modèle n’est qu’une jolie boucle d’outils. La première vraie étape consiste donc à connecter le fournisseur avec /login, puis à choisir le modèle avec /model. Le niveau de raisonnement se règle avec /thinking lorsque le modèle le prend en charge.
Pour un fournisseur intégré, je préfère ce parcours plutôt que de fabriquer immédiatement un gros models.json. Ce fichier devient utile pour un endpoint compatible, un modèle servi localement par Ollama, LM Studio ou vLLM, ou une infrastructure interne. Local ne veut d’ailleurs pas forcément dire rapide : un petit modèle peut suffire pour chercher ou classer, mais une refactorisation à travers un monorepo demande beaucoup plus de raisonnement et de contexte.
Voici un exemple volontairement minimal pour Ollama. La clé est factice — Ollama l’ignore — et l’adresse pointe vers la machine locale. Pour un endpoint authentifié, je référence une variable d’environnement au lieu d’inscrire le secret en clair.
{
"$schema": "https://pi.dev/schemas/models.schema.json",
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"models": [
{ "id": "qwen2.5-coder:7b" }
]
}
}
}
Le nom du modèle ne suffit pas. Il faut aussi respecter ses capacités, sa fenêtre de contexte et ses niveaux de raisonnement. Certains proposent seulement low, medium et high ; d’autres ajoutent xhigh ou max. Pi limite normalement /thinking aux niveaux déclarés par le modèle. Dans le sélecteur, Ctrl+S sauvegarde le modèle ou le niveau par défaut, tandis que Ctrl+P permet de parcourir rapidement les modèles autorisés. Une session mémorise aussi les changements de modèle : la reprendre restaure son choix sans modifier le défaut des nouvelles sessions.
Je ne mets jamais une clé d’API dans AGENTS.md ni dans un exemple destiné au dépôt. Les identifiants restent dans le mécanisme prévu pour eux. Cela semble évident, mais les agents lisent précisément les fichiers qu’on leur donne : une clé écrite « temporairement » dans une consigne finit très vite dans une session, un log ou un commit.
Pourquoi je laisse le prompt système tranquille
La tentation est forte de réécrire immédiatement SYSTEM.md pour obtenir un agent « parfait ». C’est aussi une bonne manière d’effacer des instructions que Pi utilise pour ses outils et son interface. Je ne remplace le système que si je sais exactement ce que je veux retirer et quelles conséquences j’accepte.
Dans la plupart des projets, AGENTS.md suffit. J’y décris l’architecture, les commandes, les conventions, ce qui est interdit et la définition d’un travail terminé. Une règle générale peut aller dans le fichier utilisateur ; une règle du dépôt reste dans le dépôt. Je gagne ainsi un agent cohérent sans transformer son moteur.
# Projet
- Lire le code existant avant de proposer une architecture.
- Lancer les tests concernés après chaque modification.
- Ne jamais modifier les migrations déjà déployées.
- Présenter le diff et les risques avant toute action irréversible.
- Utiliser les commandes définies dans package.json.
LSP : la première extension que j’installe
Si je devais conserver une seule amélioration pour le travail de code, ce serait le Language Server Protocol. Sans LSP, l’agent inspecte le projet avec la recherche textuelle, lit des fichiers et déduit les relations. C’est utile, mais il reste en partie aveugle à la structure comprise par le compilateur et l’éditeur.
Avec un serveur de langage, il peut demander où un symbole est défini, quelles références pointent vers lui, quel type est attendu, quelles erreurs existent et quels fichiers seront touchés par un renommage. Pour TypeScript, il faut le serveur TypeScript ; pour Go, gopls ; pour chaque langage, le composant approprié. L’extension Pi ne remplace pas ce serveur : elle lui donne accès à ses réponses.
C’est un montage en deux couches que j’avais insuffisamment expliqué. Il faut d’abord installer le vrai serveur du langage sur la machine, puis l’extension qui expose ses fonctions à Pi. Installer uniquement l’extension ne fait pas apparaître gopls, typescript-language-server, Pyright ou rust-analyzer par magie.
pi install npm:pi-lsp-extension
# puis, dans Pi
/reload
/lsp doctor
Le nom et les options de l’extension peuvent évoluer, et plusieurs implémentations LSP existent dans le catalogue. Je vérifie donc sa source et je choisis celle qui correspond à mon langage. Le contrôle utile est simple : le serveur doit apparaître actif, puis une demande de définition, de références ou de diagnostics doit réellement déclencher l’outil LSP. Le simple fait d’avoir installé un paquet ne prouve pas que l’agent s’en sert.
La différence n’est pas théorique. Sur une recherche de références, un grep avait retrouvé trente occurrences. Le LSP en a identifié trente-cinq réparties dans trois fichiers, parce qu’il comprenait le symbole et pas seulement sa chaîne de caractères. Cinq références oubliées suffisent largement à transformer un renommage « simple » en bug du vendredi soir.
Le LSP ne rend pas le modèle infaillible. Il lui fournit simplement une carte plus exacte. Je lui demande encore de lire les implémentations, de lancer les tests et de me montrer le diff. Mais je préfère un agent qui interroge la carte du compilateur à un agent qui devine les routes en regardant les enseignes.
RAG : utile pour la connaissance, pas comme décoration
La recherche textuelle répond bien à « où apparaît cette fonction ? ». Elle répond moins bien à « quels documents expliquent notre politique de rétention ? » lorsque les textes emploient des mots différents. C’est là qu’un système RAG peut devenir intéressant.
Le principe est simple : les documents sont découpés, convertis en vecteurs puis stockés dans une base adaptée, par exemple Qdrant. La question subit la même transformation. La recherche ramène les passages sémantiquement proches, même lorsqu’ils ne contiennent pas exactement les mots de la requête. Pi peut ensuite les utiliser comme contexte.
J’ai relié ce type de service via MCP, avec quelques actions claires : ajouter des documents, rechercher, supprimer et vérifier l’état. Cela fonctionne bien pour une documentation volumineuse, des décisions techniques, un corpus de procédures ou plusieurs dépôts. Pour un petit projet de vingt fichiers, c’est souvent une complication inutile. Le LSP et une recherche classique y sont plus simples, plus frais et plus faciles à contrôler.
À quoi ressemble mon RAG local
Mon installation n’est pas un nuage mystérieux. Qdrant tourne dans Docker comme base vectorielle. Un petit service RAG, lancé à côté du serveur de modèles, convertit les documents en embeddings et expose quelques opérations : ajout, recherche, suppression et contrôle de santé. Un serveur MCP traduit ensuite ces opérations en outils que Pi peut appeler. Je peux voir les processus, redémarrer le service et interroger Qdrant indépendamment de l’agent.
Pi
└─ MCP local-rag
└─ service RAG
├─ embeddings
└─ Qdrant dans Docker
Dans mon cas, ce RAG sert aussi à filtrer un grand flux de publications. Une recherche littérale de « fourgon rose » ne remontera pas forcément un texte parlant d’un « camion rouge », alors que la proximité sémantique peut juger les deux sujets voisins. J’utilise ce principe pour comparer les contenus à mes centres d’intérêt, puis les classer. C’est un bon exemple de ce que le RAG apporte réellement : non pas une mémoire magique, mais une récupération par sens.
Mon jeu de serveurs MCP, et pourquoi je ne les active pas tous
MCP fournit une manière commune d’exposer des outils et des ressources à l’agent. C’est pratique, donc l’écosystème donne vite envie d’en installer quinze. Je résiste à cette envie. Chaque serveur ajoute des descriptions, des permissions, des dépendances, parfois des secrets et une nouvelle façon d’échouer. Mon fichier mcp.json n’est pas une collection : c’est une boîte à outils de travail.
Les versions actuelles de Pi savent gérer MCP directement. Un serveur peut être global dans ~/.pi/agent/mcp.json ou local au projet dans .pi/mcp.json. Voici le cycle que j’utilise pour ne pas confondre « écrit dans le JSON » avec « fonctionnel » :
pi mcp add -l docs --url https://example.com/mcp \
--bearer-token-env-var DOCS_TOKEN
pi mcp list
# dans une session déjà ouverte
/reload
/mcp
pi mcp list se connecte aux serveurs activés et affiche les outils ou les erreurs. Dans Pi, /mcp sert à inspecter les connexions, relancer un serveur, se connecter par OAuth et changer son exposition. Je garde les outils ordinaires en mode codemode, les petits outils fréquemment utilisés en direct, les gros catalogues en deferred et tout ce qui est dangereux ou inutile en hidden. Cette distinction limite la quantité de descriptions envoyées au modèle.
Context7 pour la documentation actuelle
Le modèle connaît peut-être bien une bibliothèque, mais sa mémoire correspond à un état passé. Une méthode a pu changer de nom, une option a disparu ou un exemple ancien ne compile plus. Context7 permet à l’agent de récupérer la documentation actuelle d’une bibliothèque au moment où il en a besoin. Cela évite une catégorie particulièrement agaçante d’hallucinations : le code parfaitement plausible qui appelle une API inexistante.
SearXNG pour chercher sans piloter un navigateur
J’utilise aussi une instance SearXNG exposée par MCP. L’agent peut lancer une recherche, lire les résultats structurés et croiser plusieurs moteurs sans ouvrir graphiquement un navigateur pour chaque question. Pour vérifier une erreur récente, retrouver une documentation ou comparer plusieurs pistes, c’est beaucoup plus léger.
SearXNG est un métamoteur : selon sa configuration, il agrège notamment des résultats Web, encyclopédiques et issus de dépôts de code. L’appel passe par HTTP et le résultat revient sous une forme structurée, par exemple en JSON. Context7 et SearXNG ne sont donc pas concurrents. Le premier répond à « quelle est l’API actuelle de cette bibliothèque ? » ; le second à « que trouve-t-on aujourd’hui sur cette erreur ou ce sujet ? ».
Cela ne dispense pas de vérifier les sources. Un résultat de recherche n’est pas une vérité et une page Web peut contenir des instructions hostiles destinées aux agents. Je traite le contenu récupéré comme une donnée non fiable, jamais comme une nouvelle règle système.
Chrome DevTools et Playwright ne font pas le même métier
Pour le développement Web, le serveur Chrome DevTools est l’un des ajouts les plus pratiques. L’agent ouvre la page, clique, remplit un champ, inspecte le DOM, lit la console, examine les requêtes réseau, les réponses, les cookies ou le stockage local et prend une capture. Il ne se contente plus d’affirmer que le bouton devrait fonctionner : il peut voir ce qui se passe.
| Chrome DevTools | Playwright |
|---|---|
| Exploration et débogage interactifs | Scénarios reproductibles et automatisés |
| Console, réseau, DOM et stockage pendant le développement | Tests end-to-end et non-régression |
| Comprendre pourquoi la page échoue maintenant | Vérifier que le parcours continuera de fonctionner |
| Conversation souple avec le navigateur | Suite de tests destinée à être rejouée |
Je me sers du premier pour enquêter pendant que je construis, du second pour transformer le comportement attendu en test durable. Les deux peuvent cliquer dans une page, mais ce n’est pas une raison pour les confondre.
PostgreSQL, oui ; Postman, pas forcément
Un accès PostgreSQL limité permet à l’agent de lire le schéma, examiner une requête lente, lancer un EXPLAIN, repérer un index manquant ou préparer une migration. Je lui donne de préférence une connexion de lecture sur un environnement de développement. Un agent qui optimise une requête n’a aucune raison de pouvoir supprimer la base de production.
À l’inverse, je n’ai pas trouvé indispensable d’ajouter un serveur Postman à tous mes projets. Pi sait déjà appeler une API avec les outils du terminal, lire un schéma OpenAPI ou lancer les tests existants. Si l’équipe conserve toute sa vérité dans des collections Postman, l’intégration peut se justifier. Sinon, elle duplique souvent une capacité déjà présente.
Codemode : arrêter de faire un aller-retour pour chaque tournevis
Une succession naïve d’outils ressemble à ceci : le modèle demande une recherche, attend le résultat, réfléchit, demande un fichier, attend encore, puis appelle un serveur MCP. Chaque étape ajoute un aller-retour et gonfle le contexte.
Codemode permet à Pi d’écrire un petit programme JavaScript exécuté dans un environnement contrôlé afin d’orchestrer plusieurs appels. Il peut par exemple interroger deux ressources en parallèle, filtrer les réponses et ne renvoyer au modèle que le résultat utile. Ce n’est pas seulement plus rapide : cela évite de remplir l’historique avec chaque détail intermédiaire.
const [docs, search] = await Promise.all([
tools.mcp__context7__lookup({ library: "next" }),
tools.mcp__search__query({ q: "Next.js current cache behavior" })
]);
return { docs, search };
Le script tourne dans un sandbox QuickJS, sans accès direct à Node.js, au disque ou au réseau : il ne sort que par les outils autorisés. Seul son résultat revient au modèle. C’est important lorsque deux appels produisent chacun des milliers de lignes : le JavaScript peut trier, filtrer et résumer mécaniquement avant de consommer des tokens dans la conversation.
Avec un serveur MCP exposé en mode codemode, Pi active normalement ce mécanisme automatiquement. Pour le garder disponible même sans MCP, je peux l’ajouter dans settings.json :
{
"defaultTools": ["+codemode"]
}
Je garde malgré tout une règle simple : le programme d’orchestration doit rester court et lisible. Si l’agent produit un demi-produit logiciel caché dans un appel d’outil, il devient plus difficile à examiner que la tâche originale.
Les extensions qui ont réellement changé mon usage
L’écosystème d’extensions est l’endroit où Pi passe d’un noyau minimal à mon outil. Voici celles qui ont du sens dans mon organisation, pas une liste obligatoire.
Accéder à un autre dossier sans ouvrir tout le disque
Pi raisonne d’abord depuis son répertoire de travail. L’extension de dossiers supplémentaires sert lorsqu’un projet dépend d’un dépôt voisin, d’un dossier de documentation ou d’un schéma partagé. Je déclare ce chemin expressément au lieu de démarrer Pi trop haut dans l’arborescence. L’agent voit ce dont il a besoin, pas mon répertoire personnel entier.
fzf : recherche floue et multi-grep
L’extension fzf ajoute généralement plusieurs outils : recherche de fichiers, grep flou et recherche sur plusieurs motifs. L’agent peut continuer à employer find ou grep ; fzf devient une option supplémentaire, pas un remplacement forcé. Dans l’interface, le caractère @ ouvre aussi la recherche de fichiers et évite de retaper un chemin long.
Neovim : partir de la ligne où je travaille
Avec l’intégration Neovim, je place le curseur dans une fonction, j’utilise mon raccourci — dans ma configuration, une combinaison autour de la touche leader — et j’ouvre une petite zone de dialogue. Une question comme « explique ce passage » arrive à Pi avec le fichier et la position courante. Ce contexte est beaucoup plus précis que « regarde quelque part dans le contrôleur ».
Subagents : seulement si la séparation apporte quelque chose
Je travaille encore souvent avec un seul modèle. Les subagents deviennent utiles lorsqu’on veut réserver un modèle économique aux recherches simples et un modèle plus solide aux décisions difficiles, ou appeler une capacité spécialisée : image, vidéo, transcription audio ou synthèse vocale. Leur intérêt vient de la séparation des rôles, pas du nombre de petits personnages affichés à l’écran.
Apply patch et Toolwatch : remettre une barrière visible
Pi minimaliste n’interrompt pas chaque modification pour demander la permission. Apply patch convient lorsque je veux examiner le diff avant l’application de chaque changement. Toolwatch joue un rôle voisin pour les outils et commandes : je peux autoriser les opérations courantes, demander une validation pour certaines et bloquer les actions dangereuses. Ces deux extensions ajoutent de la friction, mais c’est précisément la friction que je veux avant une suppression ou une commande touchant l’environnement.
Une extension s’exécute dans le processus de Pi avec les droits de mon utilisateur. Ce n’est pas un petit plugin enfermé par magie derrière une vitre. Je lis le code, je vérifie la provenance et je limite les accès. Installer au hasard une extension qui promet de « rendre l’agent dix fois plus puissant » revient à exécuter le logiciel d’un inconnu sur son poste.
Les sessions sont des arbres, pas de longues bandes magnétiques
Pi conserve ses sessions en JSONL sous ~/.pi/agent/sessions. L’intérêt n’est pas seulement de reprendre une conversation. Une session forme un arbre : je peux revenir à un point antérieur, créer une branche et essayer une autre solution sans jeter tout le travail précédent.
/tree me sert à naviguer ou à bifurquer dans la session existante. /fork crée une session séparée lorsque je veux transformer une piste en travail indépendant. Je peux aussi nommer, cloner, exporter ou reprendre une session. Cette distinction paraît secondaire jusqu’au jour où une refactorisation part dans la mauvaise direction : je préfère revenir proprement au carrefour plutôt que demander au modèle d’oublier mentalement vingt messages.
L’exemple le plus parlant est un essai avec Redis. Je demande à Pi de l’intégrer, il modifie plusieurs fichiers, puis je réalise que cette direction n’était pas la bonne. Avec /tree, je reviens au message situé avant cette décision et je crée une autre branche dans le même fichier de session ; l’ancienne branche reste consultable. Avec /fork, je transforme une entrée antérieure en nouvelle session indépendante. Avec /clone, je copie simplement la branche active telle qu’elle est.
| Commande | Ce qu’elle fait | Quand je l’utilise |
|---|---|---|
/session | Affiche fichier, ID, messages, tokens et coût | Vérifier où je suis avant une opération longue |
/resume | Ouvre une session sauvegardée | Reprendre un projet après avoir quitté Pi |
/new | Démarre une session vierge | Éviter de traîner un contexte devenu inutile |
/tree | Navigue et bifurque dans la session courante | Comparer deux solutions liées |
/fork | Crée une session depuis un ancien message | Transformer une alternative en travail séparé |
/clone | Copie la branche active | Conserver un état exact avant une expérimentation |
/compact | Résume l’ancien contexte | Libérer de la place en préservant les décisions |
/name | Donne un nom lisible à la session | La retrouver parmi les fichiers JSONL |
/export | Exporte en HTML ou JSONL | Archiver ou relire — après contrôle des secrets |
Quand le contexte approche de sa limite, la compaction résume la partie ancienne et libère de la place. Le résumé sert de contexte courant, tandis que les événements d’origine restent dans la session. Ce n’est pas une mémoire parfaite : une nuance peut disparaître dans la synthèse. Pour les décisions importantes, je les inscris dans le dépôt — ADR, ticket, documentation ou AGENTS.md — au lieu de compter sur une conversation infinie.
La limite dépend du modèle : 128 000, 256 000 tokens, parfois davantage. Pi compacte normalement automatiquement, mais /compact permet d’indiquer ce que le résumé doit absolument conserver. Je garde aussi en tête que le JSONL original contient les prompts, appels d’outils, sorties de commandes et parfois le contenu de fichiers. Une session exportée n’est donc pas un document anodin à publier sans relecture.
Un AGENTS.md racine, puis des règles locales
Dans un monorepo, un unique fichier de deux cents lignes devient vite aussi pénible qu’une documentation absente. Pi peut combiner des instructions situées à plusieurs niveaux. Je garde donc les règles communes à la racine, puis j’ajoute les particularités près du code concerné.
monorepo/
├── AGENTS.md # architecture, Git, commandes communes
├── apps/
│ ├── web/AGENTS.md # Next.js, accessibilité, tests UI
│ └── admin/AGENTS.md # React, droits et composants internes
└── services/
└── api/AGENTS.md # Go, migrations et tests d’intégration
Les fichiers locaux complètent les règles parentes. Pi reconnaît aussi les variantes CLAUDE.md et AGENTS.override.md ; cette dernière remplace le fichier de contexte du même dossier, mais n’efface pas les instructions héritées des dossiers parents. Une équipe peut ainsi imposer partout la création de tests et, dans l’API seulement, préciser comment générer une migration.
Je garde ces documents concrets : versions de Next.js ou React, TypeScript strict, interdiction de any, préférence pour les composants serveur, commandes exactes, répertoires, contraintes et exemples courts. Les sermons de trente lignes sur la « qualité du code » aident beaucoup moins qu’une commande de test correcte.
Les skills : transformer une habitude en procédure
Une skill est essentiellement une instruction réutilisable que l’agent charge lorsqu’une tâche correspond. J’en crée une après avoir répété plusieurs fois le même processus : préparer une migration, publier une version, analyser un échec CI, contrôler une page avant mise en production ou rédiger une note de changement.
La bonne skill ne dit pas seulement « déploie l’application ». Elle décrit les préconditions, l’ordre des contrôles, les commandes, les critères d’arrêt et les éléments à rendre à la fin. Elle doit permettre à un collègue de comprendre le processus, même sans agent.
Je me méfie des énormes collections téléchargées en bloc. Elles remplissent l’environnement d’hypothèses qui ne correspondent pas à mon infrastructure et elles constituent du code ou des instructions non fiables. Trois skills courtes, écrites pour mon projet et entretenues avec lui, valent mieux que trois cents recettes mystérieuses.
Packages : partager une configuration devenue stable
Quand un ensemble a fait ses preuves, un package Pi peut regrouper extensions, skills, prompts et thèmes. C’est pratique pour retrouver le même environnement sur plusieurs machines ou pour fournir une base commune à une équipe.
Je ne commence pas par le package. Je commence par le problème, j’ajoute l’outil, je l’utilise, je retire ce qui ne sert pas, puis seulement je l’emballe. Sinon, je transforme des choix encore flous en standard interne et tout le monde hérite de mes essais.
Le point que les démonstrations sautent souvent : la sécurité
Pi peut lire, modifier et exécuter avec les permissions du compte qui l’a lancé. Par défaut, il ne faut pas imaginer une frontière de sandbox impénétrable ni une confirmation automatique avant chaque commande. C’est un outil de développement puissant, donc le rayon d’action est réel.
Je le traite comme un collègue technique très rapide qui pourrait mal comprendre une phrase :
- travail sous Git et sauvegardes disponibles ;
- secrets réduits au strict nécessaire, jamais de trousseau complet ;
- compte dédié, conteneur ou VM lorsque le projet est sensible ;
- connexion de base de données en lecture seule pour l’analyse ;
- diff relu avant merge et tests exécutés ;
- commandes destructrices bloquées ou soumises à validation ;
- contenu Web, issues et fichiers externes considérés comme non fiables.
Le dernier point concerne l’injection de prompt. Une page ou un ticket peut contenir une phrase destinée à convaincre l’agent d’ignorer ses règles ou d’exfiltrer un secret. Pour moi, un document consulté est une pièce à analyser, pas quelqu’un qui obtient soudain le droit de commander le terminal.
La configuration que je recommande pour commencer
Après tous ces outils, la meilleure installation initiale paraît presque décevante. C’est bon signe.
- Installer Pi et connecter un seul modèle.
- Créer un
AGENTS.mdcourt avec les commandes et limites du projet. - Installer le serveur LSP du langage et vérifier qu’il répond.
- Travailler quelques jours avec les outils intégrés.
- Ajouter un serveur MCP seulement lorsqu’un manque revient clairement.
- Transformer les procédures répétées en skills.
- Emballer l’ensemble dans un package après stabilisation.
Cette progression évite un problème fréquent : lorsqu’un agent possède dès le premier jour deux moteurs de recherche, trois navigateurs, quatre mémoires et dix bases de données, je ne sais plus quel composant a produit une réponse ni pourquoi le contexte coûte autant de tokens.
Quand je n’utilise pas Pi
Si la tâche est déterministe, connue et répétée sans ambiguïté, j’écris un script ou un test. Renommer toujours le même fichier, vérifier un port, sauvegarder un répertoire ou appeler une API avec des paramètres fixes n’a pas besoin d’un modèle qui raisonne à chaque exécution.
Pi devient intéressant lorsque je dois naviguer dans un code inconnu, relier plusieurs sources, choisir entre des options, expliquer un échec ou faire évoluer un changement après les résultats des tests. Autrement dit, je l’utilise pour l’incertitude contrôlée, pas comme remplacement coûteux de chaque commande shell.
Ce que j’ai finalement construit
Mon Pi n’a plus grand-chose d’une installation vide. Il comprend le code grâce au LSP, consulte de la documentation actuelle, interroge une recherche, observe le navigateur, explore certaines bases, délègue des sous-tâches et sait reprendre une branche de conversation. Pourtant, l’ensemble reste lisible parce que chaque pièce répond à une raison précise.
C’est là que le minimalisme devient vraiment intéressant. Il ne consiste pas à rester avec le moins de fonctions possible. Il consiste à pouvoir expliquer pourquoi chaque fonction est là, quelles données elle voit et ce qui se passe quand elle tombe en panne.
Je ne cherche donc pas le meilleur agent dans l’absolu. Je cherche un outil que je peux façonner, inspecter et arrêter. Pi me convient parce qu’il commence petit et me laisse décider jusqu’où il grandit. Dans un monde où chaque logiciel veut devenir une plateforme totale, cette modestie est presque une fonction premium.
Références techniques
- Pi : installation et prise en main
- Pi : fichiers et niveaux de configuration
- Pi : fournisseurs, modèles et niveau de raisonnement
- Pi : serveurs MCP et exposition des outils
- Pi : fonctionnement de codemode
- Pi : sessions, branches, export et contexte
- Pi : extensions
- Catalogue Pi : extension LSP utilisée dans ce guide
- Pi : skills
- Pi : sessions et compaction du contexte
- Pi : modèle de sécurité
Discussion
Commentaires
Aucun commentaire pour le moment. Vous pouvez ouvrir la discussion avec une question ou un retour d’expérience.