summaryrefslogtreecommitdiff
path: root/packages/cli/src/config/settings.ts
diff options
context:
space:
mode:
authorchristine betts <[email protected]>2025-07-09 21:16:42 +0000
committerGitHub <[email protected]>2025-07-09 21:16:42 +0000
commitda50a1eefbd0751aaf137882595d500e6b6b4179 (patch)
tree4a07182ca01f20074a5544db5caf5a198cabae6c /packages/cli/src/config/settings.ts
parent063481faa4b1c86868689580ff0fbd8cb04141e3 (diff)
Add system-wide settings config for administrators (#3498)
Co-authored-by: Jack Wotherspoon <[email protected]>
Diffstat (limited to 'packages/cli/src/config/settings.ts')
-rw-r--r--packages/cli/src/config/settings.ts42
1 files changed, 41 insertions, 1 deletions
diff --git a/packages/cli/src/config/settings.ts b/packages/cli/src/config/settings.ts
index c2d03167..133701f5 100644
--- a/packages/cli/src/config/settings.ts
+++ b/packages/cli/src/config/settings.ts
@@ -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)) {
@@ -301,6 +337,10 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
return new LoadedSettings(
{
+ path: SYSTEM_SETTINGS_PATH,
+ settings: systemSettings,
+ },
+ {
path: USER_SETTINGS_PATH,
settings: userSettings,
},