konfig.json
konfig.json is the project file that tells the CLI where your sources live and where output goes. Commands find it by walking up from the current directory. The file is decoded with a strict schema: unknown keys are an error, so a typo in a field name fails the command instead of being ignored. Every relative path in the file resolves against the directory that contains it, referred to below as the config directory.
Fields
| Field | Type | Default | Meaning |
|---|---|---|---|
root | string | required | Directory (relative to konfig.json) that holds your env entries, modules, and charts. build hashes everything under it for the cache. |
envs | Record<string, { entry: string }> | required (may be {}) | Env name to entry file, relative to root. Envs not listed fall back to <root>/env/<name>.ts. |
outDir.manifests | string | required | Where build writes, relative to root. Files land in <root>/<outDir.manifests>/<env>[/<cluster>]/. |
diff.baseline | string | unset | Baseline manifest tree for konfig diff, relative to root; the env name is appended. diff fails with DiffBaselineMissing when absent. |
cacheInclude | string[] | [] | Extra files, directories, or glob patterns (relative to konfig.json) hashed into the build cache on top of root, for inputs that live outside the konfig root. |
cluster | string | "cluster.ts" | Path of the cluster module, relative to root. |
modules | string | "modules" | Path of the modules directory, relative to root. |
charts | string | "infra/k8s-konfig/charts" | Path of the chart definitions directory, relative to konfig.json’s own directory. Read by crd and helm fetch (see below). |
crd.outDir | string | ".generated/crd" | Destination for generated CRD types, relative to konfig.json’s own directory. Read by crd extract (see below). |
helm.cacheDir | string | ".konfig/helm-cache" | Helm tarball cache directory, relative to konfig.json’s own directory. Read by crd, helm fetch, and Helm.release at render time (see below). |
helm.minVersion | string | "3.16.0" | Minimum helm version. Read by the crd and helm fetch preflight check (see below); Helm.release still takes its own opt-in minVersion option and does not read this field. |
services.outFile | string | unset | Reserved for the services layer; validated only. |
services.globalPaths | string[] | [] | Reserved for the services layer; validated only. |
clusters.<name> | { registry?, ingressClass?, storageClass?, repositoryUrl? } | unset | Per-cluster values, all optional strings. |
The render commands (build, validate, diff) and set read root, envs, outDir.manifests, diff.baseline, and cacheInclude directly from the file.
The Helm-related fields (charts, crd.outDir, helm.cacheDir, helm.minVersion) work differently. They feed crd extract, crd verify, and helm fetch, and each one can also be set from an environment variable. The value is resolved in this order:
- The environment variable, if set.
- Otherwise the matching
konfig.jsonfield, resolved relative to the config directory. - Otherwise a built-in default, resolved relative to the current working directory.
This lets a project set these paths once in konfig.json without exporting environment variables, while CI or a shell override still takes priority when needed. Outside a konfig project (no konfig.json found), only the environment variable and the built-in default apply.
| Variable | Overrides field | Default | Used by |
|---|---|---|---|
KONFIG_CHARTS_DIR | charts | infra/k8s-konfig/charts | crd, helm fetch: directory of chart registry modules |
KONFIG_HELM_CACHE | helm.cacheDir | .konfig/helm-cache | crd, helm fetch, and Helm.release at render time |
KONFIG_CRD_OUT_DIR | crd.outDir | .generated/crd | crd: output directory for generated .ts files |
KONFIG_HELM_MIN_VERSION | helm.minVersion | 3.16.0 | crd, helm fetch: preflight helm version check |
The tarball cache location is also honored at render time. When a chart definition calls Helm.release() during build, validate, or diff, the chart is cached in the directory given by helm.cacheDir (or its environment variable). A cache location set once in konfig.json is therefore used consistently by helm fetch, crd extract, and rendering.
Example
The full-stack example keeps konfig.json at the workspace root with root: ".", so every other path is workspace-relative:
{
"root": ".",
"cluster": "infra/cluster.ts",
"modules": "infra/modules",
"envs": {
"prod": { "entry": "infra/envs/prod.ts" },
"staging": { "entry": "infra/envs/staging.ts" }
},
"outDir": { "manifests": ".generated/manifests" }
}The prod and staging envs are declared explicitly because their entries live under infra/envs/ rather than the default <root>/env/ location. The cluster and modules fields describe the layout for readers and tooling; the CLI does not load them.
images.json
konfig set maintains a second file, <root>/images.json, which maps each env and app to the container image it should run. It is decoded with a strict schema (defined in packages/core/src/images.ts) and has this shape:
interface ImagesConfig { readonly envs: Record<string, Record<string, string>> // env -> app -> image reference}{ "envs": { "prod": { "api": "ghcr.io/example/api:sha-1a2b3c4", "worker": "ghcr.io/example/worker:sha-1a2b3c4" }, "staging": { "api": "ghcr.io/example/api:sha-9f8e7d6", "worker": "ghcr.io/example/worker:sha-9f8e7d6" } }}Your modules read this file through two helpers from @konfig.ts/core: imagesFor({ cfg, env }) selects the map for one env, and requireImage({ e, app, envName }) picks one app’s image out of it and fails when the app is missing. Both throw on a missing key; the Effect variants (lookupEnvEffect and requireImageEffect) instead report the typed errors ImagesEnvMissing and ImagesAppMissing. The full-stack example does not ship an images.json; it derives image references from its build modules instead. See konfig set for the write path.