Manage .envrc with managed blocks and OS-backed secrets.
Project description
envrcctl
envrcctl is a CLI tool that manages .envrc files safely through a managed
block, with secrets stored in your OS key store instead of the file.
It is designed for macOS first, with Linux support via SecretService.
Features
- Safe, structured edits to
.envrc(managed block only) - Non-secret environment variables (CRUD)
- Secrets stored in Keychain (macOS) or SecretService (Linux)
- Inheritance control (
source_upon/off) - Exec-based secret injection (
envrcctl exec -- ...) - Secret injection for direnv (
eval "$(envrcctl inject)", TTY-guarded) - Secret kinds (runtime/admin), with exec injecting runtime only
- Secret get with clipboard default and TTY guard
- Diagnostics and migration helpers
- Shell completion scripts
Requirements
- Python 3.14+
direnv- macOS Keychain (built-in) or Linux SecretService (
secret-tool)
Installation
macOS (Homebrew)
Tap and install:
brew tap rioriost/envrcctl
brew install envrcctl
After release, Homebrew will download the release from GitHub.
Install direnv with Homebrew:
brew install direnv
Linux (pipx, recommended)
pipx install envrcctl
Linux (uv)
uv tool install envrcctl
From source (macOS/Linux)
git clone <REPO_URL>
cd envrcctl
uv sync
uv run python -m envrcctl.main --help
Quick Start
- Initialize a managed block in
.envrc:
envrcctl init
If .envrc already exists, you'll be prompted to confirm. Use --yes to skip the prompt in non-interactive runs.
- Add non-secret variables:
envrcctl set FOO bar
envrcctl get FOO
envrcctl list
- Enable inheritance:
envrcctl inherit on
- Store a secret:
envrcctl secret set OPENAI_API_KEY --account openai:prod
- Ensure your
.envrcincludes:
eval "$(envrcctl inject)"
- Allow direnv:
direnv allow
Commands
Non-secret variables
envrcctl set VAR value
envrcctl unset VAR
envrcctl get VAR
envrcctl list
Secrets
envrcctl secret set OPENAI_API_KEY --account openai:prod --kind runtime
envrcctl secret set OPENAI_API_KEY --account openai:admin --kind admin
envrcctl secret unset OPENAI_API_KEY
envrcctl secret list
envrcctl secret get OPENAI_API_KEY
envrcctl secret get OPENAI_API_KEY --plain
For CI-safe input:
echo -n "$OPENAI_API_KEY" | envrcctl secret set OPENAI_API_KEY --account openai:prod --stdin
Exec secrets without stdout
envrcctl exec -- python script.py
envrcctl exec -k OPENAI_API_KEY -- python script.py
Exec injects runtime secrets only.
Inject secrets for direnv
envrcctl inject
Non-interactive runs are blocked unless --force is provided.
Effective view (masked)
envrcctl eval
Diagnostics
envrcctl doctor
Migration
envrcctl migrate
You'll be prompted when unmanaged exports or secret refs are detected. Use --yes to confirm in non-interactive runs.
Backend Selection (macOS/Linux)
envrcctl selects a backend automatically by platform, or via ENVRCCTL_BACKEND.
Supported schemes:
kc— macOS Keychainss— SecretService viasecret-tool
Example:
ENVRCCTL_BACKEND=ss envrcctl secret set OPENAI_API_KEY --account openai:prod
Secret references are stored as:
<scheme>:<service>:<account>:<kind>
kind is runtime or admin (default: runtime).
Example:
kc:st.rio.envrcctl:openai:prod:runtime
kc:st.rio.envrcctl:openai:admin:admin
Shell Completion
envrcctl --install-completion
envrcctl --show-completion bash
envrcctl --show-completion zsh
envrcctl --show-completion fish
Generated scripts are stored under completions/. To refresh:
uv run python scripts/generate_completions.py
Security Notes
- Secrets are never written to
.envrc - Secrets are never passed in CLI arguments
.envrcupdates are atomicinjectis blocked in non-interactive environments unless--forceis providedsecret getis clipboard-only by default; plaintext output is TTY-guarded- The tool refuses to write to world-writable
.envrc
Development
uv sync
.venv/bin/envrcctl --help
Acknowledgements
Based on the article below, I added commands such as exec. Thank you for the helpful hints.
“もう.envにAPIキーを平文で置くのはやめた — macOS Keychain管理CLI「LLM Key Ring」”
License
MIT
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 envrcctl-0.0.1.tar.gz.
File metadata
- Download URL: envrcctl-0.0.1.tar.gz
- Upload date:
- Size: 11.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e3ae002295b28da1ea260de0e872b0b1be566176161f6c3a0ad3e9e52505a96
|
|
| MD5 |
386f2680cd8068f8bb324e5aa8648966
|
|
| BLAKE2b-256 |
703ddc55ab8f81a5b9050bbbe8fe37a7e193cd63d82834745cc299e12692bdf6
|
File details
Details for the file envrcctl-0.0.1-py3-none-any.whl.
File metadata
- Download URL: envrcctl-0.0.1-py3-none-any.whl
- Upload date:
- Size: 15.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.27 {"installer":{"name":"uv","version":"0.9.27","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1efd985dcded0fa85c45a7cef6c3c3544799dd3612abee146f896646bca602d
|
|
| MD5 |
1036484cf1d3f3501bedf954898f169f
|
|
| BLAKE2b-256 |
639891a670c741157a4bd3623202d6adecea5e553df34b761f1aa599061d6bc6
|