DocAnvil

CLI Commands

DocAnvil provides six subcommands: new, theme, doctor, serve, build, and export.

Global Flags

Flag Description
--verbose Enable verbose output
--quiet Suppress non-error output

docanvil new

Scaffold a new documentation project.

docanvil new <name>
Argument Required Description
name Yes Directory name for the new project

Creates a project directory with:

# Create a docs project
docanvil new my-docs
# Create and immediately start serving
docanvil new my-docs && cd my-docs && docanvil serve

docanvil theme

Interactively generate a custom color theme for your project.

docanvil theme [--overwrite] [--path <dir>]
Option Default Description
--overwrite false Replace existing theme customizations
--path . Path to the project root

The command walks through an interactive prompt:

  1. Color mode — choose Light only, Dark only, or Both (light + dark with toggle)
  2. Primary color — hex code for the primary accent color (prompted once per mode)
  3. Secondary color — hex code for the warning/secondary color (prompted once per mode)

It then derives all color-related CSS variables, writes them to theme/custom.css, and updates docanvil.toml with both custom_css and color_mode.

If existing theme customizations are detected (custom_css or [theme.variables] in config), the command exits with a helpful message unless --overwrite is passed.

# Generate a theme for the current project
docanvil theme
# Generate a theme for a project in another directory
docanvil theme --path ../my-docs
# Replace an existing theme
docanvil theme --overwrite

Color Modes

Mode Behavior
Light only Single light palette in :root. No toggle button.
Dark only Single dark palette in :root with dark backgrounds/text. No toggle.
Both Light as default :root, dark via [data-theme="dark"], OS prefers-color-scheme auto-detection, and a sun/moon toggle button in the header. User preference is saved to localStorage.

When "Both" is selected, you are prompted for separate primary and secondary colors for each mode, allowing independent light and dark palettes.

Derived Variables (Light)

From the two input colors, the following CSS variables are generated for light mode:

Variable Derivation
--color-primary Primary color as-is
--color-primary-light Primary lightened 10%
--color-link Same as primary
--color-link-hover Primary darkened 10%
--color-sidebar-hover Primary tinted to 95% lightness
--color-sidebar-active-bg Primary tinted to 95% lightness
--color-sidebar-active-text Primary darkened 10%
--color-note-bg Primary tinted to 95% lightness
--color-note-border Primary lightened 10%
--color-mark-bg Primary at 12% opacity
--nav-group-toggle-hover Primary at 6% opacity
--color-focus-ring Primary at 40% opacity
--color-warning-border Secondary color as-is
--color-warning-bg Secondary tinted to 95% lightness

Derived Variables (Dark)

Dark mode uses inverted derivation logic plus explicit background and text colors:

Variable Derivation
--color-bg Dark background (#0f172a)
--color-bg-secondary Slightly lighter dark (#1e293b)
--color-text Light text (#f1f5f9)
--color-text-muted Mid-light text (#94a3b8)
--color-border Dark border (#334155)
--color-code-bg Dark code background (#1e293b)
--color-primary Primary color as-is
--color-primary-light Primary lightened 10%
--color-link Same as primary
--color-link-hover Primary lightened 10% (lighter on dark bg)
--color-sidebar-hover Primary tinted to 15% lightness
--color-sidebar-active-bg Primary tinted to 15% lightness
--color-sidebar-active-text Primary lightened 10%
--color-note-bg Primary tinted to 15% lightness
--color-note-border Primary lightened 10%
--color-mark-bg Primary at 20% opacity
--nav-group-toggle-hover Primary at 12% opacity
--color-focus-ring Primary at 40% opacity
--color-warning-border Secondary color as-is
--color-warning-bg Secondary tinted to 15% lightness

Note

After generating a theme, run docanvil serve to preview the result. You can edit the generated theme/custom.css file directly for further tweaks.

docanvil doctor

Diagnose project configuration and content issues before building.

docanvil doctor [--fix] [--strict] [--format <fmt>] [--path <dir>]
Option Default Description
--fix false Automatically apply safe fixes (create missing dirs, files)
--strict false Exit with code 3 if any warnings or errors are found (for CI)
--format human Output format: human, checkstyle, or junit
--path . Path to the project root
# Check the current project
docanvil doctor
# Check and auto-fix safe issues
docanvil doctor --fix
# Use in CI to fail on any issues
docanvil doctor --strict
# Check a project in another directory
docanvil doctor --path ../my-docs

If no docanvil.toml is found, doctor prints a friendly message suggesting docanvil new and exits cleanly.

Machine-readable output

The --format flag switches from the default coloured terminal output to structured XML, which is useful for integrating with CI annotation tools or test reporters. Machine-readable output is written to stdout; progress messages are suppressed entirely.

Format Description
human Coloured, human-readable output to stderr (default)
checkstyle Checkstyle XML — compatible with reviewdog, GitHub Actions problem matchers, and most Java/linting CI tooling
junit JUnit XML — compatible with GitHub Actions test summary, GitLab CI, CircleCI, and most test result reporters
# Output Checkstyle XML (e.g. pipe to reviewdog)
docanvil doctor --format checkstyle
# Output JUnit XML (e.g. for GitHub Actions test summary)
docanvil doctor --format junit
# Fail CI and emit Checkstyle XML
docanvil doctor --format checkstyle --strict
# Save JUnit results to a file
docanvil doctor --format junit > test-results/doctor.xml

Checkstyle XML groups diagnostics by file. Each <error> element carries:

JUnit XML maps each check category to a <testsuite>. All eight categories are always emitted — categories with no issues produce a single passing <testcase name="all-checks-passed"/>. Warnings and errors appear as <failure> elements; info diagnostics appear as <skipped/>.

Note

--quiet suppresses the human-readable summary but does not suppress XML output — machine formats always write to stdout regardless of --quiet.

Check categories

The doctor runs six categories of checks, expanding to eight when versioning and/or i18n is enabled:

  1. Project structure — config file, content directory, index page
  2. Configuration — TOML parsing, file references (logo, favicon), nav.toml validation
  3. Theme — custom CSS file existence, layout template Tera syntax
  4. Content — broken wiki-links, unclosed directives, front-matter JSON errors, duplicate slugs
  5. Readability — content quality checks across all Markdown source files (see below)
  6. Versions (versioning only) — version configuration and directory health
  7. Translations (i18n only) — translation coverage across enabled locales
  8. Output — output directory writability

Readability checks

These run against raw Markdown source and catch content quality issues before they reach readers. Each diagnostic includes the file path and line number.

Heading structure

Check Severity What it catches
multiple-h1 ⚠️ Warning More than one H1 heading on the same page
skipped-heading-level ⚠️ Warning Heading level jump of more than one (e.g. H1 → H3)
consecutive-headings ⚠️ Warning Two headings with nothing but blank lines between them
empty-heading ✗ Error A heading with no text (## )
heading-punctuation ℹ Info Heading ends with . or ! — question marks are fine
duplicate-heading-text ⚠️ Warning Two headings with the same text; produces anchor ID collisions
emphasis-used-as-heading ⚠️ Warning A line that is entirely **bold** — use ## Heading instead
no-document-title ⚠️ Warning Page has no H1 and no "title" in front matter
heading-adjacent-separator ⚠️ Warning A heading is immediately adjacent to a horizontal rule — headings already create visual breaks, so the separator is redundant
Check Severity What it catches
missing-alt-text ⚠️ Warning Image with no alt text: ![](photo.jpg)
reversed-link-syntax ✗ Error (text)[url] instead of [text](url) — link won't render
empty-link ✗ Error [text]() (no destination) or [](url) (no visible text)
non-descriptive-link-text ⚠️ Warning Link text gives no navigational context: "here", "read more", "learn more", etc.
bare-url ⚠️ Warning Raw URL in prose — wrap it as <url> or [text](url)

Code blocks

Check Severity What it catches
missing-fenced-code-language ℹ Info Code fence with no language tag — syntax highlighting won't apply

Prose quality

Check Severity What it catches
long-paragraph ℹ Info Paragraph exceeds the word count threshold (default: 150 words)
repeated-word ⚠️ Warning Consecutive duplicate words: the the, is is
todo-comment ⚠️ Warning TODO, FIXME, HACK, XXX, or PLACEHOLDER in prose
placeholder-text ⚠️ Warning Lorem ipsum, TBD, or [Insert … here] in prose

All checks skip content inside fenced code blocks. Most also strip inline code spans before scanning to avoid false positives.

Version checks

These run when version.enabled is non-empty in docanvil.toml.

Check Severity What it catches
current-not-in-enabled ✗ Error version.current specifies a version not in the enabled list
version-dir-missing ✗ Error An enabled version has no matching subdirectory in the content directory — --fix creates it
empty-version ⚠️ Warning A version directory exists but contains no .md files

Auto-fix

The --fix flag applies safe, non-destructive fixes:

Issue Fix applied
Content directory missing Creates the directory
No index.md at content root Creates a minimal index page
Custom CSS file not found Creates an empty CSS file at the configured path
Version directory missing Creates the missing version subdirectory in the content directory

Readability issues are never auto-fixed — they require human judgment.

Note

Run docanvil doctor again after --fix to verify all issues are resolved. Some fixes (like creating the content directory) may reveal additional issues on the next run.

docanvil serve

Start a development server with live reload.

docanvil serve [--host <address>] [--port <port>] [--path <dir>]
Option Default Description
--host 127.0.0.1 Address to bind the server to
--port 3000 Port number
--path . Path to the project root

The server:

# Default: localhost:3000
docanvil serve
# Custom host and port
docanvil serve --host 0.0.0.0 --port 8080
# Verbose output to see rebuild events
docanvil serve --verbose
# Serve a project from another directory
docanvil serve --path ../my-docs

docanvil build

Generate the static HTML site for deployment.

docanvil build [--out <path>] [--clean] [--path <dir>]
Option Default Description
--out dist Output directory for the generated site
--clean false Remove the output directory before building
--strict false Emit warnings as errors and exit with code 3
--path . Path to the project root

The build pipeline processes each page through:

  1. Directive expansion (components)
  2. Popover conversion
  3. Markdown rendering (comrak with GFM)
  4. Wiki-link resolution
  5. Inline attribute injection
  6. Template wrapping (Tera layout)

Static assets (custom CSS, images) are copied to the output directory.

# Default build to dist/
docanvil build
# Clean build to a custom directory
docanvil build --out public --clean
# Build a project from another directory
docanvil build --path ../my-docs

Note

Broken wiki-links are reported as warnings during build. Check the output for any "broken link" messages to find references to pages that don't exist.

docanvil export

Export your documentation to other formats.

docanvil export pdf

Export docs as a single PDF using Chrome or Chromium.

docanvil export pdf --out <path> [--path <dir>] [--locale <code>]
Option Required Default Description
--out Yes Output path for the PDF file
--path No . Path to the project root
--locale No project default Locale to export. Pass all to generate one PDF per enabled locale — e.g. guide.pdfguide.en.pdf, guide.fr.pdf.

Requires Chrome or Chromium. DocAnvil searches common install locations on macOS, Windows, and Linux before falling back to PATH.

# Export the current project
docanvil export pdf --out guide.pdf
# Export a single locale
docanvil export pdf --out guide-fr.pdf --locale fr
# Export all enabled locales (i18n projects)
docanvil export pdf --out guide.pdf --locale all
# Export a project in another directory
docanvil export pdf --out guide.pdf --path ../my-docs

PDF output is configured via the [pdf] section in docanvil.toml. See PDF Export for the full guide, including cover pages, paper sizes, RTL support, and custom CSS.

Exit Codes

All commands return structured exit codes so CI pipelines can distinguish between different failure types:

Code Meaning Example causes
0 Success Build completed, doctor passed
1 General failure IO error, directory already exists, runtime setup failure
2 Configuration error Missing docanvil.toml, invalid TOML syntax
3 Content validation error Missing content directory, --strict warnings, doctor --strict failures
4 Rendering error Template syntax error, Markdown rendering failure
5 Internal error Panic (bug) — includes a message asking you to file an issue

You can use these in CI scripts to handle different failures appropriately:

docanvil build --strict
code=$?
case $code in
  0) echo "Build succeeded" ;;
  2) echo "Fix your docanvil.toml" ;;
  3) echo "Content issues found — check warnings above" ;;
  *) echo "Build failed with exit code $code" ;;
esac

Note

Exit code 5 should never happen in normal use. If you see it, please report the issue — it means DocAnvil hit an unexpected panic.