Files
gemini-cli/packages/cli/src/gemini.tsx

208 lines
6.1 KiB
TypeScript
Raw Normal View History

/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
Initial commit of Gemini Code CLI This commit introduces the initial codebase for the Gemini Code CLI, a command-line interface designed to facilitate interaction with the Gemini API for software engineering tasks. The code was migrated from a previous git repository as a single squashed commit. Core Features & Components: * **Gemini Integration:** Leverages the `@google/genai` SDK to interact with the Gemini models, supporting chat history, streaming responses, and function calling (tools). * **Terminal UI:** Built with Ink (React for CLIs) providing an interactive chat interface within the terminal, including input prompts, message display, loading indicators, and tool interaction elements. * **Tooling Framework:** Implements a robust tool system allowing Gemini to interact with the local environment. Includes tools for: * File system listing (`ls`) * File reading (`read-file`) * Content searching (`grep`) * File globbing (`glob`) * File editing (`edit`) * File writing (`write-file`) * Executing bash commands (`terminal`) * **State Management:** Handles the streaming state of Gemini responses and manages the conversation history. * **Configuration:** Parses command-line arguments (`yargs`) and loads environment variables (`dotenv`) for setup. * **Project Structure:** Organized into `core`, `ui`, `tools`, `config`, and `utils` directories using TypeScript. Includes basic build (`tsc`) and start scripts. This initial version establishes the foundation for a powerful CLI tool enabling developers to use Gemini for coding assistance directly in their terminal environment. --- Created by yours truly: __Gemini Code__
2025-04-15 21:41:08 -07:00
import React from 'react';
import { render } from 'ink';
import { AppWrapper } from './ui/App.js';
import { loadCliConfig } from './config/config.js';
import { readStdin } from './utils/readStdin.js';
import { fileURLToPath } from 'node:url';
import { dirname, basename } from 'node:path';
import { sandbox_command, start_sandbox } from './utils/sandbox.js';
import { LoadedSettings, loadSettings } from './config/settings.js';
import { themeManager } from './ui/themes/theme-manager.js';
import { getStartupWarnings } from './utils/startupWarnings.js';
import { runNonInteractive } from './nonInteractiveCli.js';
import { loadGeminiIgnorePatterns } from './utils/loadIgnorePatterns.js';
import { loadExtensions, ExtensionConfig } from './config/extension.js';
import {
ApprovalMode,
Config,
EditTool,
GlobTool,
GrepTool,
LSTool,
MemoryTool,
ReadFileTool,
ReadManyFilesTool,
ShellTool,
WebFetchTool,
WebSearchTool,
WriteFileTool,
} from '@gemini-cli/core';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export async function main() {
const workspaceRoot = process.cwd();
const settings = loadSettings(workspaceRoot);
setWindowTitle(basename(workspaceRoot), settings);
// warn about deprecated environment variables
if (process.env.GEMINI_CODE_MODEL) {
console.warn('GEMINI_CODE_MODEL is deprecated. Use GEMINI_MODEL instead.');
process.env.GEMINI_MODEL = process.env.GEMINI_CODE_MODEL;
}
if (process.env.GEMINI_CODE_SANDBOX) {
console.warn(
'GEMINI_CODE_SANDBOX is deprecated. Use GEMINI_SANDBOX instead.',
);
process.env.GEMINI_SANDBOX = process.env.GEMINI_CODE_SANDBOX;
}
if (process.env.GEMINI_CODE_SANDBOX_IMAGE) {
console.warn(
'GEMINI_CODE_SANDBOX_IMAGE is deprecated. Use GEMINI_SANDBOX_IMAGE_NAME instead.',
);
process.env.GEMINI_SANDBOX_IMAGE_NAME =
process.env.GEMINI_CODE_SANDBOX_IMAGE; // Corrected to GEMINI_SANDBOX_IMAGE_NAME
}
const geminiIgnorePatterns = loadGeminiIgnorePatterns(workspaceRoot);
if (settings.errors.length > 0) {
for (const error of settings.errors) {
let errorMessage = `Error in ${error.path}: ${error.message}`;
if (!process.env.NO_COLOR) {
errorMessage = `\x1b[31m${errorMessage}\x1b[0m`;
}
console.error(errorMessage);
console.error(`Please fix ${error.path} and try again.`);
}
process.exit(1);
}
const extensions = loadExtensions(workspaceRoot);
const config = await loadCliConfig(
settings.merged,
extensions,
geminiIgnorePatterns,
);
Ignore folders files (#651) # Add .gitignore-Aware File Filtering to gemini-cli This pull request introduces .gitignore-based file filtering to the gemini-cli, ensuring that git-ignored files are automatically excluded from file-related operations and suggestions throughout the CLI. The update enhances usability, reduces noise from build artifacts and dependencies, and provides new configuration options for fine-tuning file discovery. Key Improvements .gitignore File Filtering All @ (at) commands, file completions, and core discovery tools now honor .gitignore patterns by default. Git-ignored files (such as node_modules/, dist/, .env, and .git) are excluded from results unless explicitly overridden. The behavior can be customized via a new fileFiltering section in settings.json, including options for: Turning .gitignore respect on/off. Adding custom ignore patterns. Allowing or excluding build artifacts. Configuration & Documentation Updates settings.json schema extended with fileFiltering options. Documentation updated to explain new filtering controls and usage patterns. Testing New and updated integration/unit tests for file filtering logic, configuration merging, and edge cases. Test coverage ensures .gitignore filtering works as intended across different workflows. Internal Refactoring Core file discovery logic refactored for maintainability and extensibility. Underlying tools (ls, glob, read-many-files) now support git-aware filtering out of the box. Co-authored-by: N. Taylor Mullen <ntaylormullen@google.com>
2025-06-03 21:40:46 -07:00
// Initialize centralized FileDiscoveryService
await config.getFileService();
2025-05-02 08:15:46 -07:00
if (settings.merged.theme) {
if (!themeManager.setActiveTheme(settings.merged.theme)) {
// If the theme is not found during initial load, log a warning and continue.
// The useThemeCommand hook in App.tsx will handle opening the dialog.
console.warn(`Warning: Theme "${settings.merged.theme}" not found.`);
}
}
// hop into sandbox if we are outside and sandboxing is enabled
if (!process.env.SANDBOX) {
2025-05-02 08:15:46 -07:00
const sandbox = sandbox_command(config.getSandbox());
if (sandbox) {
await start_sandbox(sandbox);
process.exit(0);
}
}
2025-05-02 08:15:46 -07:00
let input = config.getQuestion();
const startupWarnings = await getStartupWarnings();
2025-05-02 08:15:46 -07:00
2025-04-22 18:32:03 -07:00
// Render UI, passing necessary config values. Check that there is no command line question.
if (process.stdin.isTTY && input?.length === 0) {
render(
2025-05-27 21:40:46 +00:00
<React.StrictMode>
<AppWrapper
2025-05-27 21:40:46 +00:00
config={config}
settings={settings}
startupWarnings={startupWarnings}
/>
</React.StrictMode>,
{ exitOnCtrlC: false },
);
return;
}
2025-04-22 18:32:03 -07:00
// If not a TTY, read from stdin
// This is for cases where the user pipes input directly into the command
if (!process.stdin.isTTY) {
input += await readStdin();
}
if (!input) {
console.error('No input provided via stdin.');
process.exit(1);
}
// Non-interactive mode handled by runNonInteractive
const nonInteractiveConfig = await loadNonInteractiveConfig(
config,
extensions,
settings,
);
await runNonInteractive(nonInteractiveConfig, input);
process.exit(0);
Initial commit of Gemini Code CLI This commit introduces the initial codebase for the Gemini Code CLI, a command-line interface designed to facilitate interaction with the Gemini API for software engineering tasks. The code was migrated from a previous git repository as a single squashed commit. Core Features & Components: * **Gemini Integration:** Leverages the `@google/genai` SDK to interact with the Gemini models, supporting chat history, streaming responses, and function calling (tools). * **Terminal UI:** Built with Ink (React for CLIs) providing an interactive chat interface within the terminal, including input prompts, message display, loading indicators, and tool interaction elements. * **Tooling Framework:** Implements a robust tool system allowing Gemini to interact with the local environment. Includes tools for: * File system listing (`ls`) * File reading (`read-file`) * Content searching (`grep`) * File globbing (`glob`) * File editing (`edit`) * File writing (`write-file`) * Executing bash commands (`terminal`) * **State Management:** Handles the streaming state of Gemini responses and manages the conversation history. * **Configuration:** Parses command-line arguments (`yargs`) and loads environment variables (`dotenv`) for setup. * **Project Structure:** Organized into `core`, `ui`, `tools`, `config`, and `utils` directories using TypeScript. Includes basic build (`tsc`) and start scripts. This initial version establishes the foundation for a powerful CLI tool enabling developers to use Gemini for coding assistance directly in their terminal environment. --- Created by yours truly: __Gemini Code__
2025-04-15 21:41:08 -07:00
}
function setWindowTitle(title: string, settings: LoadedSettings) {
if (!settings.merged.hideWindowTitle) {
process.stdout.write(`\x1b]2; Gemini - ${title} \x07`);
process.on('exit', () => {
process.stdout.write(`\x1b]2;\x07`);
});
}
}
// --- Global Unhandled Rejection Handler ---
2025-04-18 16:38:01 -07:00
process.on('unhandledRejection', (reason, _promise) => {
// Log other unexpected unhandled rejections as critical errors
console.error('=========================================');
console.error('CRITICAL: Unhandled Promise Rejection!');
console.error('=========================================');
console.error('Reason:', reason);
console.error('Stack trace may follow:');
if (!(reason instanceof Error)) {
console.error(reason);
}
// Exit for genuinely unhandled errors
process.exit(1);
});
async function loadNonInteractiveConfig(
config: Config,
extensions: ExtensionConfig[],
settings: LoadedSettings,
) {
if (config.getApprovalMode() === ApprovalMode.YOLO) {
// Since everything is being allowed we can use normal yolo behavior.
return config;
}
// Everything is not allowed, ensure that only read-only tools are configured.
let existingCoreTools = config.getCoreTools();
existingCoreTools = existingCoreTools || [
ReadFileTool.Name,
LSTool.Name,
GrepTool.Name,
GlobTool.Name,
EditTool.Name,
WriteFileTool.Name,
WebFetchTool.Name,
WebSearchTool.Name,
ReadManyFilesTool.Name,
ShellTool.Name,
MemoryTool.Name,
];
const interactiveTools = [ShellTool.Name, EditTool.Name, WriteFileTool.Name];
const nonInteractiveTools = existingCoreTools.filter(
(tool) => !interactiveTools.includes(tool),
);
const nonInteractiveSettings = {
...settings.merged,
coreTools: nonInteractiveTools,
};
return await loadCliConfig(
nonInteractiveSettings,
extensions,
config.getGeminiIgnorePatterns(),
);
}