Exécuter des agents de codage locaux sur un Mac avec oMLX : explication du cache KV basé sur le disque
oMLX stocke les préfixes des commandes en SSD afin que les agents de codage locaux restent rapides sur Apple Silicon. Installez-le et connectez-y Claude Code, Codex, Cursor et OpenCode.
Sources: oMLX is Quietly Becoming the Best Way to Run Local AI Agents On a Mac
Douze minutes après le début d’une session de codage, le modèle local cesse de se comporter comme un agent pour commencer à agir comme une machine à fax. Les premières requêtes vers les outils étaient traitées en deux secondes. Aujourd’hui, chaque étape nécessite trente, voire parfois quatre-vingt secondes. La tâche n’a pas changé ; le contexte s’est simplement allongé, et le serveur local récalcule silencieusement toute la conversation depuis zéro à chaque demande.
Ce symptôme, des délais de démarrage lents plutôt que des délais de traitement lents des tokens, est précisément ce que visait à éliminer un petit projet basé sur Apple Silicon nommé oMLX. Il ne s’agit ni d’un modèle ni d’un agent : c’est un serveur d’inférence dont la seule promesse est de conserver en mémoire ce que l’agent a déjà lu, même à mesure que la session s’allonge, afin que la douzième étape ressemble à la première. Le véritable test n’est pas une démonstration spectaculaire, mais son comportement à la quarantième étape d’une session réelle, sur du matériel que l’on possède réellement.
Pourquoi les Mac ont du mal avec les agents de codage
En théorie, Apple Silicon constitue une plateforme solide pour l’inférence locale. La mémoire unifiée offre au CPU et à la GPU un pool commun, ce qui permet à un modèle quantifié de rester en RAM sans avoir à traverser de bus ; de plus, le framework MLX d’Apple a été conçu pour ce type de charge de travail.
Les problèmes commencent lorsque la conversation se transforme en tâches effectuées par des agents. Un agent de codage relit la majeure partie de son contexte précédent à presque chaque étape, invoque un outil, reçoit le résultat ajouté au prompt, et répète ce processus des dizaines de fois. Le préfixe, c’est-à-dire la partie commune du prompt, correspond presque entièrement à celui de l’étape précédente, à l’exception d’un nouveau résultat d’outil à la fin.
La plupart des serveurs locaux interprètent cette correspondance partielle comme une inadéquation totale, suppriment le cache clé-valeur et recomptent à partir de zéro. Avec une requête courte, personne ne s’en aperçoit. Mais lors d’une session de 20 000 tokens, cela fait la différence entre une réponse en deux secondes et une réponse en quatre-vingt-dix secondes. Le créateur du projet a précisément indiqué cela comme motivation sur le forum de discussion MLX d’Apple : les agents de programmation envoient des requêtes dont les préfixes changent, et chaque serveur MLX existant invalide le cache et recompte tout lorsqu cela se produit.
Qu’est-ce que oMLX ?
oMLX est un serveur d’inférence open source basé sur MLX et mlx-lm d’Apple. Il est fourni sous forme d’application native de la barre des menus de macOS ainsi que d’outil en ligne de commande Python. Il a été créé par un développeur nommé Jun Kim et se trouve sur GitHub sous le nom jundot/omlx, sous licence Apache 2.0. Au moment de la rédaction de ce texte, il comptait environ 18 600 étoiles, 1 600 forks et plus de deux mille commits.
Rien de tout cela ne prouve la fiabilité. Les étoiles mesurent l’attention et non la maturité, et un projet qui publie plusieurs versions candidates par mois est encore en train de trouver son équilibre. La popularité est une raison de le tester, mais elle ne remplace pas le test lui-même.
Un seul processus gère deux styles d’API : les complétions de chat compatibles avec OpenAI et une route /v1/messages propre à Anthropic, ainsi que des routes pour les complétions, les embeddings et le réclassement. Il permet de garder chargés en même temps des modèles de langage, des modèles vision-langage, des modèles OCR et des outils de réclassement, avec un mécanisme d’éviction LRU et un verrouillage par modèle. Pour les agents, ce qui compte, c’est ce qui se passe en dessous de cette interface.
Les préfixes sont enregistrés sur le disque, pas dans la mémoire temporaire
La déduction classique MLX conserve le cache d’une conversation uniquement dans la mémoire GPU tant que le préfixe reste identique. La particularité d’oMLX réside dans un cache à deux niveaux capable de résister tant au décalage des préfixes qu’aux redémarrages. Les blocs fréquemment utilisés restent dans un niveau actif de la mémoire. Lorsque celui-ci est plein, les blocs sont écrits sur un niveau froid sur SSD au format safetensors, gérés un par un grâce au partage de préfixes et au mécanisme de copie sur écriture. Si une requête ultérieure correspond à un préfixe qui a été enregistré sur disque, ces blocs sont lu à nouveau sans être recalculés.
C’est un peu comme un bibliothécaire qui ne remettrait jamais en rayon un livre que vous avez récemment emprunté. Si vous demandez à nouveau plus tard, même après la réouverture de la bibliothèque, le livre sera déjà sur le comptoir.
Une SSD n’est pas de la RAM, donc la restauration d’un grand cache prend toujours du temps réel, bien que cela soit bien moins coûteux que de recalculer chaque token. L’avantage est maximal pour le modèle d’agent décrit précédemment : des préfixes longs, principalement répétitifs, avec une petite modification à la fin. Le serveur effectue également un agrégation continue via BatchGenerator de mlx-lm, en traitant les requêtes simultanément au lieu de les mettre en file d’attente, le niveau de cet agrégation pouvant être configuré depuis la ligne de commande ou le panneau d’administration.
Deux chiffres sont les plus importants. Le temps jusqu’au premier token indique combien de temps il faut avant que quelque chose ne soit transmis en retour. La vitesse de génération correspond à la rapidité avec laquelle les tokens arrivent une fois la génération commencée. La réutilisation du cache s’applique après le premier token, sans toucher au second. Un modèle qui génère lentement continuera de générer lentement, mais il commencera à répondre plus tôt.
Installation sur Apple Silicon
Les exigences sont macOS 15 (Sequoia) ou une version ultérieure, un Python compris entre 3.11 et 3.13, ainsi qu’un processeur de la famille M1, M2, M3 ou M4. Il existe trois méthodes, la première convenant à la plupart des utilisateurs.
La méthode recommandée est l’application macOS. Téléchargez le fichier .dmg signé et notarié depuis GitHub Releases, déplacez-le dans Applications et lancez-le. Une page d’accueil guide vous dans le choix du répertoire du modèle, lance le serveur ainsi que le premier téléchargement, et l’application installe un petit outil en ligne de commande.
Avec Homebrew :
brew tap jundot/omlx https://github.com/jundot/omlx
brew install omlx
omlx start
Source :
git clone https://github.com/jundot/omlx.git
cd omlx
pip install -e . # core
pip install -e ".[mcp]" # optional MCP support
Tout ceux qui prévoient d’utiliser GLM-5.2, MiniMax M3 ou Qwen3.5 doivent savoir qu’un simple pip install ignore leurs noyaux personnalisés natifs, ce qui fait que les modèles concernés empruntent silencieusement une voie beaucoup plus lente. Le projet indique que son noyau préchargé fusionné est environ 30 fois plus rapide sur un M3 Ultra pour l’un d’eux. La compilation des noyaux nécessite Xcode complet et non seulement les Command Line Tools, ce qui constitue l’argument le plus simple en faveur du format DMG.
Avant de connecter quoi que ce soit, vérifiez que le serveur est opérationnel :
curl -s http://localhost:8000/v1/models
Une liste vide est acceptable si aucun répertoire de modèle n’a encore été défini.
Chargement du premier modèle
oMLX détecte automatiquement les modèles de langage, les modèles vision-langage, les modèles d’embedding ainsi que les outils de réclassification dans le répertoire vers lequel il est orienté. Il lit également directement le cache existant de Hugging Face et le dossier de LM Studio, de sorte qu’aucun fichier n’a besoin d’être téléchargé deux fois.
omlx serve --model-dir ~/models
La taille du modèle doit être adaptée à la mémoire de la machine, et non au plus grand fichier disponible. Laissez quatre ou cinq gigaoctets de marge à macOS et allouez le reste aux poids du modèle ainsi qu’à l’augmentation de la mémoire cache. Un modèle de 9 milliards de paramètres en format 4 bits convient aux machines disposant de 16 à 32 Go de mémoire. Les modèles de la classe 30 à 40 milliards de paramètres nécessitent 64 Go ou plus. Les plus gros modèles, selon les benchmarks du projet, exigent une mémoire supérieure à 400 Go sur un Mac Studio.
Les modèles peuvent être téléchargés depuis le navigateur Hugging Face intégré au tableau de bord administratif à l’adresse http://localhost:8000/admin, ou à l’aide de tout flux de téléchargement hf existant destiné au répertoire des modèles. Une demande de base ressemble à une demande ordinaire de complétion de chat via OpenAI :
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "your-model-name", "messages": [{"role": "user", "content": "Say hi in five words."}]}'
Si une réponse est renvoyée, l’endpoint fonctionne.
Connexion de Claude Code, Codex, Cursor et OpenCode
Il existe deux manières pour que oMLX se connecte aux agents, et le choix dépend de la manière dont l’agent stocke sa configuration, et non du degré de support dont il dispose.
Outils disposant d’un fichier de configuration
OpenClaw, OpenCode, Codex et Pi lisent un fichier de configuration que oMLX peut atteindre directement : JSON pour les deux premiers et TOML pour Codex. Les adaptateurs d’intégration écrivent dans ce fichier, et l’onglet Intégrations du tableau de bord administratif transmet une commande :
omlx-cli launch codex --model your-model-name --api-key your-key
omlx-cli launch opencode --model your-model-name --api-key your-key
omlx-cli launch pi --model your-model-name --api-key your-key
En le lançant, la configuration de l’outil est mise à jour et l’agent est démarré en une seule étape. Toute configuration existante est d’abord sauvegardée sous forme de fichier .bak daté, afin de pouvoir annuler les changements en cas de problème.
Hermes Agent et l’entrée Copilot
Ces deux options figurent sur la liste à un clic du README, et la documentation propre à Hermes Agent le confirme séparément : l’assistant de configuration dispose d’une option d’endpoint compatible OpenAI personnalisable pour pointer vers n’importe quel serveur local, y compris oMLX. Pour passer outre le tableau de bord, pointez-le manuellement vers http://localhost:8000/v1.
La version Copilot mérite un second examen avant que quiconque ne s’y fie. Le véritable Copilot Chat de GitHub s’authentifie via OAuth auprès de api.githubcopilot.com et n’est pas conçu pour accepter une URL de base locale arbitraire. L’intégration Copilot en un clic vise donc soit un outil différent portant le même nom, soit utilise un mécanisme que la documentation publique ne confirme pas. Vérifiez directement l’onglet Intégrations avant de supposer qu’il fonctionne comme l’indique son intitulé.
Claude Code
Claude Code lit son adresse serveur depuis la variable d’environnement ANTHROPIC_BASE_URL au démarrage, et non depuis un fichier que oMLX peut modifier, ce qui rend cette étape manuelle. Comme oMLX gère directement la route native /v1/messages, aucun proxy de traduction n’est nécessaire :
export ANTHROPIC_BASE_URL="http://localhost:8000"
export ANTHROPIC_AUTH_TOKEN="local"
export ANTHROPIC_DEFAULT_SONNET_MODEL="your-model-name"
export ANTHROPIC_DEFAULT_OPUS_MODEL="your-model-name"
claude
oMLX intègre également des fonctionnalités conçues spécifiquement pour Claude Code. Les rapports de mise à l’échelle du contexte indiquent le nombre de tokens, permettant ainsi à la fonction d’auto-compaction de fonctionner correctement avec une fenêtre de contexte locale plus petite, tandis que la fonction SSE keep-alive évite les délais de lecture lors d’un préremplissage prolongé. Il s’agit de détails propres aux agents et non d’une case à cocher de compatibilité générale.
curseur
La configuration du modèle local de Cursor se trouve à l’intérieur de son interface graphique, il n’y a donc aucun fichier que l’oMLX puisse écrire. Dans les Paramètres, sous « Modèles », localisez la section « API OpenAI » et activez l’option « Override Base URL ». Cursor a déjà changé le nom de cette option par le passé, donc son étiquette peut varier selon la version. Entrez http://localhost:8000/v1 et saisissez n’importe quelle chaîne de caractères non vide dans le champ « API key », car un serveur local ne la vérifie pas. Ajoutez le modèle chargé sous « Modèles personnalisés » en utilisant son nom exact tel que dans oMLX, et désactivez les modèles par défaut de Cursor afin qu’il ne tente pas non plus de les valider auprès des serveurs d’OpenAI.
Vérifier que tout fonctionne bien
Lors d’une session réelle, les panneaux de cache chaud et froid du tableau de bord administratif doivent continuer à accumuler des blocs sans être réinitialisés à chaque tour. Une réinitialisation à chaque tour signifie généralement que le contenu fourni par le système ou le schéma de l’outil est réordonné entre les appels, ce qui perturbe le préfixe.
Évaluation du cache chaud par rapport au cache froid
Plutôt que de reprendre tel quel une affirmation du fournisseur, un test peut être exécuté localement. Corrigez le modèle, la quantification, la longueur du contexte et les prompts pour chaque outil, puis enregistrez le temps de démarrage en mode froid, le temps nécessaire pour obtenir le premier token en mode froid, le temps nécessaire pour obtenir le premier token en mode chaud avec un préfixe répété, la vitesse de génération constante, la mémoire maximale utilisée, le comportement après 15 à 20 tours simulés de l’agent, le temps de configuration, ainsi que le fait que les appels aux outils restent correctement analysés tout au long de la session.
Les chiffres publiés par le projet lui-même, obtenus avec un M3 Ultra de 512 GB clairement de première main, indiquent une génération d’environ 45 à 59 tokens par seconde pour un Qwen3-Coder-Next à 8 bits sur des contextes allant de 1 k à 32 k. Le lotage continu permet d’obtenir une accélération de la vitesse de génération d’environ 4,14 fois avec huit requêtes simultanées par rapport à une seule. Il s’agit d’une limite supérieure pour du matériel haut de gamme et non de ce que pourra atteindre un MacBook Air de 16 GB.
Un rapport indépendant indique qu’un contexte de 8 700 tokens a nécessité environ vingt secondes avec MLX classique, tandis que la réponse provenant du cache préchauffé est arrivée si rapidement que l’auteur a répété le test pour en être sûr. Il s’agit d’un compte rendu de tiers et non d’un test contrôlé, il est donc utile de le reproduire avant de le croire.
Le temps de démarrage à froid jusqu’au premier token n’est pas significativement différent de celui du MLX brut, car il n’y a rien à réutiliser pour l’instant. Tous les avantages résident dans les interactions avec des préfixes répétés, qui constituent la majeure partie d’une session d’agent de codage.
Gestion du serveur
Démarrer, arrêter et redémarrer, avec la variante en premier plan associée à la terminal :
omlx start # background service, auto-restarts on crash
omlx stop
omlx restart
omlx serve --model-dir ~/models # foreground, attached to this terminal
Vérifiez qu’il est en cours d’exécution et qu’il sert un modèle :
curl -s http://localhost:8000/v1/models
Évitez que l’utilisation de la mémoire ne interfère avec le reste du système :
omlx serve --model-dir ~/models --memory-guard safe
omlx serve --model-dir ~/models --memory-guard-gb 48
Paramétrez le cache à deux niveaux directement :
omlx serve --model-dir ~/models --paged-ssd-cache-dir ~/.omlx/cache
omlx serve --model-dir ~/models --hot-cache-max-size 20%
Augmentez la concurrence lorsque plusieurs agents se connectent au serveur en même temps :
omlx serve --model-dir ~/models --max-concurrent-requests 16
Les installations Homebrew suivent le même cycle de vie via brew services :
brew services start omlx
brew services stop omlx
brew services info omlx