Load environment variables for the CLI
Make .env values available before Runlane constructs your application runtime.
The Runlane CLI does not load .env files itself. It imports your runlane.config.ts, then uses the runtime exported by that configuration. Your application must load environment files before it reads process.env or constructs the runtime.
When the runtime owns environment loading, the process follows this path:
runlane dev
→ CLI imports runlane.config.ts
→ config imports src/runlane.ts
→ runtime loads .env.local and .env
→ runtime reads the loaded environment variablesRun the command from your application root. The CLI searches that directory for runlane.config.ts, and dotenv resolves relative file paths from that directory.
Load from the runtime module
Prefer this when application processes, workers, and the CLI should load the same files. Load them before reading environment variables or creating the runtime:
import { env as processEnvironment } from 'node:process'
import { createRunlane, queue } from '@runlane/core'
import { createLocalLane } from '@runlane/lane-local'
import { config as loadDotenv } from 'dotenv'
loadDotenv({ path: ['.env.local', '.env'], quiet: true })
const environmentName = processEnvironment.RUNLANE_ENVIRONMENT
if (environmentName === undefined) throw new Error('RUNLANE_ENVIRONMENT is required')
const defaultQueue = queue({ name: 'default', default: true })
export const runlane = createRunlane({
environment: { name: environmentName },
lane: createLocalLane(),
queues: [defaultQueue],
tasks: {},
})This example gives existing process environment variables the highest priority, followed by .env.local, then .env. That lets deployment platforms inject values without local files replacing them.
Your runlane.config.ts can then export the runtime normally:
import the runtime from src/runlane.ts
export it as the Runlane CLI runtimeLoad from the CLI config
Load files in runlane.config.ts when environment loading should apply only to CLI commands. Import the runtime after dotenv finishes so the runtime cannot read process.env too early:
import { type RunlaneCliConfig } from '@runlane/cli'
import { config as loadDotenv } from 'dotenv'
loadDotenv({ path: ['.env.local', '.env'], quiet: true })
export default {
runtime: async () => (await import('./src/runlane.js')).runlane,
} satisfies RunlaneCliConfigThe dynamic import is intentional. A normal static runtime import is evaluated before the body of runlane.config.ts, which would make the dotenv call too late for modules that read environment variables during import.
In this setup, application and worker entrypoints must load their own environment through their framework, deployment platform, or application bootstrap.
Use a different working directory
If you run the CLI outside the application root, pass the config path explicitly and resolve environment-file paths yourself:
npm exec -- runlane --config packages/api/runlane.config.ts devThe config path does not change the process working directory. Relative .env paths still resolve from the directory where you started the command.