Upgrading your project
Keystone releases roll forward only — each release supersedes the last, and templates aren't patched retroactively. "The new template" always means the template repo exactly as it stands now; tags preserve past releases, but you upgrade to the branch head, not a tag. Upgrading means moving your project onto that current release when you want its new features or security updates.
A template may also be republished between releases, to take a newer digest for
an image it runs — a security fix, most often. Those refreshes carry nothing
else: the engine is the same, so .keystone/sync.json still names the same
version, and the repo tags them vX.Y.Z.1, vX.Y.Z.2 and so on after the
release they follow. A repo with no such tags has never had a refresh.
The changelog records what each release changed, breaking changes first.
If you need neither, there's no pressure to move. Keystone builds are sandboxed and run fully offline, and the pinned image makes them reproducible: the same source and the same pinned image produce the same output today or years from now. A project that stays put keeps building exactly as it did.
The Keystone CLI will automate upgrading existing projects once it ships. Until then, here's the manual path.
Stop the project before you upgrade
A template that wires a hook — core-diagrams, or one you added — leaves it
running between builds. If the new release no longer declares its service, an
upgrade leaves the container orphaned. make ps lists what is up and
make down removes it, socket and all, leaving your
hook cache alone.
Find your current version
.keystone/sync.json records the release your project was assembled from:
{
"version": "...",
"template": "keystone-template-core-slim",
"commit": "...",
"timestamp": "..."
}
(version is the field you compare against the latest release.)
The template repository ships this file too. If its version matches yours but
its commit differs, your project is behind a pin refresh rather than a
release — the same engine, newer image digests. Each template's page links its
repository: core, core-slim,
core-diagrams.
The changelog anchors each release at #vX-Y-Z, so
v2.2.5 opens that entry directly — start at yours and read
up to see what moving would bring in.
Upgrade a project that runs the engine from an image
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.
Any other image that file pins — a hook your template wires — moves with the release too. Take the new template's digest for it rather than keeping your own: Bringing in template changes covers how.
A pin refresh brings no version to bump — the engine is the same one. What moves is the digest of an image your template runs; take the new template's copy of whichever file carries it. The checksum step below says whether you had edited that file, and the diff against the new template is what names it.
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. The changelog's Template group names them per release.
.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.
- Files your manifest lists that the new template's doesn't are ones the release
removed — delete them, unless they came back
FAILEDand you want to keep what you changed.
Upgrade a project that ships the engine source
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.