feat(ui): reduce home directory warning noise and add opt-out setting (#16229)

This commit is contained in:
N. Taylor Mullen
2026-01-09 11:56:22 -08:00
committed by GitHub
parent ca48661423
commit 14f0cb4538
6 changed files with 95 additions and 12 deletions

View File

@@ -184,6 +184,12 @@ their corresponding top-level category object in your `settings.json` file.
title
- **Default:** `false`
- **`ui.showHomeDirectoryWarning`** (boolean):
- **Description:** Show a warning when running Gemini CLI in the home
directory.
- **Default:** `true`
- **Requires restart:** Yes
- **`ui.hideTips`** (boolean):
- **Description:** Hide helpful tips in the UI
- **Default:** `false`

View File

@@ -384,6 +384,16 @@ const SETTINGS_SCHEMA = {
'Show Gemini CLI status and thoughts in the terminal window title',
showInDialog: true,
},
showHomeDirectoryWarning: {
type: 'boolean',
label: 'Show Home Directory Warning',
category: 'UI',
requiresRestart: true,
default: true,
description:
'Show a warning when running Gemini CLI in the home directory.',
showInDialog: true,
},
hideTips: {
type: 'boolean',
label: 'Hide Tips',

View File

@@ -588,7 +588,7 @@ export async function main() {
let input = config.getQuestion();
const startupWarnings = [
...(await getStartupWarnings()),
...(await getUserStartupWarnings()),
...(await getUserStartupWarnings(settings.merged)),
];
// Handle --resume flag

View File

@@ -9,6 +9,10 @@ import { getUserStartupWarnings } from './userStartupWarnings.js';
import * as os from 'node:os';
import fs from 'node:fs/promises';
import path from 'node:path';
import {
isFolderTrustEnabled,
isWorkspaceTrusted,
} from '../config/trustedFolders.js';
// Mock os.homedir to control the home directory in tests
vi.mock('os', async (importOriginal) => {
@@ -28,6 +32,11 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
};
});
vi.mock('../config/trustedFolders.js', () => ({
isFolderTrustEnabled: vi.fn(),
isWorkspaceTrusted: vi.fn(),
}));
describe('getUserStartupWarnings', () => {
let testRootDir: string;
let homeDir: string;
@@ -37,6 +46,11 @@ describe('getUserStartupWarnings', () => {
homeDir = path.join(testRootDir, 'home');
await fs.mkdir(homeDir, { recursive: true });
vi.mocked(os.homedir).mockReturnValue(homeDir);
vi.mocked(isFolderTrustEnabled).mockReturnValue(false);
vi.mocked(isWorkspaceTrusted).mockReturnValue({
isTrusted: false,
source: undefined,
});
});
afterEach(async () => {
@@ -46,16 +60,44 @@ describe('getUserStartupWarnings', () => {
describe('home directory check', () => {
it('should return a warning when running in home directory', async () => {
const warnings = await getUserStartupWarnings(homeDir);
const warnings = await getUserStartupWarnings({}, homeDir);
expect(warnings).toContainEqual(
expect.stringContaining('home directory'),
expect.stringContaining(
'Warning you are running Gemini CLI in your home directory',
),
);
expect(warnings).toContainEqual(
expect.stringContaining('warning can be disabled in /settings'),
);
});
it('should not return a warning when running in a project directory', async () => {
const projectDir = path.join(testRootDir, 'project');
await fs.mkdir(projectDir);
const warnings = await getUserStartupWarnings(projectDir);
const warnings = await getUserStartupWarnings({}, projectDir);
expect(warnings).not.toContainEqual(
expect.stringContaining('home directory'),
);
});
it('should not return a warning when showHomeDirectoryWarning is false', async () => {
const warnings = await getUserStartupWarnings(
{ ui: { showHomeDirectoryWarning: false } },
homeDir,
);
expect(warnings).not.toContainEqual(
expect.stringContaining('home directory'),
);
});
it('should not return a warning when folder trust is enabled and workspace is trusted', async () => {
vi.mocked(isFolderTrustEnabled).mockReturnValue(true);
vi.mocked(isWorkspaceTrusted).mockReturnValue({
isTrusted: true,
source: 'file',
});
const warnings = await getUserStartupWarnings({}, homeDir);
expect(warnings).not.toContainEqual(
expect.stringContaining('home directory'),
);
@@ -65,7 +107,7 @@ describe('getUserStartupWarnings', () => {
describe('root directory check', () => {
it('should return a warning when running in a root directory', async () => {
const rootDir = path.parse(testRootDir).root;
const warnings = await getUserStartupWarnings(rootDir);
const warnings = await getUserStartupWarnings({}, rootDir);
expect(warnings).toContainEqual(
expect.stringContaining('root directory'),
);
@@ -77,7 +119,7 @@ describe('getUserStartupWarnings', () => {
it('should not return a warning when running in a non-root directory', async () => {
const projectDir = path.join(testRootDir, 'project');
await fs.mkdir(projectDir);
const warnings = await getUserStartupWarnings(projectDir);
const warnings = await getUserStartupWarnings({}, projectDir);
expect(warnings).not.toContainEqual(
expect.stringContaining('root directory'),
);
@@ -87,7 +129,7 @@ describe('getUserStartupWarnings', () => {
describe('error handling', () => {
it('should handle errors when checking directory', async () => {
const nonExistentPath = path.join(testRootDir, 'non-existent');
const warnings = await getUserStartupWarnings(nonExistentPath);
const warnings = await getUserStartupWarnings({}, nonExistentPath);
const expectedWarning =
'Could not verify the current directory due to a file system error.';
expect(warnings).toEqual([expectedWarning, expectedWarning]);

View File

@@ -8,16 +8,25 @@ import fs from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
import { homedir } from '@google/gemini-cli-core';
import type { Settings } from '../config/settingsSchema.js';
import {
isFolderTrustEnabled,
isWorkspaceTrusted,
} from '../config/trustedFolders.js';
type WarningCheck = {
id: string;
check: (workspaceRoot: string) => Promise<string | null>;
check: (workspaceRoot: string, settings: Settings) => Promise<string | null>;
};
// Individual warning checks
const homeDirectoryCheck: WarningCheck = {
id: 'home-directory',
check: async (workspaceRoot: string) => {
check: async (workspaceRoot: string, settings: Settings) => {
if (settings.ui?.showHomeDirectoryWarning === false) {
return null;
}
try {
const [workspaceRealPath, homeRealPath] = await Promise.all([
fs.realpath(workspaceRoot),
@@ -25,7 +34,15 @@ const homeDirectoryCheck: WarningCheck = {
]);
if (workspaceRealPath === homeRealPath) {
return 'You are running Gemini CLI in your home directory. It is recommended to run in a project-specific directory.';
// If folder trust is enabled and the user trusts the home directory, don't show the warning.
if (
isFolderTrustEnabled(settings) &&
isWorkspaceTrusted(settings).isTrusted
) {
return null;
}
return 'Warning you are running Gemini CLI in your home directory.\nThis warning can be disabled in /settings';
}
return null;
} catch (_err: unknown) {
@@ -36,7 +53,7 @@ const homeDirectoryCheck: WarningCheck = {
const rootDirectoryCheck: WarningCheck = {
id: 'root-directory',
check: async (workspaceRoot: string) => {
check: async (workspaceRoot: string, _settings: Settings) => {
try {
const workspaceRealPath = await fs.realpath(workspaceRoot);
const errorMessage =
@@ -61,10 +78,11 @@ const WARNING_CHECKS: readonly WarningCheck[] = [
];
export async function getUserStartupWarnings(
settings: Settings,
workspaceRoot: string = process.cwd(),
): Promise<string[]> {
const results = await Promise.all(
WARNING_CHECKS.map((check) => check.check(workspaceRoot)),
WARNING_CHECKS.map((check) => check.check(workspaceRoot, settings)),
);
return results.filter((msg) => msg !== null);
}

View File

@@ -194,6 +194,13 @@
"default": false,
"type": "boolean"
},
"showHomeDirectoryWarning": {
"title": "Show Home Directory Warning",
"description": "Show a warning when running Gemini CLI in the home directory.",
"markdownDescription": "Show a warning when running Gemini CLI in the home directory.\n\n- Category: `UI`\n- Requires restart: `yes`\n- Default: `true`",
"default": true,
"type": "boolean"
},
"hideTips": {
"title": "Hide Tips",
"description": "Hide helpful tips in the UI",