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.
---metadata: name: "Code Assistant" description: "AI coding assistant with local filesystem access"model: openai/gpt-4ocoding: 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 featuresWhen given a task, open a coding session, complete the work, then close the session.
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
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.
Uses NATS messaging for communication. Best for containerized or distributed setups where OpenCode runs remotely or in a container with the Station plugin.
Copy
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)
When using opencode-nats, ensure the OpenCode container has the Station plugin installed and is connected to the same NATS server. See OpenCode Container for setup instructions.
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.
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
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.
Copy
# 1. Ensure claude CLI is authenticatedclaude --versionclaude login # if needed# 2. Configure Stationcat >> ~/.config/station/config.yaml << 'EOF'coding: backend: claudecode claudecode: timeout_sec: 300 max_turns: 10EOF# 3. Create a coding agentstn 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 itstn agent run coder "Create a hello.py that prints Hello World" --tail
Claude Code runs with --dangerously-skip-permissions for non-interactive use. Ensure workspace directories are appropriately secured.
To work with private repositories, configure git credentials in your Station config:
Copy
# ~/.config/station/config.yamlcoding: 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"
GitHub PAT
GitHub App
GitLab
Create a Personal Access Token with repo scope:
Go to GitHub Settings → Developer Settings → Personal Access Tokens
Generate a token with repo (full control of private repositories)
Set it as an environment variable:
Copy
export GITHUB_TOKEN=ghp_xxxxxxxxxxxx
For organization repos, use a GitHub App token:
Copy
# Generate installation token via GitHub API or gh CLIexport GITHUB_TOKEN=$(gh auth token)
Create a Project Access Token or Personal Access Token:
Copy
export GITHUB_TOKEN=glpat-xxxxxxxxxxxx # GitLab uses same injection method
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.)
Example: Clone and work on a private repo
Copy
# 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_push5. coding_close
The git token is automatically injected into HTTPS URLs during clone/push operations.
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.
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:
Instead of one large task, use multiple smaller ones:
Copy
# ❌ Might timeouttask: "Create a full REST API with authentication, CRUD endpoints, and database models"# ✅ Better approachtasks: - "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.
The NATS backend handles long-running tasks better:
Pass a session name or ID to continue from a previous run:
Copy
# 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 titlestn agent run "Code Assistant" "Add unit tests for login" \ --coding-session "feature branch"# Or use the exact session IDstn 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_)
Run opencode session list to see all sessions with their titles.
The coding_open tool also accepts a session name or ID:
You don’t need to remember session IDs - just use part of the session title. But if you want to see all sessions:
Copy
# List all sessions with titlesopencode 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:
Copy
stn agent run "Code Assistant" "continue the work" --coding-session "user-auth"
---model: openai/gpt-4ocoding: enabled: true # Enable coding tools for this agent workspace_path: /path # Optional: default workspace---
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.
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.
Copy
---metadata: name: code-assistant description: AI coding assistantmodel: anthropic/claude-sonnet-4-5-20250929coding: 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
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.
# Check OpenCode is accessible from containerdocker exec station-server curl http://host.docker.internal:4096/global/health# Should return: {"healthy":true}
---metadata: name: "Feature Developer" description: "Implements features end-to-end"model: openai/gpt-4ocoding: enabled: true backend: opencode---You are a senior developer. When given a feature request:1. Open a coding session in the project directory2. Read existing code to understand the codebase3. Implement the feature following existing patterns4. Write tests for the new functionality5. Commit changes with a descriptive message6. Push to the remote branch7. Close the sessionAlways follow the project's coding style and conventions.
# Check if OpenCode is runningcurl http://localhost:4096/global/health# Check which port OpenCode is usinglsof -i :4096# Restart OpenCodepkill opencode && opencode --hostname 0.0.0.0
# Verify OpenCode is bound to 0.0.0.0netstat -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