Redenv Python SDK
The official, zero-knowledge Python client for Redenv. Securely fetch, cache, and manage your environment variables at runtime.
Features
- 🔒 Zero-Knowledge: End-to-End Encryption. Secrets are decrypted locally using your Project Encryption Key (PEK).
- ⚡ High Performance: In-memory
LRUCachewithStale-While-Revalidatestrategy for zero-latency reads. - 🔄 Universal: Native Async (
asyncio) and Synchronous clients included. - 🛠️ Developer Experience:
- Smart Casting:
secrets.get("PORT", cast=int) - Scoping:
secrets.scope("STRIPE_")for namespaced configs. - Validation:
secrets.require("API_KEY")fail-fast checks. - Time Travel: Fetch historical versions of secrets.
- Smart Casting:
- 🛡️ Secure by Default: Secrets are masked (
********) in logs to prevent accidental leaks.
Installation
pip install redenv
Quick Start
Async Client (FastAPI / Modern Apps)
import asyncio
import os
from redenv import Redenv
async def main():
client = Redenv({
"project": os.getenv("REDENV_PROJECT"),
"token_id": os.getenv("REDENV_TOKEN_ID"),
"token": os.getenv("REDENV_TOKEN_KEY"),
"upstash": {
"url": os.getenv("UPSTASH_REDIS_URL"),
"token": os.getenv("UPSTASH_REDIS_TOKEN")
}
})
# 1. Load Secrets (Populates os.environ by default)
secrets = await client.load()
# 2. Access Secrets
print(f"Database URL: {secrets['DATABASE_URL']}")
# 3. Smart Casting
port = secrets.get("PORT", cast=int)
debug = secrets.get("DEBUG", cast=bool)
# 4. Safe Access (Returns None if missing)
missing = secrets["MISSING_KEY"] # None
# 5. Fallback Values
timeout = secrets.get("TIMEOUT", default=30, cast=int)
if __name__ == "__main__":
asyncio.run(main())
Synchronous Client (Flask / Scripts / Legacy)
Perfect for scripts or frameworks where async/await is not available at the top level.
from redenv import RedenvSync
client = RedenvSync({ ... }) # Same config as above
# Blocks until secrets are fetched
secrets = client.load()
print(secrets["API_KEY"])
Advanced Usage
1. Secret Expansion (Reference other keys)
Redenv supports referencing other secrets using the ${VAR_NAME} syntax. This helps avoid duplication.
Example Configuration:
BASE_URL:https://api.example.comAUTH_URL:${BASE_URL}/auth
Usage:
secrets = await client.load()
print(secrets["AUTH_URL"])
# Output: https://api.example.com/auth
2. Raw Values
You can access the unexpanded, raw value of a secret using the .raw property. This is useful for debugging or editing.
print(secrets["AUTH_URL"]) # https://api.example.com/auth
print(secrets.raw["AUTH_URL"]) # ${BASE_URL}/auth
3. Scoping & Validation
Organize large configurations and ensure critical keys exist.
secrets = await client.load()
# Fail if these keys are missing
secrets.require("STRIPE_KEY", "STRIPE_WEBHOOK")
# Create a subset of keys (e.g., keys starting with "STRIPE_")
# The prefix is automatically stripped.
stripe_config = secrets.scope("STRIPE_")
print(stripe_config["KEY"]) # Maps to STRIPE_KEY
print(stripe_config["WEBHOOK"]) # Maps to STRIPE_WEBHOOK
4. Time Travel (Version History)
Redenv stores a history of every secret change. You can access older versions for rollbacks or auditing.
# Get the absolute version 5
v5 = await client.get_version("API_KEY", 5)
# Get the previous version (1 version older than latest)
# Mode="index": 0=Latest, 1=Previous, -1=Oldest
prev = await client.get_version("API_KEY", 1, mode="index")
# Get the oldest version ever created
first = await client.get_version("API_KEY", -1)
3. Writing Secrets
You can update secrets programmatically. This automatically encrypts the value, increments the version, and updates the history.
await client.set("FEATURE_FLAG", "true")
4. Configuration Options
| Option | Type | Description | Default |
|---|---|---|---|
project |
str | Your Project ID | Required |
token_id |
str | Service Token Public ID | Required |
token |
str | Service Token Secret Key | Required |
upstash |
dict | { url: ..., token: ... } |
Required |
environment |
str | Target environment (dev, prod) | development |
log |
str | Log level (none, low, high) |
low |
cache |
dict | { ttl: 300, swr: 86400 } (seconds) |
5min / 24h |
env.override |
bool | Overwrite existing os.environ keys |
True |
client = Redenv({
# ...
"env": {
"override": False # Protects local env vars from being overwritten
}
})
Security
- Masking: If you accidentally print the
secretsobject, values are hidden:Secrets({'API_KEY': '********'}). - Zero-Knowledge: The server (Upstash) never sees the plaintext. Decryption happens only in your application's memory.
License
MIT
Metadata
Release files for redenv 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| redenv-0.4.1.tar.gz | 18.6 kB | Without provenance | Details for redenv-0.4.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| redenv-0.4.1-py3-none-any.whl | Python 3 | none | any | Details for redenv-0.4.1-py3-none-any.whl |
Total release size: 37.3 kB
Release files / redenv-0.4.1.tar.gz
| Download URL | redenv-0.4.1.tar.gz |
|---|---|
| Size | 18.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4c51aa5053a876be7451fda118f088970f02697b9dfb2f9ca909d684c7f2b041
|
|
BLAKE2b-256 checksum How to use checksums |
aafd49cf4b0018b398eb6f5e09f6f683090ebd4b914e08aa76a057e9f36a4c1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Release files / redenv-0.4.1-py3-none-any.whl
| Download URL | redenv-0.4.1-py3-none-any.whl |
|---|---|
| Size | 18.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ce3360fb4d6902c5bbb06b3e75ec0b0e4817f42c3e5a8488218fff0453305b23
|
|
BLAKE2b-256 checksum How to use checksums |
e08b52942ccdb262296ec0fc0c6a205df742d8f7a98c52d766573283ba88c8b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Security for redenv 0.4.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.