envref — Separate config from secrets in .env files

5 min read Original article ↗

Open source CLI tool

Keep secrets out of
.env files

envref replaces plaintext secrets with ref:// references that resolve at runtime from your OS keychain, 1Password, Vault, or AWS SSM. Your .env stays safe to commit.

.env ref://secrets/api_key resolve sk-abc...xyz

~/my-project

APP_NAME=my-app DATABASE_URL=ref://secrets/database_url API_KEY=ref://secrets/api_key $ envref resolve APP_NAME=my-app DATABASE_URL=postgres://localhost:5432/mydb API_KEY=sk-abc123...xyz $ envref run -- node server.js Server running on :3000

$ brew install xcke/tap/envref [copy] Copied!

# Mental model

Config and secrets, separated

Your .env holds config values and references. Secrets live in secure backends. envref bridges the gap at runtime.

.env file

API_KEY=ref://secrets/api_key

Config values and secret references. Committed to git. No plaintext secrets.

Secret backends

keychain | vault | 1password | ssm

OS keychain, local vault, 1Password, AWS SSM, HashiCorp Vault, OCI, or custom plugins.

envref resolve

config + secrets → env vars

Resolves references, merges layers, interpolates variables. Output to shell, direnv, or JSON.

>_ Zero secrets on disk

ref:// references

Secrets stay in your OS keychain or password manager. The .env file holds only references — safe to commit, share, and review.

>_ direnv integration

Automatic resolution

Run envref init --direnv and secrets resolve automatically when you cd into the project. Sub-50ms startup.

>_ 7 backend types

Flexible storage

OS keychain out of the box. Add 1Password, AWS SSM, HashiCorp Vault, OCI, or write a plugin — backends chain with fallback.

>_ Profiles

Environment switching

Layer .env.env.staging.env.local. Profile-scoped secrets keep environments isolated.

>_ Team sharing

Encrypted sync

Share secrets with teammates via age encryption. envref sync push encrypts for the whole team. New members run envref onboard.

>_ Validation

Schema checks

Validate .env against .env.example or a JSON schema. --ci flag returns exit code 1 for pipeline integration.

# Resolution pipeline

How it works

Every envref resolve call follows a deterministic pipeline from file loading to formatted output.

Load & merge .env files

Three-layer merge: .env (base) ← .env.<profile> (environment) ← .env.local (personal). Later files override earlier ones.

Variable interpolation

Expand ${VAR} references within values. DB_URL=postgres://${DB_HOST}:${DB_PORT}/app becomes a complete connection string.

Reference resolution

Parse ref:// URIs and look up each secret through the backend chain. Backends are tried in order; first match wins. Results are cached per-call.

Nested resolution

A second pass catches ${ref://secrets/key} patterns embedded in interpolated values. Supports arbitrary nesting depth.

Format & output

Emit as KEY=VALUE (plain), export KEY=VALUE (shell/direnv), JSON, or bordered table. Pipe to direnv, inject into commands, or use in CI.

# Secret backends

Seven ways to store secrets

Two built-in backends, four CLI wrappers for enterprise tools, and a plugin system for everything else. Chain them with ordered fallback.

Backend Type Use case
OS Keychain keychain Default — uses macOS Keychain, Linux Secret Service, or Windows Credential Manager. Zero setup.
Local Vault vault SQLite + age encryption. For headless servers, containers, and CI environments.
1Password 1password Teams already using 1Password. Wraps the op CLI.
AWS SSM aws-ssm AWS Systems Manager Parameter Store. For AWS infrastructure.
HashiCorp Vault hashicorp-vault Enterprise secret management with KV v2 secrets engine.
OCI Vault oci-vault Oracle Cloud Infrastructure Vault for OCI workloads.
Plugin plugin Custom external executables via a JSON protocol. Extend to any secret store.

# Quickstart

Up and running in 60 seconds

Four steps from install to resolved environment variables.

quickstart

$ brew install xcke/tap/envref $ envref init --project my-app --direnv Created .envref.yaml Created .env with example entries Created .envrc for direnv integration $ envref secret set database_url Enter value: ******** Stored database_url in keychain backend $ envref resolve APP_NAME=my-app DATABASE_URL=postgres://user:pass@localhost/mydb $ envref run -- node server.js Server listening on :3000

# CLI reference

Commands

28 commands organized by workflow. Run envref <cmd> --help for full details.

Core

envref initScaffold a new envref project

envref get <KEY>Print the resolved value of a variable

envref set <KEY>=<VALUE>Write a variable to a .env file

envref listList all merged environment variables

envref resolveResolve all references, output KEY=VALUE

envref run -- <cmd>Execute a command with resolved env injected

envref editOpen .env files in $EDITOR

Secrets

envref secret set|get|delete|listFull CRUD for secrets in backends

envref secret generate <key>Generate and store a random secret

envref secret copy <key> --from <proj>Copy secret between projects

envref secret rotate <key>Rotate with history retention

envref secret share <key> --to <age-key>Encrypt secret for a recipient

Profiles

envref profile list|use|create|diffManage environment profiles

envref profile export <name>Export profile as JSON, plain, shell, or table

Validation & diagnostics

envref validateCheck .env against schema or .env.example

envref statusShow environment overview with actionable hints

envref doctorScan .env files for common issues

envref auditDetect plaintext secrets via entropy analysis

envref audit-logView append-only log of secret operations

Team & sync

envref sync push|pullSync secrets via encrypted git file

envref team list|add|removeManage team members and age keys

envref onboardInteractive setup for new team members

Vault & config

envref vault init|lock|unlock|export|importLocal encrypted vault management

envref config showPrint resolved effective configuration

envref completion <shell>Generate shell completions (bash/zsh/fish)

envref versionPrint version

# Install

Get envref

Available for macOS and Linux via multiple package managers. Pre-built Windows binaries on GitHub Releases.

Homebrew (macOS / Linux)

$ brew install xcke/tap/envref

Go install

$ go install github.com/xcke/envref/cmd/envref@latest

Nix

$ nix run github:xcke/envref

From source

$ git clone https://github.com/xcke/envref.git
$ cd envref && make build

Pre-built binaries for all platforms on GitHub Releases.