← Retour au site Chargement…

notabene

Référence

note this well

Généré le 1 août 2026

Référence

Référence

Le pendant exhaustif du Guide — tableaux et contrats, une page par surface :

CLI

CLI

Le package npm est scopé (@z29k/notabene) ; la commande installée est simplement notabene, donc npx notabene … fonctionne tel quel dès lors que le package est une dépendance de votre repo. Sans installation locale, utilisez toujours le nom scopé — npx -y @z29k/notabene@latest … — car notabene non scopé n’est pas notre package.

CommandeCe qu’elle fait
notabene doctorÉtat en lecture seule au format JSON : config/store/port + dossiers de doc détectés — --json
notabene initÉcrit notabene.config.mjs + crée le store (sans effet s’il existe déjà) ; --detect auto-détecte les dossiers de doc. Écrit aussi le point d’entrée agent : <store>/protocol.md + un bloc borné dans AGENTS.md — désactivables via --no-protocol / --no-agents-md. Idempotent : relancez-le pour rafraîchir les deux
notabene devDémarre le serveur de revue sur les docs de ce repo (rechargement à chaud) ; --detach le lance en démon d’arrière-plan. Avec la dépendance de dev optionnelle pagefind, sa recherche devient plein texte aussi
notabene statusLe serveur détaché tourne-t-il ? (pid, port, URL) — --json
notabene stopArrête le serveur détaché
notabene buildConstruit le site (Node standalone ; docs prérendues, pas d’API d’écriture dans l’artefact)
notabene build --publicSite statique en lecture seule pour hébergement public — voir le guide. [--site URL] [--base /sub] [--out DIR]. Avec la dépendance de dev optionnelle pagefind, l’artefact gagne une recherche plein texte statique
notabene previewSert le site construit
notabene lintValide les liens inter-docs contre les routes émises par le dernier build (suggestions « did you mean » ; --json). Après build --public, attrape aussi les liens de pages publiques vers du contenu privé. Exit 1 = liens cassés, 2 = pas encore de build
notabene pdfExporte un PDF via Chromium headless (sommaire de signets + numéros de page) ; --scope doc|space:K|folder:K/P|page:K/I, --locale, --out, --chrome. Nécessite la peer dep optionnelle puppeteer (ou puppeteer-core + --chrome)
notabene migrateConvertit le store vers la disposition un-fichier-par-commentaire (estampille schemaVersion 3)
notabene comments lsListe les commentaires — --open --json --page <p> (pour agents/scripts)
notabene comments doneMarque des commentaires traités : done <id…> [--note <texte>] [--journal <entryId>]. Le statut vient de review (auto → resolved, approve → addressed) — --status force, --force agit sur un commentaire en attente (hold). Écriture atomique ; tous les autres champs préservés
notabene comments reopenRenvoie des commentaires à open : reopen <id…> [--reply <texte>] [--author <nom>] — la raison devient une réponse du thread que l’agent lira à la passe suivante (le pendant CLI du rejet sur /review)
notabene comments verifyAudite le store : statuts, liens commentaire↔journal dans les deux sens, disposition des fichiers, doublons, pages disparues. --json ; exit 1 si erreurs, 2 sans store. À lancer après une passe d’agent, ou en CI
notabene journal addAjoute une entrée de journal JSON lue depuis stdin (écriture atomique ; --json renvoie { id } pour chaîner côté agent)
notabene protocolImprime le protocole agent sur stdout — --path affiche son chemin, --write rafraîchit <store>/protocol.md

Flags globaux

FlagSignification
--root <path>Racine du repo consommateur (défaut : cwd)
--config <path>Chemin de la config (défaut : <root>/notabene.config.mjs)
--port <n>Port du serveur de dev (sinon la config port, sinon un port libre)
--detachdev uniquement : démon d’arrière-plan (géré par status/stop)
--detectinit uniquement : préremplit roots[] avec les dossiers de doc trouvés
--no-protocol / --no-agents-mdinit uniquement : ne pas écrire la copie <store>/protocol.md / le bloc AGENTS.md
--hostExpose sur le LAN — réseaux de confiance uniquement (sécurité)
--public / --site / --base / --outbuild uniquement : l’artefact de site public

Clés de configuration

Clés de configuration

notabene.config.mjs est un module ES de données uniquement à la racine de votre repo ; chaque clé est optionnelle. La version narrative, avec exemples, se trouve dans le guide de configuration.

CléDéfautSignification
siteName / tagline"Docs" / "docs"Marque de l’en-tête
locale"en"Langue de l’UI + collation du tri de la nav
format"mdx""mdx" (.mdx strict + .md tolérant) ou "commonmark" (pas de MDX du tout). init génère "commonmark"
roots[][{docs}]Espaces de doc : { key, label, path, exclude, description, publish }. label/description acceptent une map par locale avec l’i18n ; publish: false garde l’espace hors des builds publics
store"docs/.notabene"Dossier commentaires + journal — committez-le (contrat)
homePage d’accueil personnalisée : un fichier Markdown relatif au repo (ou une map par locale) rendu au-dessus des cartes d’espaces sur /
brandingAssets d’identité : { logo, logoDark, favicon, socialImage }, fichiers relatifs au repo servis sous /_nb/…. Favicon non défini → une marque par défaut intégrée
themePersonnalisation du rendu : { tokens, css, assets, code } — surcharges de tokens --nb-* (validées ; une coquille lève une erreur), une feuille de style chargée après celle du renderer (sûre vis-à-vis des cascade layers), un dossier du repo servi sous /_nb/assets/… pour les polices/images (allow-list d’extensions, pas de traversée), un thème Shiki pour le code ("github-light" ou { light, dark } — les deux palettes suivent le sélecteur de schéma), et mermaid: false pour garder la palette de diagrammes propre à Mermaid
navLiens sortants : { header[], sidebar: { title, links[] }, footer: { links[], text, poweredBy } }. Une seule forme d’entrée — { label, href, icon, iconOnly, publish } ; label accepte une map par locale, publish: false garde un lien hors des builds publics. Validé au chargement (allow-list de schémas, noms d’icônes, doublons)
port3009Port d’astro dev
hostfalsetrue/NOTABENE_HOST=1/--host expose l’API d’écriture au LAN (sécurité)
verify[][]Vérifications post-édition que l’agent exécute (le build du renderer s’exécute toujours)
review"auto""auto" = l’agent résout les commentaires ; "approve" = l’agent propose (addressed), vous validez chacun sur /review avec un diff (boucle de revue)
authorgit user.nameAuteur de commentaire par défaut ; chaque navigateur le remplace par appareil via le dialogue d’identité
authorEmailgit user.emailE-mail d’auteur par défaut ; intégré façon git (Name <email>) pour garder les identités uniques
editPatternLien « Modifier cette page » sous chaque page : une URL avec un placeholder {path} (chemin source relatif au repo), ex. https://github.com/o/r/edit/main/{path}. Placeholder obligatoire — validé au chargement
pdf{ enabled: true, pageSize: "A4", margin: "18mm" }Export PDFenabled active le menu Export + les routes /print ; pageSize/margin définissent la boîte @page
i18nDoc multilingue : { locales, defaultLocale, strategy: "directory"|"suffix" }. Omettez pour une seule langue
publishCible du build public : { site, base, exclude }. site optionnel — omis = artefact agnostique de l’origine

Surcharges CLI/env

--site/--base surchargent publish.site/publish.base ; NOTABENE_HOST=1 équivaut à host: true ; la CLI passe l’identité git du repo comme repli pour author/authorEmail. Rien d’autre n’est configurable hors de ce fichier.

Frontmatter

Frontmatter

Du YAML optionnel tout en haut d’une page. Tout a un défaut raisonnable — un repo sans aucun frontmatter se rend très bien (noms de fichiers humanisés, ordre alphabétique).

---
title: Internal network map        # <title> de la page + fil d'Ariane (prime sur le premier H1)
description: Segments and VLANs.   # builds publics : meta description + OpenGraph + JSON-LD
publish: false                     # builds publics : exclut cette page entièrement
lastUpdated: 2026-05-04            # pied de page : prime sur la date git « Mis à jour le »
sidebar:
  label: Network map               # texte de la sidebar (sinon title, sinon nom de fichier humanisé)
  order: 9                         # position parmi les pages sœurs (croissant)
  indexLabel: Start here           # pages d'accueil de dossier : renomme l'entrée « Aperçu »
---
CléEffet
title<title> de la page, fil d’Ariane, titre du résultat de recherche. Se replie sur le premier # H1, puis sur le nom du fichier
descriptionBuilds publics : <meta name="description">, description OpenGraph/Twitter, JSON-LD
publish: falseBuilds publics : la page n’est pas construite — ni route, ni nav, ni recherche, ni llms, ni double, ni sitemap. Les builds dev/normaux la montrent toujours
lastUpdatedPrime sur la date dérivée de git dans le Mis à jour le du pied de page. Toute date que YAML sait parser. Utile quand l’historique git induit en erreur (contenu importé ou généré)
sidebar.labelTexte de l’entrée dans la sidebar. Résolution : sidebar.labeltitle → nom de fichier humanisé
sidebar.orderClé de tri parmi les pages sœurs, croissante. Les entrées sans valeur gardent l’ordre alphabétique, après celles qui sont ordonnées. Groupes et pages partagent un seul ordre
sidebar.indexLabelSur la page d’accueil d’un dossier : renomme son entrée Aperçu localisée

Dossiers

Un dossier est nommé et positionné par sa page d’accueil — <folder>/index.md (ou readme.md) : son frontmatter sidebar s’applique au groupe entier, et la page elle-même apparaît comme l’entrée Aperçu du groupe. Labels et ordre se propagent aux fils d’Ariane et aux couvertures PDF.

Les clés inconnues sont ignorées et préservées — les agents qui éditent une page doivent garder le frontmatter existant intact (le skill de revue le fait).

Le contrat du store .notabene

Le contrat du store .notabene

Le store est un contrat public versionné — committé dans votre repo, lu et écrit par les agents. Sa forme ne change jamais silencieusement : <store>/meta.json porte { "schemaVersion": n } (actuellement 3), et tout changement de forme s’accompagne d’un migrateur (notabene migrate).

Disposition

<store>/
  meta.json                # { "schemaVersion": 3 }
  journal.json             # un tableau d'entrées de journal
  protocol.md              # le protocole agent (écrit par `init` ; ce n'est pas de la donnée)
  <page>/<comment-id>.json # UN FICHIER PAR COMMENTAIRE → merges git sans conflit

meta.json, journal.json et protocol.md sont des noms réservés à la racine du store ; tout le reste est de la donnée de commentaire. Les lecteurs ne parsent que du .json, donc protocol.md est inerte — il voyage avec le store pour que la spec soit toujours à côté des commentaires.

<page> est le chemin logique de la page (docs/guide/setup — avec l’i18n c’est l’id brut encodant la locale, les commentaires sont donc par langue). Les anciens stores v1 (un tableau par page) sont toujours lus ; toute écriture migre la page concernée.

Un commentaire

{ "id", "space", "page", "scope",            // scope : "selection" | "page" | "block"
  "anchor": {                                 // selection : citation de texte façon W3C
    "quote", "prefix", "suffix", "section"    // texte rendu + contexte + titre le plus proche
  } | { "kind", "key", "label",               // block (diagramme/image) : clé dérivée du contenu
        "section", "index" } | null,
  "thread": [{ "author", "body", "ts" }],     // author peut être façon git "Name <email>"
  "status": "open" | "addressed" | "resolved",
  "hold": false,                              // true → l'agent l'ignore (WIP du relecteur)
  "resolution": { "note", "journalEntryId" } | null,
  "createdAt", "updatedAt" }

addressed est l’état de la revue en deux phases : proposé par l’agent, en attente de validation humaine sur /review.

Une entrée de journal

{ "id", "date",                               // YYYY-MM-DD
  "title", "summary",
  "changes": [{ "page", "commentIds": [], "what", "why" }] }

Un enregistrement changes[] par page réellement touchée — le diff de /review est construit en inversant le journal, donc une page qui n’y figure pas n’apparaîtra pas dans le diff du relecteur. Le resolution.journalEntryId de chaque commentaire résolu pointe vers son entrée.

Règles que les agents doivent honorer

  • Les écritures sont atomiques (fichier temporaire + rename) — ne jamais écrire du JSON partiel à la main. La CLI (comments done / reopen, journal add) s’en charge ; comments verify audite le résultat.
  • Ne jamais supprimer le store en masse ; supprimez un commentaire précis par id si on vous le demande.
  • Ne traiter que status: "open" et hold: false.
  • Le protocole complet vit dans <store>/protocol.md — écrit par notabene init, committé avec le store, rafraîchi en relançant init. Pointez-y n’importe quel agent.

Modèle de sécurité

Modèle de sécurité

L’API de commentaires écrit dans votre git — elle est donc cloisonnée, par construction :

  • Dev uniquement. Le chemin d’écriture n’existe que sous notabene dev. En build/preview les mutations renvoient 403, et un build public ne contient pas ces routes du tout.
  • Loopback par défaut. Le serveur se lie à 127.0.0.1 ; l’API d’écriture n’est pas joignable depuis votre réseau sans opt-in explicite via --host / NOTABENE_HOST=1 — réseaux de confiance uniquement.
  • Chaque écriture est gardée au-delà du bind : les requêtes cross-origin sont refusées (anti-CSRF), un en-tête Host non-loopback est refusé en mode loopback (anti-DNS-rebinding), et — quand vous définissez NOTABENE_TOKEN — chaque écriture doit porter un x-notabene-token correspondant. Définir un token est recommandé avec --host.
  • Une identité par personne. Sur un hôte non-loopback, chaque visiteur est invité à renseigner son nom (+ e-mail optionnel) avant de naviguer, pour que les commentaires soient attribués à de vraies personnes plutôt qu’au défaut git du propriétaire du repo.
  • L’agent ne committe jamais sans demander et ne supprime jamais le store en masse — cela fait partie du protocole.
  • La CLI est une surface distincte. Les règles ci-dessus encadrent l’API d’écriture HTTP. Les commandes qui écrivent dans le store (comments done / reopen, journal add) sont des commandes locales que vous — ou un agent dans votre terminal — lancez délibérément : ni serveur, ni port, ni réseau. Écriture atomique, un commentaire à la fois, et comments verify audite le résultat.

L’artefact public est l’image miroir : pas d’API d’écriture, pas de données du store, pas d’identité — rien à garder, parce que rien n’est construit.