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

bash
# Install Gemini CLI
npm install -g @anthropic-ai/gemini-cli

# Verify installation
gemini --version

Quick Start

python
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.

python
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:

OptionTypeDefaultDescription
commandstr"gemini"CLI command (must be on PATH)
argsList[str]["--output-format", "text"]Default flags passed on every turn
outputstr"text"Output format expected from the CLI
inputstr"single"Prompt is passed as a single -p argument
timeout_msint300000Subprocess timeout (5 minutes)

Backend CLI Flags

The backend builds the gemini command with these flags:

FlagPurpose
--output-format textPlain-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)
--yoloSkip approval prompts — only when both unsafe=True and PRAISONAI_GEMINI_BYPASS_PERMISSIONS=1
--skip-trustSkip workspace-trust prompt — same opt-in as --yolo

Permission Bypass (opt-in)

python
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 WARNING

Configuration Options

OptionTypeDefaultDescription
workspacestr“.”Working directory for CLI execution
timeoutint300Timeout in seconds
output_formatstr“json”Output format: “json”, “text”, “stream-json”
modelstr“gemini-2.5-pro”Gemini model to use
include_directorieslistNoneAdditional directories to include in context
sandboxboolFalseRun in sandbox mode

Examples

Basic Execution

python
from praisonai.integrations import GeminiCLIIntegration

gemini = GeminiCLIIntegration(workspace="/project")

result = await gemini.execute("Explain the architecture of this codebase")
print(result)

Model Selection

python
# 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

python
gemini = GeminiCLIIntegration(
    workspace="/project/src",
    include_directories=["../lib", "../docs", "../tests"]
)

result = await gemini.execute("Analyze the entire project structure")

With Usage Stats

python
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

python
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

python
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.

python
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

bash
# 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=1

CLI Flags Used

The integration uses the following Gemini CLI flags:

FlagDescription
-pPrint mode (headless)
-mModel selection
--output-format jsonJSON output for parsing
--include-directoriesInclude additional directories
--sandboxRun in sandbox mode

JSON Output Schema

The JSON output includes:

json
{
  "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

python
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 TimeoutError is now returned as CliBackendResult(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_resume is 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

  1. Use gemini-2.5-flash for quick tasks
  2. Use gemini-2.5-pro for complex analysis
  3. Include relevant directories for better context
  4. Use execute_with_stats() to monitor usage
  5. Set appropriate timeouts for large codebases