Skip to content

Repository files navigation

envctl

Edit one key in an env file without disturbing anything else, and keep secrets out of your terminal while you do it.

$ envctl set .env DATABASE_URL 'postgres://localhost/app'
$ envctl get DATABASE_URL
postgres://localhost/app
$ envctl --redact list --values
DATABASE_URL=<redacted>
DEBUG=true

Order, comments, and spacing survive every edit. Writes go through a temp file and a rename, so a crash never leaves half a file behind. A single C11 binary with no runtime dependencies.

Install

curl -fsSL https://raw.githubusercontent.com/kjanat/envctl/master/install.sh | bash

install.sh picks the release asset for your OS and architecture, checks it against SHA256SUMS, and installs to ~/.local/bin. Override with ENVCTL_INSTALL_DIR and ENVCTL_VERSION.

Prefer to pick the asset yourself? GitHub Releases carries linux-amd64, linux-arm64, darwin-amd64, darwin-arm64, windows-amd64, and windows-arm64, each with a build provenance attestation:

gh release download -R kjanat/envctl \
  --pattern envctl-linux-amd64 --output ~/.local/bin/envctl
chmod +x ~/.local/bin/envctl
gh attestation verify ~/.local/bin/envctl --repo kjanat/envctl

From source, with any C11 compiler:

git clone https://github.com/kjanat/envctl.git && cd envctl && make && make install

make install places the binary, the man page, and the bash, zsh, and fish completion scripts under PREFIX (~/.local by default). make test runs the suite.

Commands

envctl set     [file] <KEY> [VALUE]   create or replace a key
envctl get     [file] <KEY>           print the active value
envctl disable [file] <KEY>           comment a key out, keep its value
envctl enable  [file] <KEY>           uncomment a key
envctl delete  [file] <KEY>           remove a key entirely
envctl list    [file]                 print active keys
envctl redact  [file]                 filter stdin to stdout, masking secrets
envctl env                            print the environment, always redacted
envctl completions <shell>            completion script for bash/zsh/fish/pwsh
envctl module pwsh                    PowerShell cmdlets wrapping the binary

./.env is assumed when you leave the file out. Without a command word, envctl <KEY> is a get and envctl <KEY> <VALUE> is a set. ls and rm are aliases for list and delete.

Secrets stay out of the way

Values that look like secrets are masked when a coding agent is driving your terminal, and whenever you ask with --redact:

$ envctl env
# envctl v0.5.0 (redacted)
PATH=/usr/bin:/bin
API_TOKEN=<redacted>

Pipes stay raw, so TOKEN=$(envctl get TOKEN) keeps working. envctl redact runs the same masking over any text you pipe through it, which is how build logs and agent output stop leaking:

npm run build 2>&1 | envctl redact

This is presentation hygiene, not a security boundary. See SECURITY.md.

Documentation

Page Contents
Commands Every command and flag, file format, exit codes, guarantees
Redaction When masking is on, what counts as a secret, filter mode
Shell integration Completions for four shells, PowerShell cmdlets
Recipes Rotate a secret, mask CI output, compare two env files, and friends

man envctl carries the full reference offline, and envctl <cmd> --help prints one command with only the flags it accepts.

How it stays honest

src/cli.c holds one table of commands and flags. Parser validation, --help, the man page, the completion scripts, and the PowerShell module all come out of it, so a flag cannot exist without the documentation knowing about it. The man page is regenerated by make man, and make test fails when the checked-in copy no longer matches.

Development and release workflow: CONTRIBUTING.md.
Threat model and vulnerability reporting: SECURITY.md.

License

MIT

About

manage keys in env files

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages