Skip to main content

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_up on/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

  1. 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.

  1. Add non-secret variables:
envrcctl set FOO bar
envrcctl get FOO
envrcctl list
  1. Enable inheritance:
envrcctl inherit on
  1. Store a secret:
envrcctl secret set OPENAI_API_KEY --account openai:prod
  1. Ensure your .envrc includes:
eval "$(envrcctl inject)"
  1. 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 Keychain
  • ss — SecretService via secret-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
  • .envrc updates are atomic
  • inject is blocked in non-interactive environments unless --force is provided
  • secret get is 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


Download files

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

Source Distribution

envrcctl-0.0.1.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

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

envrcctl-0.0.1-py3-none-any.whl (15.7 kB view details)

Uploaded Python 3

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

Hashes for envrcctl-0.0.1.tar.gz
Algorithm Hash digest
SHA256 1e3ae002295b28da1ea260de0e872b0b1be566176161f6c3a0ad3e9e52505a96
MD5 386f2680cd8068f8bb324e5aa8648966
BLAKE2b-256 703ddc55ab8f81a5b9050bbbe8fe37a7e193cd63d82834745cc299e12692bdf6

See more details on using hashes here.

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

Hashes for envrcctl-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c1efd985dcded0fa85c45a7cef6c3c3544799dd3612abee146f896646bca602d
MD5 1036484cf1d3f3501bedf954898f169f
BLAKE2b-256 639891a670c741157a4bd3623202d6adecea5e553df34b761f1aa599061d6bc6

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