Skip to main content

epicenv

PyPI version Python versions CI License: MIT

Stop maintaining .env.example files that drift out of sync with reality. epicenv is a schema-based environment variable manager for Python: declare your variables once in pyproject.toml (or a dedicated .env.toml) with types, defaults, initializers, and help text. Generate fresh .env files for new contributors with one command, and catch missing or malformed values before they hit production.

Table of Contents

Installation

# Run without installing
uvx epicenv create

# Or install as a dependency
uv add epicenv

# For Django projects (adds dj-database-url, dj-email-url support)
uv add epicenv[django]

Quick Start

1. Define your schema in pyproject.toml:

[tool.epicenv.variables]
SECRET_KEY = {
    type = "str",
    required = true,
    help_text = "Secret key for cryptographic signing",
    initial_func = "epicenv.initializers.url_safe_password"
}

DEBUG = { type = "bool", default = false, initial = "on" }
DATABASE_URL = { type = "str", default = "sqlite:///db.sqlite3" }

2. Generate your .env file:

uvx epicenv create

3. Use in your code:

from epicenv import Env

env = Env()
env.read_env()

SECRET_KEY = env.str("SECRET_KEY")
DEBUG = env.bool("DEBUG", default=False)

Why epicenv?

Traditional .env.example workflow With epicenv
Copy .env.example to .env Run epicenv create
Manually generate secrets Auto-generated via initializers
Templates get out of date Schema is the single source of truth
Runtime errors from missing vars epicenv validate catches mistakes early
No documentation for variables Help text in schema, shown in .env

CLI Commands

epicenv create                    # Create .env from schema
epicenv create --path config/.env # Create at specific path
epicenv create --no-backup        # Don't backup existing file

epicenv diff                      # Compare .env with schema
epicenv validate                  # Validate environment against schema
epicenv validate --strict         # Exit with error if validation fails

epicenv secrets get op://vault/item/field          # Fetch a single secret
epicenv secrets get op://vault/item --fields a,b,c # Fetch multiple fields as JSON
epicenv create-superuser                           # Create Django superuser (stdin/env/flags)

Platform note: epicenv create-superuser auto-detects piped JSON on stdin using select(), which is a POSIX primitive. On Windows the detection degrades to "no stdin," so Windows users should pass credentials via env vars (DJANGO_SUPERUSER_*) or explicit flags rather than piping JSON.

Schema Basics

Define variables in [tool.epicenv.variables]:

[tool.epicenv.variables]
MY_VAR = {
    type = "str",              # Required: str, bool, int, list, url, json, etc.
    required = true,           # Is this required? (default: true if no default)
    default = "value",         # Default for .env generation
    help_text = "Description", # Shown in generated .env
    initial = "value",         # Static initial value
    initial_func = "module.fn" # Dynamic initial value generator
}

Supported types: str, bool, int, float, list, dict, json, url, uuid, path, date, datetime, log_level, and Django types (dj_db_url, dj_email_url, dj_cache_url).

Schema location

For projects with many variables, keep pyproject.toml tidy by moving the schema into a dedicated .env.toml file next to pyproject.toml. It's auto-discovered — no pyproject.toml change needed:

# .env.toml
[variables]
DEBUG = { type = "bool", default = false, initial = "on" }

# Table form is nice for variables with several fields:
[variables.SECRET_KEY]
type = "str"
required = true
help_text = "Secret key for cryptographic signing"
initial_func = "epicenv.initializers.url_safe_password"

Or point at a custom path:

# pyproject.toml
[tool.epicenv]
config_file = "config/env-schema.toml"

See Schema Reference for complete field documentation and discovery rules.

Built-in Initializers

url_safe_password

Generate URL-safe random passwords:

SECRET_KEY = {
    type = "str",
    initial_func = "epicenv.initializers.url_safe_password"
}

# Custom length (default: 50)
API_TOKEN = {
    type = "str",
    initial_func = "epicenv.initializers.url_safe_password",
    kwargs = { length = 32 }
}

1Password

Fetch secrets from 1Password CLI during .env generation:

STRIPE_API_KEY = {
    type = "str",
    initial_func = "epicenv.initializers.onepassword",
    args = ["op://Production/Stripe/api_key"]
}

Requires 1Password CLI installed and signed in. Falls back to placeholder if unavailable.

See 1Password Integration for setup and troubleshooting.

Custom Initializers

Use any Python callable:

SECRET_KEY = { type = "str", initial_func = "secrets.token_urlsafe" }
DJANGO_KEY = { type = "str", initial_func = "django.core.management.utils.get_random_secret_key" }
CUSTOM = { type = "str", initial_func = "myapp.utils.generate_key" }

Framework Examples

Django

# pyproject.toml
[tool.epicenv.variables]
SECRET_KEY = { type = "str", required = true, initial_func = "django.core.management.utils.get_random_secret_key" }
DEBUG = { type = "bool", default = false, initial = "on" }
DATABASE_URL = { type = "dj_db_url", default = "sqlite:///db.sqlite3" }
# settings.py
from epicenv import Env

env = Env()
env.read_env()

SECRET_KEY = env.str("SECRET_KEY")
DEBUG = env.bool("DEBUG", default=False)
DATABASES = {"default": env.dj_db_url("DATABASE_URL", default="sqlite:///db.sqlite3")}

See Django Integration for complete setup including email and cache URLs.

FastAPI / Flask

# pyproject.toml
[tool.epicenv.variables]
APP_NAME = { type = "str", default = "My API" }
API_HOST = { type = "str", default = "0.0.0.0" }
API_PORT = { type = "int", default = 8000 }
DATABASE_URL = { type = "url", required = true }
LOG_LEVEL = { type = "log_level", default = "INFO" }
# config.py
from epicenv import Env

env = Env()
env.read_env()

APP_NAME = env.str("APP_NAME", default="My API")
DATABASE_URL = env.url("DATABASE_URL")
LOG_LEVEL = env.log_level("LOG_LEVEL", default="INFO")

Validation

epicenv validates that variables used in code are defined in your schema. Control with EPICENV_VALIDATE:

Mode Behavior
auto (default) Validate when DEBUG=true
strict Always validate, raise errors
warn Always validate, warn only
off Disable validation
EPICENV_VALIDATE=strict python app.py  # Always validate

Using with Mise

Mise manages tool versions and injects environment variables into your shell when you cd into a project. epicenv remains the source of truth for application variables: the schema, .env generation, typed Python accessors, and validation. Mise does not replace that layer.

They compose through the generated .env file:

# mise.toml
[env]
_.file = ".env"

Typical workflow:

  1. Declare variables in [tool.epicenv.variables] or .env.toml.
  2. Run epicenv create to generate a local .env (gitignored).
  3. Mise loads that file into the shell on cd, mise exec, and tasks.
  4. Keep env.read_env() in Python so Docker, CI, and teammates without Mise still load the same file. Existing shell values (including those Mise set) are left alone.

Do not point Mise at epicenv's .env.toml. That file is a schema (type, help_text, initial_func), not a bag of values. Keep schema in .env.toml or pyproject.toml, values in .env, and _.file = ".env" in mise.toml.

Documentation

Development

$ uv sync
$ uv run pytest
$ uv run epicenv --help

With just installed, just format, just lint, and just test wrap the common tasks, and just pre_commit runs all three. Releases are cut with just version_bump <major|minor|patch> followed by pushing the tag — see CLAUDE.md for the full release process.

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Acknowledgments

epicenv is built on top of environs, which provides the core environment variable parsing functionality.

License

MIT License

Release files for epicenv 1.6.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for epicenv 1.6.3
File Size Uploaded
epicenv-1.6.3.tar.gz 72.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for epicenv 1.6.3
File Interpreter ABI Platform
epicenv-1.6.3-py3-none-any.whl Python 3 none any Details

Total release size: 103.8 kB

Release files / epicenv-1.6.3.tar.gz

Download URL epicenv-1.6.3.tar.gz
Size 72.3 kB
Tags Source
SHA-256 checksum
How to use checksums
bcdd2b151399e2b31c90209ca6fb1e695f3d83e3616cbc295cdb4eaed71ef3a4
BLAKE2b-256 checksum
How to use checksums
a8cf3cba4f3f64c5c51c3b02b0c534fc9dcd8290f881d8a1dcd7c5c921155332
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.

Transparency log

Release files / epicenv-1.6.3-py3-none-any.whl

Download URL epicenv-1.6.3-py3-none-any.whl
Size 31.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
48d4d9cbe5e4282e1ee22eb6ee13f116afb8e46385d5d44548d4e1ce6200f149
BLAKE2b-256 checksum
How to use checksums
f32c88628167023a0eebad2abb1196fa32c5246d7154426a195d437893e7b18c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.6.3 This release

2 release files

1.6.2

2 release files

1.6.0

2 release files

1.5.0

2 release files

1.4.0

2 release files

1.3.1

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page