Add system-wide settings config for administrators (#3498)

Co-authored-by: Jack Wotherspoon <jackwoth@google.com>
This commit is contained in:
christine betts
2025-07-09 21:16:42 +00:00
committed by GitHub
parent 063481faa4
commit da50a1eefb
9 changed files with 292 additions and 31 deletions

View File

@@ -6,7 +6,7 @@
import * as fs from 'fs';
import * as path from 'path';
import { homedir } from 'os';
import { homedir, platform } from 'os';
import * as dotenv from 'dotenv';
import {
MCPServerConfig,
@@ -24,9 +24,22 @@ export const SETTINGS_DIRECTORY_NAME = '.gemini';
export const USER_SETTINGS_DIR = path.join(homedir(), SETTINGS_DIRECTORY_NAME);
export const USER_SETTINGS_PATH = path.join(USER_SETTINGS_DIR, 'settings.json');
function getSystemSettingsPath(): string {
if (platform() === 'darwin') {
return '/Library/Application Support/GeminiCli/settings.json';
} else if (platform() === 'win32') {
return 'C:\\ProgramData\\gemini-cli\\settings.json';
} else {
return '/etc/gemini-cli/settings.json';
}
}
export const SYSTEM_SETTINGS_PATH = getSystemSettingsPath();
export enum SettingScope {
User = 'User',
Workspace = 'Workspace',
System = 'System',
}
export interface CheckpointingSettings {
@@ -81,16 +94,19 @@ export interface SettingsFile {
}
export class LoadedSettings {
constructor(
system: SettingsFile,
user: SettingsFile,
workspace: SettingsFile,
errors: SettingsError[],
) {
this.system = system;
this.user = user;
this.workspace = workspace;
this.errors = errors;
this._merged = this.computeMergedSettings();
}
readonly system: SettingsFile;
readonly user: SettingsFile;
readonly workspace: SettingsFile;
readonly errors: SettingsError[];
@@ -105,6 +121,7 @@ export class LoadedSettings {
return {
...this.user.settings,
...this.workspace.settings,
...this.system.settings,
};
}
@@ -114,6 +131,8 @@ export class LoadedSettings {
return this.user;
case SettingScope.Workspace:
return this.workspace;
case SettingScope.System:
return this.system;
default:
throw new Error(`Invalid scope: ${scope}`);
}
@@ -243,10 +262,27 @@ export function loadEnvironment(): void {
*/
export function loadSettings(workspaceDir: string): LoadedSettings {
loadEnvironment();
let systemSettings: Settings = {};
let userSettings: Settings = {};
let workspaceSettings: Settings = {};
const settingsErrors: SettingsError[] = [];
// Load system settings
try {
if (fs.existsSync(SYSTEM_SETTINGS_PATH)) {
const systemContent = fs.readFileSync(SYSTEM_SETTINGS_PATH, 'utf-8');
const parsedSystemSettings = JSON.parse(
stripJsonComments(systemContent),
) as Settings;
systemSettings = resolveEnvVarsInObject(parsedSystemSettings);
}
} catch (error: unknown) {
settingsErrors.push({
message: getErrorMessage(error),
path: SYSTEM_SETTINGS_PATH,
});
}
// Load user settings
try {
if (fs.existsSync(USER_SETTINGS_PATH)) {
@@ -300,6 +336,10 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
}
return new LoadedSettings(
{
path: SYSTEM_SETTINGS_PATH,
settings: systemSettings,
},
{
path: USER_SETTINGS_PATH,
settings: userSettings,