opencode
Research notes on OpenCode's configuration, credential discovery, and runtime behavior based on agent-jj implementation.
How it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Research notes on OpenCode's configuration, credential discovery, and runtime behavior based on agent-jj implementation.
Agent definition
opencode.mdOpenCode Research
Research notes on OpenCode's configuration, credential discovery, and runtime behavior based on agent-jj implementation.
Overview
- **Provider**: Multi-provider (OpenAI, Anthropic, others)
- **Execution Method**: Embedded server via SDK, or CLI binary
- **Session Persistence**: Session ID (string)
- **SDK**: `@opencode-ai/sdk` (server + client)
- **Binary Location**: `~/.opencode/bin/opencode`
- **Written in**: Go (with Bubble Tea TUI)
CLI Usage (Alternative to SDK)
OpenCode can be used as a standalone binary instead of embedding the SDK:
Interactive TUI Mode
opencode # Start TUI in current directory
opencode /path/to/project # Start in specific directory
opencode -c # Continue last session
opencode -s SESSION_ID # Continue specific session
Non-Interactive Mode (`opencode run`)
opencode run "your prompt here"
opencode run --format json "prompt" # Raw JSON events output
opencode run -m anthropic/claude-sonnet-4-20250514 "prompt"
opencode run --agent plan "analyze this code"
opencode run -c "follow up question" # Continue last session
opencode run -s SESSION_ID "prompt" # Continue specific session
opencode run -f file1.ts -f file2.ts "review these files"
Key CLI Flags
| Flag | Description | |------|-------------| | `--format json` | Output raw JSON events (for parsing) | | `-m, --model PROVIDER/MODEL` | Model in format `provider/model` | | `--agent AGENT` | Agent to use (`build`, `plan`) | | `-c, --continue` | Continue last session | | `-s, --session ID` | Continue specific session | | `-f, --file FILE` | Attach file(s) to message | | `--attach URL` | Attach to running server | | `--port PORT` | Local server port | | `--variant VARIANT` | Reasoning effort (e.g., `high`, `max`) |
Headless Server Mode
opencode serve # Start headless server
opencode serve --port 4096 # Specific port
opencode attach http://localhost:4096 # Attach to running server
Other Commands
opencode models # List available models
opencode models anthropic # List models for provider
opencode auth # Manage credentials
opencode session # Manage sessions
opencode export SESSION_ID # Export session as JSON
opencode stats # Token usage statistics
Sources: [OpenCode GitHub](https://github.com/opencode-ai/opencode), [OpenCode Docs](https://opencode.ai/docs/cli/)
Architecture
OpenCode runs as an embedded HTTP server per workspace/change:
┌─────────────────────┐
│ agent-jj backend │
│ │
│ ┌───────────────┐ │
│ │ OpenCode │ │
│ │ Server │◄─┼── HTTP API
│ │ (per change) │ │
│ └───────────────┘ │
└─────────────────────┘
- One server per `changeId` (workspace+repo+change combination)
- Multiple sessions can share a server
- Server runs on dynamic port (4200-4300 range)
Credential Discovery
Priority Order
1. Environment variables: `ANTHROPIC_API_KEY`, `CLAUDE_API_KEY` 2. Environment variables: `OPENAI_API_KEY`, `CODEX_API_KEY` 3. Claude Code config files 4. Codex config files 5. OpenCode config files
Config File Location
| Path | Description | |------|-------------| | `~/.local/share/opencode/auth.json` | Primary auth config |
Auth File Structure
{
"anthropic": {
"type": "api",
"key": "sk-ant-..."
},
"openai": {
"type": "api",
"key": "sk-..."
},
"custom-provider": {
"type": "oauth",
"access": "token...",
"refresh": "refresh-token...",
"expires": 1704067200000
}
}Provider Config Types
interface OpenCodeProviderConfig {
type: "api" | "oauth";
key?: string; // For API type
access?: string; // For OAuth type
refresh?: string; // For OAuth type
expires?: number; // Unix timestamp (ms)
}OAuth tokens are validated for expiry before use.
Server Management
Starting a Server
import { createOpencodeServer } from "@opencode-ai/sdk/server";
import { createOpencodeClient } from "@opencode-ai/sdk";
const server = await createOpencodeServer({
hostname: "127.0.0.1",
port: 4200,
config: { logLevel: "DEBUG" }
});
const client = createOpencodeClient({
baseUrl: `http://127.0.0.1:${port}`
});Server Configuration
// From config.json
{
"opencode": {
"host": "127.0.0.1", // Bind address
"advertisedHost": "127.0.0.1" // External address (for tunnels)
}
}Port Selection
Uses `get-port` package to find available port in range 4200-4300.
Client API
Session Management
// Create session
const response = await client.session.create({});
const sessionId = response.data.id;
// Get session info
const session = await client.session.get({ path: { id: sessionId } });
// Get session messages
const messages = await client.session.messages({ path: { id: sessionId } });
// Get session todos
const todos = await client.session.todo({ path: { id: sessionId } });Sending Prompts
Synchronous
const response = await client.session.prompt({
path: { id: sessionId },
body: {
model: { providerID: "openai", modelID: "gpt-4o" },
agent: "build",
parts: [{ type: "text", text: "prompt text" }]
}
});Asynchronous (Streaming)
// Start prompt asynchronously
await client.session.promptAsync({
path: { id: sessionId },
body: {
model: { providerID: "openai", modelID: "gpt-4o" },
agent: "build",
parts: [{ type: "text", text: "prompt text" }]
}
});
// Subscribe to events
const eventStream = await client.event.subscribe({});
for await (const event of eventStream.stream) {
// Process events
}Event Types
| Event Type | Description | |------------|-------------| | `message.part.updated` | Message part streamed/updated | | `session.status` | Ses
Read more
OpenCode Research
Research notes on OpenCode's configuration, credential discovery, and runtime behavior based on agent-jj implementation.
Overview
- **Provider**: Multi-provider (OpenAI, Anthropic, others)
- **Execution Method**: Embedded server via SDK, or CLI binary
- **Session Persistence**: Session ID (string)
- **SDK**: `@opencode-ai/sdk` (server + client)
- **Binary Location**: `~/.opencode/bin/opencode`
- **Written in**: Go (with Bubble Tea TUI)
CLI Usage (Alternative to SDK)
OpenCode can be used as a standalone binary instead of embedding the SDK:
Interactive TUI Mode
opencode # Start TUI in current directory opencode /path/to/project # Start in specific directory opencode -c # Continue last session opencode -s SESSION_ID # Continue specific session
Non-Interactive Mode (`opencode run`)
opencode run "your prompt here" opencode run --format json "prompt" # Raw JSON events output opencode run -m anthropic/claude-sonnet-4-20250514 "prompt" opencode run --agent plan "analyze this code" opencode run -c "follow up question" # Continue last session opencode run -s SESSION_ID "prompt" # Continue specific session opencode run -f file1.ts -f file2.ts "review these files"
Key CLI Flags
| Flag | Description | |------|-------------| | `--format json` | Output raw JSON events (for parsing) | | `-m, --model PROVIDER/MODEL` | Model in format `provider/model` | | `--agent AGENT` | Agent to use (`build`, `plan`) | | `-c, --continue` | Continue last session | | `-s, --session ID` | Continue specific session | | `-f, --file FILE` | Attach file(s) to message | | `--attach URL` | Attach to running server | | `--port PORT` | Local server port | | `--variant VARIANT` | Reasoning effort (e.g., `high`, `max`) |
Headless Server Mode
opencode serve # Start headless server opencode serve --port 4096 # Specific port opencode attach http://localhost:4096 # Attach to running server
Other Commands
opencode models # List available models opencode models anthropic # List models for provider opencode auth # Manage credentials opencode session # Manage sessions opencode export SESSION_ID # Export session as JSON opencode stats # Token usage statistics
Sources: [OpenCode GitHub](https://github.com/opencode-ai/opencode), [OpenCode Docs](https://opencode.ai/docs/cli/)
Architecture
OpenCode runs as an embedded HTTP server per workspace/change:
┌─────────────────────┐ │ agent-jj backend │ │ │ │ ┌───────────────┐ │ │ │ OpenCode │ │ │ │ Server │◄─┼── HTTP API │ │ (per change) │ │ │ └───────────────┘ │ └─────────────────────┘
- One server per `changeId` (workspace+repo+change combination)
- Multiple sessions can share a server
- Server runs on dynamic port (4200-4300 range)
Credential Discovery
Priority Order
1. Environment variables: `ANTHROPIC_API_KEY`, `CLAUDE_API_KEY` 2. Environment variables: `OPENAI_API_KEY`, `CODEX_API_KEY` 3. Claude Code config files 4. Codex config files 5. OpenCode config files
Config File Location
| Path | Description | |------|-------------| | `~/.local/share/opencode/auth.json` | Primary auth config |
Auth File Structure
{
"anthropic": {
"type": "api",
"key": "sk-ant-..."
},
"openai": {
"type": "api",
"key": "sk-..."
},
"custom-provider": {
"type": "oauth",
"access": "token...",
"refresh": "refresh-token...",
"expires": 1704067200000
}
}Provider Config Types
interface OpenCodeProviderConfig {
type: "api" | "oauth";
key?: string; // For API type
access?: string; // For OAuth type
refresh?: string; // For OAuth type
expires?: number; // Unix timestamp (ms)
}OAuth tokens are validated for expiry before use.
Server Management
Starting a Server
import { createOpencodeServer } from "@opencode-ai/sdk/server";
import { createOpencodeClient } from "@opencode-ai/sdk";
const server = await createOpencodeServer({
hostname: "127.0.0.1",
port: 4200,
config: { logLevel: "DEBUG" }
});
const client = createOpencodeClient({
baseUrl: `http://127.0.0.1:${port}`
});Server Configuration
// From config.json
{
"opencode": {
"host": "127.0.0.1", // Bind address
"advertisedHost": "127.0.0.1" // External address (for tunnels)
}
}Port Selection
Uses `get-port` package to find available port in range 4200-4300.
Client API
Session Management
// Create session
const response = await client.session.create({});
const sessionId = response.data.id;
// Get session info
const session = await client.session.get({ path: { id: sessionId } });
// Get session messages
const messages = await client.session.messages({ path: { id: sessionId } });
// Get session todos
const todos = await client.session.todo({ path: { id: sessionId } });Sending Prompts
Synchronous
const response = await client.session.prompt({
path: { id: sessionId },
body: {
model: { providerID: "openai", modelID: "gpt-4o" },
agent: "build",
parts: [{ type: "text", text: "prompt text" }]
}
});Asynchronous (Streaming)
// Start prompt asynchronously
await client.session.promptAsync({
path: { id: sessionId },
body: {
model: { providerID: "openai", modelID: "gpt-4o" },
agent: "build",
parts: [{ type: "text", text: "prompt text" }]
}
});
// Subscribe to events
const eventStream = await client.event.subscribe({});
for await (const event of eventStream.stream) {
// Process events
}Event Types
| Event Type | Description | |------------|-------------| | `message.part.updated` | Message part streamed/updated | | `session.status` | Ses
Run Coding Agents in Sandboxes. Control Them Over HTTP. Supports Claude Code, Codex, OpenCode, and Amp.
Repo: rivet-dev/sandbox-agent
Other agents on sandbox-agent.
- amp
Research notes on Sourcegraph Amp's configuration, credential discovery, and runtime behavior.
Open agent - codex
Research notes on OpenAI Codex's configuration, credential discovery, and runtime behavior based on agent-jj implementation.
Open agent - openclaw
Research notes on OpenClaw's architecture, API, and automation patterns for integration with sandbox-agent.
Open agent

