From b70fba5b09b274c8a751d3c579fc31fe847f497f Mon Sep 17 00:00:00 2001 From: Jack Wotherspoon Date: Mon, 7 Jul 2025 01:13:13 -0400 Subject: [PATCH] fix: respect env variables in .env for settings.json variable substitution (#3416) --- packages/cli/src/config/auth.ts | 2 +- packages/cli/src/config/config.ts | 43 ----------------------------- packages/cli/src/config/settings.ts | 39 ++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 44 deletions(-) diff --git a/packages/cli/src/config/auth.ts b/packages/cli/src/config/auth.ts index 6142368c..439bd36b 100644 --- a/packages/cli/src/config/auth.ts +++ b/packages/cli/src/config/auth.ts @@ -5,7 +5,7 @@ */ import { AuthType } from '@google/gemini-cli-core'; -import { loadEnvironment } from './config.js'; +import { loadEnvironment } from './settings.js'; export const validateAuthMethod = (authMethod: string): string | null => { loadEnvironment(); diff --git a/packages/cli/src/config/config.ts b/packages/cli/src/config/config.ts index cecf904b..7eed1db7 100644 --- a/packages/cli/src/config/config.ts +++ b/packages/cli/src/config/config.ts @@ -13,7 +13,6 @@ import { setGeminiMdFilename as setServerGeminiMdFilename, getCurrentGeminiMdFilename, ApprovalMode, - GEMINI_CONFIG_DIR as GEMINI_DIR, DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_EMBEDDING_MODEL, FileDiscoveryService, @@ -23,10 +22,6 @@ import { Settings } from './settings.js'; import { Extension } from './extension.js'; import { getCliVersion } from '../utils/version.js'; -import * as dotenv from 'dotenv'; -import * as fs from 'node:fs'; -import * as path from 'node:path'; -import * as os from 'node:os'; import { loadSandboxConfig } from './sandboxConfig.js'; // Simple console logger for now - replace with actual logger if available @@ -166,8 +161,6 @@ export async function loadCliConfig( extensions: Extension[], sessionId: string, ): Promise { - loadEnvironment(); - const argv = await parseArguments(); const debugMode = argv.debug || false; @@ -279,39 +272,3 @@ function mergeExcludeTools( } return [...allExcludeTools]; } - -function findEnvFile(startDir: string): string | null { - let currentDir = path.resolve(startDir); - while (true) { - // prefer gemini-specific .env under GEMINI_DIR - const geminiEnvPath = path.join(currentDir, GEMINI_DIR, '.env'); - if (fs.existsSync(geminiEnvPath)) { - return geminiEnvPath; - } - const envPath = path.join(currentDir, '.env'); - if (fs.existsSync(envPath)) { - return envPath; - } - const parentDir = path.dirname(currentDir); - if (parentDir === currentDir || !parentDir) { - // check .env under home as fallback, again preferring gemini-specific .env - const homeGeminiEnvPath = path.join(os.homedir(), GEMINI_DIR, '.env'); - if (fs.existsSync(homeGeminiEnvPath)) { - return homeGeminiEnvPath; - } - const homeEnvPath = path.join(os.homedir(), '.env'); - if (fs.existsSync(homeEnvPath)) { - return homeEnvPath; - } - return null; - } - currentDir = parentDir; - } -} - -export function loadEnvironment(): void { - const envFilePath = findEnvFile(process.cwd()); - if (envFilePath) { - dotenv.config({ path: envFilePath, quiet: true }); - } -} diff --git a/packages/cli/src/config/settings.ts b/packages/cli/src/config/settings.ts index 28010a7a..93f042aa 100644 --- a/packages/cli/src/config/settings.ts +++ b/packages/cli/src/config/settings.ts @@ -7,8 +7,10 @@ import * as fs from 'fs'; import * as path from 'path'; import { homedir } from 'os'; +import * as dotenv from 'dotenv'; import { MCPServerConfig, + GEMINI_CONFIG_DIR as GEMINI_DIR, getErrorMessage, BugCommandSettings, TelemetrySettings, @@ -172,11 +174,48 @@ function resolveEnvVarsInObject(obj: T): T { return obj; } +function findEnvFile(startDir: string): string | null { + let currentDir = path.resolve(startDir); + while (true) { + // prefer gemini-specific .env under GEMINI_DIR + const geminiEnvPath = path.join(currentDir, GEMINI_DIR, '.env'); + if (fs.existsSync(geminiEnvPath)) { + return geminiEnvPath; + } + const envPath = path.join(currentDir, '.env'); + if (fs.existsSync(envPath)) { + return envPath; + } + const parentDir = path.dirname(currentDir); + if (parentDir === currentDir || !parentDir) { + // check .env under home as fallback, again preferring gemini-specific .env + const homeGeminiEnvPath = path.join(homedir(), GEMINI_DIR, '.env'); + if (fs.existsSync(homeGeminiEnvPath)) { + return homeGeminiEnvPath; + } + const homeEnvPath = path.join(homedir(), '.env'); + if (fs.existsSync(homeEnvPath)) { + return homeEnvPath; + } + return null; + } + currentDir = parentDir; + } +} + +export function loadEnvironment(): void { + const envFilePath = findEnvFile(process.cwd()); + if (envFilePath) { + dotenv.config({ path: envFilePath, quiet: true }); + } +} + /** * Loads settings from user and workspace directories. * Project settings override user settings. */ export function loadSettings(workspaceDir: string): LoadedSettings { + loadEnvironment(); let userSettings: Settings = {}; let workspaceSettings: Settings = {}; const settingsErrors: SettingsError[] = [];