Upgrading your project
Keystone releases roll forward only — each release supersedes the last, and
templates aren't patched retroactively. The template repositories carry no
release tags either: each release resets them to current, so "the new template"
always means the template repo exactly as it stands now (its .keystone/sync.json
names the version). Upgrading means moving your project onto that current release
when you want its new features or security updates.
If you need neither, there's no pressure to move. Keystone images are locked down and run fully offline — no network access in or out of the build container — so an older image is never a network-exposed dependency waiting to be patched. And pinning is the foundation of Keystone's reproducible-build promise: the same source and the same pinned image produce the same output today or years from now. That guarantee is part of the public contract every release ships, so a project that stays put keeps building exactly as it did.
The Keystone CLI will automate upgrading existing projects once it ships. Until then — and it's deliberately simple — here's the manual path.
Find your current version
.keystone/sync.json records the release your project was assembled from:
{
"version": "...",
"template": "keystone-template-core-slim",
"commit": "...",
"timestamp": "..."
}
(The file carries a couple more bookkeeping fields; version is the one you're
comparing against the latest release.)
Upgrade a core-slim project
The engine lives in a prebuilt image, pinned by tag in
.docker/docker-compose.yaml:
image: ghcr.io/knight-owl-dev/keystone:<version>
For most projects, bumping that tag to the new version is the entire
upgrade — the next build pulls the new engine with its latest fixes and
features. Verify it if you like (make verify), then build as usual.
Bringing in template changes
A release may also add new pandoc.yaml settings, make commands, or project
files. Those live in the template, not the engine, so a tag bump doesn't pull
them in — you copy over what you want by reviewing the diff between your project
and the new template.
.keystone/checksums.txt makes that safe. It's a SHA-256 manifest of every file
as the template shipped, so it tells you which files you've changed:
sha256sum -c .keystone/checksums.txt # Linux
shasum -a 256 -c .keystone/checksums.txt # macOS
- Files reported
OKare untouched since assembly — safe to replace wholesale with the new template's versions. - Files reported
FAILEDare yours (e.g.pandoc.yaml) — merge the new changes in by hand. - Files you added since (your chapters, images, custom fonts) aren't in the manifest at all, so they're never flagged and never touched.
Upgrade a core project
The core template has no pinned image tag to bump — it builds the
image locally from the engine source it ships under .pandoc/ (plus the
Dockerfile). Upgrading means bringing that engine source up to the new release
and rebuilding with make image. How hard that is depends entirely on what
you've changed; the checksum manifest (above) tells you:
- You didn't touch the runtime. Every engine file reports
OK— replace them wholesale with the new release's, runmake image, done. As easy as a slim upgrade. - You customized the engine. The files you changed report
FAILED— merge the release's changes into yours by hand. The effort scales with how far you've forked; see Customizing.
Hand it to an AI assistant
You don't have to do any of this by hand. If you work with an AI assistant, point
it at the procedure for your template and your project, and it can run the
upgrade — classifying files against the checksum manifest, re-syncing the
template, and reconciling your pandoc.yaml and project.conf for you:
These are the steps above, written as a deterministic procedure an agent can follow. The core procedure stops and hands back to you if you've customized the engine.