Skip to main content

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

Project description

getv — Universal .env Variable Manager

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.2.tar.gz (19.3 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.2-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: getv-0.1.2.tar.gz
  • Upload date:
  • Size: 19.3 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.2.tar.gz
Algorithm Hash digest
SHA256 3af7042c6ffa3a1c7c6bc1668d12c6d89c8e396c0dcfe19cdd52a90688e24c0f
MD5 5934e3a269c854dbfb2175d5107ce8f9
BLAKE2b-256 1b7a9049ec3504b6281c0c0248c7b64dfecbd7b0c26354c81d1f31072e59331a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: getv-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 17.4 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9902f9bb3d3df274a989c61889b740863773e7aa223b5eb60c3ad22670b11169
MD5 d2b6b8d011621080bda50f10ca53546c
BLAKE2b-256 1f08020c7df173ca0325db2433fa8bdd08c1230ea06a4aa6784463b2c53578af

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