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] | path | The site root — the directory holding trail.toml. Default . |
| Flag | Value | |
|---|---|---|
--out <DIR> | path | Where 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-links | — | Downgrade missing ~link and related: targets, missing images, and unresolvable § citations from errors to warnings. Ambiguous references stay fatal. |
--strict | — | Fail the build when any article has no description:. Alias pages are exempt. |
--render-llms-full | — | Also write each unit's print.md as llms-full.txt beside it. |
--cbpath <PATH> | one path segment | Also 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:
| Flag | Value | |
|---|---|---|
--addr <ADDR> | socket address | Default 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 buildoutput never contains it. - Misses serve the built
404.htmlwith 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 0 | The build succeeded. |
| Exit non-zero | The build failed; the error is on stderr. |
| stdout | The build summary line, and serve's serving/rebuild lines. |
| stderr | Errors 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 published | The 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 allowed | The 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 N | Two siblings with the same order prefix. |
duplicate article slug '…' | Also raised for shelf contents flattened into their parent. |
chapter '…' contains no articles | A 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 root | Likewise 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.