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
Run in restricted execution mode. Prevents file modifications. CLI Mapping :
geminicli: -s or --sandbox
codex: --sandbox
claudecli: Not supported
vibe: Not supported
Skip confirmation prompts for file operations. CLI Mapping :
geminicli: -y or --yes
vibe: --auto-approve
claudecli: --dangerously-skip-permissions
codex: --full-auto
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
Sandbox Mode
Auto-Approve
YOLO Mode
# 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
}
}
}
)
# Skip confirmations for file modifications
response = client.chat.completions.create(
model = "claudecli:claude-sonnet-4" ,
messages = [
{ "role" : "user" , "content" : "Fix all linting errors" }
],
extra_body = {
"cli" : {
"attachments" : [{ "type" : "folder" , "path" : "./src/" }],
"flags" : {
"auto_approve" : True # Skip prompts
}
}
}
)
# Maximum autonomy - use with caution!
response = client.chat.completions.create(
model = "geminicli:gemini-2.5-pro" ,
messages = [
{ "role" : "user" , "content" : "Implement the feature" }
],
extra_body = {
"cli" : {
"attachments" : [{ "type" : "folder" , "path" : "./" }],
"flags" : {
"yolo" : True # Full autonomy
}
}
}
)
YOLO mode grants maximum autonomy. Only use in controlled environments or with proper backups.
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
Value Behavior "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
Provider Files Folders Flags Sessions 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: 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
Limitation Value Notes Max file size 10 MB Configurable in config.yaml Max total size 50 MB Sum of all attachments Max files 100 Per request Supported formats All text Binary files may fail
Best Practices
Start with Sandbox : Test with read-only mode first
Use Relative Paths : More portable and secure
Minimize Attachments : Only include relevant files
Name Sessions : Use descriptive session IDs for continuity
Validate Outputs : Review AI changes before committing
Next Steps