Skip to content

Builtin variables

Varlock provides a set of builtin VARLOCK_* variables that are automatically populated with information about the current CI/deploy platform, git branch, commit, and inferred deployment environment. They are entirely opt-in: they only exist in your schema when you reference them.

Builtin variables are activated when you reference them via $VARLOCK_* in a value expression:

.env.schema
# @currentEnv=$VARLOCK_ENV
# ---
BUILD_TAG="build-$VARLOCK_COMMIT_SHA_SHORT"
DB_URL=if(
eq($VARLOCK_ENV, development),
postgres://localhost/myapp,
postgres://${VARLOCK_ENV}-db.example.com/myapp
)

If you want to include a builtin variable in your resolved env without referencing it from another item, define it with an empty value and varlock will populate it automatically:

.env.schema
VARLOCK_BRANCH=
VARLOCK_COMMIT_SHA_SHORT=

You can also use VARLOCK_ENV as your environment flag with @currentEnv, which means you don’t need to create your own APP_ENV variable. Varlock will auto-detect the environment for you.

Type: string, one of development, preview, staging, production, test

The inferred deployment environment. Detection follows this priority:

  1. Test environment: detected from NODE_ENV=test, VITEST, JEST_WORKER_ID, or VITEST_POOL_ID
  2. Platform-provided: uses the platform’s own environment concept (e.g., Vercel’s VERCEL_ENV, Netlify’s CONTEXT)
  3. Branch inference: in CI, infers from branch name: main/master/production/prodproduction, staging/stage/develop/devstaging, qa/testtest, anything else → preview
  4. CI fallback: if in CI but no branch info is available, defaults to preview
  5. Local fallback: if not in CI, defaults to development
.env.schema
# @currentEnv=$VARLOCK_ENV
# ---
DB_HOST=if(forEnv(production), "prod-db.example.com", "localhost")
DB_NAME=myapp
DB_URL="postgres://$DB_HOST/$DB_NAME"

If you already have your own flag and want to keep the name, derive its value from $VARLOCK_ENV instead of setting it yourself at runtime:

.env.schema
# @currentEnv=$APP_ENV
# ---
# @type=enum(development, preview, staging, production, test)
APP_ENV=$VARLOCK_ENV

An explicit APP_ENV=staging passed into the process still takes precedence, and test runs are detected without passing anything.

Your enum needs to cover every value $VARLOCK_ENV can produce. If your environments do not line up, use remap() to translate them. Unmatched values pass through unchanged, so you only list what differs:

.env.schema
# @currentEnv=$APP_ENV
# ---
# @type=enum(development, staging, production, test)
APP_ENV=remap($VARLOCK_ENV, preview, staging)

We do not recommend using NODE_ENV itself as your environment flag; see @currentEnv.

Test detection reads NODE_ENV=test, VITEST, VITEST_POOL_ID, and JEST_WORKER_ID. Which of those exist, and where, depends on your runner:

RunnerSignals available
Vitest, parent and workersVITEST and NODE_ENV=test (workers also get VITEST_POOL_ID)
Jest, worker-scoped code (setupFiles, setupFilesAfterEnv, test files, app code under test)JEST_WORKER_ID and NODE_ENV=test
Jest, parent-scoped code (jest.config.*, globalSetup)NODE_ENV=test only
bun test, AVANODE_ENV=test only
node --test, Mochanone

Both Vitest and Jest set their signals during their own startup, before config files are loaded, so importing varlock/auto-load from a config file, a setup file, or app code under test is late enough to see them. Verified against Vitest 4.1.5 and Jest 30.5.1; if you rely on this, confirm it for the runner and version you use.

Type: boolean

Whether the current process is running in a CI environment.

Type: string | undefined

The current git branch name. In CI environments, sourced from the platform’s environment variables. When running locally (non-CI), auto-detected via git branch --show-current. Undefined if the branch cannot be determined (e.g., detached HEAD state, no git repo, or platform doesn’t expose branch info).

Type: string | undefined

The pull/merge request number, if the current build is for a PR. Undefined otherwise.

Type: string | undefined

The full git commit SHA.

Type: string | undefined

The short (7-character) git commit SHA.

Type: string | undefined

The name of the detected CI/deploy platform (e.g., "GitHub Actions", "Vercel", "Netlify CI").

Type: url | undefined

A URL linking to the current build or deploy in the CI platform’s UI.

Type: string | undefined

The repository name in owner/repo format.

Type: string | undefined

The current JS runtime, one of node, bun, deno, workerd, fastly, netlify, edge-light, or browser. Detected from ambient globals (not environment variables), so it reflects the actual process regardless of which CI/deploy platform is detected.

Type: string | undefined

The current OS platform: darwin, win32, or linux. Undefined in environments without a process.platform (e.g., browsers, Cloudflare Workers).

Detection is built-in for these platforms (no configuration required):

  • GitHub Actions
  • GitLab CI
  • Vercel
  • Netlify
  • Cloudflare Pages / Workers
  • AWS Amplify / CodeBuild
  • Azure Pipelines
  • Bitbucket Pipelines
  • Buildkite
  • CircleCI
  • Jenkins
  • Railway
  • Render
  • Travis CI
  • Google Cloud Run
  • Deno Deploy
  • Zeabur
  • Firebase App Hosting
  • and many more

Interactive dev sandboxes (CodeSandbox, StackBlitz, GitHub Codespaces, Gitpod, Replit) are also detected and reported via VARLOCK_PLATFORM, but VARLOCK_IS_CI is false for these since they aren’t a CI pipeline.

Not all platforms expose all fields. For example, some may not provide branch name or PR number.

CI/deploy platform detection is powered by @varlock/ci-env-info, which can also be used as a standalone package.