Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- Node.js 20 or newer
{
"mcpServers": {
"mindset-red": {
"command": "npx",
"args": [
"-y",
"mindset-ctx"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Oct 26, 2026Mindset-Red · mindset-ctx
Context-as-a-Service pour projets open source & micro-SaaS.
Pour n'importe quel repo GitHub, mindset-ctx :
- génère et maintient automatiquement le contexte dont les agents IA ont besoin :
CLAUDE.md,AGENTS.md,docs/ARCHITECTURE.md,CONTRIBUTING.mdet des templates de prompts (.context/prompts.md) ; - expose une API et un CLI pour que les outils IA (Claude Code, Cursor, …) aient toujours le bon contexte, à jour ;
- ajoute un memory layer : l'historique du repo (commits aujourd'hui, PRs/issues/discussions demain) est indexé en JSONL et interrogeable, pour que chaque agent réutilise les décisions passées au lieu de les re-découvrir.
Installation
Via npm (recommandé) :
npm install -g mindset-ctx # ou : npx mindset-ctx <commande>
ctx generate .
Depuis le repo (pour contribuer ou suivre main de près) :
git clone https://github.com/Redcreator1/Mindset-Red
cd Mindset-Red
npm install
npm run build
node dist/cli.js generate .
Node ≥ 20. Une seule dépendance runtime : le SDK officiel @anthropic-ai/sdk
(utilisé uniquement par le mode --ai, optionnel à l'exécution). Tous les
exemples ci-dessous utilisent node dist/cli.js (installation depuis le
repo) — remplacez par ctx si vous avez installé via npm.
Utilisation
# Générer / rafraîchir tout le contexte d'un repo
node dist/cli.js generate [path]
# Indexer l'historique git dans le memory layer (.context/memory.jsonl)
node dist/cli.js index [path] --limit 500
# … et y ajouter les PRs, issues et discussions via l'API GitHub
# (owner/repo déduit du remote origin, ou --repo owner/name ;
# GITHUB_TOKEN pour les repos privés / plus de rate limit)
node dist/cli.js index [path] --github
# … ou via l'API GitLab (issues + merge requests ; GITLAB_TOKEN pour privé)
node dist/cli.js index [path] --gitlab
# … ou via l'API Bitbucket Cloud (pull requests + issues ; BITBUCKET_TOKEN pour privé)
node dist/cli.js index [path] --bitbucket
# … et calculer les embeddings pour la recherche sémantique
# (Voyage AI, le partenaire embeddings d'Anthropic ; VOYAGE_API_KEY requis)
node dist/cli.js index [path] --embed
# Chercher dans la mémoire depuis le terminal
# (BM25 par défaut, --semantic pour les embeddings, --hybrid pour la fusion RRF)
node dist/cli.js search "payment retry" --repo-path [path] --hybrid
# Servir un ou plusieurs repos en HTTP pour les outils IA
node dist/cli.js serve [path ...] --port 4870 --api-key SECRET
# Mode hébergé multi-tenants : clés par client, scopes par repo, quotas
node dist/cli.js serve repoA repoB --tenants ctx.tenants.json
# Webhooks GitHub temps réel : à chaque push/PR/issue, la mémoire est
# ré-indexée et le contexte régénéré (signature HMAC vérifiée)
node dist/cli.js serve [path] --webhook-secret SECRET
# GitHub App : imprime le manifest pour une création en un clic
node dist/cli.js app manifest --base-url https://mon-hote.example.com
# Encaisser : génère une clé tenant + un lien de paiement Stripe
CTX_STRIPE_API_KEY=sk_live_... STRIPE_PRICE_MAP='{"price_123":"pro"}' \
node dist/cli.js checkout --plan pro
# Facturation Stripe : les webhooks d'abonnement font basculer le plan
# d'un tenant (free/pro/team/enterprise → quotas), persisté sur disque
STRIPE_PRICE_MAP='{"price_123":"pro"}' \
node dist/cli.js serve [path] --tenants ctx.tenants.json --stripe-secret whsec_...
# Génération enrichie par Claude : une synthèse narrative du projet est
# rédigée par Claude Opus 4.8 (thinking adaptatif) et injectée dans
# CLAUDE.md et docs/ARCHITECTURE.md (nécessite ANTHROPIC_API_KEY)
node dist/cli.js generate [path] --ai
# Voir l'analyse brute du repo (JSON)
node dist/cli.js analyze [path]
# Serveur MCP (Model Context Protocol) en stdio : Claude Code / Cursor
# consomment le contexte et la mémoire comme des outils natifs
node dist/cli.js mcp [path]
MCP (Model Context Protocol)
ctx mcp expose trois outils via le standard MCP :
| Outil | Description |
|---|---|
get_context | Lit un fichier de contexte (claude, agents, architecture, contributing, prompts) |
search_memory | Recherche BM25 dans le memory layer (commits, PRs, issues) |
analyze_repo | Analyse structurée fraîche du repo |
Enregistrement dans Claude Code :
claude mcp add mindset-ctx -- node /chemin/vers/dist/cli.js mcp /chemin/vers/repo
Enregistrement dans Cursor — Cursor parle MCP nativement, aucun code
supplémentaire n'est nécessaire côté mindset-ctx. Ajoutez dans
.cursor/mcp.json (à la racine du projet, ou dans les réglages MCP globaux
de Cursor) :
{
"mcpServers": {
"mindset-ctx": {
"command": "node",
"args": ["/chemin/vers/dist/cli.js", "mcp", "/chemin/vers/repo"]
}
}
}
Rechargez la fenêtre (ou redémarrez Cursor) — le serveur apparaît dans
Settings → MCP, et get_context/search_memory/analyze_repo deviennent
des outils que l'agent Cursor peut appeler directement pendant une session de
vibe coding. (Le nom exact du fichier de config peut évoluer selon la version
de Cursor — vérifiez leur doc officielle MCP si l'emplacement a changé.)
Extension VS Code (editors/vscode/, publiée sur le VS Code Marketplace
sous mindset-ctx.mindset-ctx) : palette de commandes ("mindset-ctx: Generate Context Files", "… Index
Memory", "… Copy MCP Server Command", "… Open Hosted Dashboard") + indicateur
dans la barre de statut (CLAUDE.md présent ou non). Se teste en local via
F5 (Extension Development Host) ou en .vsix — voir
editors/vscode/README.md pour le détail, y compris la limite honnête :
la logique pure (construction de commande MCP, texte de statut) est testée
par node:test, mais le code qui appelle l'API vscode elle-même ne l'est
pas — @vscode/test-electron a besoin de télécharger un vrai binaire VS Code
et d'un serveur d'affichage, indisponibles dans ce sandbox.
API
| Route | Description |
|---|---|
GET /v1/health | Liveness (jamais protégée) |
GET /v1/repos | Repos enregistrés (filtrés par le scope du tenant) |
GET /v1/usage | Consommation du tenant appelant (mode --tenants) |
GET /v1/repos/:repo/analysis | Analyse structurée du repo (JSON) |
GET /v1/repos/:repo/context/claude | CLAUDE.md (aussi : agents, architecture, contributing, prompts) |
GET /v1/dashboard · /v1/dashboard/data | Dashboard web (HTML/JSON) : repos, tenants, plans, quotas, mémoire — scopé par tenant |
GET /v1/repos/:repo/memory/search?q=…&mode=… | Recherche BM25 (défaut), sémantique (mode=semantic) ou hybride (mode=hybrid, fusion RRF) |
POST /v1/repos/:repo/webhook | Webhook GitHub ou GitLab (push/issues/PR) : signature X-Hub-Signature-256 ou token X-Gitlab-Token vérifié selon le fournisseur détecté, mémoire ré-indexée, contexte régénéré sur push |
GET /v1/app/manifest | Manifest GitHub App (création en un clic) |
POST /v1/app/webhook | Événements d'installation de l'App (HMAC vérifiée) : provisionne/déprovisionne un tenant automatiquement |
GET /v1/app/installed?installation_id=… | Redirection post-install : remet la clé API du tenant auto-provisionné (une seule fois) |
GET /v1/checkout?plan=pro | Crée un lien de paiement Stripe pour le tenant appelant (porte d'entrée paiement) — refusé (403) à un membre d'équipe non-owner |
GET /v1/billing/portal | Ouvre une session Stripe Customer Portal (annuler, changer de carte, voir les factures — self-service, hébergé par Stripe) pour le tenant appelant — refusé (403) à un membre non-owner, 400 si aucun abonnement Stripe n'existe encore |
POST /v1/stripe/webhook | Événements d'abonnement Stripe (signature vérifiée) → change le plan du tenant (et retient son customer Stripe pour /v1/billing/portal), ou de son organisation si c'est un siège d'équipe |
GET /v1/team/invite?name=… | L'owner invite un coéquipier — clé mintée, quota et plan partagés (organisation), montrée une seule fois |
GET /v1/team/remove?key=… | L'owner retire un coéquipier de l'organisation (pas soi-même) |
GET /v1/sso/login?org=… | Redirige vers la connexion hébergée WorkOS AuthKit (SSO Entreprise) |
GET /v1/sso/callback | Échange le code WorkOS contre l'identité, provisionne organisation/tenant, pose un cookie de session signé |
GET /v1/sso/logout | Efface le cookie de session |
Avec un seul repo servi, les raccourcis sans préfixe (/v1/analysis,
/v1/context/claude, /v1/memory/search) restent disponibles.
Auth : --api-key (ou env CTX_API_KEY) exige
Authorization: Bearer <clé> ou x-api-key: <clé> sur toutes les routes sauf
/v1/health (le webhook, lui, est authentifié par sa signature HMAC).
Multi-tenants (--tenants ctx.tenants.json) :
{ "tenants": [
{ "key": "sk-alice", "name": "alice", "repos": ["frontend"], "plan": "pro" },
{ "key": "sk-ops", "name": "ops", "repos": "*", "plan": "enterprise", "admin": true }
] }
Chaque clé est scopée à ses repos (403 hors scope), le plan décide du quota
journalier (free 200 · pro 5 000 · team 50 000 · enterprise illimité —
429 au-delà), et /v1/usage expose le métering. Les webhooks Stripe font
basculer le plan automatiquement et le changement est persisté dans le fichier.
admin: true doit être posé à la main (jamais déduit du scope "*", que des
comptes clients légitimes utilisent aussi) — c'est ce qui donne la vue
dashboard de toute la plateforme.
Organisations (Team multi-sièges) — le plan Team est multi-utilisateurs
par nature : le signup self-service (/v1/signup?plan=team) crée
automatiquement une organisation et met le premier compte en role: "owner".
Facturation et quota vivent sur l'organisation, pas sur chaque tenant :
{ "tenants": [
{ "key": "sk-owner", "name": "owner", "repos": "*", "orgId": "org-1", "role": "owner" },
{ "key": "sk-bob", "name": "bob", "repos": "*", "orgId": "org-1", "role": "member" }
],
"organizations": [
{ "id": "org-1", "name": "acme", "repos": "*", "plan": "team" }
] }
- Seul
role: "owner"peut appeler/v1/checkout(changer le plan) ou/v1/team/invite//v1/team/remove(gérer les coéquipiers) — unmemberreçoit 403. /v1/usageet le quota journalier sont partagés entre tous les sièges d'une organisation (un pool commun, pas un quota par personne).- Le dashboard d'un owner montre le roster de son organisation ; un
adminexplicite voit toute la plateforme ; tout le monde d'autre ne voit que soi.
SSO (WorkOS AuthKit) — alternative à la clé API partagée pour les équipes
Entreprise : un employé se connecte via GET /v1/sso/login (redirige vers la
connexion hébergée WorkOS — email/mot de passe, Google, ou la connexion SSO
de son entreprise si configurée côté WorkOS), puis /v1/sso/callback :
- Premier employé d'une entreprise (identifiée par l'
organization_idWorkOS) à se connecter → une organisation mindset-ctx est créée automatiquement et cette personne devientrole: "owner". - Employés suivants de la même entreprise → rejoignent la même
organisation en
role: "member", quota partagé, pas de doublon. - Un cookie de session signé (
ctx_session, HttpOnly, 7 jours) authentifie ensuite le dashboard exactement comme une cléAuthorization: Bearerl'aurait fait — pas de nouveau store de session, la signature (HMAC avec la clé API WorkOS) suffit à le vérifier à la volée. - Connexion personnelle sans entreprise WorkOS derrière → simple tenant solo,
plan
free, comme n'importe quel autre onboarding.
Configuration : créer une App sur workos.com (gratuit
pour démarrer), déclarer https://<votre-domaine>/v1/sso/callback comme
redirect URI, puis exposer WORKOS_CLIENT_ID et WORKOS_API_KEY (sk_test_…
en bac à sable, sk_live_… en prod) — --workos-client-id/--workos-api-key
en self-hosted, secrets Cloudflare en hébergé (voir la section déploiement).
Édition manuelle préservée
Chaque fichier généré contient un marqueur ctx:manual. Tout ce que vous
écrivez en dessous est conservé lors des régénérations — le haut du fichier
reste toujours synchronisé avec la réalité du code.
Repos privés — comment les devs l'utilisent
Le mode self-hosted est fait pour les repos privés : l'outil lit le clone local (le tien), donc ton code privé ne quitte jamais ta machine — c'est un argument de confidentialité, pas une limite.
# 1. Dans ton repo privé déjà cloné
node /chemin/dist/cli.js generate . # génère le contexte
node /chemin/dist/cli.js index . # indexe la mémoire
# 2. Branche-le dans Claude Code / Cursor via MCP (local, rien ne sort)
claude mcp add mindset-ctx -- node /chemin/dist/cli.js mcp /chemin/repo/prive
Pour la mémoire des PRs/issues d'un repo privé, ctx index --github utilise ton
GITHUB_TOKEN personnel (scope repo) ; ctx index --gitlab fait pareil côté
GitLab avec GITLAB_TOKEN. Le webhook temps réel (POST /v1/repos/:repo/webhook)
détecte lui-même le fournisseur : signature X-Hub-Signature-256 pour GitHub,
token partagé X-Gitlab-Token pour GitLab — même endpoint, même secret configuré
côté --webhook-secret / CTX_WEBHOOK_SECRET.
En mode hébergé, installer la GitHub App (ctx app manifest) provisionne
automatiquement un tenant scopé aux repos accordés — pas besoin de compte
préalable, symétrique du signup Stripe. La clé est remise sur la page de
redirection /v1/app/installed?installation_id=… juste après l'install.
Pour lire le contenu d'un repo privé ainsi accordé, mint un token
d'installation à la demande :
export GITHUB_APP_ID=123456
export GITHUB_APP_PRIVATE_KEY="$(cat mindset-ctx.private-key.pem)"
node dist/cli.js app token <installation-id> # token 1h, scope = repos accordés
Le token imprimé s'utilise comme n'importe quel token GitHub pour cloner
(git clone https://x-access-token:<token>@github.com/owner/repo.git) ou
appeler l'API REST.
Développement
npm test # build + tests (node:test)
Ce repo est dogfoodé : ses propres CLAUDE.md, AGENTS.md et
docs/ARCHITECTURE.md sont générés par l'outil lui-même.
Roadmap
- v0.1 — analyse de repo, génération des 5 fichiers de contexte, memory layer (commits), API HTTP, CLI
- v0.2 — ingestion GitHub API (PRs, issues, discussions) dans le memory layer
- v0.2 — recherche classée par pertinence (BM25) derrière la même API
- v0.2 — GitHub Actions : CI (Node 20/22) + régénération auto du contexte à chaque push sur
main - v0.2 — serveur multi-repos + auth par clé API (graine du mode hébergé)
- v0.3 — serveur MCP (Model Context Protocol) en stdio : le contexte devient des outils natifs pour Claude Code / Cursor
- v0.3 — génération enrichie par l'API Claude (
generate --ai, SDK officiel, Opus 4.8 + thinking adaptatif) - v0.4 — recherche sémantique par embeddings (Voyage AI,
index --embed+mode=semantic, pluggable à côté de BM25) - v0.4 — webhooks GitHub temps réel : HMAC vérifiée, mémoire ré-indexée et contexte régénéré à chaque push
- v0.4 — multi-tenants : clés par client, scopes par repo, quotas journaliers, métering
/v1/usage - v0.5 — GitHub App packagée : manifest servi (
/v1/app/manifest, création un clic) + webhook d'installation (/v1/app/webhook, HMAC vérifiée, cycle de vie classifié) - v0.5 — facturation Stripe :
POST /v1/stripe/webhook(signature vérifiée sans SDK) fait basculer le plan d'un tenant ; plans → quotas, store de tenants persistant - v0.6 — recherche hybride BM25 + embeddings fusionnés par Reciprocal Rank Fusion (
mode=hybrid,ctx search --hybrid) - v0.6 — dashboard web auto-porté (
/v1/dashboard) : repos, tenants, plans, quotas et mémoire, scopé par tenant - v0.7 — checkout Stripe :
ctx checkout/GET /v1/checkoutcréent un lien de paiement (clé tenant estampée dans les métadonnées) — la porte d'entrée « premier euro » - v0.8 — page pricing publique (
/pricing), signup self-service (/v1/signup?plan=…) etctx stripe bootstrapauto-créent les produits/prix dans Stripe. - v0.9 — hébergé sur Cloudflare Workers (
src/worker/,wrangler.toml) : gratuit (100k req/j), edge, sans carte bancaire, état multi-tenant dans KV..github/workflows/deploy-cloudflare.ymldéploie sur chaque push versmain. - v0.9 —
ctx stripe webhook <url>crée (ou réutilise, idempotent) le webhook Stripe par API — plus besoin d'accéder au Dashboard Stripe à la main. - v0.10 — provisioning automatique par install GitHub App (
/v1/app/webhookcrée/retire le tenant,/v1/app/installedremet la clé) +ctx app token <installation-id>mint un token d'installation (JWT App signé RS256 → échange) pour lire les repos privés accordés. - v0.11 — support GitLab :
ctx index --gitlab(issues + merge requests via l'API v4) et webhook temps réel (X-Gitlab-Token, détection automatique du fournisseur sur le même endpoint que GitHub) - v0.12 — support Bitbucket :
ctx index --bitbucket(pull requests + issues via l'API Cloud v2.0) — ingestion mémoire uniquement ; le webhook temps réel Bitbucket attend une vérification de son mécanisme de sécurité réel avant d'être câblé (Bitbucket n'a pas d'équivalent direct au HMAC GitHub / token GitLab) - v0.12 — déploiement dédié Enterprise :
Dockerfile+docs/DEPLOYMENT.md(Docker Compose, fichier de tenants monté en volume, variables d'env documentées) — ce que/pricingpromettait sans l'avoir construit - v0.12 — doc Cursor :
ctx mcpfonctionnait déjà avec Cursor (MCP natif) mais n'était pas documenté —.cursor/mcp.jsonajouté au README - v0.13 — vitrine du domaine racine (
/,src/home.ts) séparée de/pricing, doc index (/docs) qui pointe vers le README/docs plutôt que de le dupliquer ; runbook de branchement du domaine (docs/DOMAIN-SETUP.md) — au moment de l'achat demindset-ctx.dev, ce n'est plus qu'une opération DNS - v0.14 — Teams multi-sièges : signup Team crée une organisation (facturation + quota partagés, pas par siège) avec le premier compte en
role: "owner";/v1/team/inviteet/v1/team/removegèrent le roster ;/v1/checkoutrefusé aux non-owners ; dashboard scopé (owner → son équipe, admin → toute la plateforme). C'est le prérequis RBAC identifié en v0.13 — désormais construit, sur Node et Cloudflare Workers. - v0.15 — parité GitHub App sur le Worker Cloudflare réellement déployé :
/v1/app/manifest,/v1/app/webhook(HMAC vérifiée via Web Crypto) et/v1/app/installedn'existaient que surserver.ts(self-hosted) depuis la v0.10, malgré ce que le changelog laissait entendre — le Worker en prod n'avait jamais le provisioning auto par install. Corrigé : les trois routes tournent maintenant sur KV (store.findByInstallationId),CTX_WEBHOOK_SECRETpoussé par.github/workflows/deploy-cloudflare.yml. - v0.16 — SSO Entreprise via WorkOS AuthKit :
/v1/sso/login(redirige vers la connexion hébergée),/v1/sso/callback(échange le code, auto-provisionne organisation + tenant à partir de l'organization_id/user.idWorkOS, pose un cookie de session signé),/v1/sso/logout. Premier employé d'une entreprise → owner, suivants → members poolés, symétrique du signup Stripe et de l'install GitHub App. Le cookie de session est vérifié par HMAC (signé avec la clé API WorkOS) sans store de session dédié — cohérent avec l'architecture stateless existante. Parité Node et Cloudflare Workers dès le départ. - v0.17 — extension VS Code (
editors/vscode/) : commandes de palette pour générer le contexte/indexer la mémoire, copier la commande MCP, ouvrir le dashboard hébergé ; indicateur de statut (CLAUDE.mdprésent ou non). Package séparé (son proprepackage.json/tsconfig.json, manifeste VS Code différent du reste du projet). Publiée sur le VS Code Marketplace (mindset-ctx.mindset-ctx, logo inclus depuis la v0.1.1) juste après. 6 tests sur la logique pure ; la partie qui appelle l'APIvscodese vérifie manuellement viaF5, pas par une suite automatisée (@vscode/test-electrona besoin d'un vrai binaire VS Code + d'un display, indisponibles dans ce sandbox). - v0.18 — publication npm (
npm install -g mindset-ctx/npx mindset-ctx) : le CLI ne s'installait jusque-là que par clone GitHub — limite découverte en construisant l'extension VS Code (pas denpxpar défaut possible)..github/workflows/npm-publish.ymlpublie automatiquement à chaque push surmainoù la version a changé (idempotent — ne republie pas une version déjà en ligne).LICENSE(MIT) ajoutée — déclarée danspackage.jsondepuis le début mais jamais présente en tant que fichier.files/types/prepublishOnlyajoutés pour un paquet propre (justedist/+ README + LICENSE, tests exclus). - v0.19 — durcissement sécurité après une revue complète du code : cookie de session passé en
SameSite=Strict(leLaxinitial laissait une fenêtre CSRF sur les routes GET mutantes/v1/team/*et/v1/checkoutdepuis l'arrivée de l'auth par cookie) ; paramètrestateOAuth ajouté au flux SSO WorkOS (nonce en cookie, vérifié au callback en temps constant — bloque le login-CSRF) ; extension VS Code 0.1.2 :execFilesans shell à la place d'execet réglages passés enscope: "machine"(un repo malveillant ne peut plus planter une commande via.vscode/settings.json), défautnpx mindset-ctxmaintenant que le paquet est sur npm. - v0.20 — blog natif (
GET /blog,/blog/:slug) plutôt qu'un embed X/Twitter tiers sur le site : zéro script externe, zéro tracking tiers, visuels de couverture en SVG inline (pas d'image à héberger séparément) dans la même palette que le reste du site. Premier article : présentation de mindset-ctx. Parité Node + Worker. - v0.21 — balises Open Graph / Twitter Card sur
/,/docs,/pricing,/bloget/blog/:slug: un lien partagé sur X/Slack/Discord affiche maintenant un vrai aperçu (titre, description, image) au lieu d'une URL nue. Image de prévisualisation (1200×630) servie parGET /og-image.png, encodée en base64 danssrc/og-image.tsplutôt qu'hébergée comme fichier séparé — fonctionne à l'identique sur le serveur Node et sur le Worker Cloudflare (qui n'a pas de système de fichiers), sans dépendance tierce.og:image/og:urlne sont émis que si unbaseUrlest configuré (sinon on n'imprime pas une URL relative cassée, invalide pour Open Graph). - v0.22 — favicon (
/favicon.svg, même logo que partout ailleurs, redirection depuis/favicon.ico), page 404 stylée (/v1/*garde du JSON pour les clients API, tout le reste voit une vraie page) et robots.txt/sitemap.xml pour l'indexation. Bug réel trouvé et corrigé en construisant la 404 : sur les deux runtimes, une route inconnue tombait dans la porte d'authentification avant d'atteindre le routage — un visiteur non-authentifié sur une URL mal tapée recevait "401 unauthorized" au lieu de "404 not found" dès que l'auth tenant était configurée (le cas permanent du Worker hébergé). Corrigé en sortant la 404 du chemin non-/v1/*avant la porte d'auth, surserver.tsetworker/index.ts. - v0.23 — Rank v0 (
src/rank.ts) : première brique de la Phase 4 ("Moat technique"). Pas un modèle entraîné — un reranker linéaire explicable au-dessus de la fusion RRF existante (hybridSearch), avec des poids réglés à la main (accord des deux moteurs de recherche, correspondance du titre avec la requête, décroissance de fraîcheur). Honnête sur la portée : entraîner un vrai modèle demande un jeu de données de pertinence réel (clics/retours d'usage) et du budget de calcul — ni l'un ni l'autre n'existe encore. Ce qui est livré ici est la partie réelle et testée faisable aujourd'hui : l'interface de scoring, et un reranker qui améliore mesurablement le RRF seul. Les poids sont explicitement la pièce prévue pour être remplacée plus tard par des poids appris. Branché directement danshybridSearch—ctx search --hybridetmode=hybriden profitent automatiquement, aucun nouveau paramètre d'API. - v0.24 — Rank ML (
src/rank-ml.ts,notebooks/train_rank_ml.py) : succède à Rank v0 avec un vrai cross-encoder pré-entraîné (cross-encoder/ms-marco-MiniLM-L-6-v2), fine-tunable sur un T4 gratuit via Colab (notebook fourni) sur des paires faiblement labellisées tirées de l'historique du repo. Node uniquement, décision assumée : notre prod (Cloudflare Workers) n'a ni GPU ni moyen d'exécuter de l'inférence neuronale sans passer par un service payant (Workers AI ou un hébergement externe) — le Worker garde donc Rank v0 pour l'instant, écart de parité documenté plutôt que masqué. Chargement 100% local (CTX_RANK_ML_MODEL_DIR,@huggingface/transformersenoptionalDependencies) : aucun appel réseau au runtime, jamais de HuggingFace au moment de la requête. Repli automatique et silencieux vers Rank v0 si le dossier de modèle est absent ou le chargement échoue — jamais de crash. Honnête sur les limites de vérification : la logique de blend/scoring (mlRerank) est testée (6 tests, reranker simulé) ; le câblage réel du pipeline@huggingface/transformersn'a pas pu être exécuté de bout en bout dans l'environnement où c'est écrit (huggingface.co et les binaires natifs desharp/onnxruntimey sont bloqués par le proxy — confirmé parcurl, même catégorie de blocage que JetBrains) — à vérifier après avoir fait tourner le notebook. Corrigé en route : le notebook utilisait initialement@xenova/transformers(nom historique du projet) et son ancien scriptscripts/convert.py, qui n'existe plus — le projet a déménagé vers@huggingface/transformerset l'export ONNX standardoptimum-onnx, découvert en faisant réellement tourner le notebook et en lisant le vrai README du projet. Bénéfice inattendu du changement de paquet : la vulnérabilité critiqueprotobufjs(transitive viaonnxruntime-web) qu'@xenova/transformerstraînait a disparu avec@huggingface/transformers—npm auditest repassé à 0 vulnérabilité. - v0.25 —
llms.txt(GET /llms.txt, convention llmstxt.org) : carte Markdown du site (résumé, dépôt GitHub, docs, tarifs, legal, blog) pour les agents/crawlers IA qui le lisent avant de crawler le HTML — préparation au référencement dans les annuaires MCP (awesome-mcp-servers, registre officiel MCP, Smithery, mcp.so, glama.ai). Mots-clésmcp/model-context-protocol/mcp-server/cliajoutés àpackage.jsonpour la recherche npm. Mention obsolète corrigée dans le README (l'extension VS Code disait "mindset-ctx pas encore sur npm" — faux depuis la v0.18). Parité Node + Worker. 2 nouveaux tests — 144/144. - v0.26 — Stripe Customer Portal (
GET /v1/billing/portal) : un client (ou l'owner d'une équipe) peut annuler son abonnement, changer de carte ou voir ses factures lui-même, sur une page hébergée par Stripe — jusque-là seul l'opérateur pouvait le faire, à la main, dans le Dashboard Stripe.Tenant/OrganizationgagnentstripeCustomerId, rempli automatiquement par le webhook/v1/stripe/webhook(déjà en place, juste étendu). Même garde d'autorisation que/v1/checkout(tenantCanManageBilling— refusé à un membre d'équipe non-owner) et jamais accessible via le fallback?key=du dashboard : une session portal, une fois son lien en main, permet d'annuler un abonnement sans authentification supplémentaire côté Stripe — aussi sensible qu'un lien de paiement. Nécessite une seule configuration manuelle côté Stripe Dashboard (Settings → Billing → Customer portal) — aucune API ne permet de la créer à la place de l'opérateur. Parité Node + Worker. 8 nouveaux tests — 153/153. - v0.27 — page
/securitypublique : rend visible et vérifiable la posture de sécurité au lieu de la laisser enfouie dans les commits — open source/MIT, 150+ tests en CI sur chaque push (Node 20/22),npm audità 0, principe « le code ne quitte jamais votre machine », contrôles techniques (signatures webhooks constant-time, cookiesSameSite=Strict, porte de paiement), méthode d'audit en deux passes (lien vers l'article). Discipline anti-survente verrouillée par un test : la page liste ce qu'elle ne prétend pas (pas de SOC 2, pas de pentest tiers, pas de bug bounty) — un futur commit ne peut pas silencieusement sur-vendre une certification absente. Ajoutée au sitemap, àllms.txtet au pied de page. Parité Node + Worker. 3 nouveaux tests — 155/155. - v0.30 — thème clair sur tout le site : navbar sombre + corps clair + titre géant audacieux, aligné à gauche (structure inspirée d'un design courant type NVIDIA Developer, mais avec l'accent bleu de mindset-ctx, pas une couleur de marque tierce). Appliqué de façon cohérente sur toutes les pages (accueil, docs, tarifs, blog, sécurité, legal, support, dashboard) — pas juste la page d'accueil, pour éviter un flash de thème sombre en naviguant. Les blocs de code (
pre) restent volontairement sombres pour le contraste (même motif que GitHub/Stripe). Aucun changement de logique, uniquement CSS/couleurs — vérifié visuellement page par page avant livraison. 155/155. - v0.31 — refonte du footer : bandeau sombre en colonnes (Produit / Ressources / Légal) + barre de copyright, sur le modèle structurel d'un footer SaaS courant (ex. NVIDIA Developer) mais avec uniquement des liens réels du site — pas d'icônes de réseaux sociaux ni de formulaire newsletter pour des canaux qui n'existent pas encore. Appliqué à
home.ts(partagé par accueil/docs/sécurité/blog/legal/support),pricing.tsetdashboard.ts. CSS uniquement, aucun changement de logique. 155/155. - v0.32 — refonte de
/docs: bandeau titre "Centre de documentation" en grand gras (même langage typographique que la home), barre de recherche client-side (filtre les cartes par texte, sans backend) et onglets "Parcourir par catégorie" en ancres réelles vers chaque section — structure inspirée d'un centre de doc SaaS courant (ex. NVIDIA Developer), sans bannière sombre ni image de marque tierce, cohérent avec le thème clair du site. Grille de cartes de doc inchangée en dessous. CSS + un peu de JS vanilla, aucune route serveur ajoutée. 155/155. - Extension JetBrains (stack différente : Kotlin/Gradle plutôt que TypeScript — mérite sa propre session) ; intégrations Slack/Linear/Notion ; programme de referral — voir
docs/VISION.md(bloqués sur un tooling différent, ou des identifiants que seul le fondateur peut créer)
Déploiement en production (0 → premier euro)
Le mode hébergé tourne sur Cloudflare Workers (gratuit, sans carte bancaire, 100 000 requêtes/jour). Runbook zéro-configuration :
# 1. Créer les produits/prix Stripe (idempotent)
export CTX_STRIPE_API_KEY=sk_live_...
node dist/cli.js stripe bootstrap # → imprime STRIPE_PRICE_MAP='{...}'
# 2. Déployer sur Cloudflare Workers (wrangler.toml livré, KV créé une fois)
npx wrangler kv namespace create CTX_KV # une seule fois ; colle l'id dans wrangler.toml
npx wrangler secret put CTX_STRIPE_API_KEY
npx wrangler secret put STRIPE_PRICE_MAP
npx wrangler deploy
# 3. Créer le webhook Stripe SANS toucher au Dashboard (idempotent, réutilise
# l'endpoint s'il existe déjà) :
node dist/cli.js stripe webhook https://<ton-worker>.workers.dev/v1/stripe/webhook
# → imprime CTX_STRIPE_SECRET='whsec_...' à coller :
npx wrangler secret put CTX_STRIPE_SECRET
npx wrangler deploy
# 4. (une seule fois, à la main) Activer le Customer Portal pour que
# GET /v1/billing/portal fonctionne : Dashboard Stripe → Settings →
# Billing → Customer portal → Activate. Sans ça, Stripe refuse de créer
# une session portal (erreur claire, pas un plantage) — aucune API ne
# permet de configurer ça à la place du Dashboard.
# 5. (optionnel) GitHub App — provisioning automatique par install, même sur
# le Worker déployé (pas seulement en self-hosted) :
npx wrangler secret put CTX_WEBHOOK_SECRET # même secret que celui déclaré dans l'App GitHub
npx wrangler deploy
# Crée l'App depuis le manifest : POST https://<ton-worker>.workers.dev/v1/app/manifest
# vers https://github.com/settings/apps/new
# 6. (optionnel) SSO Entreprise via WorkOS — créer une App sur workos.com,
# déclarer https://<ton-worker>.workers.dev/v1/sso/callback comme redirect URI :
npx wrangler secret put WORKOS_CLIENT_ID
npx wrangler secret put WORKOS_API_KEY
npx wrangler deploy
# 7. C'est tout. /pricing est publique, /v1/signup prend l'argent, la clé
# API est activée automatiquement par le webhook (Stripe, GitHub App ou SSO).
# Zéro humain dans la boucle.
Via GitHub Actions (recommandé, zéro terminal) : configure les secrets
CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, CTX_STRIPE_API_KEY,
STRIPE_PRICE_MAP sur le repo, lance le workflow Deploy to Cloudflare
Workers, puis le workflow Stripe — bootstrap webhook (crée le webhook
via l'API Stripe avec la clé déjà configurée — aucun accès au Dashboard
requis) et colle le CTX_STRIPE_SECRET imprimé dans les secrets GitHub avant
de relancer le déploiement.
Repo privé, code sensible ? Aucun code source ne quitte jamais votre machine :
ctx generate/index/serve— l'analyse du repo, la génération de contexte, la recherche mémoire et MCP — tournent toujours en local, sur tous les plans, gratuits comme payants. Le mode hébergé (Worker) ne fait que la facturation, le compte client et le tableau de bord de quota ; il n'a aucune route pour analyser un repo ou servir du contexte (Cloudflare Workers ne peut ni cloner ni lire un dépôt git).