Stop Sprinkling process.env Everywhere: Use env-interpolation
Tired of process.env scattered across your codebase? env-interpolation is
a TypeScript library that resolves ${VAR} and ${VAR:default} placeholders
inside config objects. It walks strings in objects/arrays and never touches
keys, so shapes stay stable and predictable—perfect for layered configuration.
I built it for mcp-tool-selector, where I needed layered config without
leaking secrets or scattering process.env calls. It became a sharp utility, so
I published it.
At a glance
- Resolves placeholders in values only (objects/arrays), keys untouched
- Supports defaults and multi-pass resolution
- Zero deps, TS-first, Node 18+, ESM/CJS
Docs & API: read the GitHub repo and the npm package page.
Quick taste: load JSON → interpolate
config.json
{"api": "${API_URL:https://api.example.com}","timeoutMs": "${TIMEOUT:5000}","flags": ["${PRIMARY:alpha}", "${SECONDARY:beta}"],"service": {"url": "${SERVICE_URL:${API_URL}/v1}","headers": { "x-tenant": "${TENANT:public}" }}}
load-config.ts
import { readFileSync } from "node:fs";import { interpolate } from "env-interpolation";const raw = readFileSync("config.json", "utf8");const input = JSON.parse(raw);const resolved = interpolate(input, {API_URL: "https://api.example.com",TIMEOUT: "8000",TENANT: "public",});console.log(resolved);
This is my second AI-engineered project (the first was mcp-server-giphy), built with multiple AI agents (Claude, Copilot, Gemini & Codex). If your configs span files, environments, and tools, this should smooth a few rough edges.
Why Not Just Use process.env Directly?
Reading environment variables inline scatters configuration logic throughout your codebase:
// Scattered approach - hard to audit and testconst apiUrl = process.env.API_URL || "https://api.example.com";const timeout = parseInt(process.env.TIMEOUT || "5000", 10);
With env-interpolation, configuration stays centralized. Define the structure once, and the library handles resolution:
// Centralized approach - config.json is the source of truthconst config = interpolate(loadConfig("config.json"), process.env);
This makes configs easier to audit, test, and share across environments.
When to Use env-interpolation
- Multi-environment configs: Development, staging, production with the same structure
- Layered configuration: Base config with environment-specific overrides
- Tool configuration: CLI tools that need portable config files
- Monorepos: Shared config templates across packages
Related: For secure secret storage without plaintext files, check out cross-keychain, which stores credentials in your OS's native credential manager.