The config loader lets you specify environment values using JSON/YAML or JS/TS config files, then overlay them deterministically with privacy and source precedence.
Behavior: In the shipped CLI (plugin-first host) and the generator path, the loader/overlay pipeline is always active and is a no-op when no config files are present.
When enabled, the loader discovers up to three configs in the following order:
getdotenv.config.jsongetdotenv.config.yaml / .ymlgetdotenv.config.js / .mjs / .cjsgetdotenv.config.ts / .mts / .ctsgetdotenv.config.jsongetdotenv.config.yaml / .ymlgetdotenv.config.js / .mjs / .cjsgetdotenv.config.ts / .mts / .ctsgetdotenv.config.local.jsongetdotenv.config.local.yaml / .ymlgetdotenv.config.local.js / .mjs / .cjsgetdotenv.config.local.ts / .mts / .ctsNotes:
.local is not expected by policy and is ignored.JSON/YAML (data only, always-on; no-op when no files are present):
dotenvToken?: stringprivateToken?: stringpaths?: string | string[]loadProcess?: booleanlog?: booleanshell?: string | booleanscripts?: Record<string, unknown>vars?: Record<string, string> (global, public)envVars?: Record<string, Record<string, string>> (per-env, public)dynamic — use JS/TS instead.JS/TS (data + dynamic):
dynamic?: GetDotenvDynamic — a map where values are either strings or functions of the form (vars: ProcessEnv, env?: string) => string | undefined.TS support:
Config privacy derives from the filename suffix:
getdotenv.config.json / .yaml / .yml (shared in VCS).getdotenv.config.local.json / .yaml / .yml (gitignored).The loader overlays config-provided values onto the “base” file-derived dotenv values using these axes (higher wins):
dynamic > env > globallocal > publicproject > packaged > baseThe overlay flow:
getDotenv (exclude dynamic; ignore programmatic vars).dynamicPath (lowest dynamic tier).outputPath (write consolidated dotenv; quote multiline), log (print final map), loadProcess (merge into process.env).All expansions are progressive within each slice: when applying a vars object, keys are expanded left-to-right so later values may reference earlier results.
After dotenv files and config overlays are composed, a final interpolation pass resolves remaining string options using the composed env:
outputPath) against { ...process.env, ...ctx.dotenv }. Precedence: ctx wins over parent process.env.afterResolve, the host interpolates that plugin’s config slice against { ...ctx.dotenv, ...process.env }. Precedence: parent process.env wins over ctx for per‑plugin slices so upstream runtime adjustments (e.g., AWS creds) are visible to children.Notes:
exclude*, loadProcess, log, shell, dynamicPath).You can validate the final composed environment via config:
requiredKeys?: string[] — each key must be present (value !== undefined) in the final env.schema?: ZodSchema — a Zod schema whose safeParse(finalEnv) is executed once after Phase C.Behavior:
--strict (or strict: true in options) to fail with a non‑zero exit when issues are detected.Examples:
# getdotenv.config.yaml
requiredKeys:
- APP_SETTING
- ENV_SETTING
// getdotenv.config.ts
import { z } from 'zod';
export default {
schema: z.object({
APP_SETTING: z.string().min(1),
ENV_SETTING: z.string().optional(),
}),
};
Presentation‑only diagnostics help audit values without altering runtime behavior:
--redact): masks secret‑like keys (default patterns include SECRET, TOKEN, PASSWORD, API_KEY, KEY) in -l/--log and --trace outputs. Add patterns with --redact-pattern <regex...>.--entropy-warn / --entropy-warn-off--entropy-threshold <n>--entropy-min-length <n>--entropy-whitelist <regex...> to suppress by key nameYou can define a scripts table in config and optionally override shell behavior per script. Script strings are resolved by the cmd and batch commands:
{
"scripts": {
"bash-only": { "cmd": "echo $SHELL && echo OK", "shell": "/bin/bash" },
"plain": { "cmd": "node -v", "shell": false }
}
}
When a script is invoked, scripts[name].shell (string or boolean) takes precedence over the global --shell setting for that script.
Project files:
# getdotenv.config.yaml (public)
vars:
FOO: 'foo'
envVars:
dev:
BAR: '${FOO}-dev'
# getdotenv.config.local.yml (private)
vars:
SECRET: 's3cr3t'
JS/TS dynamic (optional):
// getdotenv.config.ts
export default {
dynamic: {
BOTH: ({ FOO = '', BAR = '' }) => `${FOO}-${BAR}`,
},
};
With --use-config-loader (or { useConfigLoader: true } on the host), the final map for env=dev overlays global public (FOO) → env public (BAR) → global local (SECRET) → dynamic from config (BOTH):
{ FOO: "foo", BAR: "foo-dev", SECRET: "s3cr3t", BOTH: "foo-foo-dev" }