Docs
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
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."
[kempt] spec = 1 [packages.core] description = "shell, prompt, history, modern CLI tools" [[packages.core.install]] brew = { formulas = ["starship", "atuin", "ripgrep", "jq"] } apt = ["ripgrep", "jq"] [[packages.core.symlink]] from = "config/zsh" to = "~/.config/zsh" backup = true [profiles.developer] packages = ["core", "terminal", "muster"]
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 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
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.
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.
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.
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.
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.
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).
— 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.