Gemini CLI Integration
Integrate Google's Gemini CLI for AI-powered code analysis and generation
Gemini CLI Integration
PraisonAI provides integration with Google’s Gemini CLI for AI-powered code analysis, generation, and refactoring tasks.
Installation
# Install Gemini CLI
npm install -g @anthropic-ai/gemini-cli
# Verify installation
gemini --versionQuick Start
from praisonai.integrations import GeminiCLIIntegration
# Create integration
gemini = GeminiCLIIntegration(
workspace="/path/to/project",
model="gemini-2.5-pro"
)
# Execute a coding task
result = await gemini.execute("Analyze this codebase and suggest improvements")
print(result)Use as Agent Backend
Delegate an Agent’s LLM turns to gemini -p instead of the Gemini API — uses your Google account.
from praisonaiagents import Agent
agent = Agent(name="assistant", cli_backend="gemini-cli")
agent.start("Hello")Backend Configuration
The gemini-cli backend ships with this default configuration:
| Option | Type | Default | Description |
|---|---|---|---|
command | str | "gemini" | CLI command (must be on PATH) |
args | List[str] | ["--output-format", "text"] | Default flags passed on every turn |
output | str | "text" | Output format expected from the CLI |
input | str | "single" | Prompt is passed as a single -p argument |
timeout_ms | int | 300000 | Subprocess timeout (5 minutes) |
Backend CLI Flags
The backend builds the gemini command with these flags:
| Flag | Purpose |
|---|---|
--output-format text | Plain-text output (default) |
--resume <session_id> | Resume a prior session (only when session.is_resume) |
-p <prompt> | User turn (system prompt is prepended to the prompt) |
--yolo | Skip approval prompts — only when both unsafe=True and PRAISONAI_GEMINI_BYPASS_PERMISSIONS=1 |
--skip-trust | Skip workspace-trust prompt — same opt-in as --yolo |
Permission Bypass (opt-in)
import os
from praisonai_code.cli_backends.gemini import GeminiBackend
# Safe default — gemini CLI prompts on destructive actions
backend = GeminiBackend()
# Fully bypass approvals (requires BOTH signals)
os.environ["PRAISONAI_GEMINI_BYPASS_PERMISSIONS"] = "1"
backend = GeminiBackend(unsafe=True) # logs a SECURITY WARNINGConfiguration Options
| Option | Type | Default | Description |
|---|---|---|---|
workspace | str | “.” | Working directory for CLI execution |
timeout | int | 300 | Timeout in seconds |
output_format | str | “json” | Output format: “json”, “text”, “stream-json” |
model | str | “gemini-2.5-pro” | Gemini model to use |
include_directories | list | None | Additional directories to include in context |
sandbox | bool | False | Run in sandbox mode |
Examples
Basic Execution
from praisonai.integrations import GeminiCLIIntegration
gemini = GeminiCLIIntegration(workspace="/project")
result = await gemini.execute("Explain the architecture of this codebase")
print(result)Model Selection
# Use Gemini 2.5 Flash for faster responses
gemini = GeminiCLIIntegration(
workspace="/project",
model="gemini-2.5-flash"
)
result = await gemini.execute("Quick code review")Multi-Directory Context
gemini = GeminiCLIIntegration(
workspace="/project/src",
include_directories=["../lib", "../docs", "../tests"]
)
result = await gemini.execute("Analyze the entire project structure")With Usage Stats
gemini = GeminiCLIIntegration(workspace="/project")
# Get result with usage statistics
result, stats = await gemini.execute_with_stats("Analyze main.py")
print(f"Result: {result}")
print(f"Stats: {stats}")
# Stats includes token usage, latency, tool calls, etc.Streaming Output
gemini = GeminiCLIIntegration(workspace="/project")
async for event in gemini.stream("Generate comprehensive documentation"):
event_type = event.get("type")
content = event.get("content", "")
print(f"[{event_type}] {content}")As Agent Tool
from praisonai import Agent
from praisonai.integrations import GeminiCLIIntegration
gemini = GeminiCLIIntegration(
workspace="/project",
model="gemini-2.5-pro"
)
# Create tool
tool = gemini.as_tool()
# Use with agent
agent = Agent(
name="Code Analyst",
role="Software Architect",
goal="Analyze and improve code architecture",
tools=[tool]
)
result = agent.start("Review the codebase and suggest improvements")As a native async agent tool
Preferred when the agent runs on agent.astart(...) (or any async entrypoint) — the tool is awaited directly on the running loop with no thread hop.
from praisonaiagents import Agent
from praisonai.integrations import GeminiCLIIntegration
gemini = GeminiCLIIntegration(workspace="/project", model="gemini-2.5-pro")
agent = Agent(
name="Code Analyst",
role="Software Architect",
goal="Analyze and improve code architecture",
tools=[gemini.as_async_tool()], # registers as `gemini_atool`
)
await agent.astart("Review the codebase and suggest improvements")as_async_tool() was added in PraisonAI PR #4022; as_tool() still works and is now also safe to call from inside an async agent runtime.
Environment Variables
# API Key (required)
export GEMINI_API_KEY=your-key
# or
export GOOGLE_API_KEY=your-key
# Optional: with GeminiBackend(unsafe=True), insert --yolo --skip-trust
export PRAISONAI_GEMINI_BYPASS_PERMISSIONS=1CLI Flags Used
The integration uses the following Gemini CLI flags:
| Flag | Description |
|---|---|
-p | Print mode (headless) |
-m | Model selection |
--output-format json | JSON output for parsing |
--include-directories | Include additional directories |
--sandbox | Run in sandbox mode |
JSON Output Schema
The JSON output includes:
{
"response": "The main AI-generated content",
"stats": {
"models": {
"gemini-2.5-pro": {
"api": {
"totalRequests": 2,
"totalErrors": 0,
"totalLatencyMs": 5053
},
"tokens": {
"prompt": 24939,
"candidates": 20,
"total": 25113,
"cached": 21263
}
}
},
"tools": {
"totalCalls": 1,
"totalSuccess": 1,
"totalFail": 0
},
"files": {
"totalLinesAdded": 0,
"totalLinesRemoved": 0
}
}
}Error Handling
from praisonai.integrations import GeminiCLIIntegration
gemini = GeminiCLIIntegration(timeout=120)
try:
result = await gemini.execute("Complex analysis task")
except TimeoutError:
print("Task timed out")
except Exception as e:
print(f"Error: {e}")Robustness (PR #4111)
- A subprocess
TimeoutErroris now returned asCliBackendResult(error=...)instead of escaping as an exception. - On
CalledProcessError, the CLI’s actual stderr diagnostic is surfaced (previously only the exit status was shown). -m(model) and cwd are threaded through, so scheduled runs can pin a model and run in a workspace.CliSessionBinding.is_resumeis now set on the second turn of a session, so the resume branch runs instead of re-sending the system prompt every turn.
Best Practices
- Use gemini-2.5-flash for quick tasks
- Use gemini-2.5-pro for complex analysis
- Include relevant directories for better context
- Use execute_with_stats() to monitor usage
- Set appropriate timeouts for large codebases