Skip to main content

Universal .env variable manager — read, write, encrypt, delegate across services and devices

Project description

getv — Universal .env Variable Manager

PyPI version Python versions License: Apache-2.0 Downloads Tests

Read, write, encrypt, and delegate environment variables across services and devices.

Why getv?

Every project reinvents .env parsing. getv provides one library for:

  • Reading/writing .env files with comment preservation
  • Profile management — named configs for devices, LLM providers, databases
  • Secret masking — automatic detection and masking of passwords/keys in logs
  • Encryption — Fernet-based encryption of sensitive values for safe transport
  • Format export — dict, JSON, shell, docker-compose, pydantic BaseSettings
  • CLI — manage profiles from the command line

Install

pip install getv                   # core
pip install "getv[crypto]"         # + encryption (Fernet)
pip install "getv[pydantic]"       # + pydantic BaseSettings export
pip install "getv[all]"            # everything

Quick Start

Python API

from getv import EnvStore, ProfileManager

# Single .env file
store = EnvStore("~/.myapp/.env")
store.set("DB_HOST", "localhost").set("DB_PORT", "5432").save()
print(store.get("DB_HOST"))  # "localhost"

# Profile manager — multiple named configs
pm = ProfileManager("~/.fixpi")
pm.add_category("devices", required_keys=["RPI_HOST", "RPI_USER"])
pm.add_category("llm", required_keys=["LLM_MODEL"])

pm.set("devices", "rpi3", {
    "RPI_HOST": "192.168.1.10",
    "RPI_USER": "pi",
    "RPI_PASSWORD": "secret",
    "RPI_PORT": "22",
})

pm.set("llm", "groq", {
    "LLM_MODEL": "groq/llama-3.3-70b-versatile",
    "GROQ_API_KEY": "gsk_xxx",
})

# Merge profiles on top of base config
base = {"APP_NAME": "fixpi", "RPI_HOST": "default"}
cfg = pm.merge_profiles(base, devices="rpi3", llm="groq")
# cfg["RPI_HOST"] == "192.168.1.10" (overridden by device profile)
# cfg["LLM_MODEL"] == "groq/llama-3.3-70b-versatile"

CLI

# Set variables
getv set devices rpi3 RPI_HOST=192.168.1.10 RPI_USER=pi RPI_PASSWORD=secret

# Get a single variable
getv get devices rpi3 RPI_HOST
# → 192.168.1.10

# List all categories
getv list
#   devices/ (2 profiles)
#   llm/ (3 profiles)

# List profiles in a category (secrets masked)
getv list devices
#   rpi3: RPI_HOST=192.168.1.10, RPI_USER=pi, RPI_PASSWORD=secr***

# Show all variables (unmasked)
getv list devices rpi3 --show-secrets

# Export to different formats
getv export devices rpi3 --format json
getv export devices rpi3 --format shell
getv export devices rpi3 --format pydantic
getv export llm groq --format docker

# Encrypt sensitive values (Fernet)
getv encrypt devices rpi3
# → Generated key: ~/.getv/.fernet.key
# → Encrypted sensitive values in devices/rpi3

# Decrypt
getv decrypt devices rpi3

# Delete a profile
getv delete devices old-rpi

Profile Directory Structure

~/.getv/                    ← GETV_HOME (configurable)
├── .fernet.key             ← encryption key (chmod 600)
├── devices/
│   ├── rpi3.env
│   ├── rpi4-prod.env
│   └── rpi5-kiosk.env
└── llm/
    ├── groq.env
    ├── openrouter.env
    └── ollama.env

Each .env file is a standard KEY=VALUE file:

# ~/.getv/devices/rpi3.env
RPI_HOST=192.168.1.10
RPI_USER=pi
RPI_PASSWORD=secret
RPI_PORT=22

Security

Automatic Secret Detection

Keys matching these patterns are automatically masked in display/logs:

PASSWORD, PASSWD, SECRET, TOKEN, API_KEY, APIKEY, PRIVATE_KEY, ACCESS_KEY, ACCESS_TOKEN, AUTH, CREDENTIAL

from getv.security import mask_dict, is_sensitive_key

data = {"RPI_HOST": "10.0.0.1", "RPI_PASSWORD": "secret123"}
print(mask_dict(data))
# {"RPI_HOST": "10.0.0.1", "RPI_PASSWORD": "secr***"}

Encryption for Transport

from getv.security import generate_key, encrypt_store, decrypt_store

key = generate_key()
data = {"RPI_HOST": "10.0.0.1", "RPI_PASSWORD": "secret"}
encrypted = encrypt_store(data, key, only_sensitive=True)
# {"RPI_HOST": "10.0.0.1", "RPI_PASSWORD": "ENC:gAAA..."}

original = decrypt_store(encrypted, key)
# {"RPI_HOST": "10.0.0.1", "RPI_PASSWORD": "secret"}

Format Export

Format Function Output
dict store.as_dict() {"KEY": "val"}
JSON to_json(data) {"KEY": "val"}
Shell to_shell_export(data) export KEY='val'
Docker to_docker_env(data) KEY=val
.env to_env_file(data) KEY=val
Pydantic to_pydantic_settings(data) Python class source
Pydantic model to_pydantic_model(data) BaseSettings instance

Integration with fixpi

getv powers fixpi's device and LLM profile management:

from getv import ProfileManager

pm = ProfileManager("~/.fixpi")
pm.add_category("devices")
pm.add_category("llm")

# fixpi delegates all .env operations to getv
cfg = pm.merge_profiles(base_env, devices="rpi3", llm="groq")

Environment Variables

Variable Default Description
GETV_HOME ~/.getv Base directory for profiles

License

Apache License 2.0 - see LICENSE for details.

Author

Created by Tom Sapletta - tom@sapletta.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

getv-0.1.3.tar.gz (19.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

getv-0.1.3-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

Details for the file getv-0.1.3.tar.gz.

File metadata

  • Download URL: getv-0.1.3.tar.gz
  • Upload date:
  • Size: 19.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for getv-0.1.3.tar.gz
Algorithm Hash digest
SHA256 b8f23d23ab39f8bb471417c91bad0a3c20d5eeb66d488ddb638055747868fb46
MD5 e2dada6989d927ce924cebc02af85756
BLAKE2b-256 95f9d9056b2450df0b7a1250818cd1d957353daa9f0c82c412077797874f7315

See more details on using hashes here.

File details

Details for the file getv-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: getv-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 17.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for getv-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 5ea2d71612c36b689e13a094dc4f4535864132e7fc6feb068ce77d714993dfe3
MD5 73ab0a777ba9dcf22a4fb0b05199d241
BLAKE2b-256 ee44701249b2d829bfc3560a2730b06841d77754a9aab27f98ff4d4239e79f85

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page