> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instructorphp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 12 gemini bridge

## Overview

> Deprecated: the Gemini CLI bridge is kept for compatibility only. The upstream Google CLI flow is obsolete for this package, so new integrations should use another AgentCtrl backend.

The Gemini bridge wraps the `gemini` CLI (from [@google/gemini-cli](https://github.com/google-gemini/gemini-cli)), Google's terminal-based coding agent. Gemini CLI supports model aliases, approval modes (default, auto\_edit, yolo, plan), sandbox isolation, extensions, MCP servers, policy files, session management, and stream-json event streaming. It provides token usage data including cached token counts.

The bridge is implemented by `GeminiBridge` and configured through `GeminiBridgeBuilder`. Access the builder through the `AgentCtrl` facade:

```php theme={null}
use Cognesy\AgentCtrl\AgentCtrl;
use Cognesy\AgentCtrl\Enum\AgentType;

// Dedicated factory method
$builder = AgentCtrl::gemini();

// Or via the generic factory
$builder = AgentCtrl::make(AgentType::Gemini);
// @doctest id="2da1"
```

### Prerequisites

Install Gemini CLI globally:

```bash theme={null}
# npm
npm install -g @google/gemini-cli

# Homebrew
brew install gemini-cli

# npx (no install)
npx @google/gemini-cli
# @doctest id="4a16"
```

Configure authentication (one of):

```bash theme={null}
# Gemini API key
export GEMINI_API_KEY=...

# Google Cloud API key
export GOOGLE_API_KEY=...

# Or authenticate via Google account (free tier)
gemini
# @doctest id="b684"
```

## Basic Usage

```php theme={null}
use Cognesy\AgentCtrl\AgentCtrl;

$response = AgentCtrl::gemini()
    ->execute('Explain the architecture of this project.');

echo $response->text();
// @doctest id="7d9a"
```

With model selection:

```php theme={null}
$response = AgentCtrl::gemini()
    ->withModel('flash')
    ->execute('Review the test suite.');

echo $response->text();
// @doctest id="4b19"
```

## Model Selection

Gemini CLI supports model aliases and full model names:

```php theme={null}
// Model aliases
AgentCtrl::gemini()->withModel('auto');        // Default (gemini-2.5-pro)
AgentCtrl::gemini()->withModel('pro');         // gemini-2.5-pro
AgentCtrl::gemini()->withModel('flash');       // gemini-2.5-flash
AgentCtrl::gemini()->withModel('flash-lite');  // gemini-2.5-flash-lite

// Full model name
AgentCtrl::gemini()->withModel('gemini-2.5-pro');
// @doctest id="cd80"
```

## Approval Modes

Gemini CLI supports four approval modes that control how tool execution is approved:

```php theme={null}
use Cognesy\AgentCtrl\Gemini\Domain\Enum\ApprovalMode;

// Default — prompt for approval on each tool use
AgentCtrl::gemini()->withApprovalMode(ApprovalMode::Default);

// Auto-edit — auto-approve edit tools, prompt for others
AgentCtrl::gemini()->withApprovalMode(ApprovalMode::AutoEdit);

// YOLO — auto-approve all tool executions
AgentCtrl::gemini()->yolo();

// Plan — read-only analysis mode
AgentCtrl::gemini()->planMode();
// @doctest id="43ee"
```

## Sandbox Mode

Enable sandboxed execution for process isolation:

```php theme={null}
AgentCtrl::gemini()
    ->withSandbox()
    ->execute('Analyze the codebase.');
// @doctest id="323e"
```

On macOS, this uses Seatbelt (`sandbox-exec`). Docker, Podman, and gVisor are also supported.

## System Prompt

Gemini CLI reads instructions from a `GEMINI.md` file in the project root (similar to `CLAUDE.md`). You can also set the `GEMINI_SYSTEM_MD` environment variable to point to a custom system prompt file.

## Include Directories

Add additional workspace directories for the agent to access:

```php theme={null}
AgentCtrl::gemini()
    ->withIncludeDirectories(['/projects/shared-lib', '/projects/config'])
    ->execute('Check for shared dependencies.');
// @doctest id="11be"
```

## Extensions

Use specific extensions:

```php theme={null}
AgentCtrl::gemini()
    ->withExtensions(['my-extension'])
    ->execute('...');
// @doctest id="9152"
```

## MCP Servers

Restrict which MCP servers are available:

```php theme={null}
AgentCtrl::gemini()
    ->withAllowedMcpServers(['filesystem', 'github'])
    ->execute('...');
// @doctest id="9d5d"
```

## Policy Files

Load additional policy files for fine-grained tool approval rules:

```php theme={null}
AgentCtrl::gemini()
    ->withPolicy(['/path/to/policy.yaml'])
    ->execute('...');
// @doctest id="45ab"
```

## Allowed Tools

Restrict which tools the agent can use:

```php theme={null}
AgentCtrl::gemini()
    ->withAllowedTools(['read_file', 'search_files', 'list_directory'])
    ->execute('Analyze the codebase structure.');
// @doctest id="6089"
```

## Debug Mode

Enable debug output for troubleshooting CLI behavior:

```php theme={null}
AgentCtrl::gemini()
    ->debug()
    ->execute('Analyze the codebase.');
// @doctest id="1bc5"
```

## Streaming with Gemini

Gemini streams output as JSONL with the `stream-json` format. The bridge normalizes these into the standard callback API:

```php theme={null}
use Cognesy\AgentCtrl\AgentCtrl;
use Cognesy\AgentCtrl\Dto\AgentResponse;

$response = AgentCtrl::gemini()
    ->onText(fn(string $text) => print($text))
    ->onToolUse(fn(string $tool, array $input, ?string $output) => print("\n> [{$tool}]\n"))
    ->onError(fn(string $message, ?string $code) => print("\nError: {$message}\n"))
    ->onComplete(fn(AgentResponse $r) => print("\n--- Done ---\n"))
    ->executeStreaming('Analyze the error handling in this codebase.');
// @doctest id="2a86"
```

### Event Normalization

Gemini emits stream-json events that are normalized:

* **`message` (role=assistant, delta=true)** -- Text deltas delivered through `onText()`.
* **`tool_result`** -- Tool results delivered through `onToolUse()` with tool name, input (from paired `tool_use` event), result, and error status.
* **`error`** -- Errors delivered through `onError()` with severity and message.
* **`init`, `tool_use`, `result`** -- Lifecycle events available through the `wiretap()` event system.

## Session Management

Gemini CLI maintains session history. Agent-Ctrl extracts session IDs from the `init` event:

```php theme={null}
// First execution
$first = AgentCtrl::gemini()->execute('Create an implementation plan.');
$sessionId = $first->sessionId();

// Continue the most recent session
$next = AgentCtrl::gemini()
    ->continueSession()
    ->execute('Begin implementing the plan.');

// Resume a specific session by ID
if ($sessionId !== null) {
    $next = AgentCtrl::gemini()
        ->resumeSession((string) $sessionId)
        ->execute('Continue with the next step.');
}
// @doctest id="e10f"
```

## Usage Data

Gemini provides token usage data from the `result` event stats:

```php theme={null}
$response = AgentCtrl::gemini()
    ->withModel('flash')
    ->execute('Analyze the project dependencies.');

$usage = $response->usage();
if ($usage !== null) {
    echo "Input tokens:    {$usage->input}\n";
    echo "Output tokens:   {$usage->output}\n";
    echo "Total tokens:    {$usage->total()}\n";

    if ($usage->cacheRead !== null) {
        echo "Cached tokens:   {$usage->cacheRead}\n";
    }
}
// @doctest id="5db4"
```

## Data Availability

| Data Point        | Available | Notes                                                        |
| ----------------- | --------- | ------------------------------------------------------------ |
| Text output       | Yes       | Extracted from `message` events (role=assistant, delta=true) |
| Tool calls        | Yes       | Normalized from `tool_use` + `tool_result` event pairs       |
| Session ID        | Yes       | Extracted from `init` event                                  |
| Token usage       | Yes       | Input, output, cached tokens from `result` stats             |
| Cost              | No        | Gemini CLI does not expose cost data                         |
| Parse diagnostics | Yes       | Malformed JSON line counts and samples                       |

## Complete Example

```php theme={null}
use Cognesy\AgentCtrl\AgentCtrl;
use Cognesy\AgentCtrl\Dto\AgentResponse;
use Cognesy\AgentCtrl\Gemini\Domain\Enum\ApprovalMode;

$response = AgentCtrl::gemini()
    ->withModel('pro')
    ->withApprovalMode(ApprovalMode::AutoEdit)
    ->withIncludeDirectories(['/projects/shared'])
    ->withTimeout(300)
    ->inDirectory('/projects/app')
    ->onText(fn(string $text) => print($text))
    ->onToolUse(fn(string $tool, array $input, ?string $output) => print("\n> [{$tool}]\n"))
    ->onComplete(fn(AgentResponse $r) => print("\n--- Complete ---\n"))
    ->executeStreaming('Review the application architecture and suggest improvements.');

if ($response->isSuccess()) {
    echo "\nReview completed successfully.\n";
    echo "Tools used: " . count($response->toolCalls) . "\n";

    $usage = $response->usage();
    if ($usage !== null) {
        echo "Tokens: {$usage->total()} (in: {$usage->input}, out: {$usage->output})\n";
    }
} else {
    echo "\nFailed with exit code: {$response->exitCode}\n";
}
// @doctest id="b523"
```

## Comparison with Other Bridges

| Feature               | Claude Code            | Codex          | OpenCode   | Pi                     | Gemini                              |
| --------------------- | ---------------------- | -------------- | ---------- | ---------------------- | ----------------------------------- |
| System prompts        | Yes (replace + append) | No             | No         | Yes (replace + append) | Yes (GEMINI.md file)                |
| Permission modes      | Yes (4 levels)         | No             | No         | No                     | Yes (4 modes)                       |
| Turn limits           | Yes                    | No             | No         | No                     | Yes (via settings)                  |
| Sandbox modes         | No                     | Yes (3 levels) | No         | No                     | Yes (Seatbelt/Docker/Podman/gVisor) |
| Image input           | No                     | Yes            | No         | No                     | No                                  |
| Thinking levels       | No                     | No             | No         | Yes (6 levels)         | No                                  |
| Named agents          | No                     | No             | Yes        | No                     | No                                  |
| File attachments      | No                     | No             | Yes        | Yes (@-prefix)         | No                                  |
| Extensions            | No                     | No             | No         | Yes (TypeScript)       | Yes                                 |
| Skills                | No                     | No             | No         | Yes                    | No                                  |
| Tool control          | No                     | No             | No         | Yes (select/disable)   | Yes (allowlist)                     |
| MCP servers           | No                     | No             | No         | No                     | Yes                                 |
| Policy engine         | No                     | No             | No         | No                     | Yes                                 |
| Session sharing       | No                     | No             | Yes        | No                     | No                                  |
| Session titles        | No                     | No             | Yes        | No                     | No                                  |
| Ephemeral mode        | No                     | No             | No         | Yes                    | No                                  |
| API key override      | No                     | No             | No         | Yes                    | No                                  |
| Token usage           | No                     | Yes (partial)  | Yes (full) | Yes                    | Yes                                 |
| Cost tracking         | No                     | No             | Yes        | Yes                    | No                                  |
| Multi-provider models | No                     | No             | Yes        | Yes                    | No                                  |
| Include directories   | No                     | No             | No         | No                     | Yes                                 |
| Debug mode            | No                     | No             | No         | No                     | Yes                                 |
| Free tier             | No                     | No             | No         | No                     | Yes                                 |

## Environment Variables

| Variable                         | Description                     |
| -------------------------------- | ------------------------------- |
| `GEMINI_API_KEY`                 | Gemini API key                  |
| `GOOGLE_API_KEY`                 | Google Cloud API key            |
| `GOOGLE_APPLICATION_CREDENTIALS` | Service account JSON path       |
| `GOOGLE_CLOUD_PROJECT`           | Project ID for Code Assist      |
| `GOOGLE_GENAI_USE_VERTEXAI`      | Enable Vertex AI                |
| `GEMINI_SANDBOX`                 | Enable sandbox without CLI flag |
