Varlock: schema-first env files that stay safe around AI tooling

Varlock: schema-first env files that stay safe around AI tooling

Introduction

varlock.dev positions Varlock as “AI-safe .env files”: a workflow where .env.schema holds the authoritative list of variables, constraints, and documentation—but not the secret values themselves—while real values resolve at runtime via git-ignored files (for example .env.local), plugins, or your shell environment. The project is MIT-licensed open source (dmno-dev/varlock on GitHub) alongside reference docs at varlock.dev.

That framing assumes collaborators and agents primarily consume the checked-in schema, not files that contain resolved secrets. It helps prevent accidental checks-ins and transcript paste mistakes; it does not stop an agent or script from reading .env.local, exported process.env, or any path you explicitly expose—so access control and review habits still matter.

If you already treat agent sessions as risky around pasted keys (for example alongside a minimal harness like Pi or scripted flows from Archon), Varlock is pitched as workflow infrastructure: shared schema for agents and CI, plaintext secrets only where you deliberately put them.

That discipline stacks with environment isolation, not replaces it (AI coding devbox, dev-ore devbox for Lima guests).

Cover art here is Varlock’s default Open Graph raster from the upstream site package (packages/varlock-website/public/default-og-image-new.png), same MIT-licensed monorepo as the tool.

Why .env.example drifts (and what Varlock proposes instead)

Teams often duplicate structure between .env, .env.example, README tables, and hand-written TypeScript process.env types. One change updates one file but not another; agents read oversized .env-like blobs and may echo secrets back into transcripts or commits.

Varlock’s answer is .env.schema as a single checked-in artifact annotated with @env-spec: comment-line decorators (similar in spirit to JSDoc) that encode types, optionality/sensitivity defaults, interpolation, docs links, plugins, and more. Human-written secrets belong in .env.local or other ignored layers; the README contrasts that explicitly with drifting .env.example files (Varlock README).

A minimal shape from upstream looks conceptually like this (structure and decorators are illustrative; paste from the README when bootstrapping a real repo):

Copy
# @defaultSensitive=false @defaultRequired=infer @currentEnv=$APP_ENV # --- # @type=enum(development, preview, production, test) APP_ENV=development # @type=port API_PORT=8080 # @type=url API_URL=http://localhost:${API_PORT} # @required @sensitive @type=string(startsWith=sk-) OPENAI_API_KEY=

The @plugin(@varlock/1password-plugin) form (with @initOp(…) where needed) loads optional npm packages so secrets can resolve from op(op://…) references instead of pasted literals (README § plugins). The README’s Published Packages tables list first-party plugins including 1Password, AWS Secrets Manager, Azure Key Vault, Google Secret Manager, HashiCorp Vault, Infisical, Bitwarden, KeePass, pass, Passbolt, and Proton Pass—homepage copy highlights a subset (“six provider plugins”) while the repo enumerates the full set.

Site copy also describes built-in encryption for local overrides in .env.local so overrides need not stay plaintext on disk—a separate concern from .env.schema, which intentionally stays readable.

@env-spec as the interchange format

Implementation-wise, @env-spec is documented as Varlock’s DSL: JSDoc-style comments above keys carry schema metadata, and tooling parses them into structured config (the @env-spec/parser package ships the parser per the README). Official entry points linked from the repository are the @env-spec overview, decorator reference item decorators, and an RFC-style discussion on GitHub (discussion #17).

That separation matters architecturally: you can evolve editors, MCP servers, and generators around one grammar instead of scattering ad hoc validators.

CLI: resolve, guard, inject

Rough workflow straight from upstream (CLI reference):

  • varlock load — validate .env.schema and pretty-print resolved variables (sanitized where sensitive).
  • varlock run -- <cmd> — resolve and validate, then execute <cmd> with injected environment.
  • varlock scan — scan your tree for leaked secrets (README pairs this with git hooks).

The Docker image ghcr.io/dmno-dev/varlock:latest is listed as an install path (README Installation); local setup also supports npx varlock init, Homebrew dmno-dev/tap/varlock, or the documented install shell script (https://varlock.dev/install.sh).

Site and README copy describe runtime protections such as log/console redaction and leak detection in bundled or browser-facing paths when those integrations are enabled—they depend on how you wire varlock/auto-load, framework packages, or varlock run, not on Varlock being present in the repo alone.

JavaScript and frameworks

For plain Node, the varlock/auto-load import path uses execSync to invoke the Varlock CLI, sets resolved values on process.env, and initializes runtime behavior documented there: the ENV object from varlock/env, plus optional log redaction and leak detection when enabled. The integration page states Node.js 22 or higher as a requirement.

Alternatively, varlock run -- node … avoids injecting that runtime shim; ENV from varlock/env is then unavailable, but process.env still receives injected values. Framework integrations published in the README include @varlock/nextjs-integration, @varlock/vite-integration, and @varlock/astro-integration (npm listings linked from README); GitHub Actions is also documented on the site for CI injection patterns.

Editor and MCP ergonomics

The repository ships an official VS Code / Open VSX “env-spec language” extension (varlock.env-spec-language on Marketplace; link in README).

For MCP-capable assistants, Varlock publishes HTTP and SSE MCP servers that proxy documentation—https://docs.mcp.varlock.dev/mcp (HTTP) and https://docs.mcp.varlock.dev/sse (SSE) per the README—with wiring instructions under guides/mcp/—useful when you want citations to converge on canonical docs pages instead of guesswork.

When Varlock shines—and when not to pretend it solves everything

Good fits: Polyglot repos where varlock run can front Python/Go/Ruby scripts uniformly; JS monorepos where Astro/Next/Vite integrations mesh with your toolchain; organizations already standardizing on 1Password, cloud secret managers, or Infisical; teams whose biggest pain is .env/agent drift coupled with preventable leaks.

Caveats: Strong product copy (“agents … never your secrets,” “prevent leaks to AI servers by design”) describes intent when agents read only the schema and you keep secret material out of commits and transcripts—it is not a guarantee against a compromised runner, a .cursorignore-style mistake that exposes .env.local, or pasting resolved values into cloud chat. You still need disciplined IAM, least privilege on backends and secret stores, CI rotation, and reviewer habits—schema tooling does not replace vault policy.

Conclusion

Varlock bundles a checked-in .env.schema, @env-spec decorators, the varlock load/run/scan CLI, plugin-backed secret backends, and first-class JavaScript tooling so collaborators and autonomous tools can share intent and validation rules while keeping secret values out of the tracked schema—provided your tooling and habits actually steer agents at that surface. Pair it with whichever agent workflow you already use—for example reviewing diffs in Pi, multiplexed shells via cmux on macOS, or repeatable graphs in Archon—and treat varlock scan plus git hooks as one layer alongside isolation and review.

Facts and package names above follow dmno-dev/varlock’s README and varlock.dev integration pages as of mid‑May 2026; CLI flags and decorators evolve quickly, so keep the official reference open while you migrate from plain dotenv.

Featured Posts