Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/cli/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ Arguments passed directly when running the CLI can override other configurations
- **`--proxy`**:
- Sets the proxy for the CLI.
- Example: `--proxy http://localhost:7890`.
- **`--include-directories <dir1,dir2,...>`**:
- Includes additional directories in the workspace for multi-directory support.
- Can be specified multiple times or as comma-separated values.
- 5 directories can be added at maximum.
- Example: `--include-directories /path/to/project1,/path/to/project2` or `--include-directories /path/to/project1 --include-directories /path/to/project2`
- **`--version`**:
- Displays the version of the CLI.

Expand Down
11 changes: 11 additions & 0 deletions packages/cli/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export interface CliArgs {
listExtensions: boolean | undefined;
ideMode: boolean | undefined;
proxy: string | undefined;
includeDirectories: string[] | undefined;
}

export async function parseArguments(): Promise<CliArgs> {
Expand Down Expand Up @@ -199,6 +200,15 @@ export async function parseArguments(): Promise<CliArgs> {
description:
'Proxy for gemini client, like schema://user:password@host:port',
})
.option('include-directories', {
type: 'array',
string: true,
description:
'Additional directories to include in the workspace (comma-separated or multiple --include-directories)',
coerce: (dirs: string[]) =>
// Handle comma-separated values
dirs.flatMap((dir) => dir.split(',').map((d) => d.trim())),
})
.version(await getCliVersion()) // This will enable the --version flag based on package.json
.alias('v', 'version')
.help()
Expand Down Expand Up @@ -366,6 +376,7 @@ export async function loadCliConfig(
embeddingModel: DEFAULT_GEMINI_EMBEDDING_MODEL,
sandbox: sandboxConfig,
targetDir: process.cwd(),
includeDirectories: argv.includeDirectories,
debugMode,
question: argv.promptInteractive || argv.prompt || '',
fullContext: argv.allFiles || argv.all_files || false,
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/gemini.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export async function main() {
process.exit(1);
}
}
await start_sandbox(sandboxConfig, memoryArgs);
await start_sandbox(sandboxConfig, memoryArgs, config);
process.exit(0);
} else {
// Not in a sandbox and not entering one, so relaunch with additional
Expand Down
10 changes: 10 additions & 0 deletions packages/cli/src/ui/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
getSessionId: vi.fn(() => 'test-session-id'),
getUserTier: vi.fn().mockResolvedValue(undefined),
getIdeMode: vi.fn(() => false),
getWorkspaceContext: vi.fn(() => ({
getDirectories: vi.fn(() => []),
})),
};
});

Expand Down Expand Up @@ -292,6 +295,13 @@ describe('App UI', () => {

// Ensure a theme is set so the theme dialog does not appear.
mockSettings = createMockSettings({ workspace: { theme: 'Default' } });

// Ensure getWorkspaceContext is available if not added by the constructor
if (!mockConfig.getWorkspaceContext) {
mockConfig.getWorkspaceContext = vi.fn(() => ({
getDirectories: vi.fn(() => ['/test/dir']),
}));
}
vi.mocked(ideContext.getIdeContext).mockReturnValue(undefined);
});

Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/ui/commands/aboutCommand.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ describe('aboutCommand', () => {
});

it('should call addItem with all version info', async () => {
process.env.SANDBOX = '';
if (!aboutCommand.action) {
throw new Error('The about command must have an action.');
}
Expand Down
17 changes: 17 additions & 0 deletions packages/cli/src/ui/components/InputPrompt.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ describe('InputPrompt', () => {
getProjectRoot: () => path.join('test', 'project'),
getTargetDir: () => path.join('test', 'project', 'src'),
getVimMode: () => false,
getWorkspaceContext: () => ({
getDirectories: () => ['/test/project/src'],
}),
} as unknown as Config,
slashCommands: mockSlashCommands,
commandContext: mockCommandContext,
Expand Down Expand Up @@ -731,6 +734,7 @@ describe('InputPrompt', () => {
// Verify useCompletion was called with correct signature
expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -756,6 +760,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -781,6 +786,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -806,6 +812,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -831,6 +838,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -857,6 +865,7 @@ describe('InputPrompt', () => {
// Verify useCompletion was called with the buffer
expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -882,6 +891,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -908,6 +918,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -934,6 +945,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -960,6 +972,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -986,6 +999,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand Down Expand Up @@ -1014,6 +1028,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand All @@ -1040,6 +1055,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand Down Expand Up @@ -1068,6 +1084,7 @@ describe('InputPrompt', () => {

expect(mockedUseCompletion).toHaveBeenCalledWith(
mockBuffer,
['/test/project/src'],
path.join('test', 'project', 'src'),
mockSlashCommands,
mockCommandContext,
Expand Down
11 changes: 11 additions & 0 deletions packages/cli/src/ui/components/InputPrompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,19 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
}) => {
const [justNavigatedHistory, setJustNavigatedHistory] = useState(false);

const [dirs, setDirs] = useState<readonly string[]>(
config.getWorkspaceContext().getDirectories(),
);
const dirsChanged = config.getWorkspaceContext().getDirectories();
useEffect(() => {
if (dirs.length !== dirsChanged.length) {
setDirs(dirsChanged);
}
}, [dirs.length, dirsChanged]);

const completion = useCompletion(
buffer,
dirs,
config.getTargetDir(),
slashCommands,
commandContext,
Expand Down
4 changes: 4 additions & 0 deletions packages/cli/src/ui/hooks/atCommandProcessor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ describe('handleAtCommand', () => {
respectGeminiIgnore: true,
}),
getEnableRecursiveFileSearch: vi.fn(() => true),
getWorkspaceContext: () => ({
isPathWithinWorkspace: () => true,
getDirectories: () => [testRootDir],
}),
} as unknown as Config;

const registry = new ToolRegistry(mockConfig);
Expand Down
Loading
Loading