Winix.EnvVault
0.4.0
Prefix Reserved
dotnet tool install --global Winix.EnvVault --version 0.4.0
dotnet new tool-manifest
dotnet tool install --local Winix.EnvVault --version 0.4.0
#tool dotnet:?package=Winix.EnvVault&version=0.4.0
nuke :add-package Winix.EnvVault --version 0.4.0
envvault
Cross-platform keychain-backed environment-variable manager. Envchain-compatible on macOS/Linux, with a native Windows backend (DPAPI + Credential Manager). Store secrets once, export them into any child process on demand.
Why
Secrets don't belong in shell .rc files, .env files, or commit history. envvault keeps them in your OS key store (Credential Manager on Windows, Keychain on macOS, libsecret on Linux) and re-injects them as environment variables only for the processes you ask for. Works as a drop-in for envchain — existing muscle-memory (envchain github gh pr list) still works, and there's a Windows backend envchain never had.
Install
via winget
winget install Winix.EnvVault
via scoop
scoop bucket add winix https://github.com/Yortw/winix
scoop install envvault
via NuGet as a .NET global tool
dotnet tool install --global Winix.EnvVault
Native binary (GitHub Releases)
Download the platform-appropriate archive from releases and place envvault on your PATH.
Usage
Exec form (envchain-compatible)
Run a command with a namespace's variables merged into its environment:
envvault github gh pr list
envvault aws terraform apply
envvault postgres psql -h db.example.com
Merge multiple namespaces in order (later entries win on key collisions):
envvault github,aws ./deploy.sh
envvault base,prod,secrets ./release.sh
Store a value
Interactive (no echo — value never appears in terminal or shell history):
envvault --set github GITHUB_TOKEN
# prompt: GITHUB_TOKEN: (hidden)
Multiple keys in one call:
envvault --set aws AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
Non-interactive (convenient for scripts, but exposes the value on argv and in shell history):
envvault --value "ghp_xxx..." --set github GITHUB_TOKEN
Empty values are refused by default — silently storing "" is the exact footgun envvault exists to prevent (child command fails hours later with "credentials invalid"). Pass --allow-empty if an empty value is deliberate:
envvault --allow-empty --value "" --set demo OPTIONAL_TOKEN
Retrieve a single value
envvault --get github GITHUB_TOKEN
Exits 127 with a clear message if the namespace or key doesn't exist.
Remove a value
envvault --unset github GITHUB_TOKEN
Exits 127 if the key didn't exist.
List namespaces and keys
envvault --list # all namespaces
envvault --list github # all keys in one namespace (values never printed)
envvault --list --json # machine-readable output
Options
| Flag | Arg | Description |
|---|---|---|
--set |
<NAMESPACE> <KEY>... |
Store one or more keys. Prompts per key (hidden input) unless --value is given. |
--value |
<VALUE> |
Non-interactive value for --set. Single key only. Exposes value on argv/shell history. |
--allow-empty |
— | Permit --set to store an empty string. Refused by default; see "Store a value" above. |
--get |
<NAMESPACE> <KEY> |
Print the stored value to stdout. |
--unset |
<NAMESPACE> <KEY> |
Remove a stored key. |
--list |
[<NAMESPACE>] |
List namespaces, or keys in one namespace. Never prints values. |
--json |
— | JSON output for --list. |
--noecho |
— | Accepted for envchain compat. --set already hides input by default. |
--require-passphrase |
— | Deferred to v1.1. Currently errors out. |
--no-color, --color |
— | ANSI colour control. Respects NO_COLOR env var. |
--describe |
— | Emit structured metadata for AI agents. |
--help, --version |
— | Standard introspection. |
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success. |
| 125 | Usage error — bad flags, missing arguments, conflicting options, empty value without --allow-empty, deferred feature used (--require-passphrase). |
| 126 | Runtime error — key store unavailable, permission denied launching child command. |
| 127 | Not found — namespace or key missing for --get/--unset; command for exec form not on PATH. |
| 130 | Interrupted — user pressed Ctrl+C during an interactive value prompt (POSIX 128 + SIGINT). |
| * | Exec form: on success or child failure, passes through the child process's exit code. |
Coming from envchain?
Things that work identically:
envvault <NAMESPACE> <command>— the bare envchain formenvvault --set <NAMESPACE> <KEY>with hidden-input promptenvvault --listandenvvault --list <NAMESPACE>--noechois accepted (but input is always hidden)
Things that are extended:
- Multi-namespace merge via comma-separated list:
envvault github,aws deploy.sh - Windows backend (DPAPI + Credential Manager) — envchain is *nix only
--jsonoutput for--list--valueflag for scripted non-interactive--set
Things that are deferred:
--require-passphrase— queued for v1.1, pending a native macOS Security.framework path.
Alias hint for muscle memory:
alias envchain=envvault
Security Notes
- Stored values live in the OS key store — Windows Credential Manager (DPAPI under the hood), macOS Keychain, or Linux libsecret. The OS owns the encryption keys;
envvaultnever sees them directly. --value <V>exposes the secret on the process argv and in your shell history. Prefer the interactive prompt.envvault --get <NS> <KEY>prints the value to stdout. Piping into another tool is safe; echoing to a terminal may leave the value in scrollback.- The exec form never round-trips secrets through a file — values go straight into the child process environment block.
- Values in the child's environment are visible to that process and (on some OSes) to root/admin users who can read
/proc/<pid>/environor equivalent.
Colour Handling
- Error and warning lines on stderr are coloured when output is a terminal — red for errors (the
envvault:prefix and message), yellow for warnings (theenvvault: warning:prefix and message). - Respects the
NO_COLORenvironment variable (any value disables colour). --no-color/--colorflags override the auto-detection and theNO_COLORenv var.- When stderr is not a terminal (piped or redirected) no escape codes are emitted regardless of flag.
- Normal output (
--get,--list) is never coloured — it's data, not diagnostics.
Related Tools
protect— encrypt individual files at rest using the same OS key primitivesdigest— HMAC a payload with a stored key:envvault hmac digest --hmac sha256 --key-env HMAC_KEY payload.jsonclip— push values to the clipboard for paste-only workflows
See Also
man envvault(afterwinix install man)envvault --describefor JSON metadata- Upstream envchain: https://github.com/sorah/envchain
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
## [0.3.0] - 2026-05-10
- Initial release.
See full changelog at https://github.com/Yortw/winix/blob/main/src/envvault/CHANGELOG.md