From 0996d91f0b4a0befe3553016518fd40898699f0a Mon Sep 17 00:00:00 2001 From: Yuki Okita Date: Mon, 21 Jul 2025 06:57:09 +0900 Subject: [PATCH] feat(cli): add warnings when gemini-cli is called in the root directory (#4542) Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: N. Taylor Mullen --- .../cli/src/utils/userStartupWarnings.test.ts | 57 +++++++++++++++++++ packages/cli/src/utils/userStartupWarnings.ts | 26 ++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/utils/userStartupWarnings.test.ts b/packages/cli/src/utils/userStartupWarnings.test.ts index 61053029..7c0e1264 100644 --- a/packages/cli/src/utils/userStartupWarnings.test.ts +++ b/packages/cli/src/utils/userStartupWarnings.test.ts @@ -8,6 +8,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { getUserStartupWarnings } from './userStartupWarnings.js'; import * as os from 'os'; import fs from 'fs/promises'; +import path from 'path'; vi.mock('os', () => ({ default: { homedir: vi.fn() }, @@ -71,4 +72,60 @@ describe('getUserStartupWarnings', () => { // // Tests for node version check would go here // // This shows how easy it is to add new test sections // }); + + describe('root directory check', () => { + it('should return a warning when running in root directory on Unix', async () => { + vi.mocked(fs.realpath) + .mockResolvedValueOnce('/') + .mockResolvedValueOnce(homeDir); + + const warnings = await getUserStartupWarnings('/'); + + expect(warnings).toContainEqual( + expect.stringContaining('root directory'), + ); + expect(warnings).toContainEqual( + expect.stringContaining('folder structure will be used'), + ); + }); + + it('should return a warning when running in root directory on Windows', async () => { + vi.mocked(fs.realpath) + .mockResolvedValueOnce('C:\\') + .mockResolvedValueOnce(homeDir); + + vi.spyOn(path, 'dirname').mockImplementation(path.win32.dirname); + + const warnings = await getUserStartupWarnings('C:\\'); + + expect(warnings).toContainEqual( + expect.stringContaining('root directory'), + ); + expect(warnings).toContainEqual( + expect.stringContaining('folder structure will be used'), + ); + }); + + it('should not return a warning when running in a non-root directory', async () => { + vi.mocked(fs.realpath) + .mockResolvedValueOnce('/some/project/path') + .mockResolvedValueOnce(homeDir); + + const warnings = await getUserStartupWarnings('/some/project/path'); + expect(warnings).not.toContainEqual( + expect.stringContaining('root directory'), + ); + }); + + it('should handle errors when checking root directory', async () => { + vi.mocked(fs.realpath) + .mockRejectedValueOnce(new Error('FS error')) + .mockResolvedValueOnce(homeDir); + + const warnings = await getUserStartupWarnings('/'); + expect(warnings).toContainEqual( + expect.stringContaining('Could not verify'), + ); + }); + }); }); diff --git a/packages/cli/src/utils/userStartupWarnings.ts b/packages/cli/src/utils/userStartupWarnings.ts index 3d76a6e1..8a740906 100644 --- a/packages/cli/src/utils/userStartupWarnings.ts +++ b/packages/cli/src/utils/userStartupWarnings.ts @@ -6,6 +6,7 @@ import fs from 'fs/promises'; import * as os from 'os'; +import path from 'path'; type WarningCheck = { id: string; @@ -32,8 +33,31 @@ const homeDirectoryCheck: WarningCheck = { }, }; +const rootDirectoryCheck: WarningCheck = { + id: 'root-directory', + check: async (workspaceRoot: string) => { + try { + const workspaceRealPath = await fs.realpath(workspaceRoot); + const errorMessage = + 'Warning: You are running Gemini CLI in the root directory. Your entire folder structure will be used for context. It is strongly recommended to run in a project-specific directory.'; + + // Check for Unix root directory + if (path.dirname(workspaceRealPath) === workspaceRealPath) { + return errorMessage; + } + + return null; + } catch (_err: unknown) { + return 'Could not verify the current directory due to a file system error.'; + } + }, +}; + // All warning checks -const WARNING_CHECKS: readonly WarningCheck[] = [homeDirectoryCheck]; +const WARNING_CHECKS: readonly WarningCheck[] = [ + homeDirectoryCheck, + rootDirectoryCheck, +]; export async function getUserStartupWarnings( workspaceRoot: string,