- zerostack est un agent de codage minimaliste écrit en Rust, qui prend en charge plusieurs fournisseurs de LLM ainsi que des fournisseurs personnalisés
- Il fournit la lecture, l’écriture et l’édition de fichiers,
grep, la recherche de fichiers, le listing de répertoires, l’exécution de Bash avec contrôle d’autorisation, MCP et les outils web Exa - Il compte environ 7 kLoC, produit un binaire de 8,9 Mo, et consomme environ 8 Mo de RAM à vide, 12 Mo en cours de travail, avec 0,0 % de CPU au repos
- Le fournisseur par défaut est OpenRouter ; l’installation se fait avec
cargo install zerostack, et bubblewrap est nécessaire pour isoler Bash avec--sandbox - Il inclut des prompts intégrés comme
code,planetreview, 4 modes d’autorisation, la reprise de session, des boucles itératives et l’intégration des Git worktrees
Vue d’ensemble de zerostack
- zerostack est un agent de codage minimaliste écrit en Rust, inspiré de pi et opencode
- Il adopte une architecture multi-fournisseurs prenant en charge OpenRouter, OpenAI, Anthropic, Gemini, Ollama et des fournisseurs personnalisés
- Il fournit des outils de fichiers comme la lecture, l’écriture et l’édition de fichiers,
grep, la recherche de fichiers, le listing de répertoires, ainsi que l’exécution de Bash avec contrôle d’autorisation - Il inclut la sauvegarde, le chargement et la reprise de session, la compression automatique pour préserver la fenêtre de contexte, une interface terminal basée sur crossterm, la connexion à des serveurs MCP, et les outils WebFetch et WebSearch basés sur Exa
- Il permet de naviguer entre des Git worktrees avec
/worktreeet intègre aussi des boucles itératives pour les tâches de longue durée
Performances et installation
- zerostack représente environ 7 kLoC et la taille du binaire est de 8,9 Mo
- L’utilisation mémoire est d’environ 8 Mo pour une session vide et 12 Mo en cours de travail, contre environ 300 Mo pour opencode ou d’autres agents de codage basés sur JS
- L’utilisation CPU a été mesurée à 0,0 % au repos et environ 1,5 % pendant l’utilisation des outils ; sur un Intel i5 de 7e génération, opencode est comparé à environ 2 % au repos et 20 % en charge
- L’installation nécessite Cargo et git, avec la commande suivante
cargo install zerostack - Lors de l’utilisation de
--sandbox, il faut installer bubblewrap pour exécuter toutes les commandes Bash dans un environnement isolé# Debian/Ubuntu apt install bubblewrap # Fedora dnf install bubblewrap # Arch pacman -S bubblewrap
Démarrage rapide
- Le fournisseur par défaut est OpenRouter, et la clé API se définit via une variable d’environnement
export OPENROUTER_API_KEY="[api_key]" - La session interactive s’exécute avec le prompt par défaut
codezerostack - Le mode d’exécution ponctuelle transmet un prompt avec
-pzerostack -p "Explain this project" - La dernière session peut être reprise avec
-czerostack -c - Il est possible de préciser le fournisseur et le modèle
zerostack --provider openrouter --model deepseek/deepseek-v4-flash
Système de prompts
- zerostack inclut un ensemble de prompts système intégrés qui modifient le comportement et le ton de l’agent
- L’objectif est de créer une famille de prompts pouvant remplacer superpower ou les skills officiels de Claude
/promptpermet de lister les prompts enregistrés ou de basculer vers un autre prompt-
Prompts intégrés
codeest la valeur par défaut ; c’est un mode de codage utilisant l’accès complet aux fichiers et à Bash ainsi qu’un workflow TDDplanest un mode dédié à la planification, qui explore avant de produire un plan sans écrire de codereviewest un mode de revue de code examinant l’exactitude, la conception, les tests et l’impactdebugest un mode de débogage qui cherche la cause racine avant de proposer une correctionaskest un mode en lecture seule qui n’autorise que read,grepetglob, sans écriture ni Bashbrainstormest un mode dédié à la conception qui explore des idées et propose une architecture sans écrire de codefrontend-designest un mode de design frontend pour des interfaces uniques et prêtes pour la productionreview-securityest un mode de revue sécurité qui recherche des vulnérabilités exploitablessimplifyest un mode de simplification du code qui améliore la clarté sans changer le comportementwrite-promptest un mode de rédaction de prompts pour créer et optimiser des prompts d’agent- Des prompts personnalisés peuvent être créés en plaçant des fichiers Markdown dans
$XDG_CONFIG_HOME/zerostack/prompts/et en les référant par leur nom - Les fichiers
AGENTS.mdouCLAUDE.mdà la racine du projet ou dans un répertoire parent sont lus automatiquement et injectés dans le prompt système ; cela peut être désactivé avec-nou--no-context-files
Système d’autorisations
- zerostack propose 4 modes d’autorisation, du plus sûr au plus permissif
-
Modes d’autorisation
restrictiveou-Rdemande une approbation pour toute action d’outil qui n’est pas explicitement autorisée dans la configurationstandardest le mode par défaut ; il approuve automatiquement les commandes sûres commels,cd,git logoucargo check, et demande une confirmation pour l’écriture et les opérations destructricesaccept-allou--accept-allapprouve automatiquement toutes les opérations dans le répertoire de travail et demande confirmation pour les chemins externesyoloou--yoloapprouve automatiquement toutes les opérations sans prompt- Des patterns glob par outil peuvent être définis dans le fichier de configuration pour affiner les autorisations
- Par exemple, il est possible d’autoriser automatiquement
write **.rstout en exigeant une confirmation pour l’écriture des autres fichiers - La liste blanche de session conserve les décisions approuvées pendant toute la session afin d’éviter de redemander la même validation
- Si le même appel d’outil se répète 3 fois ou plus, la détection de doom loop affiche un prompt d’avertissement ou bloque l’action selon la configuration, afin d’empêcher l’agent de répéter des opérations destructrices
Commandes slash et gestion des sessions
- Les principales commandes slash contrôlent le modèle, le niveau de réflexion, la conversation, les sessions, les boucles, les prompts et les modes d’autorisation
/modelpermet de changer de modèle, et/thinkingde définir le niveau de réflexion/clearefface la conversation, et/sessionpermet de lister, sauvegarder et charger les sessions/loopprogramme un prompt itératif, et/promptpermet de lister ou modifier le prompt de l’agent/modedéfinit le mode du système d’autorisations, et l’ensemble des commandes est consultable avec/help- Les sessions sont enregistrées dans
$XDG_DATA_HOME/zerostack/sessions/ -creprend la session la plus récente,-rpermet de parcourir et choisir une session, et--session <id>charge une session précise
Boucle itérative
- zerostack inclut une boucle de codage itérative pour les tâches de longue durée
- L’agent relit la tâche de manière répétée, choisit un élément du plan, exécute le travail, lance les tests, met à jour le plan, puis continue jusqu’à l’achèvement ou jusqu’à atteindre la limite d’itérations
- Le système de boucle est une fonction expérimentale
-
Utilisation de la boucle
/loop Implement the user authentication systemdémarre une boucle avec le prompt indiqué/loop stoparrête la boucle active/loop statusaffiche l’état actuel de la boucle- Chaque itération inclut la tâche d’origine, le fichier
LOOP_PLAN.mdévolutif, le résumé des itérations précédentes et la sortie de validation - Tant que la boucle est active, les entrées qui ne sont pas des commandes slash sont bloquées
-
Boucle headless via CLI
- La boucle headless peut être lancée avec la commande suivante
zerostack --loop --loop-prompt "Refactor the API" --loop-max 10 --loop-run "cargo test" --loopactive le mode boucle headless--loop-prompt <text>définit le prompt à utiliser à chaque itération--loop-plan <path>indique le chemin d’un fichier de plan personnalisé, dont la valeur par défaut estLOOP_PLAN.md--loop-max <N>définit le nombre maximal d’itérations, avec aucune limite par défaut--loop-run <cmd>définit la commande de validation à exécuter après chaque itération
- La boucle headless peut être lancée avec la commande suivante
Intégration des Git worktrees
- zerostack propose un flux de travail par branche via les git worktrees
- Depuis l’interface de chat, il est possible de créer un worktree, d’y travailler, de fusionner, puis d’en sortir
- L’intégration des Git worktrees est une fonction expérimentale
-
Commandes worktree
/worktree <name>crée un git worktree sur la branche<name>et y bascule ; si elle existe déjà, la création est ignorée/wt-merge [branch]fusionne la branche du worktree dans[branch], effectue un push, nettoie, puis revient au dépôt principal/wt-exitrevient au dépôt principal sans fusionner
-
Exemple de workflow
/worktree feature-xcrée une nouvelle branche et un répertoire worktree, puis s’y déplace- Ensuite, l’utilisation de zerostack se fait normalement et les modifications restent sur la branche feature
/wt-mergepermet à l’agent de fusionner la branche, faire le push, nettoyer, puis revenir au dépôt principal/wt-exitpermet de revenir immédiatement au dépôt principal sans fusion
Fournisseurs pris en charge et licence
- Le fournisseur par défaut est OpenRouter
- Les fournisseurs compatibles OpenAI incluent vLLM, LiteLLM, etc.
- Anthropic, Gemini et Ollama sont pris en charge
- Les fournisseurs personnalisés peuvent être configurés dans
$XDG_CONFIG_HOME/zerostack/config.jsonavec une base URL arbitraire et une variable d’environnement pour la clé API - La licence est GPL-3.0-only
1 commentaires
Commentaires Hacker News
Je ne connais pas très bien ce genre d’outil, mais je me demande quels sont les avantages par rapport à des modèles/outils comme Claude Code.
J’étais en train de construire quelque chose de similaire sur mon temps libre, à la fois pour mieux comprendre les agents et pour apprendre Rust.
Cela dit, je voulais conserver la configurabilité de
pi. La capacité à se modifier soi-même et à créer de nouveaux outils est très utile, et je pense que ce type d’outil ne devrait pas avoir le droit d’exécuter du code arbitraire viabash.Bien sûr, si l’on a accès à
editet àcargo run, on peut quand même exécuter du code arbitraire, mais lorsqu’un agent sansbasha besoin de faire quelque chose, je préfère qu’il génère les outils au cas par cas.J’ai donc choisi d’autoriser la personnalisation autrement. La bibliothèque de prompts dans
~/.config/hypernova/prompts/est une alternative simple aux Skills, et les prompts intégrés doivent remplacer superpowers et frontend-design de Claude.Les fonctionnalités susceptibles d’alourdir l’agent peuvent être désactivées à la compilation via des feature flags, et comme le code est court et facile à lire, on peut faire tourner zerostack sur le code source de zerostack lui-même pour créer un fork personnalisé si besoin.
Concernant le modèle de permissions, après beaucoup de réflexion comme on peut le voir dans le README, j’ai créé 4 niveaux, allant de « Restrictive » sans commandes à « YOLO » où l’agent fait ce qu’il veut, avec aussi des regex autoriser/demander/refuser pour les appels
bash. Dans ce cas, il suffit d’exécuterzerostack -Rpour forcer tous les outils à demander une permission.Je travaille aussi sur des fonctionnalités d’agent programmable, mais ce n’est pas encore prêt à être annoncé.
J’en ai aussi fait un récemment, à moitié pour rire, en moins de 200 lignes : https://github.com/pnegahdar/nano
Il inclut un REPL, des sessions, une exécution non interactive, des validations, etc. Plus les modèles deviennent intelligents, plus l’importance du harnais diminue, en dehors de l’expérience développeur.
Je le passerai peut-être un jour sur SWE-bench.
J’en ai moi aussi bricolé un la semaine dernière pour m’amuser et apprendre, et il fonctionne même avec des intégrations vers des
mcpServersconfigurés, comme la plupart des agents de code.J’ai documenté étape par étape ce qui est nécessaire et pourquoi : https://nb1t.sh/building-a-real-agent-step-by-step/
« RAM footprint: ~8MB on an empty session, ~12MB when working »
J’aime beaucoup ce point. Claude Code consomme plusieurs Go, ce qui est assez pénible sur un portable modeste.
Le démarrage prend moins de 0,5 seconde et l’usage RAM est très faible. Il tourne très bien sans ralentir, même sur un portable vieux de 12 ans.
Quelque chose qui est essentiellement proche d’un moteur de concaténation de chaînes ne devrait pas être lent sur quelque machine que ce soit, y compris du matériel ancien.
1: https://zed.dev/acp
Je vais essayer ça en rentrant chez moi. Les outils légers et rapides changent vraiment l’expérience de programmation.
Je me demande ce que vaut concrètement l’approche par prompts par rapport à la combinaison plus classique de skills et sous-agents. Personnellement, s’il y a un échec de build, je lance souvent un skill
/fix-ci, puis je fais extraire par un sous-agent le message d’erreur, la stack trace et les logs pertinents pour résoudre le problème.Quand un test d’intégration révèle un problème de requête DB, l’agent peut aussi appeler un skill d’accès DB en lecture seule, soit de lui-même, soit avec un léger guidage de ma part. Quand il faut creuser longtemps et en profondeur, je dis des choses comme « utilise un sous-agent Sonnet et demande-lui de déboguer ce comportement avec le skill de requêtes DB ».
Les skills ajoutent des capacités à la volée, et les sous-agents permettent l’isolation pour éviter l’explosion du contexte. Un agent qui se relancerait lui-même via
bashavec d’autres prompts pourrait peut-être produire quelque chose de similaire, mais cela me semble un peu moins fluide ; il faudra que je teste.Par exemple, l’un des prompts intégrés,
/prompt debug, ouvre un agent orienté débogage, et depuis cet état on peut discuter comme avec un agent normal, puis revenir à l’agent de code standard avec/prompt code.Les sous-agents ne sont pas encore pris en charge, car actuellement l’ensemble de l’agent tourne dans un seul buffer de contexte et je veux que cela reste léger. Mais comme les tâches très exploratoires gonflent souvent la fenêtre de contexte, il est probable que des sous-agents soient ajoutés.
J’ai aussi demandé à Claude Code de m’en fabriquer un, et j’y ai ajouté le hachage de lignes de Dirac pour l’édition.
Je l’ai fait en Rust, et j’avais aussi pensé à rendre l’auto-modification possible via des hooks en plugin, mais j’ai finalement opté pour une approche où il crée un fichier séparé avec des détails sur les améliorations, met à jour le code source, puis recompile.
Comme l’emplacement du code source est fixe, l’agent peut se réécrire et se reconstruire lui-même. Je l’utilise avec DeepSeek 4 Flash sur 2x RTX 6000 Pro, et j’obtiens environ 138 tok/s.
Honnêtement, c’est surtout un mélange repris de Pi, Dirac et OpenCode. Y a-t-il ici de nouvelles techniques intéressantes à reprendre ?
Je viens de l’essayer rapidement et c’était effectivement assez rapide.
Je me demande si vous cherchez des contributeurs, ou si c’est plutôt un outil personnel.
En revanche, j’ai rencontré quelques problèmes en essayant d’utiliser d’autres modèles. Avec l’endpoint compatible OpenAI d’Azure, gpt-5.5 ne fonctionne pas parce que
max_tokensdevientmax_completion_tokens.Je n’ai pas non plus trouvé de moyen de transmettre des en-têtes personnalisés, donc impossible de définir
reasoning_effortpour les modèles DeepSeek.Ce que tu décris ressemble clairement à des bugs dans la base de code, donc si possible, ce serait bien d’ouvrir un ticket GitHub distinct pour chacun.
Claude Code et Opencode fonctionnent bien chez moi.
C’est un peu drôle de voir que les agents de code tournent dans des datacenters avec plus de 1000 W de puissance et plus de 2 To de mémoire, alors que les gens se focalisent sur les derniers watts et quelques centaines de Mo de RAM de leur portable.
Au final, ce sera de toute façon négligeable face au coût énergétique de la compilation du code, mais ce n’est pas une mauvaise chose de les rendre plus rapides et plus légers.
Quand j’utilise des agents de code maintenant, la batterie se vide assez vite, ce qui est surprenant étant donné que la plupart du travail n’a pas lieu sur mon ordinateur portable.
Optimiser les agents de code côté client, ce n’est pas pour sauver le climat, c’est pour allonger mon temps de travail. En réalité, cela pourrait même être pire pour le climat.
Ce qui tourne sur les ordinateurs des autres n’est pas mon problème. Je ne contrôle pas ce qui tourne sur les serveurs d’autrui, et même si je le pouvais, ce n’est pas moi qui paie le coût de cette RAM, donc cela m’importe peu.
En revanche, la RAM de ma machine, c’est moi qui la paie. Si un TUI qui affiche moins de 1 Ko de texte occupe plusieurs Go de mémoire, au point de faire tomber d’autres applications en OOM sous Windows, ou de faire swapper Linux sur le HDD jusqu’à figer toute la machine, alors oui, je suis obligé de m’en préoccuper.
Avec un prix de la RAM multiplié par 5 dans les faits, et celui des autres composants multiplié par 2 ou 3, il est particulièrement important d’éviter le gaspillage mémoire.
Oui, le modèle est énorme et consomme beaucoup de ressources, mais le harnais peut avoir une grande influence sur la quantité de travail réellement demandée au modèle.
Par exemple, avec un ensemble d’outils puissant dans le harnais, le modèle peut travailler de manière bien plus efficace.
Comme la base de code est petite, je l’ai donnée à DeepSeek v4 Flash dans Pi pour qu’il repère d’éventuels points dangereux, et il n’a rien trouvé de particulièrement inquiétant. Beau travail.
Sur les projets Rust, si l’on n’indique pas explicitement au modèle de ne pas modifier
Cargo.tomldirectement mais d’utilisercargo add, j’ai souvent vu même Claude 4.7 Opus ajouter presque systématiquement des dépendances anciennes.J’ai vérifié manuellement les dépendances de ce projet et elles étaient toutes à jour, ce qui est appréciable. Cela ne veut évidemment pas dire qu’il n’y a pas de problèmes cachés dans les dépendances transitives.
Faire relire du code par un LLM peut très vite devenir une affaire de préférences. Par exemple, en parcourant le code, je me suis dit à plusieurs reprises que certaines méthodes convertissant des chaînes en enum et inversement auraient peut-être pu se résumer à un simple
#[derive]avecstrum. Cela aurait renduprovider.rsbien plus concis, au prix d’une seule crate sans dépendances.Pour le plaisir, j’ai demandé à DeepSeek V4 Pro en mode Max thinking d’« auditer » la base de code, et il a dit n’avoir trouvé aucun signe évident de télémétrie cachée. En revanche, il a relevé que le projet configurait le gestionnaire de panic sur
abort, et j’ai un avis tranché sur ce point.C’est sans doute pour éviter le lien avec
libunwindet économiser quelques Ko sur la taille du binaire, mais cela donne un exécutable qui s’interrompt immédiatement en cas de crash sans fournir de stack trace à l’utilisateur. Je préfère un binaire environ 50 KiB plus gros si cela permet d’obtenir des informations de débogage utiles lors d’une panic.En plus, si une panic survient dans une tâche asynchrone, on ne peut pas la récupérer pour afficher un message d’erreur normal : tout le processus s’arrête immédiatement.
DeepSeek échouait sans cesse sur une logique précise de déplacement du curseur. Pour l’optimisation mémoire, j’ai tout géré moi-même, en combinant comme je l’ai écrit ailleurs des optimisations du compilateur et l’utilisation de crates Rust fournissant des structures de données plus efficaces.
C’est amusant que ça sorte justement aujourd’hui. J’étais justement sur le point d’en commencer un en Rust moi aussi.
Quand on voit opencode fuir lentement en mémoire sur de gros projets jusqu’à atteindre 6 Go et devenir de plus en plus lent, c’est assez impressionnant.
Je vais regarder ça. Ça a l’air chouette.