EnvShield Features & Real-Life Examples

Learn how each EnvShield feature solves real-world problems. Real monorepo scenarios. Real code. Real benefits.

👀 Visual learner? You're in the right place! Scroll through each feature to see real before/after code examples and learn why EnvShield is different.

Ready to get started? Check the Quick Start guide →

✅ One Schema, All Services

Declare what configuration each service needs in one place. EnvShield is the ONLY tool with native multi-service support.

Gitleaks, dotenvx, Infisical, and direnv all treat configuration as a single-service problem. EnvShield solves for multi-service from the ground up.

Real-Life Example: E-Commerce Monorepo

❌ Before EnvShield

Your project has API, web, and worker services:

services/
├── api/
│   ├── .env (has DATABASE_URL, missing STRIPE_KEY)
│   └── config.py (uses getenv, untyped)
├── web/
│   ├── .env.example (outdated, has LEGACY_VAR)
│   └── config/.env (fresh, correct)
└── worker/
    └── (no documented env vars at all)

Problem: Is DATABASE_URL the same across all three? Nobody knows.
New dev: "I set up my .env but the API won't start."
         → After 2 hours: missing STRIPE_KEY (only used in API, not documented)
✅ After EnvShield
# Single source of truth for all services
cat envshield.yml

project_name: ecommerce-platform
services:
  api:
    path: services/api/env.schema.toml
    description: "Stripe payment API (Flask)"
  web:
    path: services/web/env.schema.toml
    description: "Customer storefront (React)"
  worker:
    path: services/worker/env.schema.toml
    description: "Background jobs (Celery)"

# Import existing configs in seconds
envshield import services/api/.env --service api
envshield import services/web/.env --service web
envshield import services/worker/.env --service worker

What you get:

  • ✓ Single source of truth for all services
  • ✓ Machine-readable, versionable (in git)
  • ✓ No more "is it in this service or that one?"
  • ✓ Changes to one service visible to all

See it in action:

Multi-service configuration demo

✅ Migrate Existing Projects in Seconds

envshield import reads your existing .env or settings.py and auto-generates 90% of the schema. No manual TOML writing.

Real-Life Example: Django Project with 5 Years of Config

❌ Before

Django settings.py with 200 lines of getenv() calls:

import os

DEBUG = os.getenv('DEBUG', 'False') == 'True'
SECRET_KEY = os.getenv('SECRET_KEY')
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'localhost').split(',')
DATABASE_URL = os.getenv('DATABASE_URL')
STRIPE_API_KEY = os.getenv('STRIPE_API_KEY')
# ... 50 more lines like this

# Nobody has time to manually write TOML for all of these
✅ After
# One command
envshield import settings.py --interactive

# EnvShield reads the file and shows:
# ? Variable: DEBUG
#   Value: False (parsed from code)
#   Detected as: non-secret, boolean
#   Use 'False' as default? (y/n) y
#
# ? Variable: SECRET_KEY
#   Detected as: secret (keyword match: "secret")
#   Confirm as secret? (y/n) y
#
# ... (for all 50+ variables)
#
# ✓ Generated env.schema.toml (52 variables)
# - Marked 18 as secrets
# - Suggested 12 default values
# - Please review and add descriptions!

Result: Schema generated in 30 seconds, ready to review and enhance.

See it in action:

Importing existing configuration

✅ Typed Config Code Generation

Compile schema into real, importable Python (pydantic-settings) or TypeScript (zod) code. EnvShield is the ONLY tool that generates typed, validated config modules from a schema.

Other tools encrypt, scan, or store secrets. Only EnvShield turns your schema into production-ready typed code for Python and TypeScript.

Python: From Untyped Strings to Type-Safe Config

❌ Before EnvShield
import os

class Config:
    DEBUG = os.getenv('DEBUG', 'false').lower() == 'true'
    DATABASE_URL = os.getenv('DATABASE_URL')
    PORT = int(os.getenv('PORT', '5000'))  # Fails at runtime if not a number
    STRIPE_KEY = os.getenv('STRIPE_KEY')   # Could be None (untyped)
    LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO')

    # Problems:
    # - STRIPE_KEY could be None at runtime (untyped)
    # - If PORT isn't a number, fails at runtime, not startup
    # - STRIPE_KEY visible in logs if printed
    # - No IDE autocomplete for config keys
✅ After EnvShield
from pydantic import Field
from pydantic_settings import BaseSettings
from typing import Literal

class Env(BaseSettings):
    DEBUG: bool = Field(False, description="Enable Flask debug mode")
    DATABASE_URL: str = Field(..., description="PostgreSQL connection string")
    PORT: int = Field(5000, description="Port the API listens on")
    STRIPE_KEY: SecretStr = Field(..., description="Stripe API secret key")
    LOG_LEVEL: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR'] = Field(
        'INFO', description="Log verbosity level"
    )

    class Config:
        env_file = '.env'

env = Env()

# Now in your code:
from config import env

stripe_client = stripe.Client(env.STRIPE_KEY)  # SecretStr (won't log)

# If .env is missing STRIPE_KEY: error on startup, not silent failure
# If .env has PORT="invalid": type validation error on startup
# IDE autocomplete: env. shows all available vars

TypeScript: From Any to Validated Types

❌ Before
const API_URL = process.env.REACT_APP_API_URL;  // string | undefined
const DEBUG = process.env.REACT_APP_DEBUG === 'true';  // string comparison
const MAX_RETRIES = parseInt(process.env.REACT_APP_MAX_RETRIES || '3');  // ??

// Problems: API_URL could be undefined, MAX_RETRIES parsing is fragile
✅ After
import { z } from 'zod';

const envSchema = z.object({
  REACT_APP_API_URL: z.string().url("API URL must be valid"),
  REACT_APP_DEBUG: z.boolean().default(false),
  REACT_APP_MAX_RETRIES: z.coerce.number().default(3),
});

const env = envSchema.parse(process.env);

export default env;

// Now in your code:
import env from './config';

const response = await fetch(`${env.REACT_APP_API_URL}/api/users`);
// env.REACT_APP_API_URL is typed as string (never undefined)
// REACT_APP_DEBUG is typed as boolean (not string)
// MAX_RETRIES is typed as number (not string or NaN)

// If .env is missing REACT_APP_API_URL: build fails at startup
// If REACT_APP_API_URL isn't a valid URL: build fails at startup
// IDE autocomplete works

See it in action:

Typed config generation demo

✅ Interactive Onboarding Wizard

envshield setup walks new developers through creating .env, knows which vars are secrets, shows descriptions. Free and works offline — no cloud dependency.

Infisical offers onboarding, but only through their cloud dashboard. EnvShield is CLI-first and works completely offline.

Real-Life Example: New Dev's First Day

❌ Before EnvShield
New dev: "Hey, how do I set up my local env?"
Senior dev: "Copy .env.example to .env, then ask me for the secrets"
New dev: "Which ones are secrets?"
Senior dev: "Uh, the ones that end in _KEY and _SECRET... I think?"
New dev: (spends 30 min sorting it out, gets it wrong)
✅ After EnvShield
new-dev$ envshield setup

🛡️  EnvShield Setup
This wizard will help you create your local .env file.

Select service (or 'all'):
> api
  web
  admin

✓ Selected: api

Reading variables from .env.example...

Please provide values for the following variables:

[DATABASE_URL]
PostgreSQL connection string for this service
Enter value (password): •••••••••••••••••••••••••••

[STRIPE_SECRET_KEY]
Stripe API secret for processing payments
Enter value (password): •••••••••••••••••••••••••••

[LOG_LEVEL]
Log verbosity (DEBUG, INFO, WARNING, ERROR)
Enter value: INFO

[REDIS_URL]
Redis connection string for session cache (optional)
Enter value (optional, press Enter to skip):

✓ Successfully created your .env file!
Ready to go. Run: source venv/bin/activate && python app.py

What happened:

  • ✓ Prompted for all required variables
  • ✓ Secrets prompted as hidden input (passwords)
  • ✓ Descriptions shown (what each var is for)
  • ✓ Optional variables skipped if not provided
  • ✓ No mistakes because it walked through the contract
  • ✓ Took 2 minutes, not 30

See it in action:

Interactive setup wizard

✅ Prevents Configuration Drift

envshield doctor checks if .env.example is in sync with schema, if local .env has all required vars, and more.

Real-Life Example: Caught a Production Bug

❌ The Scenario (Without EnvShield)
Friday afternoon, API service adds new feature:
- Changes require new env var: FEATURE_FLAG_NEW_ORDERS

Dev commits feature code, adds FEATURE_FLAG_NEW_ORDERS to .env

But forgets to update .env.example

Merges to main

Ops deploys to staging
Staging works (ops has .env from production)

Deploys to production
Production deployment: env var missing!
→ Feature silently disabled
→ New orders broken
→ Customers angry 😡
✅ With EnvShield
# Dev finishes feature, commits
git add src/orders.py env.schema.toml .env.example
git commit -m "Add new orders feature"

# Pre-commit hook runs
$ envshield scan --staged
✓ No secrets found

# Someone runs doctor before merge
$ envshield doctor --service api
✓ Configuration Files
✓ Local Environment Sync
✗ Example File Sync: .env.example missing FEATURE_FLAG_NEW_ORDERS

  Suggestion: run `envshield schema sync --service api`

# Dev fixes it:
$ envshield schema sync --service api
$ git add .env.example
$ git commit -m "Update .env.example"

# Merge
# Deploy
# Production: all env vars present ✅

See it in action:

Health check catching drift

✅ Secret Scanning at Commit Time

Pre-commit hook scans staged content (not working-tree files), catching secrets that were committed but later edited out on disk.

Real-Life Example: The Secret That Almost Shipped

❌ The Scenario
Dev writes code with a hardcoded secret:

# app.py
STRIPE_SECRET = "sk_live_ABCDEFGHIJKLMNOPQRSTUVWxyz"  # Oops!

git add app.py
git commit -m "Add payment processing"  # BEFORE this commit, secret still there!

# Then realizes mistake, edits file:
STRIPE_SECRET = os.getenv("STRIPE_SECRET")

# File on disk now looks clean
# But the secret is already staged!

git push
# Secret shipped to production in git history
✅ EnvShield Catches It
$ git add app.py
$ git commit -m "Add payment processing"

# Pre-commit hook runs:
$ envshield scan --staged
🚨 DANGER: Found 1 potential secret(s)!

Line 5: STRIPE_SECRET = "sk_live_ABCDEFGHIJKLMNOPQRSTUVWxyz"
Secret Type: Stripe API Key

Commit aborted. Please fix the issues above before committing.

# Dev can't commit the secret to history
# Even though they edited it out on disk ✅

See it in action:

Secret and undeclared variable detection

✅ Schema Syncing & Documentation

envshield schema sync regenerates .env.example from the schema. Always keeps docs in sync.

Real-Life Example: Add a New Variable

❌ Before
Dev adds new env var to code but forgets to update .env.example
→ .env.example becomes stale
→ New devs miss the var
→ Production breaks

Or:

Dev changes description of DATABASE_URL in comments
But forgets to update .env.example
→ Two sources of truth
→ Docs rot
✅ With EnvShield
# Dev edits schema to add new var:
cat services/api/env.schema.toml

[ANALYTICS_SERVICE_KEY]
description = "API key for Segment analytics tracking"
secret = true

# One command regenerates .env.example from schema:
$ envshield schema sync --service api

# .env.example now includes:
# ANALYTICS_SERVICE_KEY=

What you get:

  • ✓ .env.example is always in sync with schema
  • ✓ One source of truth (schema)
  • ✓ Documentation doesn't rot
  • ✓ No manual copy-paste errors

🎯 Why EnvShield is Different

Each of these features exists in other tools, but EnvShield is the ONLY tool that does ALL of them together:

Feature EnvShield Competitors
Schema-driven configuration ✅ Unique ❌ None
Multi-service natively ✅ Unique ❌ None
Typed config generation ✅ Unique ❌ None
Interactive onboarding ⚠️ Cloud-only
Local-first (offline) ⚠️ Some
Secret scanning ✅ Gitleaks/TruffleHog

The bottom line: Gitleaks detects secrets. dotenvx encrypts files. Infisical stores them in the cloud. But only EnvShield treats configuration as a contract, generates typed code, and supports multi-service projects natively.

🚀 The Roadmap: What's Coming

Phase 1 is the free foundation. Phase 2 and 3 bring team collaboration and enterprise features:

Phase 2: The Team Collaborator (Coming Soon)

  • 🔄 Environment Profiles: Switch between dev/staging/prod with one command
  • 📊 Schema Diffing: See exactly what changed in configuration between environments
  • 🤖 Automated Onboarding: Setup command that also runs migrations and scripts
  • 👥 Team Collaboration: Securely share secrets with teammates
  • 🔌 CI/CD Integration: Validate config before deployment

Phase 3: The Enterprise System (Future)

  • ☁️ Cloud Secret Vault: Optional centralized backend for teams (local-first still supported)
  • 🔐 Vault Integration: Connect to HashiCorp, AWS Secrets, Azure Key Vault
  • 📋 Audit Logs & RBAC: Full compliance trail with role-based access control
  • 📏 Policy Engine: Enforce naming conventions and best practices

Ready to dive into the implementation?

Head to the docs for detailed command reference, configuration guides, and roadmap.

View Full Documentation →