dotenvage
Python bindings for
dotenvage — encrypt
secrets in .env files using age encryption (X25519).
Installation
pip install dotenvage
# or with uv
uv add dotenvage
Quick start
import dotenvage
# Generate a new identity (key pair)
manager = dotenvage.SecretManager.generate()
print(f"Public key: {manager.public_key_string()}")
# Encrypt a secret
encrypted = manager.encrypt_value("my-secret-password")
print(f"Encrypted: {encrypted}")
# Output: ENC[AGE:b64:...]
# Decrypt it back
decrypted = manager.decrypt_value(encrypted)
print(f"Decrypted: {decrypted}")
# Output: my-secret-password
# Check if a value is encrypted
print(dotenvage.SecretManager.is_encrypted(encrypted)) # True
print(dotenvage.SecretManager.is_encrypted("plain")) # False
Loading .env files
import dotenvage
# Load .env files (decrypts encrypted values automatically)
loader = dotenvage.EnvLoader()
loaded_files = loader.load()
print(f"Loaded: {loaded_files}")
# Or get all variables as a dict
variables = loader.get_all_variables()
print(variables)
Auto-detection
dotenvage can detect which keys should be encrypted based on naming patterns:
import dotenvage
# Keys containing PASSWORD, SECRET, KEY, TOKEN, etc. are detected
dotenvage.should_encrypt("API_KEY") # True
dotenvage.should_encrypt("DATABASE_URL") # False
dotenvage.should_encrypt("SECRET_TOKEN") # True
Key discovery
The SecretManager automatically discovers keys in this order:
- Auto-discover
AGE_KEY_NAMEfrom.envor.env.localfiles DOTENVAGE_AGE_KEYenvironment variable (full identity string)AGE_KEYenvironment variableEKG_AGE_KEYenvironment variable- OS keychain entry (service:
dotenvageorDOTENVAGE_KEYCHAIN_SERVICE; account:AGE_KEY_NAMEor{CARGO_PKG_NAME}/dotenvage) - Key file from
AGE_KEY_NAME→~/.local/state/{namespace}/{keyname}.key - Default:
~/.local/state/dotenvage/dotenvage.key
OS keychain lookup currently uses:
- macOS: Keychain via
security - Linux/Unix: Secret Service via
secret-tool - Windows: lookup falls back to file/env sources (no keychain lookup yet);
keygen --store os|bothstores usingcmdkey
AGE_KEY_NAME format is {namespace}/{keyname}, e.g., myapp/production
→ ~/.local/state/myapp/production.key
API reference
SecretManager
Manager for encrypting and decrypting secrets using age encryption.
class SecretManager:
def __init__(self) -> None:
"""Create from discovered key file."""
@staticmethod
def generate() -> SecretManager:
"""Generate a new random identity (key pair)."""
@staticmethod
def from_identity_string(identity: str) -> SecretManager:
"""Create from an age identity string (AGE-SECRET-KEY-...)."""
@staticmethod
def is_encrypted(value: str) -> bool:
"""Check if a value is in encrypted format."""
def public_key_string(self) -> str:
"""Get public key as age1... string."""
def encrypt_value(self, plaintext: str) -> str:
"""Encrypt to ENC[AGE:b64:...] format."""
def decrypt_value(self, value: str) -> str:
"""Decrypt if encrypted, otherwise return unchanged."""
EnvLoader
Loader for .env files with automatic decryption.
class EnvLoader:
def __init__(self) -> None:
"""Create with default SecretManager."""
@staticmethod
def with_manager(manager: SecretManager) -> EnvLoader:
"""Create with a specific SecretManager."""
def load(self) -> list[str]:
"""Load .env files from current directory. Returns loaded paths."""
def load_from_dir(self, dir: str) -> list[str]:
"""Load .env files from specific directory."""
def get_all_variable_names(self) -> list[str]:
"""Get all variable names from .env files."""
def get_all_variable_names_from_dir(self, dir: str) -> list[str]:
"""Get all variable names from .env files in directory."""
def get_all_variables(self) -> dict[str, str]:
"""Load and return all variables as dict (decrypted)."""
def get_all_variables_from_dir(self, dir: str) -> dict[str, str]:
"""Load and return all variables from directory (decrypted)."""
def resolve_env_paths(self, dir: str) -> list[str]:
"""Get ordered list of .env file paths that would be loaded."""
Functions
def should_encrypt(key: str) -> bool:
"""Check if key name should be encrypted based on patterns."""
License
Metadata
Release files for dotenvage 0.7.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| dotenvage-0.7.1-cp310-abi3-win_amd64.whl | CPython 3.10 | abi3 | Windows x86-64 | Details |
| dotenvage-0.7.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| dotenvage-0.7.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.10 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| dotenvage-0.7.1-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
| dotenvage-0.7.1-cp310-abi3-macosx_10_12_x86_64.whl | CPython 3.10 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 3.3 MB
Release files / dotenvage-0.7.1-cp310-abi3-win_amd64.whl
| Download URL | dotenvage-0.7.1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 563.3 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
5b50f723b6d80a0bf75349182a50a458ace97196306898f52ae0e9aafc0796e2
|
|
BLAKE2b-256 checksum How to use checksums |
d9ec5850553cc19576da484a9dc0c0feafbf18bdfc182a0902c89bd848083057
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 12, 2026.
Transparency logRelease files / dotenvage-0.7.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | dotenvage-0.7.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 680.4 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
e6ce25457960a50770ac327270d6a5119776c1db010f1c2b0ac6ace471f7912e
|
|
BLAKE2b-256 checksum How to use checksums |
a9c1c7b6d92495b457c1e8e9587ed520e10017b0cb4e7f9e9d52d70725785363
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 12, 2026.
Transparency logRelease files / dotenvage-0.7.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | dotenvage-0.7.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 642.9 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
b0aac463943252b849660bac52259f886b0d4ff12f1d7fc33c1b40992b586331
|
|
BLAKE2b-256 checksum How to use checksums |
f3c33806a6e633926620fd2c3da8bd21a18191a8f67d85f7d301a2c5da2ffef1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 12, 2026.
Transparency logRelease files / dotenvage-0.7.1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | dotenvage-0.7.1-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 678.8 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
ecc81bbdef377e6645ea0bde05059f634f6147ec3f0edf0f07f48743f27b0ddc
|
|
BLAKE2b-256 checksum How to use checksums |
024e70143e1d324382794766cb97a08f4026ecb3491b1244d753b644015c655f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 12, 2026.
Transparency logRelease files / dotenvage-0.7.1-cp310-abi3-macosx_10_12_x86_64.whl
| Download URL | dotenvage-0.7.1-cp310-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 697.8 kB |
| Tags | CPython 3.10 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
24627d162527564a9b4764fada6e63e911e81950fa620de0429a8885753ce062
|
|
BLAKE2b-256 checksum How to use checksums |
628bb17943082c4f9cd6e88189837165bee424f4a96a168a410f2d2976145f23
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 12, 2026.
Transparency log