Implementing Environment Variable Management Best Practices with Claude Code
Learn about implementing environment variable management best practices using Claude Code. Practical tips and code examples included.
Why Environment Variable Management Matters
In application development, you need to safely manage sensitive information such as API keys and database credentials. Environment variables are the basic mechanism, but they often lack type safety and validation. With Claude Code, you can quickly build a robust environment variable management system.
Type-Safe Environment Loading
> Create a module that validates environment variables with Zod and
> loads them in a type-safe way.
> Support required/optional distinction and default values.
import { z } from 'zod';
const envSchema = z.object({
NODE_ENV: z.enum(['development', 'staging', 'production']).default('development'),
PORT: z.coerce.number().int().positive().default(3000),
DATABASE_URL: z.string().url(),
REDIS_URL: z.string().url().optional(),
API_KEY: z.string().min(1, 'API_KEY is required'),
JWT_SECRET: z.string().min(32, 'JWT_SECRET must be at least 32 characters'),
CORS_ORIGINS: z.string().transform((s) => s.split(',')).default('http://localhost:3000'),
LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
});
export type Env = z.infer<typeof envSchema>;
function loadEnv(): Env {
const result = envSchema.safeParse(process.env);
if (!result.success) {
const formatted = result.error.format();
console.error('Environment variable validation error:');
for (const [key, value] of Object.entries(formatted)) {
if (key !== '_errors' && value && '_errors' in value) {
console.error(` ${key}: ${(value as any)._errors.join(', ')}`);
}
}
process.exit(1);
}
return result.data;
}
export const env = loadEnv();
Managing .env Templates
> Create a script that auto-generates .env.example.
> Don't include actual values, but add descriptive comments.
import fs from 'fs';
import path from 'path';
function generateEnvExample(envPath: string, outputPath: string) {
const envContent = fs.readFileSync(envPath, 'utf-8');
const lines = envContent.split('\n');
const exampleLines = lines.map((line) => {
if (line.startsWith('#') || line.trim() === '') return line;
const [key] = line.split('=');
const descriptions: Record<string, string> = {
DATABASE_URL: '# Database connection URL (e.g., postgresql://user:pass@localhost:5432/db)',
API_KEY: '# API key (manage securely in production)',
JWT_SECRET: '# JWT signing secret (32+ characters)',
};
const comment = descriptions[key?.trim()] || '';
return `${comment}\n${key?.trim()}=`;
});
fs.writeFileSync(outputPath, exampleLines.join('\n'));
}
Per-Environment Configuration
> Create a Config class that manages per-environment settings.
> Support three environments: development, staging, and production.
interface AppConfig {
database: { pool: number; ssl: boolean };
cache: { ttl: number; enabled: boolean };
logging: { level: string; format: string };
}
const configs: Record<string, AppConfig> = {
development: {
database: { pool: 5, ssl: false },
cache: { ttl: 60, enabled: false },
logging: { level: 'debug', format: 'pretty' },
},
production: {
database: { pool: 20, ssl: true },
cache: { ttl: 3600, enabled: true },
logging: { level: 'warn', format: 'json' },
},
};
export function getConfig(): AppConfig {
const nodeEnv = env.NODE_ENV;
return configs[nodeEnv] ?? configs.development;
}
Supporting Secret Rotation
To rotate credentials safely, you can build a mechanism that holds multiple versions of a secret at once.
class SecretManager {
private secrets: Map<string, string[]> = new Map();
register(key: string, ...values: string[]) {
this.secrets.set(key, values.filter(Boolean));
}
getCurrent(key: string): string {
const values = this.secrets.get(key);
if (!values || values.length === 0) {
throw new Error(`Secret not found: ${key}`);
}
return values[0];
}
verify(key: string, token: string, verifyFn: (secret: string, token: string) => boolean): boolean {
const values = this.secrets.get(key) ?? [];
return values.some((secret) => verifyFn(secret, token));
}
}
const secrets = new SecretManager();
secrets.register('JWT_SECRET', env.JWT_SECRET, process.env.JWT_SECRET_PREVIOUS ?? '');
Summary
With Claude Code, you can build an entire environment variable management stack, from Zod-based type-safe validation to per-environment config and secret management. For security basics, see the authentication implementation guide. For automation testing, see the testing strategies article.
For more on Zod, see the official Zod documentation. For environment variable security, the OWASP Configuration Guide is also a great reference.
Level up your Claude Code workflow
50 battle-tested prompt templates you can copy-paste into Claude Code right now.
Free PDF: Claude Code Cheatsheet in 5 Minutes
Key commands, shortcuts, and prompt examples on a single printable page.
About the Author
Masa
Engineer obsessed with Claude Code. Runs claudecode-lab.com, a 10-language tech media with 2,000+ pages.
Related Posts
Creating Custom Slash Commands in Claude Code — Tailor Your Workflow
Learn how to create custom slash commands in Claude Code. Covers file placement, arguments, and automating frequent tasks with practical code examples.
10 Tips to Triple Your Productivity with Claude Code
Learn about 10 tips to triple your productivity using Claude Code. Practical tips and code examples included.
Canvas/WebGL Optimization with Claude Code
Learn about Canvas/WebGL optimization using Claude Code. Practical tips and code examples included.