Skip to content

CLI reference

This page is the exhaustive, option-by-option reference for every scribpy command, generated by reading src/scribpy/cli/main.py directly. For workflow-level explanations — when to reach for which command, and how commands compose — read Using the CLI and the end-to-end demo instead; this page favors completeness over narrative.

The Click entry point is:

scribpy [OPTIONS] COMMAND [ARGS]...

Global options:

Option Effect
--version Print Scribpy's package version and exit.
--help Print the command list and exit.

Every subcommand also accepts --help, e.g. scribpy build --help prints that command's own argument and option list without executing anything.

All commands use exit status 0 for success. validate and diagnose use 1 when blocking findings exist. Other expected domain or filesystem failures are translated to a Click error with status 1: Click prints Error: <message> to stderr and exits, so these failures are visible in scripts through both exit status and stderr content. The seven commands map directly onto the seven end-user Python functions documented in Python API reference — each command is a thin adapter, not a separate implementation, so behavior described there (default values, raised exceptions, side effects) also holds for the CLI.

Command Wraps this Python call
new scribpy.init_skeleton(...)
scaffold scribpy.init_from_outline(...)
validate scribpy.valid_report(...)
diagnose scribpy.MarkdownCollection.from_tree(root).diagnose()
build scribpy.MarkdownCollection.from_tree(root) + scribpy.concatenate(...)
html scribpy.html_export(...)
mkdocs-export scribpy.mkdocs_export(...)

new

scribpy new [OPTIONS] OUTPUT_DIR

Create a minimal root manifest and index.md.

Parameter Type Required Default
OUTPUT_DIR path yes
--title TEXT text yes
--author TEXT text no empty string
--project-version TEXT text no 0.1.0
--help flag no

Output:

Created Scribpy project at OUTPUT_DIR

OUTPUT_DIR need not exist. Existing unrelated contents are not removed, but an existing OUTPUT_DIR/scribpy.yml raises ScaffoldCollisionError.

scribpy new notes --title "Engineering Notes" --author "Ada"

This creates notes/scribpy.yml and notes/index.md. The manifest looks like:

project:
  title: Engineering Notes
  author: Ada
  version: 0.1.0
build:
  toc: false
  heading_numbering:
    enabled: false
order:
  - index.md

author is omitted from the written manifest when left at its default empty string; version is always written, defaulting to 0.1.0 unless --project-version overrides it. The generated build block explicitly turns TOC and heading numbering off — enable them by editing the manifest once your project has more than one page (see Root manifest). index.md itself is a one-line stub: # Engineering Notes. Use new for a project you intend to grow by hand, one file at a time. If you already have an outline of your intended structure (a Markdown file of nested headings), use scaffold instead — it generates the whole tree in one step.

scribpy new notes --title "Engineering Notes" --author "Ada" \
  --project-version "0.3.0"

scaffold

scribpy scaffold [OPTIONS] OUTLINE_PATH OUTPUT_DIR

Parse a headings-only outline and generate directories, stub pages, and local manifests.

Parameter Type Required Default
OUTLINE_PATH existing file yes
OUTPUT_DIR path yes
--max-depth INTEGER integer 1–6 no 4
--help flag no

Output:

Scaffolded Scribpy project at OUTPUT_DIR

Expected failures include unreadable outline, invalid structure, max-depth outside 1–6, sibling slug collision, and existing target manifest.

scribpy scaffold outline.md notes --max-depth 5

Given this outline:

# Engineering Handbook

## Getting Started

## Architecture

### Domain Model

### Pipeline

scaffold produces:

notes/
├── scribpy.yml              # project.title: Engineering Handbook
├── index.md                 # "# Engineering Handbook"
├── getting-started.md       # leaf heading -> stub file
└── architecture/            # heading with children -> subdirectory
    ├── scribpy.yml          # title: Architecture, order: [domain-model.md, pipeline.md]
    ├── domain-model.md
    └── pipeline.md

Headings are slugified for filenames and directory names (Domain Modeldomain-model), using the same slug function MkForge uses elsewhere in the toolchain. A single top-level H1 becomes the project title and its direct children become the root order; an outline with multiple H1s instead produces a generic Project title with each H1 as a top-level entry. Every generated stub file contains only its heading, ready to be filled in.

validate

scribpy validate [OPTIONS] ROOT

Run manifest inspection, MkForge Markdown verification, and collection diagnostics; render the complete report with Rich.

Parameter Type Required Default
ROOT path yes
--help flag no

The command has no formatting, strictness, rule-selection, or output-file option. Use the Python API for structured report handling.

scribpy validate notes
status=$?

validate is the broadest check available: it inspects every reachable manifest (root and folder), verifies every Markdown source through MkForge (heading structure, front matter, image references), and runs the full collection diagnostics engine — then renders everything as one Rich report with render_validation_report. It always runs to completion and prints findings even when there are zero errors, so it is safe to run on every change, including in CI:

scribpy validate notes || exit 1

Because validate prints a formatted report and only signals pass/fail through the exit code, prefer scribpy.validate_project() from Python when your caller needs to branch on individual finding codes rather than parse text output.

diagnose

scribpy diagnose [OPTIONS] ROOT

Load the collection, run default collection rules, and print the plain-text summary. This does not replace the broader validate command.

Parameter Type Required
ROOT path yes
--help flag no

An invalid manifest, filesystem error, or decoding failure becomes a Click error. A diagnostic report containing errors exits 1 after printing findings.

scribpy diagnose notes

diagnose is narrower and faster than validate: it only runs the eight default CollectionDiagnosticRule checks (see Diagnostic reference) and skips MkForge front-matter/heading verification and the broader manifest inspection that validate performs. Reach for diagnose when you only care about Markdown-structure and link/image problems — for example while iterating quickly on a single page — and reach for validate before publishing or in CI, where the fuller check matters more than speed.

validate diagnose
Manifest inspection yes no
MkForge Markdown verification yes no
Collection diagnostics (8 rules) yes (adapted into ProjectDiagnostic) yes (raw CollectionDiagnostic)
Output Rich table via render_validation_report plain-text report.summary()
Underlying call scribpy.valid_report(root) MarkdownCollection.from_tree(root).diagnose()

build

scribpy build [OPTIONS] ROOT OUTPUT

Assemble a project into one Markdown file.

Parameter Type Required
ROOT path yes
OUTPUT path yes
--help flag no

All policy options come from the root manifest; there are no CLI overrides for TOC, numbering, or renderer backends. The output parent is created. Successful output is:

Built Markdown document at OUTPUT

Expected errors include invalid Markdown/manifest, renderer failure, unimplemented PlantUML local backend, filesystem failure, and decoding failure.

scribpy build notes work/notes/document.md

build runs the full assembly pipeline described in Assembly pipeline: heading numbering (if enabled), internal link rewriting, TOC insertion (if enabled), PlantUML/Mermaid rendering, and image collection — always in that fixed order, always driven entirely by the project's scribpy.yml. The output is one Markdown file plus an assets/ directory next to it holding copied and generated images:

work/notes/
├── document.md
└── assets/
    ├── generated/
    │   └── 3f9c2a…8b1e.png   # diagram, named by content hash
    └── logo.png               # copied local image

If validation matters to you before committing to a build, chain validate first — build itself still runs collection diagnostics internally and raises InvalidMarkdownError on any error-level finding, but it does not print the findings the way validate does:

scribpy validate notes && scribpy build notes work/notes/document.md

html

scribpy html [OPTIONS] SOURCE OUTPUT

Convert one already assembled Markdown file into standalone HTML.

Parameter Type Required Default
SOURCE path yes
OUTPUT path yes
--toc-depth INTEGER integer no 3
--css FILE existing file no built-in CSS only
--help flag no

SOURCE is not a project root. OUTPUT's parent must already exist. toc-depth is relative to H1: 1 includes H2, 2 includes H2 and H3, and 3 includes through H4. The command reports:

Exported HTML document at OUTPUT
scribpy html work/notes/document.md work/notes/document.html \
  --toc-depth 2 --css custom.css

html operates on an already-assembled document — normally build's output, not a raw project source tree. It strips the Markdown TOC block that build inserted (if any), converts the remaining Markdown to HTML, and rebuilds the navigation from headings up to --toc-depth, presented as a collapsible burger menu. All CSS and JavaScript are inlined into the HTML file itself, but referenced images (assets/…) remain separate files next to the HTML — copy the whole output directory, not just the .html file, when distributing it. Run build then html back to back for a one-command style pipeline:

scribpy build notes work/notes/document.md && \
scribpy html work/notes/document.md work/notes/document.html

mkdocs-export

scribpy mkdocs-export [OPTIONS] SOURCE OUTPUT

Export a Scribpy project as MkDocs input while keeping pages separate.

Parameter Type Required
SOURCE project-root path yes
OUTPUT destination-directory path yes
--help flag no

The command has no force, theme, serve, build, or deploy option. It refuses an existing OUTPUT/mkdocs.yml. Successful output is:

Exported MkDocs project at OUTPUT
scribpy mkdocs-export notes work/notes/mkdocs-source

Unlike build, mkdocs-export runs directly against the project source tree, not an assembled file, and never merges pages into one document. Every source page is copied to docs/ at its original relative path with its diagrams rendered and its images collected in place; links between pages are left as ordinary Markdown paths — MkDocs resolves them at its own build time, so Scribpy's link-rewriting and heading-numbering transforms do not run for this output shape. Navigation (nav: in the generated mkdocs.yml) mirrors the manifest hierarchy, using each page's first H1 as its navigation label:

work/notes/mkdocs-source/
├── mkdocs.yml
└── docs/
    ├── index.md
    └── architecture/
        ├── domain-model.md
        └── assets/
            └── generated/…

The generated mkdocs.yml only contains site_name, docs_dir, and nav — no theme, plugins, or Material configuration. Add those yourself before running mkdocs build or mkdocs serve on the result, or adapt this project's own mkdocs.yml as a starting template.

Path validation behavior

Click existence-checks OUTLINE_PATH and --css because they use an existing file type. Other path parameters are converted to pathlib.Path without early existence checking; the called public API produces the relevant domain or filesystem failure.