npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bloom-terminal

v0.1.0

Published

Terminal Bloom : se connecter a l'app Bloom Experience depuis un poste de travail et y lancer des operations.

Readme

Terminal Bloom

Le programme que l'on installe sur un poste de travail pour agir sur l'app Bloom depuis un terminal. Il ne contient aucune connaissance métier : il connecte, garde la session, transmet les commandes à l'app et affiche la réponse. Le catalogue de ce qui est faisable vit dans l'app, pas ici, ce qui permet d'ajouter une capacité sans réinstaller quoi que ce soit.

À ne pas confondre avec le dossier cli/ du dépôt, qui est l'outil interne d'administration : celui-là passe par une clé maîtresse et n'est pas partageable. Les deux ne se mélangent jamais.

Commandes

bloom login          # ouvrir une session (mot de passe demandé à l'invite)
bloom qui-suis-je    # qui est connecté, et ce que cette personne peut lancer
bloom logout         # fermer la session ici et côté serveur

bloom qui-suis-je est le bon premier appel d'une session Claude Code : il évite de tâtonner en lançant des commandes qui seront refusées.

Tout le reste passe par la forme bloom <domaine> <objet> <action> [options], détaillée ci-dessous. Ce programme ne connaît lui-même aucun domaine, aucun objet, aucune action : tout vient de l'app, interrogée à la demande. Ajouter une capacité côté app la rend donc disponible ici sans rien réinstaller.

L'aide en escalier

Deux marches, jamais plus d'une à la fois — le catalogue complet ne s'affiche jamais en un seul geste, quelle que soit la combinaison de paramètres tentée. C'est voulu : c'est l'économie de contexte qui a fait préférer ce terminal au format MCP, et une aide qui déballerait tout l'annulerait.

bloom --help                # les domaines existants, une ligne chacune
bloom commercial --help     # le détail des seules opérations du domaine « commercial »

Le détail d'un domaine (deuxième marche) montre, pour chaque opération : son identifiant complet (commercial.devis.lister), une phrase de description, si elle écrit ou lit seulement, si elle est destructive, et ses paramètres (nom, type, obligatoire ou non). Il ne montre jamais le détail d'un second domaine en même temps.

L'aide est gardée un court moment sur le poste (cinq minutes) pour ne pas refaire un aller-retour à chaque commande ; elle se rafraîchit d'elle-même passé ce délai, sans geste à faire, pour qu'une capacité ajoutée côté app apparaisse rapidement.

Lancer une opération

bloom commercial devis lister --entite_id bloom --statut envoye
bloom commercial devis supprimer --id <uuid> --confirmer

Chaque mot après bloom se traduit directement : le premier domaine, le deuxième l'objet, le troisième l'action — commercial devis lister devient l'opération commercial.devis.lister. Les options suivantes (--cle valeur, --cle=valeur, ou --cle seul pour un booléen) deviennent les arguments de l'opération, tels quels. Ce programme ne valide rien lui-même : c'est l'app qui juge si l'opération existe et si les paramètres conviennent, avec un message qui dit quoi corriger sinon (PARAMETRE_INVALIDE, OPERATION_INCONNUE…).

Confirmation. Une opération destructive (une suppression, par exemple) est refusée par l'app tant que --confirmer n'est pas ajouté à la même commande. Il n'y a pas de confirmation interactive : depuis un terminal piloté par Claude Code, la relance explicite du même appel avec --confirmer est le geste qui vaut accord.

Sorties. Par défaut, la réponse est mise en forme pour être lue. Ajouter --json (n'importe où après le domaine) pour recevoir la forme brute, telle que l'app l'a rendue — utile pour l'enchaînement plutôt que la lecture.

Listes tronquées. Une opération *.lister ne renvoie que 20 lignes par défaut, 100 au plus. En sortie lisible, une page qui ne montre pas tout se signale explicitement, avec le paramètre à ajouter pour voir la suite (--offset <n>, et --limite jusqu'à 100 si besoin) — sans cela, rien ne dit qu'il en restait, et une liste de 20 lignes sur 45 se lirait comme le compte entier.

Erreurs. Un refus de l'app garde son code stable (DROIT_INSUFFISANT, PARAMETRE_INVALIDE, CONFIRMATION_REQUISE…) et un message en français qui dit quoi faire — relancer la connexion, corriger un paramètre, ou rajouter --confirmer. Le code de sortie du programme est alors 1.

Le mot de passe n'entre que par l'invite masquée

C'est la règle centrale de ce programme, et elle est volontairement rigide. Le mot de passe est refusé s'il est passé en paramètre (--mot-de-passe, -p, --password…), par variable d'environnement (BLOOM_MOT_DE_PASSE et équivalents) ou par entrée redirigée (echo … | bloom login). Sans terminal interactif, la commande échoue en expliquant pourquoi.

La raison : ce terminal est piloté par Claude Code. Un mot de passe fourni autrement qu'à l'invite resterait écrit dans un historique de conversation, dans l'historique du shell et dans les journaux de la machine, c'est-à-dire à trois endroits où personne ne pense à aller l'effacer.

La session sur le disque

Le laissez-passer et son moyen de renouvellement sont écrits dans ~/.bloom/session.json, en 0600, dans un dossier 0700. Le mot de passe n'y est jamais écrit : il est échangé contre un jeton à la connexion, puis oublié.

Les permissions sont revérifiées à chaque lecture : un fichier devenu lisible par d'autres comptes fait échouer la commande avec la marche à suivre, plutôt qu'un simple avertissement qui passerait inaperçu.

Le jeton d'accès vaut une heure. Quand l'app répond qu'il a expiré, le programme le renouvelle et rejoue l'appel une seule fois, sans le dire. Il n'y a pas de reprise en boucle : si le second essai échoue aussi, la commande s'arrête et renvoie vers bloom login.

Configuration

Le paquet ne contient que deux valeurs, toutes deux publiques : l'adresse de l'app et la clé publique Supabase, la même que celle déjà servie dans le site web. Aucune clé d'administration ne doit y entrer, et le programme refuse de démarrer s'il en reconnaît une (terminal/src/config.ts, vérifié par terminal/paquet.test.ts).

Ces valeurs sont figées dans src/config.ts au moment de publier le paquet (BLO-608). En attendant, et pour viser un déploiement d'essai, elles se surchargent par l'environnement :

| Variable | Rôle | |---|---| | BLOOM_APP_URL | Adresse de l'app à interroger | | BLOOM_SUPABASE_URL | Adresse du serveur d'authentification | | BLOOM_SUPABASE_ANON_KEY | Clé publique Supabase |

Développement

bun run test            # depuis la racine du dépôt : les tests de ce dossier y sont inclus
cd terminal && npx tsc -p tsconfig.json   # fabrique dist/, ce qui part sur npm

Le paquet doit rester installable seul : aucun fichier de terminal/ n'importe quoi que ce soit du reste du dépôt, et paquet.test.ts échoue si cela arrive. Seul dist/ est publié (files dans package.json), donc ni les tests ni le faux terminal qui les sert.