smart-envy-manager
v1.0.0
Published
Smart .env manager and validator for Node.js. Schema validation, codebase auditing, typed generation, and team sync.
Downloads
17
Maintainers
Readme
envy
The .env manager your team actually needs
Every Node.js project has the same .env problems. Someone adds a variable and forgets to tell the team. You clone a repo and have no idea what goes in .env. Staging breaks because a variable was renamed. envy fixes all of this.
Installation
# Install globally for CLI use
npm install -g envy
# Or use with npx
npx envy initQuick Start
# 1. Initialise envy in your project (reads existing .env or .env.example)
npx envy init
# 2. Check your .env against .env.example
npx envy check
# 3. Validate .env against the schema
npx envy validate
# 4. Scan codebase for undeclared process.env usage
npx envy audit
# 5. Generate a typed env.ts
npx envy generate
# 6. Sync shared non-secret vars from team config
npx envy syncThe .env.schema Format
The schema file is the heart of envy. It describes every environment variable your app uses.
DATABASE_URL required url format:postgresql-url
JWT_SECRET required string min-length:32
PORT optional number min:1 max:65535 default:3000
NODE_ENV required string enum:development,staging,production
RESEND_API_KEY required string prefix:re_
AWS_REGION required string enum:us-east-1,eu-west-2,ap-south-1
STRIPE_KEY required string min-length:16 description:Stripe secret key
APP_URL required url example:https://myapp.comFormat: KEY required|optional type [modifier ...]
Each line has three required parts followed by optional modifiers (space-separated):
| Part | Values | Description |
|------|--------|-------------|
| KEY | MY_VAR | The environment variable name |
| required/optional | required / optional | Whether the variable must be present |
| type | string, number, boolean, url, email | Value type |
Modifiers
| Modifier | Example | Description |
|----------|---------|-------------|
| format:VALUE | format:postgresql-url | Apply a format validator |
| default:VALUE | default:3000 | Default value if not set |
| prefix:VALUE | prefix:re_ | Value must start with this |
| suffix:VALUE | suffix:.com | Value must end with this |
| min-length:N | min-length:32 | Minimum string length |
| max-length:N | max-length:255 | Maximum string length |
| min:N | min:1 | Minimum numeric value |
| max:N | max:65535 | Maximum numeric value |
| enum:V1,V2 | enum:development,staging,production | Allowed values |
| description:TEXT | description:Stripe API key | Human-readable description |
| example:VALUE | example:re_abc123 | Example value |
Supported Types and Formats
Types
| Type | Validates | Example |
|------|-----------|---------|
| string | Any non-empty string | hello |
| number | Numeric value | 3000 |
| boolean | true or false | true |
| url | Valid URL (via URL constructor) | https://example.com |
| email | Basic email format | [email protected] |
Format Validators
| Format | Description | Example |
|--------|-------------|---------|
| postgresql-url | PostgreSQL connection URL | postgresql://user:pass@host/db |
| redis-url | Redis connection URL | redis://localhost:6379 |
| mongodb-url | MongoDB connection URL | mongodb+srv://user:pass@cluster/db |
| jwt-secret | JWT secret — minimum 32 characters | a-very-long-secret-key-for-jwt-signing |
| hex-color | Hex colour code | #FF5733 |
| semver | Semantic version | 1.2.3 |
| iso-date | ISO 8601 date string | 2024-01-15T10:30:00Z |
| port | Port number (1–65535) | 3000 |
Commands
envy init
Initialises envy in your project. Reads your existing .env or .env.example and generates a .env.schema with sensible defaults, plus an empty .env.team.json.
envy initInitialising envy
ℹ Discovered 7 variables from .env.example
✓ Created .env.schema (7 fields)
✓ Created .env.team.json
ℹ Next steps:
1. Edit .env.schema to fill in types, formats, and constraints
2. Commit .env.schema and .env.team.json (never commit .env!)
3. Run: envy check — to check your .env against .env.example
4. Run: envy validate — to validate against the schemaenvy check
Compares your .env against .env.example to find missing or extra variables.
envy check [--env <path>] [--example <path>]Checking .env against .env.example
Missing variables:
✗ DATABASE_URL missing — required
✗ JWT_SECRET missing — required
Extra variables (not in .env.example):
⚠ MY_LOCAL_VAR not in .env.example
Present variables:
✓ PORT present
✓ NODE_ENV present
✓ AWS_REGION present
────────────────────────────────────────────────
✗ 3 issues found.envy validate
Validates your .env against .env.schema with full type, format, and constraint checking.
envy validate [--env <path>] [--schema <path>] [--strict]Validating .env against .env.schema
Errors:
✗ DATABASE_URL "DATABASE_URL" does not match format "postgresql-url"
✗ JWT_SECRET "JWT_SECRET" is too short (min 32 chars, got 12)
✗ RESEND_API_KEY "RESEND_API_KEY" must start with "re_"
Warnings:
⚠ PORT Using default value "3000"
┌────────────────┬───────┐
│ Metric │ Count │
├────────────────┼───────┤
│ Total fields │ 7 │
│ Valid │ 4 │
│ Errors │ 3 │
│ Warnings │ 1 │
│ Missing │ 0 │
│ Using defaults │ 1 │
└────────────────┴───────┘Use --strict to also exit with code 1 if there are warnings.
envy audit
Scans your entire codebase for process.env usage and identifies variables that are used but not declared in your schema.
envy audit [--dir <path>] [--schema <path>]Auditing codebase for undeclared process.env usage
Scanning /path/to/project...
Scanned 47 files
Undeclared variables:
✗ STRIPE_SECRET_KEY
Found in: src/services/billing.ts line 42
Context: const key = process.env.STRIPE_SECRET_KEY
✗ SENDGRID_API_KEY
Found in: src/services/email.ts line 8
Context: const client = new Client(process.env.SENDGRID_API_KEY)
Declared variables (found in code):
✓ DATABASE_URL declared in schema
✓ JWT_SECRET declared in schema
────────────────────────────────────────────────
✗ 2 undeclared variables found.Detects all of these patterns:
process.env.MY_VARprocess.env["MY_VAR"]process.env['MY_VAR']const { MY_VAR } = process.env
envy sync
Syncs non-sensitive shared variables from .env.team.json into your local .env. Safe to run repeatedly — it never overwrites existing values.
envy sync [--team <path>] [--env <path>] [--schema <path>].env.team.json (committed to version control):
{
"LOG_LEVEL": "info",
"APP_NAME": "myapp",
"APP_ENV": "development",
"NODE_ENV": "development"
}Syncing team config to .env
Added:
✓ LOG_LEVEL added from team config
✓ APP_NAME added from team config
Skipped:
ℹ NODE_ENV already present
ℹ JWT_SECRET skipping sensitive key
────────────────────────────────────────────────
ℹ 2 variables added. 2 skipped.envy generate
Generates a fully-typed src/env.ts from your schema. Import it instead of process.env directly for type safety and auto-validation on startup.
envy generate [--schema <path>] [--output <path>]Generated src/env.ts:
/**
* Auto-generated by envy
* Do not edit this file manually
* Run: envy generate
*/
import { validateEnv } from "envy";
// Validate on import — app won't start with missing required variables
validateEnv({ throwOnError: true });
export const env = {
DATABASE_URL: process.env.DATABASE_URL as string,
JWT_SECRET: process.env.JWT_SECRET as string,
PORT: Number(process.env.PORT ?? "3000"),
NODE_ENV: process.env.NODE_ENV as "development" | "staging" | "production",
RESEND_API_KEY: process.env.RESEND_API_KEY as string,
AWS_REGION: process.env.AWS_REGION as "us-east-1" | "eu-west-2" | "ap-south-1",
FEATURE_FLAG_BETA: process.env.FEATURE_FLAG_BETA === "true",
} as const;
export type Env = typeof env;Then use it in your app:
import { env } from "./env";
const client = new DatabaseClient(env.DATABASE_URL); // typed as string
const port = env.PORT; // typed as number
const isDev = env.NODE_ENV === "development"; // union typeLibrary API
Use envy programmatically in your Node.js/TypeScript apps:
import { validateEnv } from "envy";
// Add to top of your main entry file — throws if any required var is missing
validateEnv({ throwOnError: true });import { EnvValidator, EnvParser } from "envy";
const parser = new EnvParser();
const validator = new EnvValidator();
const env = parser.parseEnvFile(".env");
const schema = parser.parseSchemaFile(".env.schema");
const result = validator.validate(env, schema);
if (!result.valid) {
console.error("Validation failed:");
for (const error of result.errors) {
console.error(` ${error.key}: ${error.message}`);
}
process.exit(1);
}import { EnvScanner } from "envy";
const scanner = new EnvScanner();
const result = scanner.scan("./src", ["DATABASE_URL", "PORT"]);
console.log(`Scanned ${result.scanned} files`);
console.log(`Undeclared: ${result.undeclared.map(u => u.key).join(", ")}`);Available exports
| Export | Type | Description |
|--------|------|-------------|
| validateEnv(options?) | Function | Validate and optionally throw |
| EnvValidator | Class | Core validator |
| EnvParser | Class | Parse .env and .env.schema files |
| EnvScanner | Class | Scan codebase for process.env usage |
| EnvGenerator | Class | Generate typed env.ts |
| EnvSyncer | Class | Sync team config to .env |
| SUPPORTED_FORMATS | Constant | Format validators map |
| version | string | Package version |
Team Workflow
Here is the recommended workflow for a team:
- Run
envy initin your project root — generates.env.schemaand.env.team.json - Edit
.env.schema— fill in correct types, formats, and constraints for every variable - Edit
.env.team.json— add non-sensitive shared defaults (log levels, feature flags, etc.) - Commit
.env.schemaand.env.team.json— never commit.env! - New developers run
envy sync(pulls in shared defaults) thenenvy check(see what's still missing) - Add
envy validateto your CI pipeline to catch bad deployments early
.gitignore:
.env
.env.local
git add .env.schema .env.team.json
git commit -m "Add envy configuration"CI Integration
GitHub Actions
name: CI
on: [push, pull_request]
jobs:
validate-env:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Validate .env
run: npx envy validate --env .env.ci --schema .env.schemapackage.json prestart
{
"scripts": {
"prestart": "envy validate",
"start": "node dist/index.js"
}
}This ensures your app refuses to start if any required environment variable is missing or malformed.
Contributing
Contributions are welcome! Please open an issue first to discuss what you would like to change.
git clone https://github.com/boluwatifeajayi/envy.git
cd envy
npm install
npm test
npm run buildLicense
MIT © boluwatifeajayi
