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

# Coding Backends

> Enable AI coding capabilities with OpenCode or Claude Code

Station integrates with AI coding assistants to provide powerful coding capabilities. Unlike sandbox execution which runs in isolated containers, coding backends work directly on your local filesystem with full IDE-like features.

## Supported Backends

| Backend         | Transport      | Description                                                                                           |
| --------------- | -------------- | ----------------------------------------------------------------------------------------------------- |
| `opencode`      | HTTP           | [OpenCode](https://github.com/sst/opencode) server                                                    |
| `opencode-cli`  | CLI subprocess | OpenCode CLI binary                                                                                   |
| `opencode-nats` | NATS messaging | OpenCode via NATS for distributed setups                                                              |
| `claudecode`    | CLI subprocess | [Claude Code](https://docs.anthropic.com/en/docs/claude-code) CLI (Anthropic's official coding agent) |

## Coding Backends vs Sandbox

<CardGroup cols={2}>
  <Card title="Coding Backends" icon="code">
    **Local development** with full filesystem access. AI reads, writes, and refactors code on your machine.
  </Card>

  <Card title="Sandbox Execution" icon="box">
    **Isolated containers** for safe code execution. Code runs in ephemeral Docker containers.
  </Card>
</CardGroup>

| Feature      | Coding Backends                       | Sandbox                           |
| ------------ | ------------------------------------- | --------------------------------- |
| Filesystem   | Direct local access                   | Container isolated                |
| Use case     | Code development, refactoring         | Script execution, data processing |
| Persistence  | Changes persist on disk               | Ephemeral (container destroyed)   |
| Tools        | `coding_open`, `code`, `coding_close` | `sandbox_run`, `sandbox_exec`     |
| Requirements | OpenCode or Claude Code CLI           | Docker                            |

## How It Works

OpenCode backend creates **coding sessions** that give agents access to your local filesystem:

```
┌─────────────────────────────────────────────────────────────┐
│  YOUR MACHINE                                               │
│                                                             │
│  ┌─────────────┐      ┌─────────────┐      ┌─────────────┐  │
│  │   Station   │─────▶│  OpenCode   │─────▶│ Filesystem  │  │
│  │   Agent     │      │   Server    │      │  /my/code   │  │
│  └─────────────┘      └─────────────┘      └─────────────┘  │
│        │                    │                               │
│        │    1. coding_open  │                               │
│        │───────────────────▶│  Creates session              │
│        │                    │                               │
│        │    2. code         │                               │
│        │───────────────────▶│  AI writes/edits files        │
│        │                    │                               │
│        │    3. coding_close │                               │
│        │───────────────────▶│  Ends session                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

1. **Session Creation**: Agent calls `coding_open` with a workspace path
2. **Code Operations**: Agent sends tasks via `code` tool - OpenCode's AI reads, writes, and modifies files
3. **Session End**: Agent calls `coding_close` to clean up

## Quick Start

### 1. Install OpenCode

```bash theme={null}
# macOS
brew install opencode-ai/tap/opencode

# Linux (via curl)
curl -fsSL https://opencode.ai/install.sh | sh

# Or build from source
go install github.com/sst/opencode@latest
```

### 2. Start OpenCode Server

```bash theme={null}
# Start OpenCode (binds to localhost:4096 by default)
opencode

# Or specify a different port
opencode --port 4000
```

<Warning>
  For container mode (`stn up`), you must bind to all interfaces:

  ```bash theme={null}
  opencode --hostname 0.0.0.0
  ```

  See [Container Mode](#container-mode-stn-up) for details.
</Warning>

### 3. Configure Station

Add OpenCode URL to your Station config:

```yaml theme={null}
# ~/.config/station/config.yaml
coding:
  opencode:
    url: http://localhost:4096
```

### 4. Create an Agent with Coding Backend

```yaml theme={null}
---
metadata:
  name: "Code Assistant"
  description: "AI coding assistant with local filesystem access"
model: openai/gpt-4o
coding:
  enabled: true
  backend: opencode
---

You are an expert software engineer. Use your coding tools to:
- Read and understand existing code
- Write new files and functions
- Refactor and improve code quality
- Fix bugs and implement features

When given a task, open a coding session, complete the work, then close the session.
```

### 5. Run the Agent

```bash theme={null}
stn agent run "Code Assistant" "Create a Python CLI tool that converts CSV to JSON"
```

## Coding Tools

When `coding.enabled: true` and `coding.backend: opencode`, agents receive these tools:

| Tool            | Description                                           |
| --------------- | ----------------------------------------------------- |
| `coding_open`   | Start a coding session in a workspace directory       |
| `code`          | Send coding tasks to OpenCode (read, write, refactor) |
| `coding_close`  | End the coding session                                |
| `coding_commit` | Commit changes with a message (if in git repo)        |
| `coding_push`   | Push commits to remote (if in git repo)               |
| `coding_branch` | Create and/or switch to a git branch                  |

### Tool Reference

<Tabs>
  <Tab title="coding_open">
    Start a new coding session or continue an existing one.

    | Parameter             | Type   | Required | Description                        |
    | --------------------- | ------ | -------- | ---------------------------------- |
    | `workspace_path`      | string | No       | Directory to work in               |
    | `repo_url`            | string | No       | Git repository to clone            |
    | `branch`              | string | No       | Branch to checkout after cloning   |
    | `existing_session_id` | string | No       | Continue an existing session by ID |
    | `title`               | string | No       | Friendly name for the session      |
    | `scope`               | string | No       | `agent` (default) or `workflow`    |

    ```json theme={null}
    {
      "workspace_path": "/home/user/my-project"
    }
    ```

    To continue an existing session:

    ```json theme={null}
    {
      "existing_session_id": "ses_47b42f435ffeOJLjZKhPMk0Adu",
      "workspace_path": "/home/user/my-project"
    }
    ```

    Returns session ID for subsequent operations.
  </Tab>

  <Tab title="code">
    Execute a coding task. OpenCode's AI will read, write, or modify files as needed.

    | Parameter | Type   | Required | Description                   |
    | --------- | ------ | -------- | ----------------------------- |
    | `task`    | string | Yes      | What to do (natural language) |

    ```json theme={null}
    {
      "task": "Add error handling to the parse_config function in config.py"
    }
    ```
  </Tab>

  <Tab title="coding_close">
    End the current coding session.

    No parameters required. Call when done with coding tasks.
  </Tab>

  <Tab title="coding_commit">
    Commit changes to git.

    | Parameter | Type   | Required | Description    |
    | --------- | ------ | -------- | -------------- |
    | `message` | string | Yes      | Commit message |

    ```json theme={null}
    {
      "message": "Add error handling to config parser"
    }
    ```
  </Tab>

  <Tab title="coding_push">
    Push commits to remote repository.

    No parameters required. Pushes current branch to origin.
  </Tab>

  <Tab title="coding_branch">
    Create and/or switch to a git branch.

    | Parameter    | Type    | Required | Description                                           |
    | ------------ | ------- | -------- | ----------------------------------------------------- |
    | `session_id` | string  | Yes      | The coding session ID                                 |
    | `branch`     | string  | Yes      | Branch name to create/switch to                       |
    | `create`     | boolean | No       | Create the branch if it doesn't exist (default: true) |

    ```json theme={null}
    {
      "session_id": "abc123",
      "branch": "feature/add-logging",
      "create": true
    }
    ```

    Returns branch operation result:

    ```json theme={null}
    {
      "success": true,
      "branch": "feature/add-logging",
      "created": true,
      "switched_to": true,
      "previous_branch": "main"
    }
    ```
  </Tab>
</Tabs>

## Backend Options

Station supports three backend options for OpenCode integration:

| Backend         | Transport      | Use Case                                        |
| --------------- | -------------- | ----------------------------------------------- |
| `opencode`      | HTTP           | Local development, same machine                 |
| `opencode-nats` | NATS           | Containers, distributed setups, remote OpenCode |
| `opencode-cli`  | CLI subprocess | CI/CD, GitHub Actions, no server required       |

<Note>
  The backend is configured at the **Station level** (`config.yaml`), not per-agent. All agents with `coding.enabled: true` use the same backend. This keeps agent definitions portable across environments.
</Note>

### HTTP Backend (`opencode`)

Direct HTTP communication with OpenCode. Best for local development where OpenCode runs on the same machine.

```
Station Agent → HTTP → OpenCode Server → Filesystem
```

### NATS Backend (`opencode-nats`)

Uses NATS messaging for communication. Best for containerized or distributed setups where OpenCode runs remotely or in a container with the Station plugin.

```
Station Agent → NATS → Station Plugin → OpenCode → Filesystem
```

The NATS backend enables:

* Running OpenCode in a separate container
* Decoupled architecture (Station and OpenCode can restart independently)
* Multiple Station instances sharing one OpenCode

### CLI Backend (`opencode-cli`)

Spawns `opencode run` as a subprocess for each task. No server required - OpenCode bootstraps itself on a random port for each execution.

```
Station Agent → spawn process → opencode run --format json "task" → Filesystem
```

The CLI backend is ideal for:

* **CI/CD pipelines** (GitHub Actions, GitLab CI)
* **Serverless environments** where you can't run a persistent server
* **Simple setups** without infrastructure dependencies
* **Session continuation** across multiple agent runs

## Configuration Reference

### HTTP Backend Config

```yaml theme={null}
# ~/.config/station/config.yaml
coding:
  backend: opencode               # HTTP backend
  opencode:
    url: http://localhost:4096    # OpenCode server URL
  max_attempts: 3
  task_timeout_min: 10
```

### NATS Backend Config

```yaml theme={null}
# ~/.config/station/config.yaml
coding:
  backend: opencode-nats          # NATS backend
  nats:
    url: nats://localhost:4222    # NATS server URL
    # creds_file: /path/to/creds  # Optional: NATS credentials
  max_attempts: 3
  task_timeout_min: 10
```

<Warning>
  When using `opencode-nats`, ensure the OpenCode container has the Station plugin installed and is connected to the same NATS server. See [OpenCode Container](/station/opencode-container) for setup instructions.
</Warning>

### CLI Backend Config

```yaml theme={null}
# ~/.config/station/config.yaml
coding:
  backend: opencode-cli           # CLI subprocess backend
  cli:
    binary_path: opencode         # Path to opencode binary (default: "opencode")
    timeout_sec: 300              # Task timeout in seconds (default: 300)
  workspace_base_path: /tmp/station-coding
  cleanup_policy: on_session_end  # on_session_end | on_success | manual
```

<Note>
  The CLI backend requires `opencode` to be installed and available in your PATH. No server needs to be running - each task spawns a fresh OpenCode process.
</Note>

### Claude Code Backend Config

[Claude Code](https://docs.anthropic.com/en/docs/claude-code) is Anthropic's official AI coding agent. It uses your Claude Max/Pro subscription or API key.

```yaml theme={null}
# ~/.config/station/config.yaml
coding:
  backend: claudecode              # Claude Code CLI backend
  claudecode:
    binary_path: claude            # Path to claude CLI (default: "claude")
    timeout_sec: 300               # Task timeout in seconds (default: 300)
    model: sonnet                  # Model: sonnet, opus, haiku (optional)
    max_turns: 10                  # Max agentic turns (default: 10)
    allowed_tools:                 # Whitelist specific tools (optional)
      - Read
      - Write
      - Edit
      - Bash
      - Glob
      - Grep
    disallowed_tools: []           # Blacklist tools (optional)
  workspace_base_path: /tmp/station-coding
  cleanup_policy: on_session_end
```

<Tabs>
  <Tab title="Prerequisites">
    1. **Install Claude Code CLI**: [https://docs.anthropic.com/en/docs/claude-code](https://docs.anthropic.com/en/docs/claude-code)
    2. **Authenticate**: Run `claude login` for Max/Pro, or set `ANTHROPIC_API_KEY`

    ```bash theme={null}
    # Verify installation
    claude --version

    # Authenticate (for Max/Pro subscribers)
    claude login
    ```
  </Tab>

  <Tab title="Authentication">
    Claude Code CLI manages its own authentication, **separate from Station**:

    | Auth Method    | Setup                                        |
    | -------------- | -------------------------------------------- |
    | Claude Max/Pro | Run `claude login` in terminal               |
    | API Key        | Set `ANTHROPIC_API_KEY` environment variable |

    <Note>
      Station's OAuth tokens (from `stn auth anthropic login`) are used for Station's orchestration layer, NOT for Claude Code. This separation allows using different accounts for orchestration vs coding.
    </Note>
  </Tab>

  <Tab title="Quick Start">
    ```bash theme={null}
    # 1. Ensure claude CLI is authenticated
    claude --version
    claude login  # if needed

    # 2. Configure Station
    cat >> ~/.config/station/config.yaml << 'EOF'
    coding:
      backend: claudecode
      claudecode:
        timeout_sec: 300
        max_turns: 10
    EOF

    # 3. Create a coding agent
    stn agent create coder \
      --description "Coding assistant using Claude Code" \
      --prompt "You are a coding assistant. Use coding tools to accomplish tasks." \
      --coding '{"enabled":true}' \
      --max-steps 10

    # 4. Run it
    stn agent run coder "Create a hello.py that prints Hello World" --tail
    ```
  </Tab>
</Tabs>

<Warning>
  Claude Code runs with `--dangerously-skip-permissions` for non-interactive use. Ensure workspace directories are appropriately secured.
</Warning>

### Private Repository Authentication

To work with private repositories, configure git credentials in your Station config:

```yaml theme={null}
# ~/.config/station/config.yaml
coding:
  backend: opencode-cli  # or any backend
  git:
    # Option 1: Reference an environment variable (recommended)
    token_env: GITHUB_TOKEN
    
    # Option 2: Direct token (supports env expansion)
    # token: ${GITHUB_TOKEN}
    
    # Optional: Custom git identity for commits
    user_name: "My Bot"
    user_email: "bot@example.com"
```

<Tabs>
  <Tab title="GitHub PAT">
    Create a Personal Access Token with `repo` scope:

    1. Go to **GitHub Settings → Developer Settings → Personal Access Tokens**
    2. Generate a token with `repo` (full control of private repositories)
    3. Set it as an environment variable:

    ```bash theme={null}
    export GITHUB_TOKEN=ghp_xxxxxxxxxxxx
    ```
  </Tab>

  <Tab title="GitHub App">
    For organization repos, use a GitHub App token:

    ```bash theme={null}
    # Generate installation token via GitHub API or gh CLI
    export GITHUB_TOKEN=$(gh auth token)
    ```
  </Tab>

  <Tab title="GitLab">
    Create a Project Access Token or Personal Access Token:

    ```bash theme={null}
    export GITHUB_TOKEN=glpat-xxxxxxxxxxxx  # GitLab uses same injection method
    ```
  </Tab>
</Tabs>

<Warning>
  **Security Notes:**

  * Never commit tokens to config files - use `token_env` to reference environment variables
  * Tokens are automatically redacted from logs and error messages
  * In CI/CD, use secrets management (GitHub Secrets, Vault, etc.)
</Warning>

**Example: Clone and work on a private repo**

```yaml theme={null}
# Agent prompt
---
coding:
  enabled: true
---
Clone the private repository and add a README:

1. coding_open with repo_url="https://github.com/myorg/private-repo"
2. code with instruction="Create a comprehensive README.md"
3. coding_commit with message="Add README"
4. coding_push
5. coding_close
```

The git token is automatically injected into HTTPS URLs during clone/push operations.

### When to Use Each Backend

<Tabs>
  <Tab title="Decision Matrix">
    | Scenario                                    | Recommended Backend            | Reason                                    |
    | ------------------------------------------- | ------------------------------ | ----------------------------------------- |
    | Claude Max/Pro subscriber                   | `claudecode`                   | Use your subscription, minimal setup      |
    | Prefer Anthropic's official tooling         | `claudecode`                   | First-party Claude integration            |
    | Local development, OpenCode on same machine | `opencode` (HTTP)              | Simplest setup, direct communication      |
    | Docker/container deployments                | `opencode-nats`                | Cross-container networking works reliably |
    | Long-running tasks (>60s)                   | `opencode-nats`                | Avoids MCP timeout issues                 |
    | Multiple Station instances                  | `opencode-nats`                | Shared OpenCode server                    |
    | CI/CD pipelines (GitHub Actions)            | `opencode-cli` or `claudecode` | No server required, self-bootstrapping    |
    | Serverless / ephemeral environments         | `opencode-cli` or `claudecode` | Zero infrastructure dependencies          |
    | Session continuation across runs            | `opencode-cli`                 | Built-in session ID tracking              |
    | Quick prototyping                           | `opencode` (HTTP)              | Zero additional infrastructure            |
  </Tab>

  <Tab title="Architecture Comparison">
    **HTTP Backend (OpenCode):**

    ```
    Station → HTTP Request → OpenCode → Response
    (synchronous, ~60s timeout)
    ```

    **NATS Backend (OpenCode):**

    ```
    Station → NATS Publish → Station Plugin → OpenCode → NATS Reply
    (asynchronous, configurable timeout)
    ```

    **CLI Backend (Claude Code):**

    ```
    Station → spawn process → claude -p "task" --print → Response
    (subprocess, configurable timeout)
    ```

    The NATS backend decouples Station from OpenCode, allowing:

    * Independent restarts
    * Multiple consumers
    * Better timeout handling
  </Tab>

  <Tab title="Backend Comparison">
    | Feature        | Claude Code        | OpenCode HTTP | OpenCode CLI   |
    | -------------- | ------------------ | ------------- | -------------- |
    | Setup          | `claude login`     | Start server  | Install binary |
    | Auth           | Max/Pro or API key | API key       | API key        |
    | Latency        | Low (local)        | Medium (HTTP) | Low (local)    |
    | Multi-tenant   | No                 | Yes           | No             |
    | Session Resume | Yes (`--resume`)   | Yes           | Yes            |
    | Streaming      | Yes                | Yes           | Yes            |
    | OTEL Tracing   | Yes                | Yes           | Yes            |
  </Tab>
</Tabs>

## Long-Running Tasks and Timeouts

<Warning>
  MCP (Model Context Protocol) has a **default timeout of \~60 seconds**. Complex coding tasks like project scaffolding, large refactors, or multi-file changes may exceed this limit.
</Warning>

### Understanding the Timeout

When Station executes agent tools via MCP, each tool call has a timeout. If OpenCode takes longer than 60 seconds to complete a task, the MCP call will fail with a timeout error.

**Tasks that commonly timeout:**

* Generating entire project structures (scaffolding)
* Large codebase refactors
* Complex multi-file changes
* Tasks requiring many LLM calls (iterative refinement)

**Tasks that typically complete quickly:**

* Single file edits
* Adding/modifying functions
* Code review and analysis
* Simple bug fixes

### Solutions for Long-Running Tasks

<Tabs>
  <Tab title="Break Into Smaller Tasks">
    Instead of one large task, use multiple smaller ones:

    ```yaml theme={null}
    # ❌ Might timeout
    task: "Create a full REST API with authentication, CRUD endpoints, and database models"

    # ✅ Better approach
    tasks:
      - "Create the database models for User and Post"
      - "Add authentication middleware"
      - "Create CRUD endpoints for User"
      - "Create CRUD endpoints for Post"
    ```

    Design your agents to work incrementally.
  </Tab>

  <Tab title="Use NATS Backend">
    The NATS backend handles long-running tasks better:

    ```yaml theme={null}
    # config.yaml
    coding:
      backend: opencode-nats
      task_timeout_min: 15  # 15 minutes
      nats:
        url: nats://localhost:4222
    ```

    The `task_timeout_min` setting controls how long to wait for OpenCode responses.
  </Tab>

  <Tab title="Async Execution">
    For very long tasks, use async agent execution:

    ```bash theme={null}
    # Start task async
    stn agent call "Code Assistant" \
      --task "Refactor the entire codebase to TypeScript" \
      --async

    # Check status
    stn runs list
    stn runs get <run_id>
    ```

    Async execution is not bound by MCP timeouts.
  </Tab>
</Tabs>

### Timeout Configuration

| Setting            | Location         | Default | Description                           |
| ------------------ | ---------------- | ------- | ------------------------------------- |
| `task_timeout_min` | `config.yaml`    | 10      | Minutes to wait for OpenCode response |
| `max_attempts`     | `config.yaml`    | 3       | Retry attempts on failure             |
| MCP timeout        | Protocol default | \~60s   | Cannot be changed easily              |

```yaml theme={null}
# config.yaml
coding:
  backend: opencode-nats
  max_attempts: 3
  task_timeout_min: 15  # Increase for complex tasks
```

<Note>
  The `task_timeout_min` setting only affects the NATS backend. For HTTP backend, you're constrained by the MCP protocol timeout.
</Note>

## Session Continuation (CLI Backend)

The CLI backend supports **session continuation** - allowing multiple agent runs to share the same OpenCode context. This is useful for:

* Multi-step workflows where each step builds on previous work
* Interactive development with human-in-the-loop review
* CI/CD pipelines that need to maintain state across jobs

### How It Works

1. **First run** creates a new session (title = your task message)
2. **Subsequent runs** use `--coding-session <name>` to continue by title
3. OpenCode maintains conversation history, file context, and tool state

```
Run 1: "Create feature branch for user-auth"
         ↓ session title: "Create feature branch for user-auth"
Run 2: --coding-session "user-auth" → finds session by title
         ↓ context preserved
Run 3: --coding-session "user-auth" → same session
         ↓ context preserved  
Run 4: --coding-session "user-auth" → commit and push
```

### Using Session Continuation

<Tabs>
  <Tab title="CLI Flag">
    Pass a session name or ID to continue from a previous run:

    ```bash theme={null}
    # First run - creates new session (title = first message)
    stn agent run "Code Assistant" "Create a new feature branch for user-auth"
    # Session title: "Create a new feature branch for user-auth"

    # Second run - continue by name (partial match works!)
    stn agent run "Code Assistant" "Implement the login endpoint" \
      --coding-session "user-auth"

    # Or use any part of the title
    stn agent run "Code Assistant" "Add unit tests for login" \
      --coding-session "feature branch"

    # Or use the exact session ID
    stn agent run "Code Assistant" "Final cleanup" \
      --coding-session "ses_47b42f435ffeOJLjZKhPMk0Adu"
    ```

    The `--coding-session` flag accepts:

    * **Session name** - Searches titles (case-insensitive, partial match)
    * **Session ID** - Direct lookup (starts with `ses_`)

    <Tip>
      Run `opencode session list` to see all sessions with their titles.
    </Tip>
  </Tab>

  <Tab title="Tool Parameter">
    The `coding_open` tool also accepts a session name or ID:

    ```json theme={null}
    {
      "existing_session_id": "user-auth",
      "workspace_path": "/path/to/project"
    }
    ```

    Or with the full ID:

    ```json theme={null}
    {
      "existing_session_id": "ses_47b42f435ffeOJLjZKhPMk0Adu",
      "workspace_path": "/path/to/project"
    }
    ```
  </Tab>

  <Tab title="GitHub Actions">
    Use session continuation in multi-job workflows:

    ```yaml theme={null}
    jobs:
      implement:
        runs-on: ubuntu-latest
        outputs:
          session_id: ${{ steps.implement.outputs.session_id }}
        steps:
          - uses: actions/checkout@v4
          - name: Install Station & OpenCode
            run: |
              # Install station and opencode
              curl -fsSL https://station.dev/install.sh | sh
              curl -fsSL https://opencode.ai/install.sh | sh
          
          - name: Implement Feature
            id: implement
            run: |
              OUTPUT=$(stn agent run "Developer" "Implement the requested feature" 2>&1)
              SESSION_ID=$(echo "$OUTPUT" | grep -oP 'Session ID: \K[^\s]+')
              echo "session_id=$SESSION_ID" >> $GITHUB_OUTPUT
      
      test:
        needs: implement
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - name: Add Tests
            run: |
              stn agent run "Developer" "Add tests for the new feature" \
                --coding-session "${{ needs.implement.outputs.session_id }}"
    ```
  </Tab>
</Tabs>

### Listing Sessions

You don't need to remember session IDs - just use part of the session title. But if you want to see all sessions:

```bash theme={null}
# List all sessions with titles
opencode session list

# Output:
# Session ID                      Title                              Updated
# ───────────────────────────────────────────────────────────────────────────
# ses_47b8a7be0ffe...             Create feature branch for user-auth    12:28 AM
# ses_483ea4a0bffe...             Fix login validation bug                12:26 AM
```

Then continue any session by name:

```bash theme={null}
stn agent run "Code Assistant" "continue the work" --coding-session "user-auth"
```

### Environment Variables

| Variable           | Description                                   |
| ------------------ | --------------------------------------------- |
| `STN_OPENCODE_URL` | Override OpenCode HTTP URL                    |
| `NATS_URL`         | Override NATS URL for `opencode-nats` backend |

### Agent Frontmatter

```yaml theme={null}
---
model: openai/gpt-4o
coding:
  enabled: true           # Enable coding tools for this agent
  workspace_path: /path   # Optional: default workspace
---
```

<Note>
  The agent frontmatter only controls whether coding tools are **enabled** for that agent. The backend transport (HTTP vs NATS) is determined by Station's global config. This makes agents portable - the same agent definition works whether Station uses HTTP or NATS backend.
</Note>

### Agent Prompt Template

When creating agents that use coding tools, you must use the `{{userInput}}` template variable to pass the user's task to the `code` tool. Without this, the agent won't correctly forward the task.

```yaml theme={null}
---
metadata:
  name: code-assistant
  description: AI coding assistant
model: anthropic/claude-sonnet-4-5-20250929
coding:
  enabled: true
---

Execute this coding task: {{userInput}}

Steps:
1. Call coding_open with workspace_path="/path/to/project"
2. Call code with instruction="{{userInput}}"
3. Call coding_close
```

<Warning>
  The `{{userInput}}` variable is populated by Station with the user's task message. If you don't reference it in your prompt, the agent won't know what task to execute and may ask for clarification or pass incorrect instructions to the code tool.
</Warning>

## Container Mode (stn up)

When running Station in container mode via `stn up`, special configuration is needed for OpenCode connectivity.

### The Problem

By default, OpenCode binds to `127.0.0.1:4096` which is only accessible from localhost. Docker containers cannot reach `127.0.0.1` on the host.

### The Solution

Start OpenCode with `--hostname 0.0.0.0` to listen on all interfaces:

```bash theme={null}
# Required for container mode
opencode --hostname 0.0.0.0
```

Station's `stn up` command automatically rewrites the config:

```yaml theme={null}
# Your config (host)
coding:
  opencode:
    url: http://localhost:4096

# Rewritten config (in container)
coding:
  opencode:
    url: http://host.docker.internal:4096
```

### Verify Connectivity

```bash theme={null}
# Check OpenCode is accessible from container
docker exec station-server curl http://host.docker.internal:4096/global/health
# Should return: {"healthy":true}
```

### Architecture

```
┌─────────────────────────────────────────────────────────────┐
│  HOST MACHINE                                               │
│                                                             │
│  ┌─────────────────┐       ┌─────────────────────────────┐  │
│  │  OpenCode       │◀──────│  station-server container   │  │
│  │  0.0.0.0:4096   │       │  coding.opencode.url:       │  │
│  │  (--hostname    │       │  host.docker.internal:4096  │  │
│  │   0.0.0.0)      │       │                             │  │
│  └─────────────────┘       └─────────────────────────────┘  │
│         │                                                   │
│         ▼                                                   │
│  ┌─────────────────┐                                        │
│  │  Local Files    │  ◀── Files created/modified here      │
│  │  /my/project    │                                        │
│  └─────────────────┘                                        │
└─────────────────────────────────────────────────────────────┘
```

<Note>
  Files created by OpenCode persist on the host machine, not in the container. This is the key difference from sandbox mode.
</Note>

## Example Workflows

### Simple File Creation

```bash theme={null}
stn agent run "Code Assistant" "Create hello.py with a hello world function"
```

Agent workflow:

1. `coding_open({"workspace_path": "/tmp/workspace"})`
2. `code({"task": "Create hello.py with a hello world function"})`
3. `coding_close()`

Result: `/tmp/workspace/hello.py` created on your filesystem.

### Code Refactoring

```bash theme={null}
stn agent run "Code Assistant" "Refactor the database module to use connection pooling"
```

Agent workflow:

1. `coding_open({"workspace_path": "/home/user/my-app"})`
2. `code({"task": "Read the current database.py implementation"})`
3. `code({"task": "Refactor to use connection pooling with a pool size of 10"})`
4. `coding_commit({"message": "Refactor: add database connection pooling"})`
5. `coding_close()`

### Full Development Cycle

```yaml theme={null}
---
metadata:
  name: "Feature Developer"
  description: "Implements features end-to-end"
model: openai/gpt-4o
coding:
  enabled: true
  backend: opencode
---

You are a senior developer. When given a feature request:

1. Open a coding session in the project directory
2. Read existing code to understand the codebase
3. Implement the feature following existing patterns
4. Write tests for the new functionality
5. Commit changes with a descriptive message
6. Push to the remote branch
7. Close the session

Always follow the project's coding style and conventions.
```

## Troubleshooting

### OpenCode Not Responding

```bash theme={null}
# Check if OpenCode is running
curl http://localhost:4096/global/health

# Check which port OpenCode is using
lsof -i :4096

# Restart OpenCode
pkill opencode && opencode --hostname 0.0.0.0
```

### Container Can't Reach OpenCode

```bash theme={null}
# Verify OpenCode is bound to 0.0.0.0
netstat -tlnp | grep 4096
# Should show 0.0.0.0:4096, not 127.0.0.1:4096

# If bound to 127.0.0.1, restart with:
opencode --hostname 0.0.0.0
```

### Session Errors

If you see "no active session" errors:

* Ensure `coding_open` was called first
* Check OpenCode logs for connection issues
* Verify workspace path exists and is accessible

## Next Steps

<CardGroup cols={2}>
  <Card title="OpenCode Container" icon="docker" href="/station/opencode-container">
    Run OpenCode in Docker with OAuth
  </Card>

  <Card title="Sandbox Execution" icon="box" href="/station/sandbox">
    Run code in isolated containers
  </Card>

  <Card title="Agent Development" icon="robot" href="/station/agents">
    Create custom agents
  </Card>

  <Card title="Workflows" icon="diagram-project" href="/station/workflows">
    Multi-step agent orchestration
  </Card>
</CardGroup>
