Brume permet de partager un plan Markdown ou MDX, de publier un site HTML statique ou d’exposer temporairement un serveur local.
Le CLI couvre ces trois usages:
| Commande | Usage |
|---|---|
brume plan |
Prévisualiser, construire, publier et gérer un plan Markdown ou MDX. |
brume deploy |
Publier tel quel le contenu d’un dossier HTML statique. |
brume tunnel |
Donner une URL publique temporaire à un serveur HTTP local. |
Les publications, les tunnels et les commandes de gestion nécessitent une connexion.
brume loginLa commande ouvre GitHub sur auth.brume.dev, puis conserve en clair dans ~/.brume/credentials.json un access token d’une heure et un refresh token rotatif de 90 jours.
Le CLI renouvelle automatiquement l’access token.
La prévisualisation et la construction locale d’un plan fonctionnent sans connexion.
Pour afficher toutes les options disponibles:
brume --help
brume plan --help
brume deploy --help
brume tunnel --helpLa commande brume plan transforme un dossier de documents en site navigable.
Le dossier doit contenir une page d’entrée nommée index.mdx, index.md, plan.md ou README.md.
brume plan preview ./mon-planLa prévisualisation démarre un serveur local et ouvre le plan dans le navigateur. Le dossier courant est utilisé si aucun chemin n’est fourni.
brume plan preview
brume plan preview ./mon-plan --port 3000
brume plan preview ./mon-plan --no-openSans --port, Brume choisit un port disponible.
L’option --no-open empêche l’ouverture automatique du navigateur.
brume plan build ./mon-planPar défaut, le résultat est écrit dans ./mon-plan/.brume/dist.
Utiliser --destination pour choisir un autre dossier.
brume plan build ./mon-plan --destination ./distbrume plan deploy ./mon-planUn nouveau plan utilise l’authentification token par défaut.
Les modes disponibles sont token, password et none.
brume plan deploy ./mon-plan --slug architecture-v2
brume plan deploy ./mon-plan --auth none
brume plan deploy ./mon-plan --auth password
printf '%s' "$SITE_PASSWORD" | brume plan deploy ./mon-plan --auth password --password-stdin
brume plan deploy ./mon-plan --auth token --no-overlay --pin--slugchoisit la dernière partie de l’URL.--authchoisit le mode d’authentification.--password-stdinlit le mot de passe depuis l’entrée standard dans un contexte non interactif.--no-overlaydésactive la toolbar Brume.--pinempêche l’expiration automatique du plan.
Avec --auth password, le CLI demande et confirme le mot de passe sans l’afficher.
Le mot de passe ne peut pas être passé dans un argument, le fichier de configuration ou une variable d’environnement.
Sans --slug, Brume utilise le slug défini dans brume.toml, puis le nom du dossier en dernier recours.
Une republication avec le même slug remplace atomiquement la version active.
Un fichier brume.toml optionnel placé à la racine du plan évite de répéter les mêmes options.
[plan]
title = "Plan Brume"
entry = "index.mdx"
slug = "brume-v1"
auth = "token"
overlay = trueLes options passées dans la commande remplacent les valeurs de brume.toml.
Les commandes suivantes utilisent le slug du plan:
brume plan list
brume plan show brume-v1
brume plan open brume-v1
brume plan auth brume-v1 none
brume plan auth brume-v1 password
printf '%s' "$SITE_PASSWORD" | brume plan auth brume-v1 password --password-stdin
brume plan pin brume-v1
brume plan unpin brume-v1
brume plan delete brume-v1plan list affiche notamment le mode d’authentification, la dernière lecture et la date d’expiration.
Dans un terminal interactif, les dates sont raccourcies et les URL complètes des plans sont cliquables.
plan delete demande une confirmation avant de supprimer définitivement le plan et ses fichiers.
L'option globale --output json produit des données structurées sur la sortie standard et fonctionne avec toutes les commandes.
Elle peut être placée avant ou après les sous-commandes.
brume plan list --output json
brume plan show brume-v1 --output json
brume deploy ./dist --output json
brume deploy list --output jsonLes commandes longues comme plan preview et tunnel produisent un objet JSON par événement, séparé par une nouvelle ligne.
Les diagnostics et les confirmations interactives restent sur la sortie d'erreur afin de ne pas corrompre la sortie JSON.
Le mode token utilise un token Bearer stable par destinataire.
Un destinataire n’a pas besoin de compte Brume.
Son token possède un identifiant public et peut recevoir une permission de lecture sur plusieurs plans ou déploiements.
Les permissions restent sur le serveur et une révocation prend effet immédiatement.
Le propriétaire peut créer depuis la toolbar une invitation à usage unique valable un jour.
Le destinataire peut associer l’invitation à son token existant ou laisser Brume créer un nouveau token.
Un nouveau token est affiché une seule fois et ne peut pas être récupéré.
Le même token peut être collé sur un autre navigateur ou envoyé directement dans l’en-tête Authorization: Bearer.
Le mode password affiche l’écran Brume avant de charger le site.
Une authentification réussie crée une session d’un jour limitée à ce site.
Le mode none rend le site accessible sans authentification.
Un changement de mode ou de mot de passe invalide immédiatement les sessions et invitations du site.
Brume conserve le token principal uniquement sur auth.brume.dev.
Chaque domaine reçoit une session distincte d’un jour, afin que le JavaScript d’un site déployé ne puisse jamais lire le token principal.
Brume ajoute par défaut un bouton rond ☁️ en bas à droite de chaque plan ou site statique hébergé.
Il ouvre une toolbar compacte inspirée de l’interaction de la Vercel Toolbar.
Elle permet de copier ou partager l’URL.
La gestion des invitations, des destinataires et de l’authentification s’ouvre sur le domaine d’authentification Brume.
Seule l’identité GitHub ayant déployé le site peut utiliser ces contrôles de gestion.
La toolbar peut être déplacée à gauche ou à droite et mémorise sa position dans le navigateur.
--no-overlay ou overlay = false la désactive.
La prévisualisation et les builds locaux ne contiennent jamais cette toolbar.
La commande brume deploy publie directement le contenu d’un dossier sans passer par le renderer Markdown.
Le serveur injecte le CSS et le JavaScript de la toolbar dans chaque document HTML pendant le déploiement.
La toolbar est donc servie directement avec le bundle, sans iframe ni réécriture à la lecture.
Le dossier doit contenir un fichier index.html à sa racine.
brume deploy ./distLe dossier courant est utilisé si aucun chemin n’est fourni.
Sans --url, le serveur génère un identifiant public aléatoire.
brume deploy ./dist --url mon-app
brume deploy ./dist --url mon-spa --spa
brume deploy ./dist --url documentation --auth none --pin
brume deploy ./dist --url demo --auth passwordAvec --url mon-app, le déploiement est disponible à l’adresse https://mon-app-<handle>.brume.dev/.
--urlchoisit le slug utilisé dans l’URL publique.--spaactive le fallback versindex.htmlpour une application monopage.--auth,--password-stdinet--no-overlaysuivent les mêmes règles queplan deploy.--pinempêche l’expiration automatique du déploiement.
L’option --spa sert index.html pour les routes GET inexistantes sans extension, tout en conservant une réponse 404 pour les assets inexistants.
Les chemins de fichiers exacts et les fichiers index.html des sous-dossiers sont servis normalement.
Chaque fichier est limité à 20 MiB, avec une limite de 100 MiB et 5 000 fichiers par déploiement.
Les liens et les chemins d’assets ne sont pas réécrits.
Le site est servi depuis la racine de son propre sous-domaine, donc les chemins absolus comme /assets/app.js fonctionnent directement.
Comme les plans, les déploiements non pin expirent après quinze jours sans lecture et une republication remplace atomiquement la version active.
Lister les déploiements actifs:
brume deploy list
brume deploy show mon-app
brume deploy auth mon-app none
brume deploy auth mon-app passwordLa liste contient le slug, l’identifiant UUID, le type de site, le mode d’accès, la rétention et l’URL publique. Un déploiement peut être supprimé avec son slug ou son UUID:
brume deploy delete mon-app
brume deploy delete 019f0000-0000-7000-8000-000000000000La suppression demande une confirmation avant de supprimer définitivement le déploiement et tous ses fichiers.
L’option --yes désactive la confirmation interactive pour les scripts:
brume deploy delete mon-app --yesLa commande brume tunnel rend accessible un serveur qui écoute sur 127.0.0.1.
Démarrer d’abord le serveur local, puis indiquer son port et le slug public à Brume.
brume tunnel 3000 --url mon-app--url est optionnel.
Sans cette option, le serveur génère un identifiant public aléatoire.
La commande affiche l’URL publique une fois la connexion établie:
https://mon-app-<handle>.brume.dev
Le tunnel reste actif tant que la commande tourne.
Utiliser Ctrl-C pour l’arrêter.
Les requêtes HTTP, les corps en streaming et les WebSockets sont relayés vers http://127.0.0.1:3000.
Le chemin public est transmis tel quel au serveur local, sans préfixe ajouté ou retiré.
L'URL est publique et ne doit pas exposer un service local contenant des données sensibles.
L'option --review de brume plan deploy et brume deploy ouvre un round de revue sur le site publié.
Chaque visiteur autorisé peut surligner du texte ou cibler un élément de la page pour ouvrir un fil de commentaires, comme dans Notion.
Les fils acceptent des réponses et un visiteur anonyme peut indiquer son nom.
Le panneau Brume affiche le nombre de commentaires et le bouton Finish review termine la revue.
La revue passe par le JavaScript injecté de la toolbar, donc --no-overlay désactive aussi les commentaires.
brume plan deploy ./mon-plan --review
brume deploy ./dist --reviewChaque déploiement remplace le round ouvert, et --review en ouvre un nouveau.
Les rounds précédents restent stockés avec le statut superseded et leurs commentaires restent accessibles par numéro de round.
L'agent qui a publié le site suit la revue avec les commandes suivantes:
brume review status mon-plan
brume review comments mon-plan --round 2
brume review wait mon-plan --interval 5 --timeout 3600
brume review status mon-app --site--site cible un déploiement statique au lieu d'un plan.
brume review wait interroge le serveur jusqu'à la fin de la revue puis affiche les commentaires.
Toutes ces commandes acceptent --output json.
Les outils MCP review_status et review_comments exposent le même cycle aux agents.
Les slugs passés à --slug contiennent entre 1 et 80 caractères.
Pour --url, le slug et le handle doivent tenir ensemble dans la limite DNS de 63 caractères du sous-domaine.
Ils acceptent uniquement les lettres ASCII minuscules, les chiffres et les tirets internes.
Exemples valides: documentation, mon-app et api-v2.
brume version
brume mcp configbrume version affiche la version du CLI, le SHA court, le titre et le corps du message du commit utilisé pour le construire.
brume mcp config affiche la configuration MCP à copier dans Codex.
Le renderer accepte Markdown, GFM, Mermaid et un ensemble fermé de composants MDX: Accordion, Accordions, Callout, Card, CardGrid, CodeGroup, Decision, FileTree, Mermaid, Risk, Step, Steps, Tab et Tabs.
Les imports, exports, expressions JavaScript et spread props MDX sont refusés.
Le serveur assainit une seconde fois le HTML avant de le stocker.
Les documents du dossier deviennent automatiquement des pages.
Les liens Markdown vers d’autres fichiers .md ou .mdx sont réécrits vers leur route publiée.
Les images PNG, JPEG, GIF et WebP sont copiées comme assets du bundle.
Après brume login, la commande suivante affiche la configuration MCP à copier dans Codex:
brume mcp configLe serveur MCP permet de lister les plans et leur dernière lecture, inspecter un plan, déployer un dossier, changer son authentification, le pin, l’unpin et le supprimer avec une confirmation en deux étapes.
crates/brume-clicontient la commandebrume.crates/brume-servercontient l’API, l’authentification GitHub et les serveurs des plans et déploiements statiques.crates/brume-mcpexpose les opérations de gestion aux agents via MCP stdio.crates/brume-corecontient le contrat partagé des plans et des bundles.crates/brume-api-clientcontient le client HTTP utilisé par le CLI et le MCP.renderercontient le renderer React 19, MDX 3, Mermaid et Shiki.migrationscontient le schéma PostgreSQL.brunocontient les tests de bout en bout du backend.
Le développement nécessite Rust 1.97 avec rustfmt et clippy, Bun 1.3.14 ou plus récent, Docker et Bruno CLI.
Chaque commit doit incrémenter la version SemVer du workspace dans Cargo.toml et synchroniser Cargo.lock.
Les scripts de build refusent une version invalide, inchangée ou inférieure à celle du commit parent.
Ils incorporent également le SHA complet, le titre et le corps du message du dernier commit dans les binaires CLI et serveur.
Le script du CLI compile le renderer web et le worker Bun autonome, puis incorpore les trois artefacts dans le binaire Rust.
./scripts/build-cli.sh --releaseLe serveur incorpore uniquement le runtime web et la feuille de style.
./scripts/build-server.sh --releasePour tout construire:
./scripts/build-all.sh --releaseLe cross-build du CLI accepte aussi --target <triple-rust> pour les cibles macOS, Linux et Windows reconnues par scripts/build-renderer.sh.
Copier .env.example vers .env, puis démarrer PostgreSQL:
docker compose up -d postgresConstruire et démarrer le serveur:
./scripts/build-server.sh
set -a
source .env
set +a
target/debug/brume-server servePour créer un token local sans GitHub OAuth:
target/debug/brume-server create-dev-token --github-id 1 --login paulCette commande est destinée au développement local et utilise la même base configurée que le serveur.
Le test backend complet démarre PostgreSQL, lance le serveur, publie la fixture via le CLI puis vérifie les routes de gestion et la suppression avec Bruno:
./scripts/e2e-bruno.shCréer quatre ressources dans le même projet Railway:
- Un service web lié à ce dépôt et configuré avec
railway.toml. - Un service PostgreSQL.
- Un Storage Bucket Railway.
- Un service Cron lié au même dépôt, avec
/railway.gc.tomlcomme chemin Config as Code.
Le service web exécute automatiquement les migrations au démarrage.
Le Cron exécute garbage-collect chaque heure et supprime les plans et déploiements non pin après quinze jours sans lecture.
Une lecture est enregistrée après cinq secondes continues avec la page visible et les écritures sont limitées à une fois par heure et par plan.
Pour un déploiement statique, une réponse HTML enregistre directement la lecture, au maximum une fois par heure.
Variables du service web et du Cron:
BRUME_API_PUBLIC_URL=https://api.brume.dev
BRUME_AUTH_PUBLIC_URL=https://auth.brume.dev
BRUME_PLAN_PUBLIC_URL=https://plan.brume.dev
BRUME_PUBLIC_DOMAIN=brume.dev
BRUME_DATABASE_URL=${{Postgres.DATABASE_URL}}
BRUME_STORAGE_BACKEND=s3
BRUME_GITHUB_CLIENT_ID=...
BRUME_GITHUB_CLIENT_SECRET=...
BRUME_GITHUB_ALLOWED_IDS=123456Injecter aussi les credentials du Bucket dans les deux services.
Brume accepte les variables Railway natives ENDPOINT, REGION, BUCKET, ACCESS_KEY_ID, SECRET_ACCESS_KEY, ou les variantes AWS produites par railway bucket credentials.
La valeur AWS_S3_URL_STYLE=virtual correspond aux buckets Railway récents.
Pour un ancien bucket path-style, utiliser AWS_S3_URL_STYLE=path.
Créer une GitHub OAuth App avec https://auth.brume.dev/auth/github/callback comme callback URL.
Le champ BRUME_GITHUB_ALLOWED_IDS est une liste d’identifiants GitHub numériques séparés par des virgules.
Une liste vide autorise tous les comptes GitHub.
Configurer api.brume.dev, auth.brume.dev, plan.brume.dev et *.brume.dev vers le même service web.
Le CLI et le MCP utilisent api.brume.dev, GitHub OAuth utilise auth.brume.dev, et les plans utilisent plan.brume.dev.
Tous les autres sous-domaines sont réservés aux tunnels et aux déploiements statiques.
Le token principal et la session GitHub restent limités à auth.brume.dev.
Les plans et les sous-domaines wildcard reçoivent uniquement des sessions de site limitées à leur chemin ou leur hôte.
Le service doit rester sur une seule réplique tant que le registre des tunnels n’est pas distribué.
Le domaine brume.dev reste réservé au site marketing.
Le serveur sélectionne le routeur à partir de l’en-tête Host, sans réécriture de chemin par le proxy.
Le healthcheck Railway est /health et vérifie également PostgreSQL.
Chaque déploiement charge un nouveau bundle puis bascule la référence active dans une transaction PostgreSQL. Une republication remplace atomiquement la version visible et réinitialise sa fenêtre de rétention. L’ancien bundle est supprimé après la bascule. Un plan pin n’expire pas. La suppression manuelle demande un challenge court avant d’effacer le bundle et la ligne PostgreSQL.