↑ subaud · local-first · MIT  

Docs

The manifest and its primitives.

A config repo is one kempt.toml plus the files it references. This page covers the manifest, where kempt can read a config from, and the closed set of primitives a manifest can use. The spec has the full schema.

the manifest

One kempt.toml, plus the files it references.

A config repo is a single kempt.toml and the config files it points at. The manifest is TOML and declares spec = 1; a parser rejects spec values it doesn't know rather than mis-parse a manifest from the future. Packages are made of ordered steps and run in dependency (needs) order. Crucially, a manifest describes what — the safety class of each action (software, files, read-only) lives in kempt's own code, never in the manifest, so a config can't declare its own installs "safe."

Profiles are named package sets — personas like developer or minimal — not conditionals. The only conditional in the manifest is only = { os, arch } on a package or a step, and it is always visible in plan output.

config sources

A git repo, a tarball, or a single file.

A config source can be a git repo (cloned; kempt update pulls it) or a gzipped tarball URL (fetched and extracted, no git; update re-fetches it), so sharing a full config tree does not require a cloneable repo. A self-contained manifest (software installs, config merges, downloads, and no repo-relative file steps) needs no tree at all: point plan/apply/verify/lint straight at a single file over HTTP or stdin with kempt plan -manifest https://…/kempt.toml or curl … | kempt apply -manifest - -yes.

primitives

A closed set of primitives.

Every action a manifest can take is one of the primitives below — that is the whole vocabulary. The set is deliberately closed: when a real capability gap appears, the answer is a new versioned primitive in kempt, not a script hook. That is what keeps a plan fully reviewable. Each primitive carries a fixed safety class — software, files, or read-only — assigned by kempt, not the manifest.

install

brew · winget · apt · npm · pi

Cross-platform backends; kempt selects the applicable ones at plan time. Backends are additive — npm/pi install on any host with the runtime, alongside the OS backend. npm and pi entries can be pinned as name@version; kempt then converges to that exact version.

github-release

download

github-release templates the asset with {os}/{arch}, sha256-verifies against checksums.txt, and installs atomically. download fetches from a domain distribution instead of GitHub, verifying a .sha256 sidecar via the same stage-and-atomic-move path.

git-clone

service

git-clone pins a ref or branch. service renders a launchd plist (macOS) or systemd --user unit (Linux) and does a cmp-before-reload, so an unchanged service never restarts.

files

symlink · json-merge · toml-merge · line-in-file

symlink links a repo-relative source (backup = true moves a real file to .bak first). json-merge and toml-merge do an additive, idempotent deep merge; line-in-file ensures a line or block.

verify

command-exists · http-ok · version-current

Read-only checks that touch nothing: is a command on PATH (command-exists / command-exists-any), does a URL return 2xx (http-ok), does a symlink point where it should, has a GitHub release drifted (version-current).

no exec, ever

— absent by design —

There is no primitive that runs an arbitrary command, and there is no plan to add one. A notes field can surface post-install hints in plan output, but notes are documentation only — they run nothing.