@concourse/env gives apps and packages an explicit environment contract. It validates values without loading files or exposing secrets in errors.
Read the repository development environment guide. Root Dotenvx commands load files before Turbo starts a task.
Turbo tracks, filters, and hashes declared environment values. Turbo does not load .env files or prove that a value is valid.
src/ contains the reusable environment contract and its unit tests. This package has no executable package commands, so it has no scripts/ directory.
@concourse/env as a workspace dependency.env:check script that calls runEnvironmentCheck.turbo.json.import { defineEnvironment } from "@concourse/env";
import { z } from "zod";
const schema = z.object({
WORKER_TOKEN: z.string().min(1),
});
export const workerEnvironment = defineEnvironment({
name: "@concourse/worker",
loadWith: "pnpm worker:dev",
validate(environment) {
return schema.parse(environment);
},
});Use definition.parse() inside the application. Use runEnvironmentCheck(definition) in the task preflight script.
Add a second script such as env:test:check when a task uses a different profile. Give its error the exact root command that loads that profile.
Keep production-only requirements in the consumer validator. For example, the app requires HTTPS and a trusted proxy header only in production.
Do not make a shared package search parent directories or infer the repository root. Pass explicit, validated options to reusable code.
Package-specific task definitions replace generic task fields. Repeat every required dependency, input, output, and environment field in an override.
Put behavior-changing values in env so Turbo hashes them. Put execution-mechanism values in passThroughEnv only when they do not change the result.
Do not declare secrets on unrelated shared package tasks. This reduces exposure and avoids unnecessary cache misses.
State the missing variable name and the command that loads it. Never include the current value in an error.
Validate related values together. For example, require the Resend key and test recipient when
EMAIL_PROVIDER=resend.
| Command | Purpose |
|---|---|
pnpm --filter @concourse/env check-types | Run the package type check |
pnpm --filter @concourse/env test | Run environment contract tests |
pnpm verify | Run every package environment preflight in its real task graph |
@concourse/env gives apps and packages an explicit environment contract. It validates values without loading files or exposing secrets in errors.
Read the repository development environment guide. Root Dotenvx commands load files before Turbo starts a task.
Turbo tracks, filters, and hashes declared environment values. Turbo does not load .env files or prove that a value is valid.
src/ contains the reusable environment contract and its unit tests. This package has no executable package commands, so it has no scripts/ directory.
@concourse/env as a workspace dependency.env:check script that calls runEnvironmentCheck.turbo.json.import { defineEnvironment } from "@concourse/env";
import { z } from "zod";
const schema = z.object({
WORKER_TOKEN: z.string().min(1),
});
export const workerEnvironment = defineEnvironment({
name: "@concourse/worker",
loadWith: "pnpm worker:dev",
validate(environment) {
return schema.parse(environment);
},
});Use definition.parse() inside the application. Use runEnvironmentCheck(definition) in the task preflight script.
Add a second script such as env:test:check when a task uses a different profile. Give its error the exact root command that loads that profile.
Keep production-only requirements in the consumer validator. For example, the app requires HTTPS and a trusted proxy header only in production.
Do not make a shared package search parent directories or infer the repository root. Pass explicit, validated options to reusable code.
Package-specific task definitions replace generic task fields. Repeat every required dependency, input, output, and environment field in an override.
Put behavior-changing values in env so Turbo hashes them. Put execution-mechanism values in passThroughEnv only when they do not change the result.
Do not declare secrets on unrelated shared package tasks. This reduces exposure and avoids unnecessary cache misses.
State the missing variable name and the command that loads it. Never include the current value in an error.
Validate related values together. For example, require the Resend key and test recipient when
EMAIL_PROVIDER=resend.
| Command | Purpose |
|---|---|
pnpm --filter @concourse/env check-types | Run the package type check |
pnpm --filter @concourse/env test | Run environment contract tests |
pnpm verify | Run every package environment preflight in its real task graph |