---
title: Envlock Overview
description: Typed environment variable contracts for TypeScript. Define schemas, validate at startup, generate .env.example files, and diff actual env against the contract.
url: https://pr-1-ff84656b4b8a.thally.app/envlock/overview
---

# Envlock Overview

Typed environment variable contracts for TypeScript. Define schemas, validate at startup, generate .env.example files, and diff actual env against the contract.

Envlock lets you declare a typed contract for the environment variables your application reads, then validate that contract at startup. It can generate `.env.example` files from the contract, diff a live environment or dotenv file against what the contract expects, and mask secrets throughout every output path.

Envlock is part of the Seamline toolkit and guards the configuration seam of your application.

## Packages

Envlock ships as three packages, all at version 0.1.0.

| Package | What it does | Dependencies |
|---|---|---|
| `@envlock/core` | Zero-dependency library for schema definition, validation, dotenv parsing, example rendering, and diffing | None |
| `@envlock/cli` | CLI tool (`envlock` binary) for checking, diffing, inspecting, and initializing contracts | `@envlock/core` |
| `@envlock/mcp` | MCP server (`envlock-mcp` binary) exposing contract tools to AI assistants | `@envlock/core`, `@modelcontextprotocol/sdk`, `zod` |

## Key concepts

### Schema definition

Use `defineEnv` to declare the variables your application needs. Each variable is described by a field builder from the `env` namespace.

```ts
import { defineEnv, env } from "@envlock/core";

export default defineEnv({
  PORT: env.port().default(3000).describe("HTTP listen port"),
  DATABASE_URL: env.url({ protocols: ["postgres:"] }).secret(),
  LOG_LEVEL: env.enum(["debug", "info", "warn", "error"]).default("info"),
});
```

The schema records declaration order, validates variable names, and freezes the result. See [Defining Schemas](/envlock/defining-schemas) for the full builder reference.

### Field builders

The `env` object provides ten builder factories:

`env.string()`, `env.number()`, `env.integer()`, `env.boolean()`, `env.port()`, `env.url()`, `env.enum()`, `env.json()`, `env.duration()`, `env.list()`

Each returns a required, non-secret field. Chain methods like `.optional()`, `.default()`, `.secret()`, `.describe()`, and `.example()` return new frozen fields with the requested modification.

### Validation

`loadEnv` validates a source record (defaulting to `process.env`) against a schema and returns typed values or throws an `EnvValidationError`. For non-throwing validation, `parseEnv` returns a result object with an `ok` flag and an issues array.

```ts
import { loadEnv } from "@envlock/core";
import schema from "./envlock.config.mjs";

const config = loadEnv(schema);
// config is fully typed based on the schema
```

See [Validation](/envlock/validation) for details on issue codes, strict mode, and error formatting.

### Secrets masking

Fields marked with `.secret()` are masked as `"••••••"` in validation issues, rendered examples, schema descriptions, and the `redact` helper. Secret values never leak through Envlock outputs.

### Dotenv parsing

The `parseDotenv` function parses `.env` file content into a plain record, supporting quoted values, multiline strings, comments, and `export` prefixes. `formatDotenv` serializes a record back into dotenv format. See [Dotenv](/envlock/dotenv) for the full specification.

### Diffing and examples

`diffEnv` compares a dotenv file against the contract and reports missing, unknown, and invalid variables. `renderExample` generates a `.env.example` file from the schema with type annotations, descriptions, and placeholder values.

## Design decisions

- **Empty string equals absent.** `KEY=` counts as unset, so placeholder env files fail validation instead of silently passing.
- **Declaration order preserved.** All output follows the order variables appear in `defineEnv`.
- **Immutable fields.** Every chain method returns a new frozen object. Sharing fields between schemas is safe.
- **Secrets masked everywhere.** Issues, examples, descriptions, and redacted output all mask secret values.
- **No process.env mutation.** `parseDotenv` returns a plain record. `loadEnv` accepts any record. Your `process.env` is never written to.
- **ESM only.** All three packages use `"type": "module"`.

## Installation

```sh
# Runtime validation (zero dependencies)
npm install @envlock/core

# CLI for local checks and CI
npm install -D @envlock/cli

# MCP server (optional, for AI tool integration)
npm install -D @envlock/mcp
```

## Requirements

- Node.js >= 22
- ESM only (all packages are `"type": "module"`)

## Version and license

All three packages are at version 0.1.0, released under the MIT license.

## Next steps

#### [Defining Schemas](/envlock/defining-schemas)

    Learn every field builder, chain method, and type helper.

#### [Validation](/envlock/validation)

    Understand parseEnv, loadEnv, issue codes, and strict mode.

#### [CLI](/envlock/cli)

    Check, diff, inspect, and initialize contracts from the command line.

#### [Dotenv](/envlock/dotenv)

    Parse and format dotenv files with full quoting and escaping support.

#### [MCP Server](/envlock/mcp)

    Expose contract tools to AI assistants via the Model Context Protocol.