Skip to main content

Overview

CLI providers (geminicli:, claudecli:, codex:, vibe:, opencode:) support file and folder attachments through the extra_body.cli parameter. This enables the AI to read, analyze, and modify local files.
CLI attachments are only supported with CLI providers. API providers (gemini:, claude:, etc.) do not support this feature.

Syntax

Add attachments via the extra_body.cli.attachments array:
{
  "model": "geminicli:gemini-2.5-pro",
  "messages": [{"role": "user", "content": "Analyze this code"}],
  "extra_body": {
    "cli": {
      "attachments": [
        {"type": "file", "path": "/path/to/file.py"},
        {"type": "folder", "path": "./src/"}
      ]
    }
  }
}

Attachment Types

File Attachments

Attach a single file:
{
  "type": "file",
  "path": "/absolute/or/relative/path/to/file.py"
}
Supported Path Formats:
  • Absolute: /home/user/project/main.py
  • Relative: ./src/main.py (relative to server working directory)
  • Home directory: ~/projects/file.py

Folder Attachments

Attach an entire directory:
{
  "type": "folder",
  "path": "./src/"
}
All files in the folder and subdirectories are included.

Examples

Single File

curl http://localhost:18080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-test-123" \
  -d '{
    "model": "geminicli:gemini-2.5-pro",
    "messages": [
      {"role": "user", "content": "Fix the bugs in this code"}
    ],
    "extra_body": {
      "cli": {
        "attachments": [
          {"type": "file", "path": "./main.py"}
        ]
      }
    }
  }'

Multiple Files

response = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {"role": "user", "content": "Review this pull request"}
    ],
    extra_body={
        "cli": {
            "attachments": [
                {"type": "file", "path": "./src/main.py"},
                {"type": "file", "path": "./src/utils.py"},
                {"type": "file", "path": "./tests/test_main.py"}
            ]
        }
    }
)

Folder Attachment

response = client.chat.completions.create(
    model="claudecli:claude-sonnet-4",
    messages=[
        {"role": "user", "content": "Refactor this codebase to use TypeScript"}
    ],
    extra_body={
        "cli": {
            "attachments": [
                {"type": "folder", "path": "./src/"}
            ]
        }
    }
)

Mixed Attachments

Combine files and folders:
response = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {"role": "user", "content": "Add tests for the new features"}
    ],
    extra_body={
        "cli": {
            "attachments": [
                {"type": "folder", "path": "./src/"},       # Source code
                {"type": "folder", "path": "./tests/"},     # Existing tests
                {"type": "file", "path": "./package.json"}  # Dependencies
            ]
        }
    }
)

CLI Flags

Control CLI behavior with flags:
{
  "extra_body": {
    "cli": {
      "attachments": [...],
      "flags": {
        "sandbox": true,
        "auto_approve": true,
        "yolo": false
      }
    }
  }
}

Available Flags

sandbox
boolean
default:false
Run in restricted execution mode. Prevents file modifications.CLI Mapping:
  • geminicli: -s or --sandbox
  • codex: --sandbox
  • claudecli: Not supported
  • vibe: Not supported
auto_approve
boolean
default:false
Skip confirmation prompts for file operations.CLI Mapping:
  • geminicli: -y or --yes
  • vibe: --auto-approve
  • claudecli: --dangerously-skip-permissions
  • codex: --full-auto
yolo
boolean
default:false
Maximum autonomy mode. Combines auto-approve with other permissive flags.CLI Mapping:
  • geminicli: --yolo
  • vibe: --auto-approve
  • claudecli: --dangerously-skip-permissions
  • codex: --full-auto

Flag Examples

# Read-only mode - AI can view but not modify files
response = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {"role": "user", "content": "Analyze code quality"}
    ],
    extra_body={
        "cli": {
            "attachments": [{"type": "folder", "path": "./src/"}],
            "flags": {
                "sandbox": True  # Read-only
            }
        }
    }
)

Session Management

Resume or name CLI sessions:
response = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {"role": "user", "content": "Continue working on the feature"}
    ],
    extra_body={
        "cli": {
            "session_id": "my-project-session",
            "attachments": [{"type": "folder", "path": "./"}]
        }
    }
)

Session ID Values

ValueBehavior
"latest"Resume most recent session
"new"Force new session
"my-session-name"Named session (resumable)

Session Example

# First request: Start named session
response1 = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {"role": "user", "content": "Create a user authentication system"}
    ],
    extra_body={
        "cli": {
            "session_id": "auth-feature",
            "attachments": [{"type": "folder", "path": "./src/"}]
        }
    }
)

# Later request: Resume same session
response2 = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {"role": "user", "content": "Add password reset functionality"}
    ],
    extra_body={
        "cli": {
            "session_id": "auth-feature",  # Same session
            "attachments": [{"type": "folder", "path": "./src/"}]
        }
    }
)

Use Cases

Code Review

response = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {
            "role": "user",
            "content": "Review this code for security vulnerabilities and suggest improvements"
        }
    ],
    extra_body={
        "cli": {
            "attachments": [
                {"type": "folder", "path": "./src/"},
                {"type": "file", "path": "./package.json"}
            ],
            "flags": {"sandbox": True}  # Read-only review
        }
    }
)

Automated Refactoring

response = client.chat.completions.create(
    model="claudecli:claude-sonnet-4",
    messages=[
        {
            "role": "user",
            "content": "Refactor to use async/await throughout"
        }
    ],
    extra_body={
        "cli": {
            "attachments": [{"type": "folder", "path": "./src/"}],
            "flags": {"auto_approve": True}  # Auto-apply changes
        }
    }
)

Test Generation

response = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {
            "role": "user",
            "content": "Generate comprehensive unit tests for all functions"
        }
    ],
    extra_body={
        "cli": {
            "attachments": [
                {"type": "folder", "path": "./src/"},
                {"type": "folder", "path": "./tests/"}  # Existing tests for reference
            ]
        }
    }
)

Documentation Generation

response = client.chat.completions.create(
    model="codex:gpt-5",
    messages=[
        {
            "role": "user",
            "content": "Add comprehensive JSDoc comments to all functions"
        }
    ],
    extra_body={
        "cli": {
            "attachments": [{"type": "folder", "path": "./src/"}],
            "flags": {"auto_approve": True}
        }
    }
)

Codebase Migration

response = client.chat.completions.create(
    model="geminicli:gemini-2.5-pro",
    messages=[
        {
            "role": "user",
            "content": "Migrate from JavaScript to TypeScript. Add type definitions to all files."
        }
    ],
    extra_body={
        "cli": {
            "attachments": [
                {"type": "folder", "path": "./src/"},
                {"type": "file", "path": "./tsconfig.json"}
            ],
            "session_id": "ts-migration",
            "flags": {"auto_approve": True}
        }
    }
)

Provider Support

ProviderFilesFoldersFlagsSessions
geminicli
claudecli⚠️
codex
vibe⚠️
opencode
⚠️ = Partial support (limited flags)

Security Considerations

switchAILocal validates all file paths to prevent directory traversal attacks:
# Safe: Relative paths are resolved securely
{"type": "file", "path": "./src/main.py"}

# Unsafe: Absolute paths outside workspace are rejected
{"type": "file", "path": "/etc/passwd"}  # Blocked
Use sandbox mode for untrusted operations:
# Safe: Read-only analysis
extra_body={
    "cli": {
        "attachments": [...],
        "flags": {"sandbox": True}
    }
}
Large files may exceed CLI limits:
config.yaml
cli:
  max_attachment_size: 10485760  # 10MB
  max_total_size: 52428800       # 50MB
Avoid attaching sensitive files:
# Don't attach:
# - .env files
# - credentials.json
# - private keys
# - API tokens

Error Handling

from openai import OpenAI, APIError

client = OpenAI(
    base_url="http://localhost:18080/v1",
    api_key="sk-test-123"
)

try:
    response = client.chat.completions.create(
        model="geminicli:gemini-2.5-pro",
        messages=[
            {"role": "user", "content": "Analyze this file"}
        ],
        extra_body={
            "cli": {
                "attachments": [
                    {"type": "file", "path": "./nonexistent.py"}
                ]
            }
        }
    )
except APIError as e:
    if "file not found" in str(e).lower():
        print("File does not exist")
    elif "permission denied" in str(e).lower():
        print("Cannot access file")
    else:
        print(f"Error: {e.message}")

Limitations

LimitationValueNotes
Max file size10 MBConfigurable in config.yaml
Max total size50 MBSum of all attachments
Max files100Per request
Supported formatsAll textBinary files may fail

Best Practices

  1. Start with Sandbox: Test with read-only mode first
  2. Use Relative Paths: More portable and secure
  3. Minimize Attachments: Only include relevant files
  4. Name Sessions: Use descriptive session IDs for continuity
  5. Validate Outputs: Review AI changes before committing

Next Steps

Provider Prefixes

Learn about CLI provider routing

Chat Completions

Master the chat completions API

Configuration

Configure CLI provider settings

Build docs developers (and LLMs) love