# varlock
varlock is an [[Open Source]] tool for managing environment variables, built by DMNO Inc. and released under the [[MIT License]]. Its tagline says the whole thing: *"AI-safe .env files: Schemas for agents, secrets for humans."*
That split is the idea worth remembering. Structure goes to the machine, values stay with the person.
It's built on top of `@env-spec`, a specification for annotating `.env` files, and it is deliberately language and framework agnostic. The [[JavaScript]] integrations get the most attention, but the tool is meant for any project that needs configuration at build or boot time.
## The problem it goes after
`.env` files have been the default for years, and they have always had the same three holes:
- **`.env.example` drifts.** You add a variable, you forget the example file, a teammate clones the repo and spends an hour finding out why nothing boots.
- **Misconfiguration shows up at runtime.** A missing or malformed variable becomes a crash in production instead of an error at startup.
- **Secrets sit in plaintext exactly where tools look.** That was survivable when only you read your own files. It stopped being survivable once [[AI Agents]] started reading your project to understand it, and potentially sending what they read somewhere else.
The third one is what makes varlock timely rather than just tidy. Your `.env` is now part of the context window.
## How it works
One file, `.env.schema`, replaces `.env.example`. It declares what each variable is, using JSDoc-style decorators:
```bash
# @type=enum(development, preview, production, test)
APP_ENV=development
# @type=port
API_PORT=8080
# @required @sensitive @type=string(startsWith=sk-)
OPENAI_API_KEY=
```
The decorators (`@type`, `@required`, `@sensitive`, `@defaultSensitive`) do several jobs at once: documentation, validation, [[TypeScript]] type generation with IDE completion, and the marking of which values must never be shown.
Values can come from anywhere. Composed across defaults, per-environment overrides, git-ignored local files, and process variables, or pulled from an external secret manager through function calls like `op("op://api-prod/xyz/auth-token")`. Over a dozen backends are supported: 1Password, AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, Infisical, Bitwarden, Google Secret Manager. `.env.local` is encrypted device-locally with hardware backing, so nothing sits in plaintext.
The CLI is small:
- `varlock load` validates the schema and shows the resolved values
- `varlock run -- <command>` injects them into a subprocess
- `varlock scan` hunts for leaked secrets in your code, and runs as a git hook
- `varlock proxy run` starts the local credential proxy
It also works as a drop-in replacement for dotenv with `import 'varlock/auto-load'`, and integrates with [[Next.js]], Vite, Astro and SvelteKit. Install via `npx varlock init`, Homebrew, a curl script, or the Docker image.
## The agent-safety part
Two mechanisms, and they're different from each other.
**The schema is the agent's copy.** An agent reading `.env.schema` learns every variable name, its type, its validation rules and its description. Enough to generate correct code. It never sees a single value. Combine that with `varlock scan` and you also catch the secrets that agent-written code accidentally hardcodes.
**The credential proxy handles the runtime case.** When an agent actually has to make an authenticated call, it receives a placeholder instead of the real credential, and the real value gets injected at a verified network boundary. The agent can use the key without ever holding it.
[[Hermes Agent]] shipped the same mechanism for Docker sandboxes in the same month, independently. Two projects, different starting points, identical answer: stand-in inside, real value swapped at egress. That convergence is a good sign the pattern is right rather than clever.
Alongside that, sensitive values are redacted from logs at runtime, which closes the oldest leak of all: the secret that ends up in a stack trace.
## Why I keep this note
The specific tool matters less to me than the pattern it names. We spent years treating configuration as a flat list of strings, and the schema lived in a stale example file or in someone's head. varlock makes the schema the real artifact and demotes the values to something you fetch.
That reframing generalises well beyond environment variables. Anywhere an agent needs to understand your system, the question is now: what is the structure I can hand over freely, and what are the values I must keep back? Answer it once, deliberately, and a whole category of leaks stops being possible.
## References
- [varlock.dev](https://varlock.dev/)
- [varlock on GitHub](https://github.com/dmno-dev/varlock)
- [Documentation](https://varlock.dev/getting-started/introduction/)
- [Blog](https://varlock.dev/blog/)
- [Community Discord](https://chat.dmno.dev/)
## Related
- [[AI Agents]]
- [[Hermes Agent]] — same credential-proxy pattern for Docker sandboxes
- [[DrSkill]] — scans for secrets in committable agent config
- [[Claude Code]]
- [[TypeScript]]
- [[JavaScript]]
- [[Node.js]]
- [[Next.js]]
- [[Open Source]]
- [[MIT License]]
- [[DevOps]]