BACK

Stop Sprinkling process.env Everywhere: Use env-interpolation

2 min read

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 test
const 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 truth
const 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.