@rse/specbook
v1.3.0
Published
Markdown-based Specification Format (API, CLI and MCP service)
Readme
SpecBook
Markdown-based Specification Format
About
SpecBook defines a generic, Markdown-based specification format which can be configured for the specifications of particular contexts through a YAML-based schema configuration. SpecBook allows specifications to be initialized, linted, exported (JSON, JSON5, YAML, TOON, HTML, PDF, and normalized Markdown), previewed (HTML, live in the browser), and described to LLMs.
SpecBook ships with an API class with methods <xxx>(), a
CLI with commands specbook <xxx>, and an MCP service with tools
specbook_<xxx>().
SpecBook provides the following distinct features:
Hierarchical Object Model: A specification is a tree of typed objects, each with a kind and name, an optional id, optional properties, optional description, and optional child objects. The allowed object hierarchy is defined per context by the YAML schema configuration.
Versatile Object to Markdown Mapping: Objects are authored as plain Markdown headings, property lists, and description prose. The objects can be mapped to nested sections ("complex" format) or compact bullet point lists ("concise" and "group" format).
Wiki-Style Object Linking: Objects can hierarchically reference each other through Wiki-style
[[xxx]]references, which are resolved against the locally-unique ids and names of all objects. In the HTML and PDF exports they become navigable links onto precise anchors.Strict Validation with Custom Schema: The YAML schema configuration strictly defines the allowed object kinds, hierarchies, and properties, whose values are constrained by an expression language (regex, enum, tags, list, and reference). Beyond the plain values, it constrains the uniqueness and presence of a property among the sibling objects and the shape of a reference-valued property (local, symmetric, and/or acyclic), and it can declare the child objects of an object kind a finite state machine, whose reachability, dead-ends, and livelocks are then checked. Violations are reported as file- and line-precise diagnostics, while the reference coverage an object kind demands is reported as a warning only. A bundled standard schema configuration applies if no particular one is given.
Object Model Diagram Visualisation: Object kinds can declare "graph", "hub", or "grid" diagrams in the schema, whose nodes and edges are automatically derived from the object model and its references. The diagrams are rendered with the sibling project Gradia, which is specialized in rendering object models.
CLI, MCP, and API Interface: All commands are implemented once in the API class
SpecBook, on which both the CLI and the MCP service are just thin wrappers. This way, humans, scripts, and AI agents use exactly the same functionality.AST Exports for AI/LLMs: The parsed specification Abstract Syntax Tree (AST) can be exported in JSON, JSON5, YAML, or TOON format for machine consumption, with the derived diagram of an object attached to it as a textual Gradia spec and the reference coverage it reports attached as its counts. Together with the
describecommand, which explains the models and formats, this enables LLMs to both read and write specifications.HTML Export for Developers: The HTML export is a self-contained single document with a title page, a table-of-contents (also as a slide-in side panel for quick navigation), a diagram-of-contents, a fuzzy full-text search, embedded images, reference coverage tables (e.g. the share of the use cases, scenarios, requirements, and rules the test cases verify), a scroll progress meter (which also scrolls back to the top on click), diagram maximization (into the viewport or the fullscreen), description popups (which show the schema and corpus description of an object kind, property, or object instance on hover), and a light/dark theme toggle. It is intended for the day-to-day online reading during development. The HTML export can map all object kinds to nested sections or compact tables, or an automatic mixture which collapses only the deepest level into tables. The HTML export even can be previewed in the browser with live updates.
PDF Export for Customers: The PDF export prints the HTML rendering via Chromium and post-processes it with page numbers, headers/footers, a brand bar, and a hierarchical PDF outline. The paper size (A4, Letter, or Legal) drives the pagination and scales the diagrams down to fit onto a single page. It is intended as a polished, paginated offline document for handing over to customers.
Document Theming and Typography: The title object of the specification drives the entire document: its title, subtitle, author, version, and logo fill the title page (with an optional light/dark variant of the logo), its language selects the smart typography quote style, its color tone seeds the theme color spreads of both the light and the dark theme, and its character set subsets the embedded fonts down to the actually needed glyphs.
Overview
Installation
$ npm install -g @rse/specbookUsage
CLI
Commands:
$ specbook init \
[-v|--verbose [<level>]] \
[-c|--config <schema-yaml-file>] \
[-b|--basedir <spec-md-file-basedir>]
$ specbook lint \
[-v|--verbose [<level>]] \
[-c|--config <schema-yaml-file>] \
[-b|--basedir <spec-md-file-basedir>]
$ specbook export \
[-v|--verbose [<level>]] \
[-c|--config <schema-yaml-file>] \
[-b|--basedir <spec-md-file-basedir>] \
[-o|--output [<format>:]<output-file>] \
[-w|--watch] \
[-O|--omit <aspect>[,...]] \
[...]
$ specbook preview \
[-v|--verbose [<level>]] \
[-c|--config <schema-yaml-file>] \
[-b|--basedir <spec-md-file-basedir>] \
[-O|--omit <aspect>[,...]] \
[-a|--addr <ip-addr>] \
[-p|--port <tcp-port>]
$ specbook describe \
[-v|--verbose [<level>]] \
[-c|--config <schema-yaml-file>] \
[-b|--basedir <spec-md-file-basedir>] \
[-e|--embed] \
[-z|--compress [<level>]] \
[-f|--format <format>] \
[-p|--part <part>] \
[-o|--output <output-file>]
$ specbook mcp \
[-v|--verbose [<level>]]Options:
-v|--verbose [<level>]: Enable verbose logging of processing information tostderrat the given verbosity level:0(the default) logs the notices only,1(the bare flag) also the regular processing information,2also the reference coverage ratios, and3also the unreferenced objects of a reference coverage.-c|--config <schema-yaml-file>: The YAML schema configuration (default: theconfigentry of the project configuration file.specbook.yaml, else the bundled standard schema configurationspecbook-format.yaml) determines the specification: exactly the artifact files itsfilefields reference are loaded and parsed; all other Markdown files below the base directory are ignored. A referenced file which is absent is reported, unless all of its artifacts areoptional, and so is an artifact absent from its present file, unless it isoptionalitself. Bothlintandexportreport all diagnostics and fail on any error among them (a warning, like a lapse of the reference coverage areferencedobject kind demands, is reported only), so a partial or invalid specification is never exported. The verbose output additionally states at verbosity level2the reference coverage ratios: the ones thereferencedobject kinds receive and the ones thecoverageobject kinds report, the latter naming the unreferenced objects at level3. The option accepts glob patterns and can be given multiple times: the matching files (in the order of the patterns and alphabetically within a pattern, where the literalstdnames the bundled standard schema configuration, and where a pattern matching no file is an error) are merged in order into one effective schema configuration, the later files into the earlier ones. The objects merge deeply, while the elements of the lists are matched by identity (artifacts bykindplusid/name, nested objects bykind, properties byname, and scalar entries by value): a matching element is merged into its counterpart, an unmatched one is appended. Every file has to be valid YAML on its own, while the merged result alone is validated against the schema of the configuration.-b|--basedir <spec-md-file-basedir>: The base directory (default: thebasedirentry of the project configuration file.specbook.yaml, else.) is the directory the referenced artifact files are resolved against, and generated specification Markdown files are placed inside it, too.-o|--output [<format>:]<output-file>(exportonly): The output file (-for stdout) is required and can be given multiple times. The format (json,json5,yaml,toon,html,pdf, ormd) is inferred from the filename extension, unless it is explicitly given as a<format>:prefix, and plain-(stdout) defaults to JSON. Themdexport format normalizes the entire corpus into a single Markdown document.-w|--watch(exportonly): Keep the outputs in sync with their sources: after the regular export, the YAML schema configuration files, the referenced artifact files, and all assets they embed are observed, and every change re-exports the specification once the sources stayed silent for one second. A failed re-export is reported and leaves the observe loop intact, so a transiently invalid specification (or configuration) does not end the watch. The outputs have to be regular files, as-(stdout) cannot receive a repeated export, and none of them may be an observed source file itself, as its own write would re-trigger the observation endlessly.-O|--omit <aspect>[,...](exportandpreviewonly): Omit content aspects (comma-separated, repeatable) from the HTML and PDF outputs at generation time, instead of just leaving them foldable in the browser. The aspects match the folding controls of the HTML export:diagram:graph,diagram:hub, anddiagram:gridomit all diagrams of a type,diagram:1(alias:diagram),diagram:2, anddiagram:3omit all diagrams from an object tree nesting level on (level 1 hence all, including the "Diagram of Contents" page), andtext:longcuts every table cell whose estimated number of text lines towers over all other cells of its row (by themaxCellHeightpercentage of the object kind, default 40) at a word boundary, ending it in a grey[...]. An omitted diagram leaves nothing behind and is not even rendered, the folding controls of the omitted aspects leave the brand bar, and the AST outputs (json,json5,yaml,toon) drop thediagramfields of the omitted diagrams, too, while themdoutput ignores the option.-a|--addr <ip-addr>,-p|--port <tcp-port>(previewonly): The IP address (default:127.0.0.1) and TCP port (default:12345) the live preview listens on. The HTML export is served onhttp://<ip-addr>:<tcp-port>/, kept in sync with its sources exactly likeexport --watch, and updated in the browser after every change through a WebSocket connection the served page keeps open, where the document is replaced in place, so the scroll position and the theme choice survive (a failed re-export keeps the previous HTML in place, and a request before the first successful export is answered with a placeholder page which replaces itself with the document once that export arrives). A status tab at the bottom of the brand bar shows the connection state: its plug icon carries the search highlight color while disconnected and blinks for 2s after every update.-o|--output <output-file>(describeonly): The output file (default:-for stdout) receives the described Markdown document.-e|--embed(describeonly): Embed the given YAML schema configuration itself instead of just referencing it, so the resulting document describes the specification format entirely on its own.-z|--compress [<level>](describeonly): The compression level (default and bare flag:1) of the YAML schema configuration (embedded into the Markdown or emitted as the raw file content), so the configuration costs fewer tokens:0emits it verbatim,1re-emits it with 2-space indentation, unwrapped lines, and without comments,2additionally leaves out itsrefs,diagram, andformatfields, and3additionally leaves out itsdescfields of objects and properties. The MCP toolspecbook_describedefaults to2instead, as its consumer is an LLM.-f|--format <format>(describeonly): The output format (default:md) switches from the rendered Markdown onto the raw original file content (theschemaone compressed by the-z|--compresslevel) withraw, which is available for the file-backed partsmetaandschemaonly.-p|--part <part>(describeonly): The document part (default:all) reduces the output to a single part:metafor the description of the generic SpecBook models and formats,schemafor the YAML schema configuration (the given one, referenced or embedded with-e|--embed, else the bundled standard one, embedded), orspecfor the reference to the base directory.
The defaults of -c|--config and -b|--basedir are, unless
SPECBOOK_CONFIG and SPECBOOK_BASEDIR provide them (see below), taken
from the optional project configuration file .specbook.yaml, which is searched
in the current working directory and then upwards in all of its parent
directories (the closest one wins), so SpecBook works from any directory
below the project root:
config: docs/spec/schema.yaml
basedir: docs/specThe entry config is a single file or glob pattern or a list of them
(exactly like the repeatable -c|--config, including the literal
std), and the entry basedir is a directory. Relative paths resolve
against the directory of the .specbook.yaml itself, the file is
validated (an unknown entry or a wrongly typed value fails the command),
and both an explicitly supplied option and its environment variable
win over its entry.
The default value of every CLI option --xxx can be overridden
by a corresponding SPECBOOK_XXX environment variable (e.g.
SPECBOOK_BASEDIR, SPECBOOK_CONFIG, SPECBOOK_OUTPUT,
SPECBOOK_VERBOSE, SPECBOOK_ADDR, SPECBOOK_PORT), while an
explicitly supplied option always wins. As -c|--config is repeatable,
SPECBOOK_CONFIG carries a list of patterns separated by the path
delimiter of the platform (: on Unix, ; on Windows). Unlike all
others, SPECBOOK_CONFIG and SPECBOOK_BASEDIR are resolved by the API
itself, so they apply to the API methods and the MCP tools, too.
Beyond those, the option-less SPECBOOK_BROWSER selects the browser
printing the PDF export: a value carrying a path separator is taken as
an executable path and any other one as a Playwright channel name
(chromium, chromium-headless-shell, chrome, chrome-beta,
chrome-dev, chrome-canary, msedge, msedge-beta, msedge-dev,
or msedge-canary). The variable itself has no default value: when it
is unset, the downloaded Playwright Chromium is used (the equivalent of
chromium) and only if that one is absent a system-installed Google
Chrome (the equivalent of chrome). An explicitly configured browser
failing to launch fails the export instead of falling back onto another
browser.
Agent Skill
For Claude Code, SpecBook ships the plugin specbook, which registers
the MCP service specbook mcp and provides the skill /specbook on top
of it:
$ claude plugin marketplace add rse/specbook
$ claude plugin install specbook@specbook/specbook [-c|--config <yaml-file>] [-b|--basedir <basedir>] [<query>]
/specbook init [-c|--config <yaml-file>] [-b|--basedir <basedir>]
/specbook lint [-c|--config <yaml-file>] [-b|--basedir <basedir>] [-g|--gitignore]
/specbook export [-c|--config <yaml-file>] [-b|--basedir <basedir>] [-g|--gitignore]
[-O|--omit <aspect>[,...]] [-o|--output [<format>:]<output-file>] [...]
/specbook edit [-c|--config <yaml-file>] [-b|--basedir <basedir>] [-g|--grill]
[-r|--grill-rounds <n>] [-v|--verify] [-l|--loop] [<query>]Without a command, the skill activates the SpecBook know-how: it
learns the format and the schema configuration through the MCP tool
specbook_describe, so the specification can be queried and changed
ad-hoc in plain conversation for the remainder of the session, and it
directly serves an optional query. The agent invokes the skill this
way on its own, as soon as you want to read or change the specification.
The commands init, lint, and export just pass their options
through to the corresponding MCP tools. The command edit edits the
specification in one shot from a query: it learns the format and the
schema configuration through the MCP tool specbook_describe, reads the
related specification files, optionally interviews you about the open
points of the query first (--grill, for --grill-rounds rounds),
applies the change set, optionally lints the result and fixes the
reported diagnostics (--verify), and optionally asks for the next
query (--loop). All commands leave an absent --config and
--basedir to the MCP service, which resolves them through
SPECBOOK_CONFIG and SPECBOOK_BASEDIR and then through the
.specbook.yaml found from the working directory of the session upwards.
Example: Simple
Check out the simple specification of simple example data model:
Sources
Generation
$ specbook export -v \
-b smp/sample \
-o smp/sample/sample.html \
-o smp/sample/sample.pdfHTML Rendering

Example: Complex
Check out the complex specification of the Broadcast application, based on SpecBook's built-in "standard" schema:
Sources
Generation
$ specbook export -v \
-b smp/broadcast \
-o smp/broadcast/broadcast.html \
-o smp/broadcast/broadcast.pdfHTML Rendering

PDF Rendering

See Also
Support
SpecBook is developed in the experience context of industrial Software Engineering at the msg group and in the educational context of the Software Engineering Academy (SEA). SpecBook development is supported by msg Research and Software Engineering Academy (SEA).
License
Copyright © 2026 Dr. Ralf S. Engelschall Licensed under Apache 2.0


