Aller au contenu

Fichiers d'instructions pour l'IA

Chaque assistant attend ses règles dans un fichier différent. Claude Code lit CLAUDE.md, Cursor lit .cursorrules, Windsurf lit .windsurfrules, Copilot lit .github/copilot-instructions.md, et la convention multi-fournisseurs est AGENTS.md. Maintenir les mêmes instructions dans cinq fichiers est le meilleur moyen d’en avoir quatre obsolètes.

rebase init génère les cinq — sous forme de pointeurs vers un fichier unique que vous modifiez réellement :

your-project/
├── ai-instructions.md ← the real content
├── CLAUDE.md ← pointer
├── AGENTS.md ← pointer
├── .cursorrules ← pointer
├── .windsurfrules ← pointer
└── .github/
└── copilot-instructions.md ← pointer

Chaque fichier pointeur comporte trois lignes :

# Rebase AI Rules
Please refer to and follow the instructions defined in [ai-instructions.md](./ai-instructions.md).
The Rebase skills for this assistant live in `.claude/skills/`. If they are not there yet, install them, with the Rebase MCP server: `rebase skills install --agent claude --mcp`.

Sur la 0.23, la troisième ligne se contente de dire à l’assistant de lancer rebase skills install --agent claude, et le .mcp.json ci-dessous démarre le serveur avec npx -y @rebasepro/mcp depuis le registre.

Les autres ne diffèrent que par le répertoire de skills de l’agent et sa valeur --agent — --agent cursor, --agent windsurf, --agent codex, --agent copilot — et par le chemin relatif, qui est ../ai-instructions.md dans .github/copilot-instructions.md et ai-instructions.md dans AGENTS.md. La troisième ligne est conditionnelle parce que rebase init --agent a pu déjà installer les skills avant que l’assistant ne la lise.

Cela se produit lors de chaque rebase init, pour chaque preset y compris --headless. Il n’y a aucun flag ni aucune invite.

rebase init écrit également .mcp.json, qui pointe Claude Code, Cursor et n’importe quel autre client MCP vers le serveur MCP Rebase — sa propre copie du projet, une devDependency épinglée avec la CLI (npx --no rebase-mcp dans un projet npm) :

{
"mcpServers": {
"rebase": {
"command": "pnpm",
"args": ["exec", "rebase-mcp"],
"env": {
"REBASE_PROJECT_DIR": "."
}
}
}
}

REBASE_PROJECT_DIR vaut ".", pas un chemin absolu : le client lance le serveur à la racine du projet, et un chemin absolu est la seule ligne de ce fichier qui ne peut pas être commitée. Il est là parce que ~/.rebase/projects.json vaut pour toute la machine — un projet qui ne nomme aucun répertoire retombe sur ce que le dernier projet de cette machine y a enregistré. Voir la priorité.

Les fichiers pointeurs sont délibérément dépourvus de contenu. Les assistants suivent les liens Markdown relatifs, ainsi un fichier de trois lignes désignant le fichier réel produit le même résultat qu’une copie — avec des avantages qu’une copie n’a pas :

  • Un seul fichier à éditer. Les règles ne peuvent pas diverger entre les assistants, car il n’existe qu’un seul ensemble de règles.
  • Un seul diff à relire. Une modification des conventions du projet concerne un seul fichier, et non cinq fichiers identiques qu’un relecteur doit comparer.
  • Ajouter un assistant ne prend que trois lignes. Un nouvel outil avec un nouveau nom de fichier reçoit un pointeur, et non une sixième copie de vos conventions.

Ce modèle vaut la peine d’être conservé si vous forkez le modèle de base (scaffold), et mérite d’être adopté dans des dépôts qui ne sont pas du tout des projets Rebase.

Le fichier généré est délibérément court — il renvoie à rebase skills install pour plus de détails, puis énonce les règles que les assistants ne respectent pas assez souvent pour qu’il soit utile de les répéter au début de chaque session :

  1. Schéma en tant que code. Les collections sont définies dans config/collections/. Ne modifiez jamais manuellement le schéma Drizzle généré ni les tables Postgres — voir Schéma en tant que code.
  2. La façon d’appliquer un changement de collection dépend de la base de données. Tant que pnpm dev tourne, enregistrer le fichier de la collection est toute l’étape : le démarrage régénère le schéma Drizzle et crée les tables et colonnes manquantes. pnpm db:push ne sert qu’à ce que le démarrage laisse délibérément de côté — une colonne renommée, un type restreint, un champ supprimé — sur la base de données de développement gérée comme sur votre propre PostgreSQL. En production, c’est pnpm db:generate puis pnpm db:migrate. Depuis 0.25 En 0.24, pnpm db:push exige votre propre PostgreSQL, et le fichier le dit.
  3. Utilisez le SDK. Passez par rebase.dataAsAdmin.<slug> pour le travail effectué sous l’identité du service, ou par getDriver(c) dans une fonction lorsque la lecture doit s’exécuter en tant qu’appelant. Le client serveur n’expose pas d’accesseur data simple ; le SQL brut et les appels Drizzle directs contournent la validation, les callbacks et le RLS.
  4. Protégez chaque route personnalisée. Les routes dans backend/functions/ sont montées sans authentification. Utilisez requireAuth / requireAdmin de @rebasepro/server/functions dans l’emplacement middleware propre à la route — lire c.get("user") n’est pas une protection, tout comme app.use() placé après la route.

Cette dernière règle est essentielle. C’est la différence entre un middleware qui s’exécute et un qui ne s’exécute pas, et un assistant qui n’a pas été prévenu écrira systématiquement la version qui ne s’exécute pas — voir Fonctions personnalisées.

requireAdmin n’admet que le rôle admin. Quand un rôle plus restreint ou une clé API doit pouvoir appeler une route, la garde à ajouter est requireScope, avec une portée que l’application déclare — voir Rôles et portées.

ai-instructions.md est votre fichier. Rien ne le régénère ni ne l’écrase — contrairement aux skills installés, qui sont remplacés à chaque rebase skills install. Les conventions spécifiques au projet ont leur place ici.

Ce qui mérite d’y figurer est ce qu’un assistant ne peut pas déduire du code : quelles collections sont héritées (legacy), quel service gère quelle table, la convention de nommage qui n’est appliquée nulle part, la migration qui ne doit pas être réexécutée. Restez concis — les instructions chargées à chaque requête concurrencent la tâche en cours pour l’attention de l’IA, et un fichier trop long sera simplement survolé.

Et gardez la limite à l’esprit : ce fichier détermine ce qu’un assistant écrit. Il n’a aucun impact sur ce qu’un agent connecté à votre base de données peut faire — cela dépend des identifiants dont il dispose, et aucun contenu Markdown ne peut changer cela. Consultez le modèle d’identifiants du serveur MCP.