Skip to content

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 OK are untouched since assembly — safe to replace wholesale with the new template's versions.
  • Files reported FAILED are 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, run make 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.