From harness-claude
Loads, validates, and provides type-safe access to environment config using dotenv and Zod. Fails fast at startup on missing or invalid variables.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:node-environment-configThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Manage environment configuration with process.env, dotenv, and validation for 12-factor apps
Manage environment configuration with process.env, dotenv, and validation for 12-factor apps
.env files with dotenv (or Node.js 20.6+ built-in):// Node.js 20.6+: use --env-file flag
// node --env-file=.env app.js
// Or with dotenv package
import 'dotenv/config';
import { z } from 'zod';
const EnvSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string().url(),
REDIS_URL: z.string().url().optional(),
API_KEY: z.string().min(1),
LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
});
export const env = EnvSchema.parse(process.env);
// Throws at startup if any required variable is missing or invalid
// env.PORT is number, env.DATABASE_URL is string
// No more process.env.PORT! (which is always string | undefined)
const server = app.listen(env.PORT);
.env files:# .env — defaults for local development (committed)
NODE_ENV=development
PORT=3000
LOG_LEVEL=debug
# .env.local — local overrides and secrets (gitignored)
DATABASE_URL=postgresql://localhost:5432/myapp
API_KEY=dev-key-123
.env.example as documentation:# .env.example — committed, shows all required variables
NODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://user:pass@host:5432/db
API_KEY=your-api-key-here
const config = {
development: {
logLevel: 'debug',
corsOrigin: '*',
},
production: {
logLevel: 'info',
corsOrigin: 'https://myapp.com',
},
test: {
logLevel: 'error',
corsOrigin: '*',
},
}[env.NODE_ENV];
Never hardcode secrets. Use environment variables for:
Add to .gitignore:
.env.local
.env.*.local
.env.production
The 12-factor app methodology recommends storing configuration in environment variables. This separates config from code and enables different configurations per deployment without code changes.
process.env limitations:
string | undefined — no numbers, booleans, or arraysundefined, not errors — code can run with missing config and fail laterValidation at startup with Zod solves all three problems. The application fails immediately with a clear error message if any required variable is missing.
Node.js 20.6+ --env-file: Built-in .env loading without the dotenv package. Supports multiple files: node --env-file=.env --env-file=.env.local app.js.
Trade-offs:
.env files are convenient for development — but should never be used in production (use the deployment platform's secrets management)process.env is global — consider dependency injection for testabilityhttps://nodejs.org/api/process.html#processenv
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeManage environment variables, runtime config, and server-only module boundaries safely for Next.js apps. Validates env vars at build time with Zod and prevents client-side leaks.
Analyzes environment variables in code, generates .env.example templates, validates configurations and types, documents variables with examples, and provides naming and security best practices.
Enforces type-safe environment variables using t3-env with Zod validation and blocks raw process.env access outside dedicated env files.