Skip to content
Docs menu / Installation

Installation

konfig.ts is a workspace dependency, not a global tool. You add the CLI as a dev dependency, add the packages your manifests import, and point a konfig.json at your environment entry files.

Install the packages

Install @konfig.ts/cli as a dev dependency and the library packages as regular dependencies. Which libraries you need depends on what you render:

PackageWhat it gives youWhen you need it
@konfig.ts/coreManifests, module wrappers, Helm releases, dependency declarations, YAML output and diffingAlways
@konfig.ts/k8sBuilders for Kubernetes resources: workloads, containers, Secrets, ConfigMaps, and binding an env contract to a podWhen you build Kubernetes resources directly
@konfig.ts/envThe env contract: declare secrets, literals, and downward-API values, plus the runtime decoder for the running process. @konfig.ts/k8s re-exports the decoder as Environment.runtimeWhen you declare env contracts
@konfig.ts/argocdArgo CD Applications, the app-of-apps composition, and sync optionsWhen you compose modules into an Argo CD environment
@konfig.ts/sops, @konfig.ts/sealed-secrets, or @konfig.ts/external-secretsOne secret backendWhen you render Secrets
bun add -d @konfig.ts/cli

bun add @konfig.ts/core @konfig.ts/k8s @konfig.ts/env @konfig.ts/argocd @konfig.ts/sops effect@^4.0.0-rc.111

The binary is exposed as konfig. Run bunx konfig --help (or npx konfig --help) to confirm the install.

The Effect peer range

Every @konfig.ts/* library declares effect as a peer dependency with a caret range over the release-candidate line, currently ^4.0.0-rc.111: any rc build from rc.111 on satisfies it. @konfig.ts/core and the CLI additionally depend on @effect/platform-node at the same range, as a regular dependency rather than a peer, because they use the Node filesystem and subprocess services to write files and call helm. All packages declare engines.node >= 22.

The range is deliberately narrow: it floats across rc builds of 4.0.0 but never crosses into another prerelease line or a stable major. When Effect ships a stable 4.x, the range widens to ^4.x.

konfig.json

konfig.json tells the CLI where your sources live, which environments exist, and where rendered output goes. The commands that render (konfig build, validate, diff, and set) walk up from the current directory until they find one, and fail with ConfigNotFound otherwise. The tooling commands (konfig helm, crd, docker, and graph) do not read it. This is the file from examples/full-stack:

examples/full-stack/konfig.json
{
  "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" }
}

Only three fields are required: root, envs, and outDir.manifests. Decoding is strict: unknown keys, missing required keys, and invalid JSON are all reported as ConfigParseError with the file path.

The full schema accepts the fields below. Only the first five are read by a command today; the rest are accepted, defaulted, and exported as types, but no command consumes them yet.

FieldRequiredMeaning
rootyesDirectory holding your infra sources, relative to konfig.json. Env entries, images.json, outDir.manifests, and diff.baseline resolve relative to it.
envsyesMap of env name to { "entry": "<path>" }, relative to root. An env not listed here falls back to <root>/env/<name>.ts (EnvEntryNotFound if that file is missing).
outDir.manifestsyesWhere konfig build writes rendered manifests, relative to root. The env name (and --cluster name) is appended.
diff.baselinenoBaseline manifest tree for konfig diff, relative to root; the env name is appended, so konfig diff staging reads <root>/<baseline>/staging. Without it konfig diff fails with DiffBaselineMissing.
cacheIncludenoExtra files, directories, or glob patterns hashed into the build cache on top of everything under root, relative to konfig.json (absolute paths allowed). Use it for inputs outside root that affect a render. Default [].
clusternoString, default "cluster.ts". Not read by any command.
modulesnoString, default "modules". Not read by any command.
chartsnoString, default "infra/k8s-konfig/charts", relative to konfig.json’s own directory. Read by konfig helm fetch and konfig crd, beneath KONFIG_CHARTS_DIR.
crd.outDirnoString, default ".generated/crd", relative to konfig.json’s own directory. Read by konfig crd extract, beneath KONFIG_CRD_OUT_DIR.
helm.cacheDirnoString, default ".konfig/helm-cache", relative to konfig.json’s own directory. Read by konfig helm fetch, konfig crd, and Helm.release during build/validate/diff, beneath KONFIG_HELM_CACHE.
helm.minVersionnoString, default "3.16.0". Read by the konfig helm fetch/konfig crd preflight check, beneath KONFIG_HELM_MIN_VERSION; Helm.release still takes its own opt-in minVersion option and does not read this field.
services.outFile, services.globalPathsnoOptional string and string array (default []). Not read by any command.
clustersnoMap of cluster name to { registry?, ingressClass?, storageClass?, repositoryUrl? }. Not read by any command; --cluster <name> only sets the cluster name on the render context and the output subdirectory.

Environment variable overrides

Four environment variables configure the Helm and CRD tooling. Precedence is: environment variable, then the matching konfig.json field, then the built-in default. The default applies when no konfig.json is found or the field is left unset; in that fallback case the path resolves against the current working directory.

VariableOverrides fieldDefaultRead by
KONFIG_HELM_CACHEhelm.cacheDir.konfig/helm-cacheHelm.release during build/validate/diff, konfig helm fetch, konfig crd
KONFIG_CRD_OUT_DIRcrd.outDir.generated/crdkonfig crd extract
KONFIG_CHARTS_DIRchartsinfra/k8s-konfig/chartskonfig helm fetch, konfig crd (chart registry directory)
KONFIG_HELM_MIN_VERSIONhelm.minVersion3.16.0konfig helm fetch, konfig crd. Helm.release checks the binary version only when you pass minVersion in its options.

Project layout

konfig.ts does not prescribe a tree, but examples/full-stack and the defaults assume this shape (the example itself has no images.json):

konfig.json # "root": "."
images.json # { "envs": { "<env>": { "<app>": "<image ref>" } } }, edited by `konfig set`, lives at <root>/images.json
infra/
cluster.ts # cluster-wide constants (domain, repositoryUrl, per-cluster overlays)
envs/
prod.ts # default export: AppOfApps.fromModules({ ... })
staging.ts
modules/
postgres.ts # one Module.fixedNs / Module.dynamicNs per Application
api.ts
secrets/
SopsSecret-db-creds.yaml # encrypted secret sources read by the sops backend
.generated/manifests/ # outDir.manifests, one directory per env
.konfig/ # cache/ (build cache, next to konfig.json) and helm-cache/, ignore in git

Two conventions matter. Each env file’s default export must be an AppOfApps.fromModules({ ... }) program, because that is what the CLI loads and runs. Each module file exports a module definition (Module.fixedNs or Module.dynamicNs) that the env file instantiates with a name, an Argo CD source, and its options.

Runtime requirements

konfig build, validate, and most other commands import() your .ts sources, so the CLI needs a runtime that executes TypeScript directly.

RequirementNeeded forNotes
Bunall commandsRecommended. Runs .ts without flags.
Node >= 22.18 or >= 23.6all commandsNative type stripping, no flags. The packages declare engines.node >= 22.
Node 22.6 to 22.17all commandsRun with --experimental-strip-types.
tsxall commandstsx node_modules/.bin/konfig build prod.
helm (3.16.0 or newer for konfig helm fetch and konfig crd)modules that use Helm.release, konfig helm fetch, konfig crdCalled as helm pull and helm template. Helm.release enforces a minimum only when given minVersion.
kubeconformkonfig validate --strictMust be on PATH.
sops / kubesealSops.backend (sops --decrypt), SealedSecrets backend (kubeseal)Sops.passthrough reads a pre-encrypted file and needs no binary.

Next

Your first environment walks through one module, one env file, and the first konfig build.