Intro
Claude Code sur un modèle de laptop a réussi une de nos deux vraies tâches. La plupart des démos de cette config s'arrêtent à "hello" ; nous avons donné deux jobs à un petit modèle local dans un package Python, et nous racontons ce qui s'est passé, avec l'alias et la règle que nous avons gardés.
Le principe est simple. Quand la limite de votre forfait tombe en pleine tâche, vous attendez le reset ou vous confiez le travail au même Claude Code, branché sur un modèle de votre propre machine. Sur le job qui touchait plusieurs fichiers, le modèle local a annoncé que tous les tests passaient alors que son renommage avait cassé un import. Un seul flag, --bare, a transformé un run local qui ne changeait rien en un passage propre sur la même tâche.
Cet article couvre l'alias, le flag qui règle le problème, le piège de la context window, le job qui traverse les fichiers, et la règle qui décide quels jobs vont en local et lesquels attendent votre forfait.
Claude Code sur votre propre modèle
Claude Code se compose de deux parties. Le harness est le programme de votre terminal qui lit vos fichiers, lance vos commandes et fait les modifications. Le modèle décide de la suite, et par défaut il vit sur les serveurs d'Anthropic et compte dans votre forfait.
Un seul réglage, l'URL de base, dit au harness où envoyer ses questions. Ollama est un programme qui télécharge des modèles ouverts et les sert sur une adresse de votre propre machine. Rien ne change dans Claude Code, seule l'adresse à laquelle il parle, ce qui explique qu'une ligne dans votre shell suffise. C'est un peu comme pointer votre app vers une base de données locale plutôt que vers la production.
Pour la mise en place, installez Ollama avec Homebrew, puis téléchargez un modèle qui tient dans votre mémoire. Le nôtre était qwen3.5:9b, 7,6 Go, sur un MacBook Pro M1 Pro avec 16 Go. Les versions plus grosses du même modèle ne tenaient pas du tout. Comparez la taille du modèle à votre mémoire avant de télécharger quoi que ce soit, car le modèle entier doit y tenir à côté de tout ce que vous avez d'ouvert.
Une réserve tirée de la doc d'Anthropic elle-même : elle ne prend pas en charge le routage de Claude Code vers des modèles qui ne sont pas Claude. Si quelque chose casse avec cette config, vous êtes seul, et le modèle que vous faites tourner est bien plus petit que celui que vous donne votre forfait.
L'alias claude-alt
Un alias est un nom court que votre shell développe en une commande plus longue. Mettre toute la bascule dans un seul alias garantit que votre claude de tous les jours continue d'utiliser votre forfait, puisque les réglages ne s'appliquent que quand vous appelez l'alias.
Le guide d'Ollama fournit les réglages : l'adresse locale, un token factice et une clé d'API. La clé mérite l'attention. La doc de Claude Code dit qu'une clé que vous définissez est utilisée à la place de votre abonnement, même si vous êtes connecté, c'est pourquoi elle ne vit que sur la ligne de l'alias. Vous ouvrez votre fichier de shell, collez l'alias avec le nom du modèle à la fin, puis rechargez le fichier.
alias claude-alt='CLAUDE_CODE_ATTRIBUTION_HEADER=0 ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_API_KEY=ollama ANTHROPIC_BASE_URL=http://localhost:11434 claude --bare --model qwen3.5:9b'
C'est la version finale, avec --bare déjà dedans (la section suivante explique pourquoi). CLAUDE_CODE_ATTRIBUTION_HEADER=0 est un réglage que recommandent les guides pour les modèles locaux. Nous n'avons jamais mesuré son effet, considérez-le donc comme optionnel.
Nous avons commencé sans --bare. La première vraie tâche, dans un petit package Python écrit pour ce test, consistait à ajouter une option à un fichier et à la lancer. Claude Code a démarré, a prévenu qu'il ne connaissait pas ce modèle, et a continué de travailler pendant que le chrono tournait. Au bout de 15 minutes, il n'avait pas modifié une seule ligne, nous l'avons donc arrêté, et l'option n'existait pas.
Si vous essayez l'alias tel quel, vous verrez probablement la même chose : une session qui continue de travailler et un fichier qui ne change jamais. L'alias pointe Claude Code vers votre modèle, mais sur un petit modèle cela ne suffit pas pour mener la tâche à bien.
Le flag qui le fait répondre : --bare
Chaque session Claude Code s'ouvre sur un long jeu d'instructions : votre fichier de mémoire et vos outils. C'est très bien pour Claude et lourd pour un petit modèle sur un laptop. Le flag --bare est le mode minimal de Claude Code. Il saute les hooks, les plugins, la mémoire et le fichier de projet, si bien que le modèle reçoit une courte page au lieu d'un manuel.
Vous ajoutez --bare à la fin de l'alias et vous mettez le mot ollama dans ANTHROPIC_API_KEY, parce qu'en mode minimal Claude Code ne lit sa clé qu'à cet endroit. Avec la même demande, le même petit modèle et la même context window courte, le run a lu le fichier, l'a modifié et a lancé la commande. Il a fini en 93 secondes avec un fichier modifié, et la commande a affiché le slug avec le préfixe devant, exactement comme demandé : blog-hello-world.
Vous le vérifiez comme vous vérifieriez la modification d'un collègue : vous lisez un petit diff et vous lancez la commande vous-même.
Le coût est réel. Le mode minimal supprime aussi vos hooks et vos règles de projet, donc le modèle local ne voit jamais les conventions que vous avez écrites. Si votre projet dépend d'un hook pour bloquer quelque chose de dangereux, gardez ce job sur le forfait, là où vos hooks tournent vraiment.
Le piège du 4k et le correctif à 64k
Le deuxième piège est facile à rater, parce qu'Ollama choisit pour vous la taille de la mémoire du modèle. Cette mémoire, c'est la context window, c'est-à-dire la quantité de conversation que le modèle peut garder sous les yeux à la fois. La doc d'Ollama dit que sur une machine comme la nôtre la fenêtre par défaut est petite, 4k tokens sous 24 GiB de VRAM, très loin des 64 000 qu'ils recommandent pour les outils de code. Tous nos premiers runs ont utilisé cette valeur par défaut, et vous ne le sauriez pas sans vérifier.
Pour corriger, arrêtez Ollama et relancez-le avec la longueur de contexte à 64 000 (OLLAMA_CONTEXT_LENGTH=65536), puis lancez ollama ps et lisez la colonne CONTEXT. Vous devez le définir à chaque démarrage du serveur, et ollama ps est le seul endroit qui montre que c'est bien pris en compte. La colonne est passée de 4096 à 65536, et le modèle a pris à peine plus de mémoire : 7,6 Go avant, 7,7 Go après.
| Run | Contexte | --bare |
Résultat | Durée |
|---|---|---|---|---|
a-4k-nobare (alias sans --bare) |
4096 | non | ÉCHEC : tué au plafond de 15 min, zéro modification, aucune réponse | 900 s |
| a-4k (alias) | 4096 | oui | RÉUSSI, blog-hello-world | 93 s |
| a-64k (alias) | 65536 | oui | RÉUSSI, blog-hello-world | 35 s |
La tâche sur un fichier est passée en 35 secondes, bien plus vite qu'avec la petite fenêtre. Le job sur plusieurs fichiers, traité juste après, est lui aussi passé de plusieurs minutes à deux environ. Le petit réglage par défaut ne limite pas seulement la mémoire, il ralentit chaque tour, et vous accuseriez le modèle alors que la cause est le réglage.
Claude Code affiche aussi un avertissement : il ne connaît pas ce modèle, et il suppose une fenêtre de 200k tokens pour l'auto-compact, bien plus grande que ce qu'Ollama sert. CLAUDE_CODE_MAX_CONTEXT_TOKENS fixe la vraie valeur. Cet écart n'a pas posé de problème sur nos tâches courtes, et nous ne l'avons pas testé sur une longue session. La limite, c'est la mémoire, car une fenêtre plus grande en prend plus, et sur un laptop de 16 Go c'est à peu près le maximum.
Le job multi-fichiers : tests verts, code cassé
Avec un modèle local qui répond vite, la tentation est de lui confier du vrai travail. Nous lui avons donc donné un job qui traverse les fichiers : renommer smart_truncate en truncate_words partout dans le package, et garder smart_truncate comme alias dans slugkit/truncate.py. Un alias dans le code, c'est l'ancien nom conservé comme pointeur vers la nouvelle fonction, pour que le code qui utilise encore l'ancien nom continue de tourner.
Le modèle local a travaillé quelques minutes, modifié les fichiers, lancé les tests, et tous les tests sont passés. Puis il a annoncé que le job était terminé.
| Run | Contexte | --bare |
Résultat | Durée |
|---|---|---|---|---|
| b-plan (forfait, Claude) | n/a | non | RÉUSSI : 12 tests OK, ancien et nouvel import fonctionnent, tests renommés | 38 s |
| b-4k (alias) | 4096 | oui | CASSÉ : "All 12 unit tests pass", mais from slugkit import truncate_words donne ImportError ; les tests appellent encore smart_truncate via import truncate_words as smart_truncate |
464 s |
| b-64k (alias) | 65536 | oui | CASSÉ : 12 tests OK, job annoncé terminé, mais l'alias est allé dans __init__.py, donc from slugkit.truncate import smart_truncate donne ImportError (la consigne disait truncate.py) |
142 s |
Quand nous avons importé l'ancien nom comme le ferait l'ancien code, Python l'a refusé. Le modèle avait mis l'alias dans le fichier d'entrée du package au lieu du module demandé, si bien que l'ancien chemin d'import avait disparu. Avec la petite fenêtre, la même tâche a cassé autrement : le nouveau nom n'était jamais exporté, et les tests appelaient toujours l'ancien.
Comment tous les tests peuvent-ils être verts alors que le code est cassé ? Les tests ne vérifient que ce qu'ils vérifient, et personne n'avait écrit de test pour l'ancien import. Un run vert du modèle local ne dit rien de plus que : ce que les tests couvrent n'a pas cassé. Il ne dit rien sur ce qu'ils ne couvrent pas.
Sur le forfait, Claude a fait le même job en 38 secondes, a renommé aussi les tests, et l'ancien comme le nouvel import fonctionnaient. Pour être juste, le travail du forfait mérite lui aussi une vérification, mais ici le modèle local s'est trompé sur le job multi-fichiers les deux fois. Après chaque run local, lisez le diff vous-même et importez les anciens noms à la main avant de faire confiance à un run de tests vert. Cette vérification prend moins de temps que le run, et elle empêche un import cassé d'arriver sur votre branche principale.
La règle de bascule
Quand votre limite tombe, vous avez quelques secondes pour décider si un job part en local ou attend. Une règle de bascule, ce sont quelques lignes que vous gardez à côté de l'alias, pour que la décision soit prise avant d'être pressé. Ouvrez votre fichier de shell et écrivez trois commentaires au-dessus de l'alias :
# claude-alt: one-file jobs I can check in a glance
# plan: anything across files, or that I can't check by reading the diff
# always: read the diff before committing
Le modèle local reçoit les jobs sur un seul fichier que vous pouvez vérifier d'un coup d'œil, comme ajouter une option, expliquer une fonction ou tester une fonction. Tout ce qui traverse les fichiers, ou que vous ne pouvez pas vérifier en lisant le diff, attend votre forfait. Quel que soit le modèle qui a écrit le code, vous lisez le diff avant de faire un commit.
La règle découle directement de notre run : la tâche sur un fichier a réussi les deux fois, et le renommage entre fichiers a cassé les deux fois. Le schéma devient logique une fois qu'on l'a vu échouer, car un job sur un fichier garde sous les yeux du modèle tout ce dont il a besoin.
Cette config a aussi des limites que la doc d'Ollama énumère. Il n'y a pas de prompt caching, c'est-à-dire que le serveur ne garde pas prêt le début de la conversation, donc sur une longue session chaque tour relit tout et vous ralentit. Elle ne peut pas forcer le modèle à utiliser un outil précis. Et Anthropic ne prend pas en charge Claude Code sur des modèles qui ne sont pas Claude. Notre règle vient de deux tâches sur un petit package, considérez-la donc comme un point de départ et élargissez-la avec vos propres runs.
Verdict
Quand la limite de votre forfait tombe en pleine tâche, un alias fait tourner le même Claude Code sur un modèle de votre laptop. Dans notre test, il a réussi la tâche sur un fichier et cassé celle qui traversait les fichiers. Le run cassé est le dangereux, parce qu'il a annoncé tous les tests verts alors qu'un import échouait.
Utilisez-le quand vous êtes bloqué, que le job tient dans un fichier et que vous pouvez lire tout le diff avant de faire un commit. Ne l'utilisez pas pour ce qui traverse les fichiers, pour les longues sessions, ni pour du travail que vous ne relirez pas, car c'est là qu'il échoue en silence.
Sur le forfait, chaque tâche a pris moins de 40 secondes (21 s et 38 s), donc quand votre reset est proche, attendre est souvent plus rapide. L'alias ne remplace pas votre forfait. Il vous permet de continuer sur les petits jobs en attendant son retour, et si vous le mettez en place aujourd'hui, il est prêt la prochaine fois que votre limite tombe.
La règle à retenir : le modèle local sert aux jobs que vous pouvez vérifier d'un coup d'œil.
AIDive