Declarative bootstrap for Kubernetes.
One static binary that takes a freshly created cluster from
"API server answers" to "workloads can be deployed" — a declarative,
idempotent DAG of helm, apply, wait, and friends. No kubectl, no helm
binary, no bash.
Docs · Quickstart · DSL · CLI · vs Terraform
Terraform (or eksctl, or CAPI) hands you a cluster. ArgoCD takes over once it's
installed. In between lives everybody's least favorite artifact: the bootstrap
script — a few hundred lines of kubectl apply, helm upgrade --install,
sleep 30, and retry loops, duct-taped into a null_resource and feared by
everyone on call.
khook replaces that gap with a declarative spec:
apiVersion: khook.io/v1
kind: Khook
metadata:
name: bootstrap
steps:
- name: cilium
helm:
chart: cilium
repo: https://helm.cilium.io/
version: 1.18.4
namespace: kube-system
atomic: true
- name: all-ready
needs: [cilium]
wait:
for: condition=Ready
on: pods
allNamespaces: true$ khook apply -f bootstrap.yaml
✓ cilium (helm) 21.457s
✓ all-ready (wait) 4.203s- One binary, zero dependencies. The Kubernetes and Helm SDKs are embedded; khook never shells out. Nothing to install on the runner but khook itself.
-
A DAG, not a script. Steps declare
needs:; khook topologically sorts them and runs each level in parallel. Cycles are caught before anything touches the cluster. -
Idempotent by design. Re-running a spec is always safe — Helm release
history decides install-vs-upgrade, applies converge existing resources,
deletes treat "already gone" as success. Run it on every
terraform apply. -
Fails loud, precisely. Per-step timeouts and retries,
onError: fail | continue, and a summary table naming exactly what succeeded, failed, or was skipped — with distinct exit codes for validation vs execution failures. - Bootstrap, then hand off. khook installs your CNI, secrets tooling, and GitOps controller — then gets out of the way. It is deliberately not a GitOps engine.
Seven verbs cover the bootstrap surface — helm, apply, delete, patch,
wait, rollout, job — with ${VAR} substitution, sprig
pipelines, and when: (CEL) conditionals so one spec serves
many environments. Full field reference: the DSL spec.
make build
k3d cluster create dev
bin/khook apply -f examples/simple.yaml \
--set NAMESPACE_NAME_TO_CREATE=demo \
--set NAMESPACE_NAME_FOR_INGRESS=ingressOn a terminal each step is a live status line; in CI you get plain logs and a
summary table, or --output json. Run it again — everything converges, nothing
breaks. That's the point.
Full walkthrough in Getting started.
- Getting started — install, first spec, variables
- DSL specification — the seven step types, variables, pipelines, conditionals
- CLI reference — commands, flags, variable precedence, exit codes, semantics
-
vs Terraform — why not the
kubernetes/helmproviders -
Examples —
real-case.yaml(production-shaped EKS bootstrap),localenv.yaml(k3d/kind)
The v1 core is implemented and tested (unit + k3d end-to-end): the seven step
types, DAG engine, variables, resumable runs (state:), teardown (destroy),
and the CLI. Pre-release — a Terraform/Lambda integration is on the
roadmap.
go test ./... # unit tests (engine, spec, executors against fakes)
./tests/e2e.sh # end-to-end against a throwaway k3d clusterContributions welcome — read AGENTS.md for repo conventions and
the reading order.