@rlabs-inc/gemini-mcp 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +46 -43
  2. package/dist/cli/commands/config.d.ts +8 -0
  3. package/dist/cli/commands/config.js +147 -0
  4. package/dist/cli/commands/image.d.ts +7 -0
  5. package/dist/cli/commands/image.js +133 -0
  6. package/dist/cli/commands/query.d.ts +7 -0
  7. package/dist/cli/commands/query.js +94 -0
  8. package/dist/cli/commands/research.d.ts +7 -0
  9. package/dist/cli/commands/research.js +147 -0
  10. package/dist/cli/commands/search.d.ts +7 -0
  11. package/dist/cli/commands/search.js +152 -0
  12. package/dist/cli/commands/speak.d.ts +7 -0
  13. package/dist/cli/commands/speak.js +168 -0
  14. package/dist/cli/commands/tokens.d.ts +8 -0
  15. package/dist/cli/commands/tokens.js +105 -0
  16. package/dist/cli/commands/video.d.ts +7 -0
  17. package/dist/cli/commands/video.js +154 -0
  18. package/dist/cli/config.d.ts +23 -0
  19. package/dist/cli/config.js +89 -0
  20. package/dist/cli/index.d.ts +6 -0
  21. package/dist/cli/index.js +180 -0
  22. package/dist/cli/ui/box.d.ts +20 -0
  23. package/dist/cli/ui/box.js +112 -0
  24. package/dist/cli/ui/colors.d.ts +46 -0
  25. package/dist/cli/ui/colors.js +106 -0
  26. package/dist/cli/ui/index.d.ts +21 -0
  27. package/dist/cli/ui/index.js +42 -0
  28. package/dist/cli/ui/progress.d.ts +37 -0
  29. package/dist/cli/ui/progress.js +125 -0
  30. package/dist/cli/ui/spinner.d.ts +42 -0
  31. package/dist/cli/ui/spinner.js +96 -0
  32. package/dist/cli/ui/theme.d.ts +48 -0
  33. package/dist/cli/ui/theme.js +200 -0
  34. package/dist/gemini-client.d.ts +1 -0
  35. package/dist/gemini-client.js +35 -8
  36. package/dist/index.d.ts +6 -3
  37. package/dist/index.js +26 -218
  38. package/dist/server.d.ts +7 -0
  39. package/dist/server.js +221 -0
  40. package/dist/tools/deep-research.js +9 -2
  41. package/package.json +9 -3
package/README.md CHANGED
@@ -1,58 +1,49 @@
1
1
  # MCP Server Gemini
2
2
 
3
- A Model Context Protocol (MCP) server for integrating Google's Gemini 3 models with Claude Code, enabling powerful collaboration between both AI systems.
3
+ A Model Context Protocol (MCP) server for integrating Google's Gemini 3 models with Claude Code, enabling powerful collaboration between both AI systems. Now with a beautiful CLI!
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/@rlabs-inc%2Fgemini-mcp.svg)](https://www.npmjs.com/package/@rlabs-inc/gemini-mcp)
6
+ [![MCP Registry](https://img.shields.io/badge/MCP-Registry-blue)](https://registry.modelcontextprotocol.io)
6
7
 
7
- ## What's New in v0.6.0
8
+ ## What's New in v0.7.0
8
9
 
9
- **35+ tools** for comprehensive Gemini 3 integration - the most complete Gemini MCP server available!
10
+ **Beautiful CLI with Themes!** Use Gemini directly from your terminal:
10
11
 
11
- **Deep Research Agent (NEW!):**
12
- - **gemini-deep-research** - Autonomous multi-step research with web search
13
- - **gemini-check-research** - Poll research status and get results
14
- - **gemini-research-followup** - Ask follow-up questions on completed research
15
-
16
- **Token Management (NEW!):**
17
- - **gemini-count-tokens** - Count tokens before API calls with cost estimates
18
-
19
- **Text-to-Speech:**
20
- - **gemini-speak** - Convert text to speech with 30 unique voices
21
- - **gemini-dialogue** - Generate two-speaker conversations
22
- - **gemini-list-voices** - Browse all available voices
12
+ ```bash
13
+ # Install globally
14
+ npm install -g @rlabs-inc/gemini-mcp
23
15
 
24
- **URL Analysis:**
25
- - **gemini-analyze-url** - Analyze web pages with questions
26
- - **gemini-compare-urls** - Compare two URLs side by side
27
- - **gemini-extract-from-url** - Extract structured data from pages
16
+ # Set your API key once
17
+ gemini config set api-key YOUR_KEY
28
18
 
29
- **Context Caching:**
30
- - **gemini-create-cache** - Cache large documents for repeated queries
31
- - **gemini-query-cache** - Query cached content efficiently
32
- - **gemini-list-caches** / **gemini-delete-cache** - Manage caches
19
+ # Generate images, videos, search, research, and more!
20
+ gemini image "a cat astronaut" --size 4K
21
+ gemini search "latest AI news"
22
+ gemini research "quantum computing applications" --wait
23
+ gemini speak "Hello world" --voice Puck
24
+ ```
33
25
 
34
- **Multimodal Analysis:**
35
- - **YouTube Analysis** - Analyze videos by URL with timestamps and clipping
36
- - **Document Analysis** - PDFs, DOCX, spreadsheets with table extraction
26
+ **5 Beautiful Themes:** terminal, neon, ocean, forest, minimal
37
27
 
38
- **Generation & Editing:**
39
- - **4K Image Generation** - Up to 4K resolution with 10 aspect ratios
40
- - **Multi-Turn Image Editing** - Iteratively refine images through conversation
41
- - **Video Generation** - Create videos with Veo 2.0
28
+ **CLI Commands:**
29
+ - `gemini query` - Direct Gemini queries with thinking levels
30
+ - `gemini search` - Real-time web search with citations
31
+ - `gemini research` - Deep research agent
32
+ - `gemini image` - Generate images (up to 4K)
33
+ - `gemini video` - Generate videos with Veo
34
+ - `gemini speak` - Text-to-speech with 30 voices
35
+ - `gemini tokens` - Count tokens and estimate costs
36
+ - `gemini config` - Manage settings
42
37
 
43
- **Advanced Tools:**
44
- - **Code Execution** - Gemini writes AND runs Python code
45
- - **Google Search** - Real-time web information with citations
46
- - **Structured Output** - JSON schema responses with validation
47
- - **Brainstorming** - Claude + Gemini collaborative problem-solving
38
+ **MCP Registry Support:** Now discoverable in the official MCP ecosystem!
48
39
 
49
40
  ### Previous Versions
50
41
 
51
- **v0.5.1:** Documentation updates, code quality improvements
52
- **v0.5.0:** 30+ tools, TTS, URL analysis, caching
53
- **v0.4.0:** YouTube, documents, code execution, search
54
- **v0.3.0:** Thinking levels, structured output
55
- **v0.2.0:** Image/Video generation with Veo
42
+ **v0.6.x:** Deep Research, Token Counting, TTS, URL analysis, Context Caching
43
+ **v0.5.x:** 30+ tools, YouTube analysis, Document analysis
44
+ **v0.4.x:** Code execution, Google Search
45
+ **v0.3.x:** Thinking levels, Structured output, 4K images
46
+ **v0.2.x:** Image/Video generation with Veo
56
47
 
57
48
  ---
58
49
 
@@ -84,16 +75,28 @@ A Model Context Protocol (MCP) server for integrating Google's Gemini 3 models w
84
75
 
85
76
  ## Quick Installation
86
77
 
87
- ### Using npm (Recommended)
78
+ ### MCP Server for Claude Code
88
79
 
89
80
  ```bash
81
+ # Using npm (Recommended)
90
82
  claude mcp add gemini -s user -- env GEMINI_API_KEY=YOUR_KEY npx -y @rlabs-inc/gemini-mcp
83
+
84
+ # Using bun
85
+ claude mcp add gemini -s user -- env GEMINI_API_KEY=YOUR_KEY bunx @rlabs-inc/gemini-mcp
91
86
  ```
92
87
 
93
- ### Using bun
88
+ ### CLI (Global Install)
94
89
 
95
90
  ```bash
96
- claude mcp add gemini -s user -- env GEMINI_API_KEY=YOUR_KEY bunx @rlabs-inc/gemini-mcp
91
+ # Install globally
92
+ npm install -g @rlabs-inc/gemini-mcp
93
+
94
+ # Set your API key once (stored securely)
95
+ gemini config set api-key YOUR_KEY
96
+
97
+ # Now use any command!
98
+ gemini search "latest news"
99
+ gemini image "sunset over mountains" --ratio 16:9
97
100
  ```
98
101
 
99
102
  **Get your API key:** Visit [Google AI Studio](https://aistudio.google.com/apikey) - it's free and takes seconds!
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Config Command
3
+ *
4
+ * Set and view CLI configuration.
5
+ * gemini config set api-key YOUR_KEY
6
+ * gemini config show
7
+ */
8
+ export declare function configCommand(argv: string[]): Promise<void>;
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Config Command
3
+ *
4
+ * Set and view CLI configuration.
5
+ * gemini config set api-key YOUR_KEY
6
+ * gemini config show
7
+ */
8
+ import { parseArgs } from 'node:util';
9
+ import { loadConfig, saveConfig, getConfigPath } from '../config.js';
10
+ import { print, printError, printSuccess, printMuted, printWarning, t, header, box } from '../ui/index.js';
11
+ function showHelp() {
12
+ const theme = t();
13
+ print(header('gemini config', 'CLI configuration'));
14
+ print('');
15
+ print(theme.colors.primary('Usage:'));
16
+ print(` gemini config ${theme.colors.muted('<command>')} [options]`);
17
+ print('');
18
+ print(theme.colors.primary('Commands:'));
19
+ print(` ${theme.colors.highlight('set')} ${theme.colors.muted('Set a configuration value')}`);
20
+ print(` ${theme.colors.highlight('show')} ${theme.colors.muted('Show current configuration')}`);
21
+ print(` ${theme.colors.highlight('path')} ${theme.colors.muted('Show config file path')}`);
22
+ print('');
23
+ print(theme.colors.primary('Settings:'));
24
+ print(` ${theme.colors.highlight('api-key')} ${theme.colors.muted('Your Gemini API key')}`);
25
+ print(` ${theme.colors.highlight('theme')} ${theme.colors.muted('Default theme (terminal, neon, minimal, ocean, forest)')}`);
26
+ print(` ${theme.colors.highlight('output-dir')} ${theme.colors.muted('Directory for generated files')}`);
27
+ print(` ${theme.colors.highlight('default-voice')} ${theme.colors.muted('Default TTS voice')}`);
28
+ print(` ${theme.colors.highlight('default-model')} ${theme.colors.muted('Default model (pro or flash)')}`);
29
+ print('');
30
+ print(theme.colors.primary('Examples:'));
31
+ print(theme.colors.muted(' gemini config set api-key AIzaSy...'));
32
+ print(theme.colors.muted(' gemini config set theme neon'));
33
+ print(theme.colors.muted(' gemini config set output-dir ~/Documents/Gemini'));
34
+ print(theme.colors.muted(' gemini config show'));
35
+ }
36
+ async function showConfig() {
37
+ const theme = t();
38
+ const config = await loadConfig();
39
+ print(header('Current Configuration', getConfigPath()));
40
+ print('');
41
+ const lines = [
42
+ `${theme.colors.primary('API Key:')} ${config.apiKey ? theme.colors.success('Set (hidden)') : theme.colors.error('Not set')}`,
43
+ `${theme.colors.primary('Theme:')} ${config.theme}`,
44
+ `${theme.colors.primary('Output Dir:')} ${config.outputDir}`,
45
+ `${theme.colors.primary('Default Voice:')} ${config.defaultVoice}`,
46
+ `${theme.colors.primary('Image Size:')} ${config.defaultImageSize}`,
47
+ `${theme.colors.primary('Image Ratio:')} ${config.defaultImageRatio}`,
48
+ `${theme.colors.primary('Video Ratio:')} ${config.defaultVideoRatio}`,
49
+ ];
50
+ print(box(lines, { title: 'Settings' }));
51
+ print('');
52
+ if (!config.apiKey) {
53
+ printWarning('API key not set. Set it with:');
54
+ print(theme.colors.muted(' gemini config set api-key YOUR_API_KEY'));
55
+ print('');
56
+ print(theme.colors.muted('Or set the GEMINI_API_KEY environment variable.'));
57
+ }
58
+ }
59
+ async function setConfig(key, value) {
60
+ const theme = t();
61
+ // Map user-friendly keys to config keys
62
+ const keyMap = {
63
+ 'api-key': 'apiKey',
64
+ 'apikey': 'apiKey',
65
+ 'theme': 'theme',
66
+ 'output-dir': 'outputDir',
67
+ 'outputdir': 'outputDir',
68
+ 'default-voice': 'defaultVoice',
69
+ 'voice': 'defaultVoice',
70
+ 'default-model': 'defaultModel',
71
+ 'model': 'defaultModel',
72
+ 'image-size': 'defaultImageSize',
73
+ 'image-ratio': 'defaultImageRatio',
74
+ 'video-ratio': 'defaultVideoRatio',
75
+ };
76
+ const configKey = keyMap[key.toLowerCase()];
77
+ if (!configKey) {
78
+ printError(`Unknown setting: ${key}`);
79
+ printMuted('Valid settings: api-key, theme, output-dir, default-voice');
80
+ process.exit(1);
81
+ }
82
+ // Validate values
83
+ if (configKey === 'theme') {
84
+ const validThemes = ['terminal', 'neon', 'minimal', 'ocean', 'forest'];
85
+ if (!validThemes.includes(value)) {
86
+ printError(`Invalid theme: ${value}`);
87
+ printMuted(`Valid themes: ${validThemes.join(', ')}`);
88
+ process.exit(1);
89
+ }
90
+ }
91
+ if (configKey === 'defaultImageSize') {
92
+ const validSizes = ['1K', '2K', '4K'];
93
+ if (!validSizes.includes(value)) {
94
+ printError(`Invalid image size: ${value}`);
95
+ printMuted(`Valid sizes: ${validSizes.join(', ')}`);
96
+ process.exit(1);
97
+ }
98
+ }
99
+ // Save the config
100
+ await saveConfig({ [configKey]: value });
101
+ // Show confirmation
102
+ const displayValue = configKey === 'apiKey' ? '***' + value.slice(-4) : value;
103
+ printSuccess(`Set ${key} = ${displayValue}`);
104
+ if (configKey === 'apiKey') {
105
+ print('');
106
+ print(theme.colors.muted('Your API key is now stored in:'));
107
+ print(theme.colors.muted(` ${getConfigPath()}`));
108
+ print('');
109
+ printWarning('Keep this file secure. Do not share it.');
110
+ }
111
+ }
112
+ export async function configCommand(argv) {
113
+ const { positionals } = parseArgs({
114
+ args: argv,
115
+ options: {
116
+ help: { type: 'boolean', short: 'h', default: false },
117
+ },
118
+ allowPositionals: true,
119
+ });
120
+ const subCommand = positionals[0];
121
+ if (!subCommand || subCommand === 'help') {
122
+ showHelp();
123
+ return;
124
+ }
125
+ switch (subCommand) {
126
+ case 'show':
127
+ await showConfig();
128
+ break;
129
+ case 'path':
130
+ print(getConfigPath());
131
+ break;
132
+ case 'set':
133
+ const key = positionals[1];
134
+ const value = positionals.slice(2).join(' ');
135
+ if (!key || !value) {
136
+ printError('Usage: gemini config set <key> <value>');
137
+ printMuted('Example: gemini config set api-key YOUR_KEY');
138
+ process.exit(1);
139
+ }
140
+ await setConfig(key, value);
141
+ break;
142
+ default:
143
+ printError(`Unknown config command: ${subCommand}`);
144
+ printMuted('Valid commands: set, show, path');
145
+ process.exit(1);
146
+ }
147
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Image Command
3
+ *
4
+ * Generate images with Gemini's Imagen model.
5
+ * gemini image "a cat in space"
6
+ */
7
+ export declare function imageCommand(argv: string[]): Promise<void>;
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Image Command
3
+ *
4
+ * Generate images with Gemini's Imagen model.
5
+ * gemini image "a cat in space"
6
+ */
7
+ import { parseArgs } from 'node:util';
8
+ import { initGeminiClient, generateImage } from '../../gemini-client.js';
9
+ import { setupLogger } from '../../utils/logger.js';
10
+ import { spinner, print, printError, printSuccess, printMuted, t, header, box } from '../ui/index.js';
11
+ // Valid options
12
+ const VALID_SIZES = ['1K', '2K', '4K'];
13
+ const VALID_RATIOS = ['1:1', '2:3', '3:2', '3:4', '4:3', '4:5', '5:4', '9:16', '16:9', '21:9'];
14
+ function showHelp() {
15
+ const theme = t();
16
+ print(header('gemini image', 'Generate images with AI'));
17
+ print('');
18
+ print(theme.colors.primary('Usage:'));
19
+ print(` gemini image ${theme.colors.muted('"your prompt"')} [options]`);
20
+ print('');
21
+ print(theme.colors.primary('Options:'));
22
+ print(` ${theme.colors.highlight('--size, -s')} ${theme.colors.muted('Resolution: 1K, 2K, 4K (default: 2K)')}`);
23
+ print(` ${theme.colors.highlight('--ratio, -r')} ${theme.colors.muted('Aspect ratio (default: 1:1)')}`);
24
+ print(` ${theme.colors.highlight('--output, -o')} ${theme.colors.muted('Output file path')}`);
25
+ print(` ${theme.colors.highlight('--style')} ${theme.colors.muted('Art style (e.g., "watercolor", "cyberpunk")')}`);
26
+ print(` ${theme.colors.highlight('--search')} ${theme.colors.muted('Use Google Search for real-world accuracy')}`);
27
+ print(` ${theme.colors.highlight('--help, -h')} ${theme.colors.muted('Show this help')}`);
28
+ print('');
29
+ print(theme.colors.primary('Aspect Ratios:'));
30
+ print(theme.colors.muted(' 1:1 - Square (default)'));
31
+ print(theme.colors.muted(' 16:9 - Widescreen landscape'));
32
+ print(theme.colors.muted(' 9:16 - Portrait/mobile'));
33
+ print(theme.colors.muted(' 4:3 - Classic landscape'));
34
+ print(theme.colors.muted(' 3:4 - Classic portrait'));
35
+ print(theme.colors.muted(' 21:9 - Ultrawide cinematic'));
36
+ print('');
37
+ print(theme.colors.primary('Examples:'));
38
+ print(theme.colors.muted(' gemini image "a cat astronaut floating in space"'));
39
+ print(theme.colors.muted(' gemini image "sunset over mountains" --ratio 16:9 --size 4K'));
40
+ print(theme.colors.muted(' gemini image "portrait of a robot" -r 3:4 --style "oil painting"'));
41
+ print(theme.colors.muted(' gemini image "Eiffel Tower at night" --search'));
42
+ }
43
+ export async function imageCommand(argv) {
44
+ const { values, positionals } = parseArgs({
45
+ args: argv,
46
+ options: {
47
+ help: { type: 'boolean', short: 'h', default: false },
48
+ size: { type: 'string', short: 's', default: '2K' },
49
+ ratio: { type: 'string', short: 'r', default: '1:1' },
50
+ output: { type: 'string', short: 'o' },
51
+ style: { type: 'string' },
52
+ search: { type: 'boolean', default: false },
53
+ },
54
+ allowPositionals: true,
55
+ });
56
+ if (values.help) {
57
+ showHelp();
58
+ return;
59
+ }
60
+ // Get prompt from positional args
61
+ const prompt = positionals.join(' ');
62
+ if (!prompt) {
63
+ printError('No image prompt provided');
64
+ printMuted('Usage: gemini image "your prompt"');
65
+ process.exit(1);
66
+ }
67
+ const theme = t();
68
+ const s = spinner();
69
+ const size = values.size;
70
+ const ratio = values.ratio;
71
+ const style = values.style;
72
+ const useSearch = values.search;
73
+ // Validate size
74
+ if (!VALID_SIZES.includes(size)) {
75
+ printError(`Invalid size: ${size}`);
76
+ printMuted(`Valid sizes: ${VALID_SIZES.join(', ')}`);
77
+ process.exit(1);
78
+ }
79
+ // Validate ratio
80
+ if (!VALID_RATIOS.includes(ratio)) {
81
+ printError(`Invalid ratio: ${ratio}`);
82
+ printMuted(`Valid ratios: ${VALID_RATIOS.join(', ')}`);
83
+ process.exit(1);
84
+ }
85
+ try {
86
+ // Suppress logger output for CLI
87
+ setupLogger('quiet');
88
+ // Initialize Gemini client
89
+ s.start('Connecting to Gemini...');
90
+ await initGeminiClient();
91
+ // Build full prompt with style if provided
92
+ let fullPrompt = prompt;
93
+ if (style) {
94
+ fullPrompt = `${prompt}, in ${style} style`;
95
+ }
96
+ // Generate image
97
+ s.update('Generating image...');
98
+ const result = await generateImage(fullPrompt, {
99
+ aspectRatio: ratio, // Type assertion for ratio string
100
+ imageSize: size,
101
+ useGoogleSearch: useSearch,
102
+ });
103
+ if (!result.filePath) {
104
+ throw new Error('Image generation failed - no file created');
105
+ }
106
+ s.success('Image generated!');
107
+ print('');
108
+ // Get file stats
109
+ const file = Bun.file(result.filePath);
110
+ const fileSize = file.size;
111
+ // Show info
112
+ const infoLines = [
113
+ `${theme.colors.primary('Prompt:')} ${prompt.substring(0, 50)}${prompt.length > 50 ? '...' : ''}`,
114
+ style ? `${theme.colors.primary('Style:')} ${style}` : null,
115
+ `${theme.colors.primary('Size:')} ${size}`,
116
+ `${theme.colors.primary('Ratio:')} ${ratio}`,
117
+ useSearch ? `${theme.colors.primary('Search:')} Enabled` : null,
118
+ `${theme.colors.primary('File:')} ${result.filePath}`,
119
+ `${theme.colors.primary('File Size:')} ${(fileSize / 1024).toFixed(1)} KB`,
120
+ ].filter(Boolean);
121
+ print(box(infoLines, { title: 'Image Generated' }));
122
+ print('');
123
+ printSuccess(`Image saved to: ${result.filePath}`);
124
+ // Hint about opening
125
+ print('');
126
+ print(theme.colors.muted(`Open with: open "${result.filePath}"`));
127
+ }
128
+ catch (error) {
129
+ s.error('Image generation failed');
130
+ printError(error instanceof Error ? error.message : String(error));
131
+ process.exit(1);
132
+ }
133
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Query Command
3
+ *
4
+ * Direct queries to Gemini with thinking level control.
5
+ * gemini query "your prompt" [--thinking high]
6
+ */
7
+ export declare function queryCommand(argv: string[]): Promise<void>;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Query Command
3
+ *
4
+ * Direct queries to Gemini with thinking level control.
5
+ * gemini query "your prompt" [--thinking high]
6
+ */
7
+ import { parseArgs } from 'node:util';
8
+ import { initGeminiClient, generateWithGeminiPro, generateWithGeminiFlash } from '../../gemini-client.js';
9
+ import { setupLogger } from '../../utils/logger.js';
10
+ import { spinner, print, printError, printMuted, t, header } from '../ui/index.js';
11
+ function showHelp() {
12
+ const theme = t();
13
+ print(header('gemini query', 'Query Gemini directly'));
14
+ print('');
15
+ print(theme.colors.primary('Usage:'));
16
+ print(` gemini query ${theme.colors.muted('"your prompt"')} [options]`);
17
+ print('');
18
+ print(theme.colors.primary('Options:'));
19
+ print(` ${theme.colors.highlight('--thinking, -t')} ${theme.colors.muted('Thinking level: minimal, low, medium, high (default: high)')}`);
20
+ print(` ${theme.colors.highlight('--model, -m')} ${theme.colors.muted('Model to use: pro, flash (default: pro)')}`);
21
+ print(` ${theme.colors.highlight('--help, -h')} ${theme.colors.muted('Show this help')}`);
22
+ print('');
23
+ print(theme.colors.primary('Examples:'));
24
+ print(theme.colors.muted(' gemini query "What is the meaning of life?"'));
25
+ print(theme.colors.muted(' gemini query "Explain quantum computing" --thinking high'));
26
+ print(theme.colors.muted(' gemini query "Quick fact check" -t minimal -m flash'));
27
+ }
28
+ export async function queryCommand(argv) {
29
+ const { values, positionals } = parseArgs({
30
+ args: argv,
31
+ options: {
32
+ help: { type: 'boolean', short: 'h', default: false },
33
+ thinking: { type: 'string', short: 't', default: 'high' },
34
+ model: { type: 'string', short: 'm', default: 'pro' },
35
+ },
36
+ allowPositionals: true,
37
+ });
38
+ if (values.help) {
39
+ showHelp();
40
+ return;
41
+ }
42
+ // Get prompt from positional args
43
+ const prompt = positionals.join(' ');
44
+ if (!prompt) {
45
+ printError('No prompt provided');
46
+ printMuted('Usage: gemini query "your prompt"');
47
+ process.exit(1);
48
+ }
49
+ // Validate thinking level
50
+ const validThinking = ['minimal', 'low', 'medium', 'high'];
51
+ const thinking = values.thinking;
52
+ if (!validThinking.includes(thinking)) {
53
+ printError(`Invalid thinking level: ${thinking}`);
54
+ printMuted(`Valid options: ${validThinking.join(', ')}`);
55
+ process.exit(1);
56
+ }
57
+ // Validate model
58
+ const validModels = ['pro', 'flash'];
59
+ const model = values.model;
60
+ if (!validModels.includes(model)) {
61
+ printError(`Invalid model: ${model}`);
62
+ printMuted(`Valid options: ${validModels.join(', ')}`);
63
+ process.exit(1);
64
+ }
65
+ const theme = t();
66
+ const s = spinner();
67
+ try {
68
+ // Suppress logger output for CLI (we use our own spinner/output)
69
+ setupLogger('quiet');
70
+ // Initialize Gemini client
71
+ s.start('Connecting to Gemini...');
72
+ await initGeminiClient();
73
+ // Query Gemini based on model
74
+ s.update(`Thinking (${thinking})...`);
75
+ const options = {
76
+ thinkingLevel: thinking
77
+ };
78
+ const result = model === 'flash'
79
+ ? await generateWithGeminiFlash(prompt, options)
80
+ : await generateWithGeminiPro(prompt, options);
81
+ s.success('Response received');
82
+ print('');
83
+ // Show the response
84
+ print(theme.colors.primary('Response:'));
85
+ print('');
86
+ print(result);
87
+ print('');
88
+ }
89
+ catch (error) {
90
+ s.error('Query failed');
91
+ printError(error instanceof Error ? error.message : String(error));
92
+ process.exit(1);
93
+ }
94
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Research Command
3
+ *
4
+ * Deep research agent for comprehensive investigation.
5
+ * gemini research "your research question"
6
+ */
7
+ export declare function researchCommand(argv: string[]): Promise<void>;