No project description provided
Project description
runenv
Manage application settings with ease using runenv, a lightweight tool inspired by The Twelve-Factor App methodology for configuration through environment variables.
runenv provides:
- A CLI for language-agnostic
.envprofile execution - A Python API for programmatic
.envloading
“Store config in the environment” — 12factor.net/config
| Section | Status |
|---|---|
| CI/CD | |
| PyPI | |
| Python | |
| Style | |
| License | |
| Docs | CHANGELOG.md |
Table of Contents
- Key Features
- Quick Start
- Multiple Profiles
- Framework Integrations
- Parsing Behaviour
- Sample
.envFile - Similar Tools
Key Features
- 🚀 CLI-First: Use
.envfiles across any language or platform. - 🐍 Python-native API: Load and transform environment settings inside Python.
- ⚙️ Multiple Profiles: Switch easily between
.env.dev,.env.prod, etc. - ⚙️ Multiple Formats: Use plain
.env,.env.json,.env.toml, or.env.yaml - ⚙️ Autodetect Env File: Looking for
.env,.env.json,.env.toml, and.env.yaml - 🔧 Parameter Expansion: Bash-style
${VAR:-default},${VAR:?msg},${VAR:+alt}operators. - ✏️ Escape Sequences:
\n,\t,\\,\"in double-quoted values;$$for a literal$. - 📄 Multi-line Values: Triple-quoted heredoc syntax (
"""..."""/'''...'''). - 🔒 Required Variables:
# @required VARdeclarations fail fast on missing config. - 📎 File Includes:
# @include pathmerges another env file inline for layered config. - 🧩 Framework-Friendly: Works well with Django, Flask, FastAPI, and more.
Quick Start
Installation
pip install runenv
pip install runenv[toml] # if you want to use .env.toml in python < 3.11
pip install runenv[yaml] # if you want to use .env.yaml
CLI Usage
Run any command with a specified environment:
runenv run --env-file .env.dev -- python manage.py runserver
runenv run --env-file .env.prod -- uvicorn app:app --host 0.0.0.0
runenv list [--env-file .env] # view parsed variables
runenv lint [--env-file .env] # check for errors in env file
runenv lint --strict [--env-file .env] # also warn on ambient/undefined refs
Python API
Load .env into os.environ
Note: The
load_envwill not parse env_file if therunenvCLI was used, unless youforce=Trueit.
from runenv import load_env
load_env() # loads .env
load_env(
env_file=".env.dev", # file to load - will be autodetected if not passed
prefix='APP_', # load only APP_.* variables from file
strip_prefix=True, # strip ^ prefix when loading variables
force=True, # load env_file even if the `runvenv` CLI was used
search_parent=1, # look for env_file in current dir and its 1 parent dirs
require_env_file=False # raise error if env file is missing, otherwise just ignore
)
Read .env as a dictionary
from runenv import create_env
config = create_env() # parse .env content into dictionary
config = create_env(
env_file=".env.dev", # file to load - will be autodetected if not passed
prefix='APP_', # parse only APP_.* variables from file
strip_prefix=True, # strip ^ prefix when parsing variables
search_parent=1, # look for env_file in current dir and its 1 parent dirs
)
print(config)
Options include:
- Filtering by prefix
- Automatic prefix stripping
- Searching parent directories
Multiple Profiles
Use separate .env files per environment:
runenv .env.dev flask run
runenv .env.staging python main.py
runenv .env.production uvicorn app.main:app
Recommended structure:
.env.dev
.env.test
.env.staging
.env.production
Framework Integrations
Note: If you're using
runenv .env [./manage.py, ...]CLI then you do not need change your code. Use these integrations only if you're using Python API.
Django
# manage.py or wsgi.py
from runenv import load_env
load_env(".env")
Flask
from flask import Flask
from runenv import load_env
load_env(".env")
app = Flask(__name__)
FastAPI
from fastapi import FastAPI
from runenv import load_env
load_env(".env")
app = FastAPI()
Parsing Behaviour
| Situation | Behaviour |
|---|---|
| Duplicate key | Last definition wins; a warning is emitted by lint |
Key exactly equal to --prefix |
Skipped (stripping would produce an empty name) |
| Key without matching prefix | Skipped and reported as info by lint |
Duplicate keys are not an error — the last value in the file takes effect, matching the behaviour of most shell .env loaders. Use runenv lint to surface duplicates as warnings before they reach production.
Variable Expansion
${VAR} references resolve against variables defined in the same file and then fall back to the calling shell's os.environ. The following bash-style parameter expansion operators are supported:
| Syntax | Behaviour |
|---|---|
${VAR} |
Value of VAR; empty string if unset |
${VAR:-default} |
Value of VAR if set and non-empty, otherwise default |
${VAR-default} |
Value of VAR if set (even if empty), otherwise default |
${VAR:?msg} |
Value of VAR if set and non-empty; fatal error with msg otherwise |
${VAR:+alt} |
alt if VAR is set and non-empty, otherwise empty string |
The :? operator causes runenv run / runenv list to exit non-zero and runenv lint to report an error-level message with the line number where the variable is declared.
Quoting and Escape Sequences
| Style | Escape processing | Variable expansion |
|---|---|---|
Unquoted VAR=value |
None | Yes |
Single-quoted VAR='value' |
None | Yes |
Double-quoted VAR="value" |
\n \t \r \\ \" |
Yes |
Triple double-quoted VAR="""...""" |
Same as double-quoted | Yes |
Triple single-quoted VAR='''...''' |
None | Yes |
Double-quoted values process the standard escape sequences:
GREETING="Hello\tWorld\n" # tab + newline
PATH_VAL="C:\\Users\\name" # literal backslashes
QUOTED="say \"hi\"" # embedded double quote
Use $$ anywhere to emit a literal $ without triggering variable expansion:
PGSERVICE=$$HOME/.pgservice # value: $HOME/.pgservice
TEMPLATE=price: $$${AMOUNT} # literal $ followed by expanded AMOUNT
Triple-quoted values span multiple lines — useful for certificates, JSON blobs, or any multi-line secret:
PRIVATE_KEY="""
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----
"""
RAW_TEXT='''
no \n escape processing here
$$HOME is literal too
'''
Inline Comments
Comments start with #. The rules depend on quoting:
| Style | # treatment |
|---|---|
Unquoted VAR=value # comment |
# ends the value; trailing spaces before # are stripped |
Double-quoted VAR="value # hash" |
# inside quotes is a literal character |
Single-quoted VAR='value # hash' |
# inside quotes is a literal character |
DEBUG=1 # this comment is stripped → value is "1"
MSG=hello world # this too → value is "hello world"
TAG="v1.0 # rc" # hash is part of the value → "v1.0 # rc"
To include a literal # in an unquoted value, quote the value instead.
Including Other Files
Use # @include path to load another env file at that point in the current file. Paths are relative to the file containing the directive.
# @include .env.base
# @include ../shared/secrets.env
PORT=8080 # overrides anything in included files above
Merge order: variables are processed in the order they appear — included files are expanded inline at the directive's position. A variable defined after the @include line overrides a same-named variable from the included file; a variable defined before is overridden by the included file.
Error cases reported by runenv lint:
- Included file not found —
error-level message, parsing continues - Circular include (A includes B includes A) —
error-level message, the cycle is broken
# @required directives inside included files are honoured.
Required Variables
Declare variables that must be present and non-empty with # @required:
# @required DATABASE_URL, SECRET_KEY
# @required PORT
DATABASE_URL=postgresql://localhost/mydb
SECRET_KEY=${APP_SECRET:?APP_SECRET must be set}
PORT=${PORT:-8000}
If any declared variable is missing or empty after full expansion, runenv lint reports an error at the directive's line number and runenv run exits non-zero. Multiple names can appear on one line (comma-separated) or across multiple directives.
# @required and ${VAR:?msg} are complementary, not duplicates. Use # @required to declare top-level contracts on the keys your application needs. Use ${SOURCE:?msg} when building a value from another variable and you want a specific error message that names the source. Don't combine both on the same variable.
Sample .env File
# Pull in shared base configuration
# @include .env.base
# Declare required variables — runenv fails fast if any are missing
# @required DATABASE_URL, SECRET_KEY
# export keyword accepted for shell-source compatibility
export HOST=localhost
PORT=${PORT:-8000}
URL=http://${HOST}:${PORT}
# Parameter expansion
CACHE_URL=${REDIS_URL:-redis://localhost:6379} # default if unset/empty
LOG_LEVEL=${LOG_LEVEL-info} # default only if unset
FEATURE_HEADER=${FEATURE_FLAG:+X-Feature: on} # set only when flag is on
# :? is for inline interpolation guards (different from # @required):
# it fails with a custom message pointing at the *source* variable
DATABASE_URL=${DATABASE_URL:?DATABASE_URL must be set}
SECRET_KEY=${SECRET_KEY:?SECRET_KEY must be set}
# Escape sequences in double-quoted strings
GREETING="Hello\tWorld"
WINDOWS_PATH="C:\\Users\\deploy"
# Literal $ with $$ — no variable expansion triggered
PGSERVICE=$$HOME/.pgservice
# Multi-line heredoc value (triple-quoted)
BANNER="""
Welcome to MyApp
Running on ${HOST}:${PORT}
"""
# Quotes and inline comments
EMAIL="admin@example.com" # Inline comment
TOKEN='s3cr3t'
DEBUG=1
Similar Tools
- python-dotenv – Python-focused, lacks CLI tool
- envdir – Directory-based env manager
- dotenv-linter – Linter for
.envfiles
With runenv, you get portable, scalable, and explicit configuration management that aligns with modern deployment standards. Ideal for CLI usage, Python projects, and multi-environment pipelines.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file runenv-1.4.4.tar.gz.
File metadata
- Download URL: runenv-1.4.4.tar.gz
- Upload date:
- Size: 220.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4904f22a40f6823114427a51e66423ab0785a85a5c854fe998ac1f87d333c1ef
|
|
| MD5 |
d620c0e82731c01a32d50348fec5a5d0
|
|
| BLAKE2b-256 |
3b8c4b9f359bc9d9d14846efa4f0c40241db8c650e2084672832f8ef8dce6a23
|
File details
Details for the file runenv-1.4.4-py3-none-any.whl.
File metadata
- Download URL: runenv-1.4.4-py3-none-any.whl
- Upload date:
- Size: 18.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69412305edaaef793082200ee3e0490995a948106a182d4de849f6fb086db6c7
|
|
| MD5 |
071911cd20d872bde3d8252be3417af7
|
|
| BLAKE2b-256 |
68b63897a9c9ebd6b0b913ee2e13b611591f156b975bbc0ff0f7ffc98d71a98a
|