Command-line reference

Trail has two commands, build and serve, plus clap's own help. Everything below is the complete flag surface; there are no others.

Synopsis #

trail build [OPTIONS] [ROOT]
trail serve [OPTIONS] [ROOT]
trail help  [COMMAND]

trail --version prints the version; trail --help and trail <command> --help print usage.

trail build #

Builds the site into the output directory.

Argument
[ROOT]pathThe site root — the directory holding trail.toml. Default .
FlagValue
--out <DIR>pathWhere the site is written. Default ROOT/dist. Excluded from the site scan, so a build into a directory inside the root is safe.
--allow-dangling-linksDowngrade missing ~link and related: targets, missing images, and unresolvable § citations from errors to warnings. Ambiguous references stay fatal.
--strictFail the build when any article has no description:. Alias pages are exempt.
--render-llms-fullAlso write each unit's print.md as llms-full.txt beside it.
--cbpath <PATH>one path segmentAlso publish a cache-busting copy of the whole site under PATH, with every link inside it rewritten to stay there.

On success:

built 1227 pages (8 products) → ./dist

With --cbpath, a second line names the copy:

built 1227 pages (8 products) → ./dist
cache-busting copy → ./dist/8f3a91c/

The page count is the site's; the copy holds the same number again and is not added in.

The count is HTML pages: articles, product and anthology landings, book covers, /print pages, the front page and 404.html. Markdown mirrors, llms.txt, site.json, the sitemap and the search bundle are not counted.

trail serve #

Builds the site, serves the output over HTTP, and rebuilds on change. Takes every build flag, plus:

FlagValue
--addr <ADDR>socket addressDefault 127.0.0.1:8724.
serving ./dist at http://127.0.0.1:8724 (watching . for changes)
rebuilt 1227 pages

Behaviour:

  • Changes are debounced for 200 ms; changes inside the output directory, and paths with a dot-prefixed component, are ignored.
  • Pages are served with a live-reload script that reloads them over server-sent events after each successful rebuild. trail build output never contains it.
  • Misses serve the built 404.html with a real 404 status.
  • A failed initial build or rebuild prints the error and keeps serving the last good output — the process does not exit.

Exit status and streams #

Exit 0The build succeeded.
Exit non-zeroThe build failed; the error is on stderr.
stdoutThe build summary line, and serve's serving/rebuild lines.
stderrErrors and warnings.

trail serve runs until interrupted.

Warnings #

These print on stderr and do not fail the build:

Warning
image '…' is not referenced by any article and was not publishedThe file stays out of the output.
in article '…': link '~…' matches no page in product '…'Only with --allow-dangling-links.
in article '…' (related): …A related: reference that did not resolve, with --allow-dangling-links.
in article '…': image '…' not found …With --allow-dangling-links.
initial build failed (serving previous output): …serve only.
rebuild failed (still serving the last good build): …serve only.

Errors #

Loading errors stop at the first problem, with the chain of contexts:

Error: loading product 'pekit'

Caused by:
    0: loading topic in '2--recipes.topic'
    1: in article '100--anatomy.md'
    2: updated: '2026-5-1' is not an ISO date (expected YYYY-MM-DD)

Link errors are collected across the whole site and reported together:

Error: 3 broken links:
in article '/pekit/recipes/anatomy': link '~pekit/running/invokation' matches no page in product 'pekit'
…

The common ones #

Message
unexpected file '…' in site root: only trail.toml is allowedThe root takes trail.toml, *.product/, the output dir, and files named by the config.
unexpected directory '…' in site root: only *.product directories are allowed
unexpected grouping type '.…' on '…' in a product (expected .antho, .book, .topic or .shelf)
a shelf cannot contain another shelf ('…')
grouping directory '…' is missing its '<order>--' prefix
'…' has a non-numeric order prefix '…'
'…' is not a valid slug (lowercase kebab-case)
items '…' and '…' share order NTwo siblings with the same order prefix.
duplicate article slug '…'Also raised for shelf contents flattened into their parent.
chapter '…' contains no articlesA book chapter must lead somewhere.
'print' is a reserved slug (every section has a /print page)
'…' is a reserved product slug (it collides with the '/…' output directory)assets and pagefind.
… has no frontmatter (must start with '---')
… has unterminated frontmatter
parsing frontmatter of …Bad YAML, a missing required key, or an unknown key.
updated: '…' is not an ISO date (expected YYYY-MM-DD)
color '…' is not a #rrggbb hex color
accent_dark without accent: set the base accent color too
edit_url must contain a {path} placeholder …
featured product '…' does not exist (no ….product directory)
favicon names '…', which does not exist in the site rootLikewise custom_css and head_html.
link '~…' is ambiguous; candidates: …Never downgradable.
unknown admonition type '[!…]' (expected NOTE, TIP, IMPORTANT, WARNING or CAUTION)
unclosed ':::tabs' block (close it with ':::')And the other tab-group errors.
inline_ref phrase '…' is claimed by both … and …
'… §…' does not match any section of '…'Downgradable.
image '…': ~references name pages, not files — use a path relative to the article
--cbpath '…' is already a path in the site; the copy would bury it …Checked before anything is built.
--cbpath '…' must be a single path segment, with no '/'Likewise the empty, dot-leading and bad-character forms.

Installing #

Trail is a single Rust binary. Build it from its source directory:

$ cargo build --release

The result is target/release/trail. It carries the templates, stylesheet, fonts, syntax definitions, search engine and diagram renderer inside it, so the binary alone is the whole tool — copy it onto your PATH and nothing else needs installing.

Edit this page