Patch Files
Patch Files
For projects with many config keys, you can supply a patch file that CNOS loads at process startup. Every entry in the file takes precedence over the CNOS-resolved value, making it ideal for local development, staging spot-fixes, and test harnesses.
Quick start
Create a patch file with full logical key paths as keys:
{ "value.server.port": 9090, "value.db.host": "localhost", "secret.db.password": "localdev"}Point CNOS at it when you start your application:
node server.js --cnos-patch=local.patch.jsonOr set the environment variable instead (useful in Docker/CI):
CNOS_PATCH_FILE=local.patch.json node server.jsSupported formats
| Extension | Supported in |
|---|---|
.json | All 8 runtimes |
.yaml, .yml | Node.js / TypeScript only |
.properties, .env | All 8 runtimes |
All other extensions are treated as properties format.
JSON
Keys are full logical CNOS keys. Values are natively typed.
{ "value.server.port": 9090, "value.feature.dark_mode": true, "value.db.host": "localhost"}YAML (Node.js / TypeScript runtime only)
value.server.port: 9090value.feature.dark_mode: truevalue.db.host: localhostProperties / .env
Keys are full logical CNOS keys. Values are strings and are auto-coerced:
true/false→ boolean- Bare numbers → number
- Everything else → string
- Surrounding quotes (
"..."or'...') are stripped - Lines with an empty value (
key=) are skipped with a warning to stderr
# Local development patchvalue.server.port=9090value.db.host=localhostvalue.feature.dark_mode=truesecret.db.password=localdevPriority order
CLI arg (OverrideSpec) > env var (OverrideSpec) > patch file > CNOS resolved valueSchema-level env and arg mappings from ConfigSpecRule always win. The patch file sits between those and the CNOS graph value.
This means you can use both schema-level env/arg overrides and a patch file — the env/arg specs still take priority.
Validation and warnings
CNOS validates override values at read time and emits warnings to stderr when a value cannot be applied:
| Situation | Behaviour |
|---|---|
| Arg or env value is empty string | Skip, warn, fall through to next source |
Value cannot be coerced to declared type (e.g. "abc" for a number field) | Skip, warn, fall through to next source |
Patch file key has empty value (key=) | Skip at parse time, warn once |
Fallthrough means the next priority source is tried — ultimately the CNOS resolved value is used if nothing else matches.
Programmatic use (Node.js)
Pass the path via CnosCreateOptions.patchFile:
import { createCnos } from '@kitsy/cnos';
const cnos = await createCnos({ patchFile: process.env.CNOS_PATCH_FILE,});Security notes
- Patch files can contain plaintext secret values — do not commit them to version control.
- Add patch files to
.gitignore:*.patch.json*.patch.yaml*.patch.propertieslocal.patch.* - The
--cnos-patchflag is not a passphrase and does not require strict mode protection. The file path itself is not sensitive. - In production, prefer proper vault integration over patch files. Patch files are a developer ergonomics tool.
Language runtimes
The flag and env var are supported in all 8 CNOS runtimes:
| Runtime | JSON | YAML | Properties |
|---|---|---|---|
| Node.js / TypeScript | ✓ | ✓ | ✓ |
| Go | ✓ | — | ✓ |
| Python | ✓ | — | ✓ |
| Rust | ✓ | — | ✓ |
| C# | ✓ | — | ✓ |
| Java | ✓ | — | ✓ |
| Kotlin | ✓ | — | ✓ |
| PHP | ✓ | — | ✓ |
See also
- Schema-level env/arg overrides — per-key
envandargmappings inConfigSpecRule - Profiles — the standard mechanism for environment-specific config
- Secrets — vault-backed secret management