Skip to content

Changelog

What each Keystone release changed, newest first. For how to move a project onto a newer release, see Upgrading your project.

Breaking: comes first where a release has one, covering anything that stops an existing project from building unchanged or silently changes what it renders; each of its bullets names what to do about it. The other two groups say where a change landed — Engine: is how Keystone builds your book, Template: is the files your project owns, the ones you would merge by hand. The Unreleased section lists work that is merged and awaiting the next release.

Unreleased

Template:

  • core-diagrams takes KEYSTONE_DIAGRAMS_LAYOUT in project.conf, choosing how diagram nodes are placed. See Matching the book.

v2.4.0 — 2026-09-20

Breaking:

  • papersize takes a name from a fixed list; anything else stops the build. See Page sizes.
  • Sizing the page in both papersize and geometry stops the build — keep whichever one you want and clear the other.
  • A classoption carrying a page size or a base font size stops the build; move the value to papersize or fontsize.
  • classoption: landscape needs geometry: auto. With geometry of your own, move landscape among those options — the pairing now stops the build.
  • geometry: auto cannot be combined with other options; any option of your own replaces it.
  • An empty papersize, geometry or fontsize falls back to Keystone's value rather than the document class's, so clearing any of them changes the page. On a KOMA target a cleared papersize moves from A4 to letter.
  • In EPUB a figure's width= sizes the image rather than capping it, matching PDF. Drop width= to keep an image smaller than that width at its natural size. See Figures.
  • Two font registry entries naming the same file stop the build, case ignored; rename your file in fonts/ or drop the surplus entry. See Duplicate font file.
  • A font you register states the terms it travels under in main.license, and one that says nothing warns on every build — so a project that registered a font before this release fails under warnings-as-errors until it does. Name the license file sitting beside the font, or write license: [] where the font is yours and there is nothing to pass on. An EPUB then carries each embedded font's license beside it. See Custom fonts and Missing font license.

Engine:

  • Diagnostics read the same whichever part of the build prints them, wrap to the terminal rather than running off it, and list what a setting accepts under one heading rather than a different phrase each time.
  • A diagnostic now prints the link to its manual page, where it has one, so the message and the explanation are one step apart.
  • A strict build stopped by a warning of Keystone's own says no artifact was written and how to build leniently. See Strict mode.
  • Where Keystone reproduces another tool's words — the Lua loader's, your operating system's, Pandoc's math converter's — they now sit behind a │ bar that marks them as not Keystone's, and keep their own lines so any line numbers or carets still point where they should.
  • Every page size builds on every target, strict builds included.
  • A build names each stage as it runs and reports how long it took, so a PDF no longer goes quiet while it typesets. See Watching a build run.
  • Warnings from Pandoc read like Keystone's own, WARN: rather than [WARNING].
  • A fenced code block can be rendered by a hook — a container you wire in yourself — without changing the engine.
  • An unrecognized fontfamily or monofont says which font it falls back to, on the formats that use one. See Typography.
  • A hook's failure reads like Keystone's own, and can carry what to do about it rather than only what went wrong. See A hook that fails.
  • Each font family the image bundles carries its own license text, beside the font files it covers. See The runtime image.
  • The image carries its own NOTICE.md, attributing what it bundles. See Attribution.
  • In core, the image build stops when tlmgr reports success without installing every package it was asked for. See Reproducibility.
  • In core, the image build stops when the TeX Live packages arrive without a verified signature. See Reproducibility.

Template:

  • A new template, core-diagrams, renders a mermaid fence as a figure. See Diagrams.
  • Your compose file comes wired for a hook — the volumes it needs and a depends_on stub — so adding one is the hook's own service.
  • KEYSTONE_HOOKS_KEEP_ALIVE in project.conf, and make publish down=true, decide whether a finished build stops the project's containers. A wired hook stays running by default, which spares the next build its startup. See Hooks.
  • NOTICE.md now attributes every container your template runs — in core-diagrams the diagram renderer and what it draws with, and the verifier behind make verify.
  • NOTICE.md now attributes the system packages the engine image installs, naming each one's license and where to read its full terms.
  • .licenses/Fonts.md is gone — NOTICE.md now carries each font family's SPDX identifier and copyright holder.
  • In core, the image installs packages from declaration files under .docker/packages/, one directory per installer.
  • make down stops your project's containers; make reset also drops the volumes they shared, hook cache included.
  • make ps lists your project's containers. See Upgrading your project.
  • KEYSTONE_PROGRESS in project.conf, and make publish progress=<mode>, set how much of a build is reported.
  • make help lists odt among the formats make publish accepts. See Output formats.
  • make help groups its targets and fits an 80-column terminal.
  • In core-slim, project.conf drops KEYSTONE_DOCKER_IMAGE. The variant pins the published image, so nothing read it.
  • README.md orients you to the template and links this manual for the rest, instead of carrying its own copy of the reference material.
  • pandoc.yaml ships geometry: auto, which sizes the text block to the page and, on a two-sided book, sets the inner margin narrower than the outer.
  • project.conf and pandoc.yaml name each setting and link the manual rather than carrying the reference; no setting changed. See Project settings and Book metadata.
  • make publish and make all create artifacts/ first, so a first build on Linux no longer fails writing into it.
  • make clean empties artifacts/ rather than removing the directory.

v2.3.0 — 2026-08-17

Breaking:

  • In PDF, a one-sided document now centers its page number in the footer, as the one-sided classes do themselves. Set page-number-position: footer:outer to keep it at the right edge. See Running headers & footers.
  • A one-sided document that also sets footer-text — or footer-text-recto — loses that text: the centered page number takes the same slot and wins, with a warning that fails a strict build. The same override keeps both.
  • In PDF, opening pages — every chapter's first page, including unnumbered ones, and the contents — now print a centered page number. Set footer-text-opening: disabled to keep them bare. See Running headers & footers.
  • Rename keystone-note-placement to note-placement in pandoc.yaml — keystone- keys now belong to your target and stop the build if you set one. See Notes & citations.

Engine:

  • In PDF, footer-text-opening-column: auto puts the opening-page footer in the same column as the body page number instead of centering it. See Running headers & footers.
  • In core, make image retries a failed package download and reports the network as the cause when it gives up.

Template:

  • In core, a custom target metadata file must declare keystone-twoside and keystone-note-placement — whether its class lays out in spreads, and where it collects notes. Builds stop with an error naming the missing key until it does.
  • In core, comments in the engine filters no longer point at documentation that ships only in Keystone's own repository.
  • pandoc.yaml gains footer-text-opening and footer-text-opening-column.

v2.2.7 — 2026-08-12

Engine:

  • The publishing container now runs under a fixed user ID (1001), so ownership of the files it writes into your project stays predictable across releases.
  • Books build on Pandoc 3.10; ODT output now carries named list, title, and subtitle styles. See DOCX and ODT.
  • Inline code in ODT output picks up its character style, which previously resolved to nothing and left the text in the body font.
  • The image ships a patched OpenSSL and a newer TeX Live snapshot.

v2.2.6 — 2026-07-25

Engine:

  • .underline (alias .ul) and .mark now render in PDF; they previously failed the build. See Native styles.

v2.2.5 — 2026-07-24

Breaking:

  • Setting a metadata key the target owns now fails the build: documentclass, css, header-includes, keystone-justify, keystone-indent, keystone-fontsize-set, or keystone-required-fields. Remove them from pandoc.yaml and style through metadata and shortcuts instead. See Reserved keys and Reserved metadata key.

v2.2.4 — 2026-07-24

Breaking:

  • fontfamily accepts font-registry keys only; an arbitrary LaTeX font-package name no longer passes through. Register the font in fonts/fonts-registry.yaml to make it a valid key. An unrecognized value warns and falls back to latin-modern, and fails the build under warnings-as-errors. See Custom fonts and Unrecognized font family.
  • A cover-image, code-theme, bibliography, or csl path pointing outside the project directory now fails the build. Move the file into the project. Font paths in fonts/fonts-registry.yaml are exempt.

Engine:

  • toc-depth sets how many heading levels reach the table of contents, and applies identically in every output format. See Structure.
  • secnumdepth caps how many heading levels are numbered, in every format that numbers them. See Whether headings number at all.
  • toc and numbersections are now honored by EPUB, DOCX, and ODT — previously only the PDF respected a false.
  • linestretch sets line spacing in the PDF, validated as a positive number. See Line spacing.
  • colorlinks colors link text instead of boxing it, with linkcolor, urlcolor, citecolor, and toccolor taking #RRGGBB values. See Link colors.
  • monofont picks the font for code blocks and inline code, so code can use a wider Unicode range than the body font. See The code font.
  • fontsize is validated against the target's document class, and KOMA targets accept sizes the standard classes reject. An unsupported size snaps to the nearest allowed one. See Base font size.
  • New registry fonts: latin-modern-mono, latin-modern-math, noto-mono, and source-code-pro.
  • All three DejaVu families now embed in EPUB, retiring the path that relied on fonts installed on the reading device.
  • Math and symbol glyph coverage is broader, and the packages behind registered fonts are pinned.
  • An appendix div marks back matter, with configurable numbering. See Appendices.
  • A sym shortcut renders characters the body font lacks — ≫, ⩽, ∀ — in the shipped math face. See sym.
  • Aligned figures take an opt-in space-after attribute. See aligned-figure.
  • XeLaTeX shell-escape is locked off during PDF builds, so a manuscript cannot run commands through the typesetter. See Shell-escape is off.
  • Importing a document runs Pandoc sandboxed, which matters when the source is untrusted. See What to expect.
  • The image drops from 1.26 GB to 737 MB — it now carries only the font files the registry references, and rebuilds its TeX Live layer on pandoc/minimal.

Template:

  • pandoc.yaml gains toc-depth, secnumdepth, linestretch, colorlinks with its four colors, and monofont, and documents the new fontsize and fontfamily validation.
  • fonts/fonts-registry.yaml drops the command field — LaTeX command names are derived now.
  • make verify pins the cosign image it runs and matches the signing identity exactly rather than by substring.
  • NOTICE.md and the bundled font licenses cover the newly registered fonts.

v2.2.3 — 2026-07-05

Engine:

  • A div or span class outside Keystone's vocabulary is now flagged instead of passing through silently. See Unrecognized class.
  • A shortcut that omits a required field fails against the shortcut's own interface, naming the field. See Missing required field.
  • Build failures name the phase they occurred in, and every diagnostic follows one format. See Errors & checks.

Template:

  • project.conf gains KEYSTONE_WARNINGS_AS_ERRORS, which turns any warning into a build failure that writes no artifact — for CI and release builds. make publish strict=true overrides it per run.

v2.2.2 — 2026-06-27

Breaking:

  • Math the target format cannot represent now fails the build instead of being dropped silently from the output. Simplify the expression, or restrict it to a format that supports it. See Math that can't convert.

Engine:

v2.2.1 — 2026-06-21

The release the public manual was first written for.

Template:

  • The comments in pandoc.yaml and shortcuts.yaml point at the manual for detail instead of describing everything in place.

v2.2.0 — 2026-06-20

Engine:

  • Running headers and footers can read author-declared marks, for content no heading tracks — the current poem in an anthology, say. Declare the names in pandoc.yaml, set them inline with .set, and read them as {name} placeholders. See Author-declared marks.
  • An undeclared mark warns instead of silently resolving to nothing. See Undeclared mark.
  • {chapter} and {section} placeholders resolve correctly for unnumbered headings, and an unnumbered div marks a heading as excluded from numbering.
  • Blank filler pages in PDF builds carry no running header, matching the KOMA targets.

Template:

  • pandoc.yaml gains marks for declaring running-header mark names.

v2.1.0 — 2026-06-15

The release where Keystone's shape settled — most of what the manual describes today arrived here.

Breaking:

  • footer-copyright is gone. Set footer-text (or header-text) instead, which takes any content you want in each slot. See Header and footer text.
  • The book, article, and report targets no longer draw a rule under the running header. Set header-rule: enabled to restore it. KOMA targets are unaffected. See The header rule.

Engine:

  • Running headers and footers replace the old copyright footer, with separate recto and verso text, configurable page-number position, and an optional rule above the header. See Recto and verso.
  • Header and footer text takes dynamic placeholders — {title}, {author}, {page}, {chapter}, {section}. See Placeholders.
  • KOMA-Script targets scrbook, scrreprt, and scrartcl join book, report, and article. See Standard vs KOMA.
  • Bibliographies and citations work through Pandoc's citeproc, with a bibliography file and a csl style. See Citations.
  • keystone-note-placement switches footnotes to endnotes.
  • ifdef and ifndef divs include or exclude content by build configuration, so one manuscript can produce several editions. See The two primitives.
  • Ornamental fonts ship for decorative fiction elements — fleurons, chapter openers, manicules. See Decorative ornaments.
  • Ragged-right text keeps hyphenation instead of dropping it.
  • The image pins a dated TeX Live snapshot, so a given version rebuilds identically.
  • Existing DOCX and ODT documents can be imported into a manuscript. See Convert a document.

Template:

  • pandoc.yaml gains header-text, header-text-recto, header-text-verso, footer-text, footer-text-recto, footer-text-verso, page-number-position, header-rule, bibliography, csl, and link-citations.
  • project.conf declares build configurations as KEYSTONE_DEFINE_<name>="symbol …", and KEYSTONE_USING picks the one to build when using= is omitted.

v2.0.7 — 2026-04-26

Engine:

  • PDF metadata carries keywords and a subject, embedded as XMP so cataloging tools can read them. xmp-metadata opts out. See Summary fields.
  • The dialog shortcut validates its style attribute, and styled dialogue blocks lay out correctly in both PDF and EPUB. See Wrapped turns.

Template:

  • pandoc.yaml gains subject and xmp-metadata.

v2.0.6 — 2026-04-26

Engine:

  • A security update to a tool bundled in the image. Nothing changes for your manuscript.

v2.0.5 — 2026-03-30

Engine:

  • An epigraph's attribution sits inside the quote rather than after it, so it aligns to the quote's indent and spaces correctly. See Epigraphs.
  • The content placeholder is available by name as a slot shortcut, for use in your own definitions. See Naming the content slot.

v2.0.4 — 2026-03-30

Engine:

  • Keyword metadata survives on Pandoc 3.9.0.2 and later, which changed how quoting reaches the PDF.

v2.0.3 — 2026-03-30

Breaking:

  • An epigraph's attribution moves from a dash-prefixed final paragraph to a source="Author" attribute. See Epigraphs.

Engine:

  • A pullquote shortcut sets a passage off from the body text. See Pull quotes.
  • A vspace div inserts explicit vertical space, and a no-indent div suppresses paragraph indentation for a stretch. See Vertical space.
  • A shortcut definition can place the author's content explicitly, so a shortcut wraps that content instead of only preceding it. See Body injection.

v2.0.2 — 2026-03-15

Engine:

  • Dialogue lines no longer overlap when indentation control is on.

v2.0.1 — 2026-03-15

Breaking:

  • The align shortcut renames its align= attribute to style=, and no longer applies italic or bold — compose it with the font shortcut instead.
  • The aside shortcut drops font-family=. Nest a .font div inside the callout.
  • The figure shortcut drops align=. Use the figure-center, figure-left, or figure-right shortcuts, which align in every format including DOCX and ODT. See Positioning.

Engine:

  • indent-control sets first-line paragraph indentation. See Suppressing indentation.
  • justify-control reaches DOCX and ODT as well.
  • An aligned-figure shortcut places a figure and its alignment together. See Reusable presets.
  • Shortcuts declare an interface, so an attribute a shortcut accepts is named explicitly and routed to the handler underneath. See The interface.
  • System shortcuts are the supported way to reach a handler; handler classes sit behind the ks- namespace. See Build on the stable layer.
  • Figure captions are constrained to the width of the image.
  • Alignment on a block-level child works in EPUB.

Template:

  • pandoc.yaml gains indent-control and justify-control.
  • shortcuts.yaml documents the interface: form, and a shortcut that shadows a system shortcut takes precedence — delete the entry to restore the default.

v2.0.0 — 2026-03-01

Keystone became multi-format here, and this is the largest upgrade it has asked authors to make.

Breaking:

  • chapters/ and appendix/ are consolidated into a single manuscript/ directory. See manuscript.
  • The target is set by target: in pandoc.yaml rather than passed as make publish target=…. See The six targets.
  • The built-in poem-date style is retired; compose the same result from the align and font shortcuts.

Engine:

  • DOCX and ODT join PDF and EPUB as output formats. Each ships a reference document carrying its styles. See DOCX and ODT.
  • article and report targets join book. See The six targets.
  • Shortcuts arrive: named style aliases for divs and spans, defined in shortcuts.yaml, composable and nestable. See How you use them.
  • New shortcuts — aside for typed callouts, dropcap for chapter-opening initials, epigraph for opening quotations, scene-break for decorative separators, figure for styled images, align for alignment, multicol for two-column layout, and container for plain grouping.
  • Code blocks are styled in PDF and EPUB, with code-theme selecting the highlighting. See Syntax-highlighting themes.
  • epub-only, docx-only, and odt-only divs include content in one format only. See Targeting a format.
  • A draft watermark prints across every PDF page, sized by draft-scale.
  • A project can supply its own font files. See Custom fonts.

Template:

  • pandoc.yaml gains target, toc, numbersections, abstract, classoption, code-theme, draft, and draft-scale.
  • shortcuts.yaml is a new file, where a project defines its own style vocabulary.
  • The compose files are hardened, and the core-slim image tag is pinned to the release during assembly.

v1.8.6 — 2026-02-22

Engine:

  • Div styling reaches EPUB chapter pages, not only the title page.

v1.8.5 — 2026-02-22

Engine:

  • Fonts are embedded in EPUB output, so a book renders as designed on a device that lacks them. See Built-in fonts.
  • TeX Gyre and EB Garamond families ship in the image.

Template:

  • Locally built images are tagged :local rather than taking :latest.

v1.8.4 — 2026-02-20

Engine:

  • fontfamily and fontsize can be overridden per element, against a unified font registry. See Local overrides with font.
  • The latex-only handler works on spans as well as divs.

Template:

  • The drafts/ and research/ scaffolding directories are gone — keep working notes wherever suits you.
  • The output directory is created on demand instead of being tracked empty.

v1.8.3 — 2026-02-18

No changes to the engine or templates.

v1.8.2 — 2026-02-18

Template:

  • verify.sh spells out the limits of what a signature check proves.

v1.8.1 — 2026-02-17

Template:

  • Assembled templates ship a GPG-signed checksum manifest, so you can confirm what you downloaded is what was published. See The template.
  • make verify checks the runtime image's signature.
  • make with no target prints the help.

v1.8.0 — 2026-02-15

Engine:

  • Released images are signed and carry an SBOM, and every release is scanned for known vulnerabilities. See The runtime image.

v1.7.5 — 2026-02-15

Breaking:

  • make sample is gone, and the sample book no longer ships inside the image. Templates start empty.

v1.7.4 — 2026-02-14

Engine:

  • Publishing containers run as a non-root user.
  • Dialogue and poem-date styling handle inline formatting inside their content.

Template:

  • fontsize defaults to 11pt, matching what the targets actually used.

v1.7.3 — 2026-02-14

Engine:

  • Published image manifests carry their annotations correctly.

v1.7.2 — 2026-02-14

Engine:

  • Multi-platform images carry manifest-level annotations, so registries show the source and license.

v1.7.1 — 2026-02-14

Engine:

  • Div handling runs in a single pass instead of one filter per handler.

v1.7.0 — 2026-02-13

Template:

  • The compose file pulls the image from ghcr.io/knight-owl-dev/keystone, its new home.

v1.6.1 — 2026-02-12

Engine:

  • The image carries a Keystone version label.

v1.6.0 — 2026-02-12

Engine:

  • An empty cover-image no longer crashes EPUB builds.

v1.5.0 — 2026-02-08

Breaking:

  • project.conf replaces .env for project settings, and pandoc.yaml is the sole source of book metadata — values no longer come from the environment. See project.conf.

v1.0.2 — 2026-02-07

Engine:

  • Release builds cache against the current image.

v1.0.1 — 2026-02-07

Engine:

  • Book metadata is read from user-metadata.yaml in preference to the environment.

v1.0.0 — 2025-06-22

The first tagged release. Keystone could take a Markdown manuscript and produce a PDF and an EPUB through Pandoc, XeLaTeX, and a pinned Docker image, driven by make.

Before v1.0.0

Keystone began on 2025-04-05. The structure was different — one repository, no templates to fork, nothing published for anyone else to use — but over the 119 commits leading to v1.0.0 the outlines of what it became were already there.

Milestones from that stretch, for the record:

  • April 2025 — the publishing pipeline: Pandoc and XeLaTeX in Docker, driven by make, with base LaTeX styling and a pinned Pandoc version.
  • April 2025 — the first div handlers, dialog and latex-only, and with them the idea that a manuscript could carry styling instructions Pandoc alone does not understand.
  • April 2025 — DOCX output and document import, so a manuscript could arrive from somewhere else and leave in more than one format.
  • April 2025 — the template model: a canonical repository syncing assembled templates to public repositories, and the first slim variant.
  • May 2025 — pagebreak and poem-date handlers, and book metadata moving out of environment variables into YAML.

None of it was published for anyone else to use. The first image reached a registry in June 2025, as v1.0.0.