konfig build
konfig build <env> turns one environment into a tree of YAML files on disk. It loads the env’s entry module, runs the app-of-apps (or bundle) program that module exports, and renders every manifest with the render context built from the shared flags. The result is one YAML file per Kubernetes resource plus one Argo CD Application per app. If nothing that feeds the render has changed since the last run, the build writes nothing and reports a cache hit.
Usage
konfig build <env> [--log text|json] [--verbose] [--no-cache] [--cluster <name>] [--k8s-version <ver>] [--flag k=v ...]Arguments
| Name | Default | Description |
|---|---|---|
env | required | Env name to build (for example prod). Resolved via envs.<env>.entry or <root>/env/<env>.ts. |
Flags
| Name | Default | Description |
|---|---|---|
--log | text | Output format for the report line: text or json. |
--verbose | false | Wrap the render in an Effect span named konfig.render.<env> so tracing output shows per-render timing. |
--no-cache | false | Skip the input-hash check and force a fresh render (debugging, first build). |
--cluster | unset | Shared render flag, see CLI overview. Adds a <cluster> directory level to the output path. |
--k8s-version | unset | Shared render flag. |
--flag k=v | unset | Shared render flag, repeatable. |
Output layout
Files land under <configDir>/<root>/<outDir.manifests>/<env>, with an extra /<cluster> level when --cluster is set. That directory contains two kinds of subdirectories:
- One directory per app, named after the app. It holds one file per rendered resource, named
<Kind>-<name>.yaml. Dots and slashes in resource names are replaced with-in the filename. Output that arrives as raw YAML text (Helm releases, sops passthrough) is split on real YAML document boundaries, so it ends up in the same per-resource files as everything else. - One directory for the app-of-apps program itself, named
appsunless you gave the program a name. It holds oneApplication-<app>.yamlfor every child app.
.generated/manifests/prod/├── apps/│ ├── Application-api.yaml│ └── Application-postgres.yaml├── api/│ ├── Deployment-api.yaml│ └── Service-api.yaml└── postgres/ └── ...Writes are atomic. Everything is first staged under <outDir>.tmp; then the live directory is removed and the staging directory is renamed into place, so a failed run never leaves a half-written tree. Files are written with mode 0600. Apps render four at a time, which keeps the number of helm and sops subprocesses bounded.
Cache
The cache lets repeated builds finish without re-rendering. Before rendering, build computes a SHA-256 hash over everything that can influence the output:
- the decoded
konfig.json - the render context (
--cluster,--k8s-version, and the sorted--flagpairs) - the env entry file
- every file under
root, skippingnode_modules,dist, and.konfig - every path matched by
cacheInclude
The input hash and a hash of the written output are stored in <configDir>/.konfig/cache/<env>-<ctxKey>.json. The context key is a digest of the render context, so --cluster and --flag combinations each get their own slot and never overwrite each other.
A run counts as a cache hit only when all of the following hold: the input hash matches, the recorded output directory is the one this invocation would write to, that directory exists, and its on-disk contents still hash to the recorded output hash. Editing or deleting a generated file by hand therefore causes a miss, and the next build rewrites the tree. The hash is deliberately conservative: touching any file under root invalidates it.
Report
In text mode the command prints Rendering env 'prod'... followed by one report line. After a real render that line reads Wrote 42 file(s) to /abs/out/prod and includes the render and write times in milliseconds. On a cache hit it reads Cached, notes that the env’s inputs are unchanged, and states the file count at the output directory.
With --log json the command prints a single JSON object per run:
{"env":"prod","files":42,"outDir":"/abs/out/prod","renderMs":812,"writeMs":9,"totalMs":821,"cached":false}Exit codes and errors
The process exits non-zero when the program fails. The tagged errors you will most commonly see:
| Error | When |
|---|---|
ConfigNotFound | No konfig.json was found walking up from the current directory. |
ConfigParseError | konfig.json exists but does not match the schema. |
EnvEntryNotFound | The env’s entry file does not exist. |
EnvLoadError | The entry has no default export, or the default export is not an Effect program. |
| render errors from your modules | For example HelmVersionTooLow, HelmDigestMismatch, or an unbound secret. |
WriteEnvError | Writing the output tree failed. |
BuildCacheError | Reading or writing the cache file failed. |
Example
konfig build prod # first run renders and writeskonfig build prod # second run: Cached, inputs unchangedkonfig build prod --cluster eu-west-1 # separate output dir and cache slotkonfig build prod --no-cache --log json # force render, machine-readable report