How OpenClaude Loads Provider Environment Files at Startup
OpenClaude loads provider environment files by first reading the global .env with dotenv, then extracting and sanitizing provider-specific variables in providerConfig.ts, and caching the result for the CLI session.
The provider configuration system in OpenClaude controls how each model integration receives its credentials, endpoints, and settings. According to the Gitlawb/openclaude source code, this configuration is constructed from environment files through a three-stage pipeline that ensures security and consistency.
Step 1: Load the Global .env File
The bootstrap process begins in src/bootstrap/state.ts, where the CLI calls the dotenv package to populate process.env.
// src/bootstrap/state.ts
import { config as loadDotEnv } from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const projectRoot = join(__dirname, '..', '..');
loadDotEnv({ path: `${projectRoot}/.env` });
This single call reads the repository-root .env file and injects all key-value pairs into the Node.js environment. The path resolution ensures the file is loaded relative to the project structure, not the current working directory.
Step 2: Merge Provider-Specific Variables
After the global file loads, the provider-configuration module at src/services/api/providerConfig.ts scans process.env for variables matching each provider's naming convention.
// src/services/api/providerConfig.ts
export function resolveProviderRequest(
provider: ProviderId,
env: Record<string, string | undefined> = process.env,
): ResolvedProviderRequest {
const vars = pickProviderEnvVars(provider, env);
// …construct a ResolvedProviderRequest from `vars`
}
The helper pickProviderEnvVars performs two critical sanitization tasks:
- Filters placeholder sentinels — Removes entries containing
${that may leak from dotenv templates or Windows-style variable expansions - Normalizes malformed values — Strips literal
${VAR}strings that can appear in certain shell environments
Supported provider variables follow predictable patterns: OPENAI_API_KEY, ANTHROPIC_API_KEY, CLAUDE_CODE_GEMINI_PROJECT_ID, and similar prefixed keys.
Step 3: Cache the Resolved Configuration
To prevent redundant environment reads and guarantee consistency, src/bootstrap/state.ts implements a singleton-style cache:
// src/bootstrap/state.ts (excerpt)
let cachedProviderRequest: ResolvedProviderRequest | undefined;
export function getProviderRequest(provider: ProviderId) {
if (!cachedProviderRequest) {
cachedProviderRequest = resolveProviderRequest(provider);
}
return cachedProviderRequest;
}
The first call to getProviderRequest triggers resolution; subsequent calls return the identical cached object. This ensures every component receives the same fully-resolved configuration throughout the CLI run.
Key Files in the Loading Pipeline
| File | Responsibility |
|---|---|
src/bootstrap/state.ts |
Entry point; loads global .env via dotenv.config() and caches resolved requests |
src/services/api/providerConfig.ts |
Parses provider-specific variables, removes template sentinels, builds ResolvedProviderRequest |
src/utils/providerProfiles.ts |
Utilities for cleaning template/dotenv sentinels post-load |
src/utils/providerFlag.ts |
Documents sentinel filtering logic for endpoints |
Security Considerations in Provider Env Loading
The OpenClaude provider environment loading system implements defensive filtering at multiple layers:
- Sentinel detection — Any value containing
${is treated as a template placeholder and discarded - Strict key matching — Only variables matching known provider prefixes are extracted
- Single-read caching — Environment is never re-parsed after initial load, preventing mid-session tampering
These safeguards prevent accidental credential leakage from incomplete .env configurations or shell environment pollution.
Summary
- Global loading —
src/bootstrap/state.tscallsdotenv.config()to read the repository-root.envfile - Provider extraction —
src/services/api/providerConfig.tsfiltersprocess.envfor provider-specific keys and strips template sentinels - Request caching — Resolved configurations are cached in bootstrap state to ensure consistency across the CLI session
- Sentinel removal — Placeholder patterns like
${VAR}are automatically discarded to prevent credential leaks
Frequently Asked Questions
Where does OpenClaude look for the .env file?
OpenClaude resolves the .env path relative to src/bootstrap/state.ts's location, traversing up two directory levels to reach the repository root. This ensures the file is found regardless of the working directory from which the CLI is invoked.
What happens if a provider environment variable contains a template placeholder?
The pickProviderEnvVars helper in src/services/api/providerConfig.ts detects values containing ${ and deletes them from the configuration. This prevents accidental use of unexpanded shell variables or copy-pasted template strings as actual credentials.
Why does OpenClaude cache the provider configuration?
Caching in getProviderRequest() guarantees that all components reference identical credential sets throughout a CLI session. Without caching, environment mutations or filesystem changes could cause inconsistent behavior between different model integrations.
Which provider environment variable prefixes are supported?
As implemented in src/services/api/providerConfig.ts, OpenClaude recognizes provider-prefixed keys including OPENAI_*, ANTHROPIC_*, and CLAUDE_CODE_GEMINI_*. The system uses dynamic key construction based on the ProviderId enum to match variables to their respective integrations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →