gup Un outil open source
Une commande pour mettre à jour toute sa machine.
Sur un poste de développeur, les logiciels arrivent par des dizaines de canaux, chacun avec sa commande de mise à jour. gup les interroge tous d’un coup, liste ce qui est en retard et lance au même endroit ce que je coche. Je l’ai conçu et je le publie en open source.
- 153 sources de mises à jour, chacune avec ses propres règles Registre du dépôt, relevé le 13/10/2026
- 3 systèmes testés à chaque pull request : Windows, macOS et Linux Intégration continue du dépôt, relevé le 13/10/2026
- 12 versions publiées sur npm Registre npm, du 19/05/2026 au 06/10/2026
- Besoin
- Mettre à jour en une fois tout ce qui est installé sur un poste de développeur, quel que soit l’outil qui l’a installé.
- Ma part
- J’ai conçu l’outil et écrit l’essentiel de son code, de son architecture à ses 153 sources, avec ses tests et sa documentation ; je relis les contributions et je publie les versions.
- Rôle
- Auteur et mainteneur
- Période
- Depuis mai 2026
- Équipe
- Projet personnel mené par son mainteneur, ouvert aux contributions ; deux pull requests extérieures fusionnées en mai 2026
- Statut
- Open source, sur npm
- Liens publics
Une commande par outil, et aucune vue d’ensemble
Sur un poste de développeur, chaque outil a sa commande de mise à jour, son format de sortie et ses angles morts. La documentation de gup le résume ainsi : dix à quinze commandes enchaînées à la main, plusieurs fois par mois, sans savoir laquelle a oublié quoi.
gup ne remplace aucun de ces outils. Il les interroge tous en parallèle, liste ce qui est en retard et les fait travailler : c’est un chef d’orchestre, pas un gestionnaire de paquets de plus.
- Winget :
winget upgrade --id Git.Git --exact - Chocolatey :
choco upgrade all -y - Scoop :
scoop update * - Homebrew :
brew upgrade --formula - npm :
npm install -g typescript@latest - pipx :
pipx upgrade-all - uv :
uv tool upgrade --all - Cargo :
cargo install-update -a - Rustup :
rustup update - VS Code :
code --install-extension … --force - gcloud :
gcloud components update --quiet
gup une commande, toutes les sources Analyser, choisir, mettre à jour, garder une trace
Quatre écrans de la vraie application, en français, sur la machine d’exemple de son dépôt. Un clic agrandit chaque écran.
-
Analyser
gup interroge toutes les sources en parallèle. Une source en panne ne coûte que sa propre ligne : l’analyse continue.
Scoop échoue ; les treize autres sources continuent. -
Choisir
Je coche un paquet, une source entière ou tout. Avant de lancer, gup annonce les paquets qui demandent les droits administrateur.
Une seule demande de droits administrateur, en fin de lot. -
Mettre à jour
Chaque installation se déroule dans l’application, dans un vrai terminal : la barre de progression et les questions de l’installateur restent visibles.
PowerToys se télécharge dans le terminal intégré. -
Garder une trace
gup tient un journal de ce qu’il a fait et en tire un rapport. Il sait aussi programmer des paquets précis, sans rien laisser tourner en arrière-plan.
Douze mois d’activité, échecs compris.
Cocher, lancer, regarder passer les paquets
La même liste, à manipuler dans la page. Une source a échoué à l’analyse : elle reste à sa ligne, sans bloquer les autres.
Le paquet marqué « admin » passe en dernier, avec les autres paquets qui demandent des droits, derrière une seule demande.
Le vrai gup s’essaie aussi sur son site, dans une démonstration de terminal.
Le site de gupDonnées d’exemple du dépôt de gup : rien n’est installé.
Aucun paquet coché.
Sans JavaScript, la démonstration reste figée : les quatre écrans ci-dessus montrent le vrai déroulé.
Apprendre les règles de 153 outils
Le vrai travail est là : chaque outil a ses exceptions, et gup les absorbe une par une.
-
winget répond dans la langue du système : gup lit aussi sa sortie en français.
Le commit du 19/05/2026 -
winget peut s’arrêter sur une question (le dossier d’installation) et retenir tout le lot : gup lui interdit d’en poser, et donne la commande à lancer à la main.
Le commit du 06/10/2026 -
Pour Chocolatey, les codes 3010 et 1641 ne sont pas des erreurs : la mise à jour a réussi, un redémarrage est requis.
La règle dans le code -
Sur macOS, le Ruby d’Apple est figé par le système : gup l’écarte au lieu d’afficher une quarantaine de mises à jour impossibles.
La règle dans le code -
Un logiciel listé par deux sources n’apparaît qu’une fois, chez celle qui sait le mettre à jour.
La règle dans le code -
Sous Windows, chercher les outils dans le PATH figeait le terminal 3,3 à 3,8 s. Cela prend maintenant 9 ms.
Les notes de la 0.5.0
Les 153 sources de gup, par famille
Sous Windows : 139 sources possibles, 14 grisées et jamais lancées. Sous macOS : 132 sources possibles, 21 grisées et jamais lancées. Sous Linux : 126 sources possibles, 27 grisées et jamais lancées.
- Systèmes d’exploitation 6 / 15 9 / 15 4 / 15
- WSL 7 / 7 0 / 7 0 / 7
- Node.js 9 / 10 9 / 10 9 / 10
- Python 8 / 9 8 / 9 8 / 9
- Gestionnaires de versions 5 / 6 6 / 6 6 / 6
- Autres langages 13 / 14 14 / 14 14 / 14
- .NET et PHP 7 / 7 7 / 7 7 / 7
- JVM 2 / 2 2 / 2 2 / 2
- Rust 2 / 2 2 / 2 2 / 2
- Shell et terminal 5 / 5 4 / 5 4 / 5
- Cloud 12 / 12 12 / 12 12 / 12
- Infrastructure as code 10 / 10 10 / 10 10 / 10
- Kubernetes 13 / 13 13 / 13 13 / 13
- Conteneurs 6 / 6 3 / 6 3 / 6
- Sécurité 10 / 10 10 / 10 10 / 10
- Outils en ligne de commande 8 / 8 7 / 8 7 / 8
- Embarqué et mobile 5 / 6 6 / 6 5 / 6
- IDE 6 / 6 5 / 6 5 / 6
- Extensions d’éditeurs 4 / 4 4 / 4 4 / 4
- Les gestionnaires eux-mêmes 1 / 1 1 / 1 1 / 1
Registre de gup, release 0.5.3, relevé le 13/10/2026. Famille : le dossier de la source dans le code.
Tenu comme un produit
Des versions publiées, testées sur trois systèmes et documentées, pour que d’autres puissent s’en servir et y contribuer.
- 0.1.0 · 0.1.1
- 0.2.0
- 0.2.1
- 0.2.2
- 0.3.0 · 0.3.1 · 0.3.2
- 0.5.0 · 0.5.1 · 0.5.2 · 0.5.3
Registre npm, relevé le 13/10/2026. La 0.4.0, préparée dans le dépôt, n’a jamais été publiée : tout son contenu est sorti avec la 0.5.0.
-
Trois systèmes à chaque pull request
L’intégration continue rejoue les tests sous Windows, macOS et Linux.
La configuration -
Une note par version
Chaque version a ses notes : ce qui change, ce qui casse, comment migrer.
Les notes de version -
L’architecture écrite
Couches, contrats des sources, pipeline de mise à jour et décisions motivées.
L’architecture -
Une gouvernance écrite
Le projet est mené par son mainteneur ; les décisions se prennent en public, sur les issues et les pull requests.
La gouvernance -
Anglais et français
L’interface parle les deux langues ; les captures de cette page sont en français.
La configuration
Une source manque ? En général, il suffit d’un fichier, d’une ligne dans le registre et de ses tests.
Le guide de contributionSous le capot
Quatre choix d’architecture qui ne se voient pas à l’écran, puis deux garanties ; chacun se déplie sur son extrait du code public.
-
Chaque source dans son fichier, derrière un contrat code
- Contrainte
- 153 outils, dont certains plantent, bloquent ou répondent n’importe quoi.
- Choix
- Chaque source dans son propre fichier, derrière un contrat commun, sans dépendre des autres.
- Effet
- Une source en panne ne perd que sa propre ligne.
src/core/types.ts· TypeScriptexport interface Provider { readonly id: string; readonly displayName: string; readonly platforms?: PlatformSet; // … isAvailable(): Promise<boolean>; listOutdated(): Promise<OutdatedPackage[]>; update(packageId: string, options?: UpdateOptions): Promise<UpdateOutcome>; // … } -
Aucun programme lancé par un shell code
- Contrainte
- gup lance des programmes avec des noms de paquets venus de l’extérieur.
- Choix
- Tous les programmes partent d’un seul point du code, arguments en liste, sans shell. Seul Scoop, qui l’exige, passe par une liste blanche contrôlée ; un test refuse tout nouvel appel à un shell.
- Effet
- Un nom de paquet reste un argument, jamais une commande.
tests/security/shell-usage.test.ts· TypeScriptit("no source file uses child_process directly — runner.ts is the single chokepoint", async () => { const files = await walk(SRC_ROOT); const offenders: string[] = []; for (const file of files) { const rel = toPosixRel(file); if (rel === "src/core/runner.ts") continue; const content = await readFile(file, "utf8"); if (/from\s+["']node:child_process["']/.test(content)) offenders.push(rel); if (/require\(["']child_process["']\)/.test(content)) offenders.push(rel); } expect(offenders).toEqual([]); }); -
Un paquet par appel au gestionnaire code
- Contrainte
- Une installation peut échouer ou dépasser son délai au milieu d’un lot.
- Choix
- Un paquet par appel au gestionnaire, même quand l’outil sait tout mettre à jour d’un coup, au prix de quelques lancements de plus.
- Effet
- Un échec ne fait tomber qu’une installation, jamais le lot entier.
src/core/update/apply-update.ts· TypeScriptasync function settledUpdate( provider: Provider, packageId: string, update: UpdateOptions | undefined, ): Promise<UpdateOutcome> { try { return update ? await provider.update(packageId, update) : await provider.update(packageId); } catch (error) { return { id: packageId, success: false, message: rejectionMessage(error) }; } } -
Un gup éphémère toutes les 15 minutes code
- Contrainte
- Programmer des mises à jour sans laisser un programme tourner en permanence.
- Choix
- Le planificateur du système lance un gup éphémère toutes les 15 minutes, seulement si une programmation existe.
- Effet
- Rien ne tourne en arrière-plan.
src/core/scheduler/scheduler-timing.ts· TypeScript/** * MAX_RUN_MINUTES + cap < TICK_WATCHDOG_MINUTES < EXECUTION_TIME_LIMIT_MINUTES * 120 + 30 < 170 < 180 */ /** How often the OS trigger starts a tick: latency against wake-ups. */ export const TICK_INTERVAL_MINUTES = 15; -
Chaque système voit ses outils code
Une source d’un autre système est grisée et n’est jamais lancée, même si un exécutable du même nom traîne dans le PATH.
Le filtre par systèmesrc/core/platform/is-supported-on.ts· TypeScriptexport function isSupportedOn( subject: PlatformScoped, platform: NodeJS.Platform = process.platform, ): boolean { return subject.platforms === undefined || subject.platforms.includes(platform); } -
Lisible partout, couleurs personnalisées comprises code
27 thèmes, et chaque texte atteint le contraste WCAG AA, couleurs personnalisées comprises.
La garantie de contrastesrc/ui/theme/contrast-rules.ts· TypeScript/** Minimum ratios: text (WCAG 1.4.3 / 1.4.6) and UI elements (1.4.11, which has no AAA). */ export const CONTRAST_TARGETS: Readonly<Record<ContrastLevel, { text: number; ui: number }>> = { AA: { text: 4.5, ui: 3 }, AAA: { text: 7, ui: 3 }, };
En une phrase
Un seul travail, tenu sur 153 sources et trois systèmes : mettre à jour ce qui est déjà installé sur une machine, quel que soit l’outil qui l’a installé.
Sources et méthode : chiffres, dates, méthode et crédits
Sources. Les 153 sont comptées à l’exécution dans le registre de gup, à la release 0.5.3 (commit 0c0e85a du 06/10/2026), le 13/10/2026. La famille est le dossier de la source dans le code ; le système, l’ensemble déclaré par la source dans le catalogue : 14 sources grisées sous Windows, 21 sous macOS, 27 sous Linux.
Versions. Douze versions publiées sur npm, de la 0.1.0 (19/05/2026) à la 0.5.3 (06/10/2026), d’après les dates du registre npm relevées le 13/10/2026. La 0.4.0 n’a jamais été publiée. Les téléchargements npm ne sont pas affichés : ils se concentrent les jours de publication et ne mesurent pas un usage.
Écrans et démonstration. Les quatre écrans et celui de l’en-tête sont produits par le générateur de captures du dépôt, à la release 0.5.3, interface en français, sur sa machine d’exemple : des versions inventées, aucune machine réelle, aucun gestionnaire lancé. La démonstration reprend les mêmes paquets. Les commandes de la première figure sont lues dans les fichiers des sources, à la même révision.
Le problème. « Dix à quinze commandes, plusieurs fois par mois » traduit la page de cadrage du projet. Les décisions d’architecture sont décrites dans ses décisions notables. La règle « sans shell » a une exception écrite : Scoop, lancé par un shell sur une liste blanche (architecture, ligne 484). La phrase de clôture traduit la première ligne de la page de cadrage, avec les relevés de l’en-tête.
Contributions. La règle des codes 3010 et 1641 de Chocolatey et le lot administrateur unique viennent d’une contribution extérieure de mai 2026 : les pull requests n° 22 et n° 23, fusionnées le 20/05/2026. Le reste de l’historique, à la release 0.5.3 : 856 commits de l’auteur et 29 de Dependabot.
Sous le capot. Extraits du dépôt public, à la release 0.5.3 (0c0e85a), relus le 15/10/2026.