Skip to content
Grimoire

Commands

Five commands. Every flag has a long form; the common ones have a short form too, and --help on any command prints the same table.

sh
grimoire --help          # the command list
grimoire build --help    # one command's flags
grimoire --version

A flag always wins over grimoire.toml, so a one-off build needs no edit to the file.

grimoire build

Render the site.

FlagDefaultWhat it does
-c, --config PATHgrimoire.tomlwhich configuration file to read
-s, --src DIRfrom configthe directory of Markdown to build
-o, --out DIRfrom configwhere to write the site
-t, --theme NAMEfrom configtheme to use; grimoire themes lists them
-m, --mode MODEfrom configfirst-visit colour mode: auto, light, dark
--nav WHEREfrom configthe book-contents column: left, right, off
--toc WHEREfrom configthe on-this-page column: left, right, off
-L, --ui-language TAGfrom configlanguage for Grimoire's own strings
--cleanfrom configempty the output directory before building
--no-cleanfrom configkeep what is already in the output directory
--raw-htmlfrom configemit hand-written HTML blocks as written
--no-raw-htmlfrom configescape hand-written HTML blocks
--title-url URLfrom configwhere the title in the top bar links; "" is the book itself
--pdfoffalso render the book to PDF
--image-dpi Nfrom configdpi a picture is drawn at in the PDF; 0 keeps the configured value
--no-searchoffskip the search index and the search UI
-j, --jobs N0chapters to render in parallel; 0 is one per CPU
-v, --verboseoffreport each chapter as it is rendered
-q, --quietoffprint nothing on success
sh
grimoire build
grimoire build --theme nordic --out /tmp/preview
grimoire build --pdf --jobs 4
grimoire build --nav right --toc off
grimoire build --clean

--clean empties the output directory before building, so a chapter deleted from the book stops being published. It keeps top-level dotfiles and refuses outright to empty a filesystem root, the working directory, or anything holding the sources - see Configuration for the whole rule and for [build] clean, which is where the setting belongs once a book has decided. --no-clean is how a single run opts out of that setting.

--nav and --toc place the two navigation columns, or leave them out. Both are covered in Configuration, which is where the setting belongs once a book has decided; the flags are for trying an arrangement before writing it down.

--no-raw-html escapes a hand-written HTML block in the Markdown instead of emitting it as written - for a book assembled from Markdown you did not write. Everything else on a page is escaped either way; see Configuration.

--title-url points the title in the top bar somewhere other than the book's own landing page - back to the site the book belongs to. An empty value is a value: --title-url "" puts it back to the book when grimoire.toml says otherwise. See Configuration for the shape of URL that belongs there.

The exit status is 1 when the outline names a chapter with no file behind it - the rest of the book still builds, and the missing entries are reported on stderr.

grimoire pdf

Render only the PDF, skipping the site.

FlagDefaultWhat it does
-c, --config PATHgrimoire.tomlwhich configuration file to read
-s, --src DIRfrom configthe directory of Markdown to build
-o, --out DIRfrom configwhere to write the PDF
-v, --verboseoffreport each chapter as it is laid out
--output FILEfrom configPDF filename, relative to the output directory
--paper SIZEfrom configa4 or letter
--image-dpi Nfrom configdpi a picture is drawn at; 0 keeps the configured value
sh
grimoire pdf
grimoire pdf --paper letter --output manual.pdf
grimoire pdf --image-dpi 192            # the same diagrams, at half the size

--image-dpi is the one PDF setting worth trying from the command line rather than from grimoire.toml: how a diagram lands on the page is a thing to look at two or three times in a row. It only reaches a picture narrower than the text column - a wider one is scaled to the column whatever its dpi - and [pdf] imageDpi is where a book settles on a value.

grimoire serve

Build, then serve the result on a local address until interrupted.

FlagDefaultWhat it does
-c, --config PATHgrimoire.tomlwhich configuration file to read
-s, --src DIRfrom configthe directory of Markdown to build
-o, --out DIRfrom configwhich directory to serve
-v, --verboseoffreport each chapter as it is rendered
-a, --addr ADDR127.0.0.1:8080address to listen on
--nav WHEREfrom configthe book-contents column: left, right, off
--toc WHEREfrom configthe on-this-page column: left, right, off
--cleanfrom configempty the output directory before the first build
--no-cleanfrom configkeep what is already in the output directory
--raw-htmlfrom configemit hand-written HTML blocks as written
--no-raw-htmlfrom configescape hand-written HTML blocks
--title-url URLfrom configwhere the title in the top bar links; "" is the book itself
-L, --ui-language TAGfrom configlanguage for Grimoire's own strings
-w, --watchoffrebuild whenever a source file changes
--no-reloadoffwith --watch, do not reload the browser
--no-buildoffserve what is already there, without rebuilding
sh
grimoire serve
grimoire serve --watch
grimoire serve --watch --nav right --toc left
grimoire serve --addr 0.0.0.0:9000 --no-build

Only the build serve does on the way in prunes. A --watch rebuild never does: it would empty the directory being served on every save, and a reader who reloaded at the wrong moment would get a 404 rather than a page.

The two column flags are here as well as on build because trying an arrangement is what --watch is for. The override lives as long as the process does: the watch loop rebuilds with the configuration serve started with, so every rebuild keeps it. It does nothing under --no-build, which serves what is already on disk.

--watch watches the source tree and rebuilds when it changes, naming the file that caused it:

$ grimoire serve --watch
built 7 pages into site/
watching docs/ for changes (the page reloads itself)
serving site/ at http://127.0.0.1:8080/ (ctrl-c to stop)
docs/commands.md modified - rebuilding
rebuilt 7 pages into site/

A change that lands on several files at once - a git checkout, a search and replace across the book - is one rebuild, reported as and 3 more. Writing the site is not a change: the output directory is left out of the watch, so a book that builds into its own source tree does not rebuild itself for ever.

The browser reloads itself

With --watch, every page served carries a small script that polls for the build and reloads when it changes, so a save in the editor shows up in the window without a keystroke. --no-reload turns it off and leaves the watching.

Two properties are worth knowing, because they are the reason it is built this way:

  • The script never touches the disk. It is spliced into the response on its way out, so the files in the output directory are the same bytes a publish would upload. This is why it is not simply written into the page at build time: a preview build that had quietly grown a polling loop would be a bad thing to rsync. Nothing outside serve --watch ever emits it.
  • It polls rather than holding a socket open. The httpd engine answers a request once and has no streaming, so there is no WebSocket and no event stream to push down; the script asks a /.grimoire-reload endpoint every 700 ms, and the endpoint answers with one stat of the stylesheet - the file every successful build rewrites. A failed build does not move it, so a page never reloads into a broken one. It also reconnects for free: restart the server under a waiting tab and it simply starts answering again.

The published site is untouched by all of this. It carries no reload script, no endpoint, and nothing that polls.

A build that fails does not stop the loop; it reports and waits for the next change, which is the moment a watch loop is most useful. Editing grimoire.toml is noticed but not applied - the loop holds the configuration resolved when serve started, command-line overrides included, so it says so rather than rebuilding with the old theme and looking like it worked:

grimoire.toml modified - restart serve to pick it up

The server runs a small pool of accept loops, because a browser asks for the page, the stylesheet, the runtime, and (on the first search) the index in parallel; a single-threaded loop would serialise them. It needs the default jennifer binary - jennifer-tiny stubs httpd and says so.

grimoire init [dir]

Write a starter book - grimoire.toml, a SUMMARY.md, and three chapters - into dir, or into the current directory if none is given.

sh
grimoire init my-book

Existing files are never overwritten. Running it twice is safe: the second run reports each file it kept, which also makes it a way to add the pieces you deleted back.

grimoire themes

List the built-in themes with a one-line description of each. See Themes for what they look like.

grimoire plugins

List the programs this book would run, and where each one comes from, without building anything:

$ grimoire plugins
Programs this book runs, from grimoire.toml:

  preprocessor  include  ->  /opt/grimoire/plugins/grimoire-include  (ships with Grimoire)
  renderer      epub     ->  /home/you/book/tools/grimoire-epub      (in this book)
  renderer      feed     ->  /usr/local/bin/grimoire-feed            (found on PATH)

Each one runs with your permissions and can do anything you can.
Nothing is discovered: every program above is named in the file.

A table name says nothing about which program answers to it: a bare name is looked for beside Grimoire and then on PATH, and a command with a separator in it is a path. This is the step before building somebody else's book - the one thing a build does that reading the repository does not show you.

The fourth answer is (not found), which is a build that will stop when it gets there.

-c, --config names the file, as everywhere else.

Verbose output

--verbose names each chapter as it goes, which is how you find the one that is slow or throwing:

$ grimoire build --verbose --jobs 1
building docs -> site (theme grimoire, 13 chapters, 1 job)
  render  index.md  ->  index.html
  render  guide/syntax.md  ->  guide/syntax.html
  ...
  assets  stylesheet, runtime, search index
  copied  2 files from docs
  plugin  renderer sitemap  ->  /opt/grimoire/plugins/grimoire-sitemap
  render  sitemap  ->  sitemap.xml

A plugin line names the program by its real path, immediately before it runs. grimoire plugins is the same information without the build.

Chapters render in parallel, so with the default --jobs the lines arrive in the order chapters finish, not the order they are listed. Pass --jobs 1 when you want outline order.

--verbose and --quiet are not exclusive: verbose adds progress, quiet suppresses the closing summary. Passing both gives progress and no summary.

--quiet suppresses output, never the answer. A build whose outline names a chapter with no file behind it still warns on stderr and still exits non-zero, because that status is the whole reason a script runs the build at all.