---
name: OpenCode-CLI-Controller
description: A powerful skill to control Open Code CLI via a local web server API. Allows executing commands, managing sessions, and automating code generation remotely in the local network.
version: 1.1.0
emoji: 🎛️
author: Malek-Rsh
tags: 
  - cli
  - api
  - automation
  - web-server
  - opencode
metadata:
  openclaw:
    requires:
      bins: 
        - curl
        - jq
        - bash

    install: |
      chmod +x scripts/*.sh
      if ! command -v jq &> /dev/null; then
          echo "Warning: jq is required but not installed."
      fi
    run: |
      echo "OpenCode Control Skill is ready for use."
      echo "Please ensure the OpenCode server is running on port 4099."
---

# OpenCode CLI API Control

> [!IMPORTANT]
> **OPERATIONAL GUIDELINES**: 
> While you may use `ls` or basic file system checks to verify that files/directories exist, you are **EXPLICITLY PROHIBITED** from reading or modifying the project's source code files directly. 
> Your primary channel for task execution and progress monitoring is the **OpenCode API and the provided scripts**.

## Overview
This skill provides a set of tools to programmatically interface with the Open Code CLI through its local web server API. It enables you to act as a **Supervisor/Orchestrator** who directs OpenCode to handle all coding, file operations, and quality checks.

## Core Mandate: Orchestrator vs. Executor
- **You are NOT the Coder**: You do not write or verify code directly. OpenCode handles the implementation.
- **You are the Orchestrator**: You send high-level instructions to OpenCode, monitor its progress, and report the outcome to the user.
- **Trust the System**: OpenCode is responsible for its own file operations. Your job is to wait for it to finish and then check the *status* and *diff summary*, not the file contents.

## When to Use
- User requests creating or managing projects through OpenCode
- User asks for coding tasks, debugging, or code analysis via OpenCode
- User wants AI-powered development with specific providers/models
- User needs to manage multiple OpenCode sessions or monitor tasks

## Prerequisites
1. OpenCode server running (Preferred: `bash ./scripts/start_server.sh`)
2. Configuration file exists: `./config.json`
3. Required scripts in `./scripts/` directory

## Configuration

Read settings from `./config.json`:
```bash
BASE_URL=$(jq -r '.base_url' ./config.json)
PROJECTS_DIR=$(jq -r '.projects_base_dir' ./config.json)
```

## Important Agent Responsibilities

### Your Role as Orchestrator
You are the **supervisor and communication bridge** between the user and OpenCode. 

**Operational Boundaries**:
- ❌ **NEVER** read or edit the code files generated by OpenCode directly for development tasks.
- ❌ **NEVER** try to fix or verify code logic by inspecting the project files yourself.
- ✅ **MAY** use `ls` or simple directory checks only to confirm file existence if necessary.
- ⚠️ **PREFER** using the provided scripts and API for all project-related information.

**Required Workflow**:
- ✅ **PRIMARY**: Use `monitor_session.sh` or `check_status.sh` to track progress.
- ✅ **PRIMARY**: Use `get_diff.sh` to see a summary of what was changed.
- ✅ **ALWAYS** report the results based on the API response or script output.
- ✅ **TRUST** OpenCode's implementation of the requested features.

### Server Initialization Wait

**CRITICAL**: After starting OpenCode web server, it takes **10-15 seconds** to fully initialize. You **MUST** verify server readiness before sending any requests.

**Correct initialization sequence**:
```bash
# Start server using the robust backgrounding script
bash ./scripts/start_server.sh


# 3. Now safe to proceed with operations
bash ./scripts/update_providers.sh
# ... continue workflow
```

**Never** send requests immediately after starting the server - always verify health first.

### Intelligent Task Monitoring

For long-running tasks, use **smart monitoring** strategies:

**Option 1: Event-based monitoring (Recommended)**
```bash
# Start task
bash ./scripts/send_message.sh "Complex task" &

# Monitor events (blocks until completion)
bash ./scripts/monitor_session.sh
```

**Option 2: Intelligent polling**
```bash
# For environments where event streaming is unreliable
bash ./scripts/send_message.sh "Build application"

# Smart polling with exponential backoff
SLEEP_TIME=2
MAX_SLEEP=30

while true; do
  STATUS=$(bash ./scripts/check_status.sh)
  
  if [ "$STATUS" = "idle" ]; then
    echo "✓ Task completed"
    break
  elif [ "$STATUS" = "busy" ]; then
    echo "⟳ Still working... (checking again in ${SLEEP_TIME}s)"
    sleep $SLEEP_TIME
    
    # Increase wait time (but cap at MAX_SLEEP)
    SLEEP_TIME=$((SLEEP_TIME < MAX_SLEEP ? SLEEP_TIME + 2 : MAX_SLEEP))
  else
    echo "⚠ Unexpected status: $STATUS"
    break
  fi
done
```

**Option 3: Timeout-based waiting**
```bash
# For predictable task durations
bash ./scripts/send_message.sh "Quick task"

# Wait reasonable time before checking
sleep 10

# Then check once
if [ "$(bash ./scripts/check_status.sh)" = "idle" ]; then
  bash ./scripts/get_diff.sh
fi
```

**Anti-patterns to AVOID**:
- ❌ Checking status every 1-2 seconds (wastes resources)
- ❌ Reading files repeatedly to see if task is done
- ❌ Using `ls` or file system checks for progress
- ❌ Making multiple API calls without waiting

**Best practices**:
- ✅ Use `monitor_session.sh` for real-time updates
- ✅ Use exponential backoff for polling (start 2s, increase to 30s)
- ✅ Estimate task duration and wait appropriately
- ✅ Only check final results after confirmation of completion
- ✅ Let OpenCode agents work independently - don't micromanage

## Task Initiation Protocol

Before starting any task (new project, code analysis, debugging, etc.), **ask the user in ONE message**:

> I'll help you with that. Two quick questions:
> 1. **Provider**: Use default from config, or specify a provider (opencode, anthropic, gemini, etc.)?
> 2. **Monitoring**: 
>    - **Standard** (recommended): Send task → wait for completion summary → notify you when done (saves tokens)
>    - **Real-time**: Show live progress, file edits, and events as they happen (uses more tokens)
>
> How would you like to proceed?

**Default if not specified**: Use config defaults + Standard mode.

### Why This Matters
- **Standard mode**: Uses `send_message.sh` → waits → shows final summary. Efficient for most tasks.
- **Real-time mode**: Uses `monitor_session.sh` with event streaming. Good for long/complex tasks where you want visibility.

### Example Response Handling
- "Default provider, standard mode" → Proceed immediately
- "Use Claude Sonnet, real-time" → Run `select_provider.sh` then `monitor_session.sh`
- "Gemini Pro" → Find provider + ask monitoring preference if not specified

---

### Task Completion Verification

When a task completes, get summary via:
```bash
# Get file changes summary (not individual files)
bash ./scripts/get_diff.sh

# Output example:
# added: src/App.tsx (+120/-0)
# modified: package.json (+5/-2)
# added: src/components/Dashboard.tsx (+89/-0)
```

This gives you all information needed to report to the user without reading actual file contents.

**Only read specific files if**:
- User explicitly asks to see code
- User requests explanation of specific implementation
- Debugging a reported issue

Otherwise, trust the diff summary and OpenCode's implementation.

## Core Workflow

### Step 1: Verify Server
```bash
# Check health
curl -s "$BASE_URL/global/health" | jq

# Expected: {"healthy": true, "version": "..."}
```

### Step 2: Update Providers Cache
```bash
# Run provider update script
bash ./scripts/update_providers.sh
```

This caches **only connected providers** to `./providers.json`.

### Step 3: Create or Select Project

**New Project**:
```bash
PROJECT_NAME="dashboard-app"
PROJECT_PATH="$PROJECTS_DIR/$PROJECT_NAME"
mkdir -p "$PROJECT_PATH"
```

**Existing Project**:
```bash
PROJECT_NAME="existing-app"
PROJECT_PATH="$PROJECTS_DIR/$PROJECT_NAME"
# Verify exists
[ -d "$PROJECT_PATH" ] || { echo "Project not found"; exit 1; }
```

### Step 4: Create Session
Create a session in the project directory using the provided script:
```bash
SESSION_ID=$(bash ./scripts/create_session.sh "$PROJECT_PATH" "Session Title")
```

### Step 5: Save Session State
```bash
# Use state management script
bash ./scripts/save_state.sh "$SESSION_ID" "$PROJECT_PATH"
```

### Step 6: Send Message
Use the provided script to send prompts to the AI:
```bash
# Use defaults from config
bash ./scripts/send_message.sh "Your prompt here"

# Or use a specific provider and model
bash ./scripts/send_message.sh "Your prompt" "anthropic" "claude-sonnet-4-5"
```

### Step 7: Monitor Progress (For Long Tasks)
```bash
# Start monitoring in background
bash ./scripts/monitor_session.sh &

# Or check status periodically
bash ./scripts/check_status.sh
```

## Provider Selection

### Automatic (uses default from config.json)
```bash
bash ./scripts/send_message.sh "Create app"
```

### User Specifies Provider
When the user specifies a provider (e.g., "use Gemini Pro" or "with Claude Sonnet"), use the search script:
```bash
# Search for provider and model hints
RESULT=$(bash ./scripts/select_provider.sh "gemini" "pro")
# Returns: gemini gemini-3-pro

# Extract and use the returned values
PROVIDER_ID=$(echo "$RESULT" | cut -d' ' -f1)
MODEL_ID=$(echo "$RESULT" | cut -d' ' -f2)

bash ./scripts/send_message.sh "Your prompt" "$PROVIDER_ID" "$MODEL_ID"
```

## Agent Selection

**Default (no agent specified - recommended)**:
```bash
bash ./scripts/send_message.sh "Build app"
```

**Planning phase**:
```bash
bash ./scripts/send_message.sh "Analyze requirements" "plan"
```

**Implementation phase**:
```bash
bash ./scripts/send_message.sh "Implement features" "build"
```

## Common Patterns

### Pattern 1: New Project from Scratch
```bash
# 1. Update providers
bash ./scripts/update_providers.sh

# 2. Create project directory
mkdir -p "$PROJECTS_DIR/new-app"

# 3. Create session
SESSION_ID=$(bash ./scripts/create_session.sh "$PROJECTS_DIR/new-app" "New App")

# 4. Send initial task
bash ./scripts/send_message.sh "Create React app with TypeScript and Tailwind"

# 5. Monitor progress
bash ./scripts/monitor_session.sh
```

### Pattern 2: Continue Existing Project
```bash
# 1. Load saved project state
bash ./scripts/load_project.sh "existing-app"

# 2. Send new task
bash ./scripts/send_message.sh "Add authentication feature"
```

### Pattern 3: Multi-Phase Development
```bash
# Phase 1: Planning
bash ./scripts/create_session.sh "$PROJECT_PATH" "Planning"
bash ./scripts/send_message.sh "Plan e-commerce platform" "plan"

# Phase 2: Implementation
bash ./scripts/send_message.sh "Implement the plan" "build"

# Phase 3: Review
bash ./scripts/get_diff.sh
```

### Pattern 4: Use Specific Provider
```bash
# User says: "Create dashboard using Claude Sonnet"

# 1. Select provider
PROVIDER_MODEL=$(bash ./scripts/select_provider.sh "claude" "sonnet")
PROVIDER_ID=$(echo "$PROVIDER_MODEL" | cut -d' ' -f1)
MODEL_ID=$(echo "$PROVIDER_MODEL" | cut -d' ' -f2)

# 2. Create project and session
mkdir -p "$PROJECTS_DIR/dashboard"
SESSION_ID=$(bash ./scripts/create_session.sh "$PROJECTS_DIR/dashboard" "Dashboard")

# 3. Send with selected provider
bash ./scripts/send_message.sh "Create dashboard" "$PROVIDER_ID" "$MODEL_ID"
```

## Event Monitoring

For long-running tasks, monitor events:
```bash
# Start monitoring (shows progress in real-time)
bash ./scripts/monitor_session.sh

# This will:
# - Show text deltas as they're generated
# - Display status changes (busy/idle)
# - Show final token count and cost
# - Exit when task completes
```

## State Management

All session state is saved in `./state/`:
```bash
# Save current session
bash ./scripts/save_state.sh "$SESSION_ID" "$PROJECT_PATH"

# Load state (sets environment variables)
source ./scripts/load_state.sh
echo $SESSION_ID
echo $PROJECT_PATH

# Save project-specific state
bash ./scripts/save_project.sh "project-name"

# Load project-specific state
bash ./scripts/load_project.sh "project-name"

# List all saved projects
ls -1 ./state/*.json | grep -v current.json | xargs -n1 basename .json
```

## File Operations

Get session changes:
```bash
bash ./scripts/get_diff.sh
```

Get file content:
```bash
curl -s "$BASE_URL/file/content?directory=$PROJECT_PATH&path=src/App.tsx" \
  jq -r '.content'
```

List directory:
```bash
curl -s "$BASE_URL/file?directory=$PROJECT_PATH&path=src" \
  jq -r '.[] | "\(.type): \(.path)"'
```

## Error Handling

All scripts return proper exit codes:
- `0` = Success
- `1` = Error

Check script status:
```bash
if bash ./scripts/send_message.sh "prompt"; then
  echo "Success"
else
  echo "Failed - check server or authentication"
fi
```

## Authentication

This skill assumes the OpenCode server is running in a trusted local environment and does not use password authentication by default.


## Quick Reference

| Task | Command |
|------|---------|
| Update providers | `bash ./scripts/update_providers.sh` |
| Create session | `bash ./scripts/create_session.sh "$PATH" "Title"` |
| Send message | `bash ./scripts/send_message.sh "prompt"` |
| With provider | `bash ./scripts/send_message.sh "prompt" "provider" "model"` |
| Monitor progress | `bash ./scripts/monitor_session.sh` |
| Check status | `bash ./scripts/check_status.sh` |
| Get changes | `bash ./scripts/get_diff.sh` |
| Save state | `bash ./scripts/save_state.sh "$SID" "$PATH"` |
| Load state | `source ./scripts/load_state.sh` |
| Save project | `bash ./scripts/save_project.sh "name"` |
| Load project | `bash ./scripts/load_project.sh "name"` |
| Select provider | `bash ./scripts/select_provider.sh "name" "model"` |

## Important Notes

1.  **Always run from skill directory**: Scripts use relative paths
2.  **Update providers at workflow start**: Ensures cache is fresh
3.  **Create projects in PROJECTS_BASE_DIR**: Configured in config.json
4.  **Each session belongs to one project directory**: Don't mix
5.  **Load state before curl commands**: Ensures variables are set
6.  **Scripts handle authentication**: No need to add headers manually

## Troubleshooting

**"No active session"**:
```bash
# Load or create session first
bash ./scripts/create_session.sh "$PROJECT_PATH" "Title"
```

**"Provider not found"**:
```bash
# Update providers cache
bash ./scripts/update_providers.sh

# Check available providers
jq -r '.providers[] | .id' ./providers.json
```

**"HTML response instead of JSON"**:
- Missing `directory` parameter
- Check: Are you using full PROJECT_PATH?


## Advanced Usage

For complex workflows, state management, or advanced patterns, see:
- `Reference/STATE_MANAGEMENT.md` - Advanced state handling
- `Reference/PROVIDERS_REFERENCE.md` - Provider selection details
- `Reference/EVENTS_GUIDE.md` - Event monitoring patterns
- `Reference/COMPLETE_EXAMPLES.md` - Full workflow examples
- `Reference/API_QUICK_REFERENCE.md` - Raw API endpoints

## Directory Structure
```
opencode-api-control/
├── SKILL.md                    # This file
├── config.json                 # Configuration
├── providers.json              # Connected providers cache
├── scripts/                    # Helper scripts
│   ├── update_providers.sh
│   ├── create_session.sh
│   ├── send_message.sh
│   ├── monitor_session.sh
│   ├── check_status.sh
│   ├── get_diff.sh
│   ├── save_state.sh
│   ├── load_state.sh
│   ├── save_project.sh
│   ├── load_project.sh
│   └── select_provider.sh
├── state/                      # Session state
│   ├── current.json
│   └── project-name.json
└── Reference/                       # Reference docs
    ├── STATE_MANAGEMENT.md
    ├── PROVIDERS_REFERENCE.md
    ├── EVENTS_GUIDE.md
    ├── COMPLETE_EXAMPLES.md
    └── API_QUICK_REFERENCE.md
```
---
**Author:** [Malek RSH](https://github.com/malek262) | **Repository:** [OpenCode-CLI-Controller](https://github.com/malek262/opencode-api-control-skill)