# OpenCode OpenCode is an open-source AI coding agent that provides a terminal-based interface for AI-assisted software development. It supports multiple AI providers (Anthropic, OpenAI, Google, Azure, local models, and others) and offers a rich set of tools for file manipulation, code search, bash command execution, and web fetching. OpenCode differentiates itself from similar tools through its provider-agnostic architecture, built-in LSP support, vim-like TUI interface, and client/server architecture that enables remote operation. The core functionality centers around interactive coding sessions where users communicate with AI agents via prompts. The AI can read/write files, execute commands, search code, browse the web, and manage todo lists. OpenCode supports Model Context Protocol (MCP) for extending functionality with external tools, a plugin system for custom integrations, multiple agent modes (build, plan, explore), and configurable permissions for tool usage. The project is built as a monorepo with packages for the main CLI, JavaScript SDK, desktop applications (Tauri and Electron), and a web console. ## Installation Install OpenCode using any of the following methods. ```bash # Quick install via curl curl -fsSL https://opencode.ai/install | bash # npm/pnpm/yarn/bun npm i -g opencode-ai@latest # Homebrew (macOS/Linux) brew install anomalyco/tap/opencode # Scoop (Windows) scoop install opencode # Chocolatey (Windows) choco install opencode # Arch Linux sudo pacman -S opencode # Nix nix run nixpkgs#opencode ``` ## CLI - Interactive TUI Mode Launch OpenCode in interactive terminal UI mode. ```bash # Start interactive TUI in current directory opencode # Start with a specific model opencode --model anthropic/claude-sonnet-4-20250514 # Start with a specific agent opencode --agent plan # Continue the last session opencode --continue # Start in a specific directory opencode --dir /path/to/project ``` ## CLI - Run Command (Non-Interactive) Execute a single prompt and receive output without interactive UI. ```bash # Run a single prompt opencode run "explain this codebase" # Continue the last session with a new message opencode run --continue "now add unit tests" # Run with a specific model opencode run --model anthropic/claude-sonnet-4-20250514 "refactor the auth module" # Pipe input from stdin echo "analyze this code" | opencode run # Attach files to the message opencode run --file ./src/main.ts "review this file" # Output in JSON format for scripting opencode run --format json "list all functions" # Skip permission prompts (dangerous!) opencode run --dangerously-skip-permissions "update dependencies" # Attach to a running remote server opencode run --attach http://localhost:4096 --password mypassword "check status" ``` ## CLI - Server Mode Start OpenCode as a headless HTTP server for remote access and API integrations. ```bash # Start server on default port (random) opencode serve # Start server with specific host and port opencode serve --hostname 0.0.0.0 --port 4096 # Set password via environment variable (recommended) export OPENCODE_SERVER_PASSWORD=mysecretpassword opencode serve --port 4096 # Server will output: opencode server listening on http://0.0.0.0:4096 ``` ## CLI - MCP Server Management Manage Model Context Protocol servers for extending OpenCode's capabilities. ```bash # List MCP server status opencode mcp # Start OAuth authentication for a remote MCP server opencode mcp auth my-mcp-server # Remove stored OAuth credentials opencode mcp auth --remove my-mcp-server ``` ## CLI - Model and Provider Management Configure and list available AI providers and models. ```bash # List all available providers opencode providers # List all available models across providers opencode models # Show models from specific provider opencode models --provider anthropic ``` ## CLI - Session Export/Import Export and import session history for backup or sharing. ```bash # Export a session to JSON opencode export --session abc123 --output session.json # Export all sessions opencode export --all --output sessions/ # Import a session from JSON opencode import session.json ``` ## Configuration - opencode.jsonc Configure OpenCode behavior through the configuration file at `~/.config/opencode/opencode.jsonc` or project-level `.opencode/opencode.jsonc`. ```jsonc { "$schema": "https://opencode.ai/config.json", // Set default model "model": "anthropic/claude-sonnet-4-20250514", // Set small model for title generation "small_model": "anthropic/claude-3-5-haiku-latest", // Default agent to use "default_agent": "build", // Log level "logLevel": "INFO", // Share behavior: "manual", "auto", or "disabled" "share": "manual", // Auto-update behavior: true, false, or "notify" "autoupdate": "notify", // Custom username "username": "developer", // Disable specific providers "disabled_providers": ["azure"], // Additional instruction files to include "instructions": ["./AGENTS.md", "./.opencode/instructions.md"], // Tool output limits "tool_output": { "max_lines": 2000, "max_bytes": 51200 }, // Context compaction settings "compaction": { "auto": true, "prune": true, "tail_turns": 2 }, // Snapshot tracking for undo/redo "snapshot": true } ``` ## Configuration - Provider Setup Configure AI providers with API keys and custom endpoints. ```jsonc { "provider": { "anthropic": { "api_key": "sk-ant-xxx" }, "openai": { "api_key": "sk-xxx", "base_url": "https://api.openai.com/v1" }, "openrouter": { "api_key": "sk-or-xxx" }, // Custom provider with OpenAI-compatible API "local-llm": { "api_key": "not-needed", "base_url": "http://localhost:11434/v1", "models": { "llama3": { "max_tokens": 8192 } } }, // Bedrock with profile authentication "bedrock": { "profile": "my-aws-profile", "region": "us-east-1" } } } ``` ## Configuration - Agent Customization Customize built-in agents or define custom agents. ```jsonc { "agent": { // Customize the build agent "build": { "system": "You are an expert software developer. Always write tests.", "model": "anthropic/claude-sonnet-4-20250514", "tools": { "bash": true, "write": true, "edit": true, "read": true, "glob": true, "grep": true } }, // Customize the plan agent (read-only by default) "plan": { "system": "Analyze code and create implementation plans.", "tools": { "bash": false, "write": false, "read": true } }, // Define a custom agent "reviewer": { "system": "You are a code reviewer. Focus on security and performance.", "model": "anthropic/claude-sonnet-4-20250514", "tools": { "read": true, "grep": true, "glob": true, "bash": false, "write": false } } } } ``` ## Configuration - MCP Servers Configure Model Context Protocol servers for extended tool capabilities. ```jsonc { "mcp": { // Local MCP server via stdio "filesystem": { "type": "local", "command": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"], "enabled": true, "timeout": 30000, "environment": { "NODE_ENV": "production" } }, // Remote MCP server via HTTP "remote-tools": { "type": "remote", "url": "https://mcp.example.com/api", "enabled": true, "headers": { "Authorization": "Bearer token123" } }, // Remote MCP with OAuth "github-mcp": { "type": "remote", "url": "https://mcp.github.example.com", "oauth": { "clientId": "my-client-id", "scope": "read:repo write:repo" } } } } ``` ## Configuration - Permissions Configure permission rules to auto-allow or deny tool usage. ```jsonc { "permission": { "rules": [ // Allow all read operations { "permission": "read", "action": "allow", "pattern": "**/*" }, // Allow writing to specific directories { "permission": "write", "action": "allow", "pattern": "src/**" }, { "permission": "write", "action": "allow", "pattern": "tests/**" }, // Deny writing to sensitive files { "permission": "write", "action": "deny", "pattern": "**/.env*" }, { "permission": "write", "action": "deny", "pattern": "**/secrets/**" }, // Allow specific bash commands { "permission": "bash", "action": "allow", "pattern": "npm test" }, { "permission": "bash", "action": "allow", "pattern": "npm run *" }, { "permission": "bash", "action": "allow", "pattern": "git *" }, // Deny dangerous commands { "permission": "bash", "action": "deny", "pattern": "rm -rf *" }, { "permission": "bash", "action": "deny", "pattern": "sudo *" } ] } } ``` ## Configuration - Server Settings Configure the OpenCode server for headless or web access. ```jsonc { "server": { "hostname": "127.0.0.1", "port": 4096, // Basic auth password (or use OPENCODE_SERVER_PASSWORD env var) "password": "mysecretpassword", // Username for basic auth (default: "opencode") "username": "admin" } } ``` ## JavaScript SDK - Creating a Client Use the JavaScript SDK to interact with OpenCode programmatically. ```typescript import { createOpencodeClient, createOpencodeServer, createOpencode } from "@opencode-ai/sdk/v2" // Connect to an existing OpenCode server const client = createOpencodeClient({ baseUrl: "http://localhost:4096", headers: { Authorization: `Basic ${Buffer.from("opencode:password").toString("base64")}` } }) // Or start a new server and get a client const { client, server } = await createOpencode({ hostname: "127.0.0.1", port: 4096, timeout: 5000 }) // Check server health const health = await client.global.health() console.log(health.data) // { status: "ok", version: "1.14.22" } // Clean up when done server.close() ``` ## JavaScript SDK - Session Management Create and manage coding sessions programmatically. ```typescript import { createOpencodeClient } from "@opencode-ai/sdk/v2" const client = createOpencodeClient({ baseUrl: "http://localhost:4096" }) // List all sessions const sessions = await client.session.list({ limit: 10 }) console.log(sessions.data) // [{ id: "abc123", title: "Refactor auth", updatedAt: 1234567890 }, ...] // Create a new session const newSession = await client.session.create({ title: "Add unit tests", permission: [ { permission: "write", action: "allow", pattern: "tests/**" } ] }) const sessionID = newSession.data.id // Get session details const session = await client.session.get({ sessionID }) console.log(session.data) // Fork a session at a specific message const forked = await client.session.fork({ sessionID, messageID: "msg123" }) console.log(`Forked to: ${forked.data.id}`) // Delete a session await client.session.delete({ sessionID: "old-session-id" }) ``` ## JavaScript SDK - Sending Prompts Send prompts to AI agents and receive streaming responses. ```typescript import { createOpencodeClient } from "@opencode-ai/sdk/v2" const client = createOpencodeClient({ baseUrl: "http://localhost:4096" }) // Create a session first const session = await client.session.create({ title: "Code Review" }) const sessionID = session.data.id // Send a text prompt await client.session.prompt({ sessionID, parts: [{ type: "text", text: "Review the authentication module for security issues" }], model: { providerID: "anthropic", modelID: "claude-sonnet-4-20250514" }, agent: "build" }) // Send a prompt with file attachment await client.session.prompt({ sessionID, parts: [ { type: "text", text: "Explain what this file does" }, { type: "file", url: "file:///path/to/main.ts", filename: "main.ts", mime: "text/typescript" } ] }) // Send async prompt (returns immediately) await client.session.promptAsync({ sessionID, parts: [{ type: "text", text: "Run the test suite and fix any failures" }] }) // Execute a command await client.session.command({ sessionID, command: "review-pr", arguments: "123" }) // Abort an active session await client.session.abort({ sessionID }) ``` ## JavaScript SDK - Event Streaming Subscribe to real-time events for session updates. ```typescript import { createOpencodeClient } from "@opencode-ai/sdk/v2" const client = createOpencodeClient({ baseUrl: "http://localhost:4096" }) // Subscribe to events const events = await client.event.subscribe() // Process events in a loop for await (const event of events.stream) { switch (event.type) { case "message.updated": console.log(`Message updated: ${event.properties.info.role}`) break case "message.part.updated": const part = event.properties.part if (part.type === "text" && part.time?.end) { console.log(`AI: ${part.text}`) } if (part.type === "tool" && part.state.status === "completed") { console.log(`Tool ${part.tool} completed`) } break case "session.status": if (event.properties.status.type === "idle") { console.log("Session is idle") } break case "permission.asked": // Handle permission requests await client.permission.reply({ requestID: event.properties.id, reply: "once" // or "always" or "reject" }) break case "session.error": console.error(`Error: ${event.properties.error.name}`) break } } ``` ## JavaScript SDK - Configuration API Read and update OpenCode configuration programmatically. ```typescript import { createOpencodeClient } from "@opencode-ai/sdk/v2" const client = createOpencodeClient({ baseUrl: "http://localhost:4096" }) // Get current configuration const config = await client.config.get() console.log(config.data) // { model: "anthropic/claude-sonnet-4-20250514", share: "manual", ... } // Update configuration await client.config.update({ config: { model: "openai/gpt-4o", logLevel: "DEBUG" } }) // Get global configuration const globalConfig = await client.global.config.get() // List available providers const providers = await client.config.providers() console.log(providers.data) // [{ id: "anthropic", name: "Anthropic", models: [...] }, ...] ``` ## JavaScript SDK - MCP Integration Interact with Model Context Protocol servers. ```typescript import { createOpencodeClient } from "@opencode-ai/sdk/v2" const client = createOpencodeClient({ baseUrl: "http://localhost:4096" }) // Get MCP server status const status = await client.mcp.status() console.log(status.data) // { "filesystem": { status: "connected" }, "github": { status: "needs_auth" } } // Connect/disconnect MCP servers await client.mcp.connect({ name: "filesystem" }) await client.mcp.disconnect({ name: "filesystem" }) // Add a new MCP server await client.mcp.add({ name: "custom-tools", config: { type: "local", command: ["node", "./my-mcp-server.js"], enabled: true } }) // Start OAuth flow for remote MCP const authResult = await client.mcp.authStart({ name: "github-mcp" }) console.log(`Open this URL: ${authResult.data.authorizationUrl}`) // Complete OAuth with authorization code await client.mcp.authCallback({ name: "github-mcp", code: "auth-code-from-callback" }) ``` ## JavaScript SDK - File Operations Read files and search the codebase. ```typescript import { createOpencodeClient } from "@opencode-ai/sdk/v2" const client = createOpencodeClient({ baseUrl: "http://localhost:4096", directory: "/path/to/project" }) // Read a file const file = await client.file.read({ path: "src/main.ts" }) console.log(file.data.content) // List files in directory const files = await client.file.list({ path: "src" }) console.log(files.data) // [{ name: "main.ts", type: "file", size: 1234 }, ...] // Search for files by pattern const found = await client.find.files({ pattern: "**/*.test.ts" }) console.log(found.data) // Search for text in files const results = await client.find.text({ query: "TODO:", path: "src" }) console.log(results.data) // Search for symbols const symbols = await client.find.symbols({ query: "handleAuth" }) console.log(symbols.data) ``` ## JavaScript SDK - TUI Control Control the Terminal UI programmatically. ```typescript import { createOpencodeClient, createOpencodeTui } from "@opencode-ai/sdk/v2" // Launch TUI with options const tui = createOpencodeTui({ project: "/path/to/project", model: "anthropic/claude-sonnet-4-20250514", session: "existing-session-id", agent: "build" }) // Or control an existing TUI via API const client = createOpencodeClient({ baseUrl: "http://localhost:4096" }) // Append text to the prompt input await client.tui.appendPrompt({ text: "fix the bug in " }) // Submit the current prompt await client.tui.submitPrompt() // Clear the prompt await client.tui.clearPrompt() // Execute a command await client.tui.executeCommand({ command: "/help" }) // Select a different session await client.tui.selectSession({ sessionID: "abc123" }) // Show a toast notification await client.tui.showToast({ title: "Build Complete", message: "All tests passed", variant: "success", duration: 5000 }) // Open modal dialogs await client.tui.openSessions() await client.tui.openModels() await client.tui.openHelp() // Clean up TUI process tui.close() ``` ## Plugin Development Create plugins to extend OpenCode functionality. ```typescript // my-plugin.ts import type { Plugin, PluginInput, Hooks } from "@opencode-ai/plugin" const myPlugin: Plugin = async (input: PluginInput): Promise => { const { client, project, directory } = input console.log(`Plugin loaded for project: ${project.id}`) console.log(`Working directory: ${directory}`) return { // Hook into session creation async sessionCreated(session, output) { console.log(`New session created: ${session.id}`) }, // Hook into message processing async messageCreated(message, output) { console.log(`Message from ${message.role}: ${message.id}`) }, // Hook into tool execution async toolExecuted(tool, output) { console.log(`Tool ${tool.name} executed with result: ${tool.result}`) }, // Subscribe to all bus events async event({ event }) { console.log(`Event: ${event.type}`) }, // Handle configuration changes async config(cfg) { console.log(`Config updated: ${JSON.stringify(cfg)}`) } } } export default myPlugin ``` Configure the plugin in `opencode.jsonc`: ```jsonc { "plugin": [ // Local plugin file "./my-plugin.ts", // NPM package "opencode-plugin-example", // Plugin with options { "name": "opencode-plugin-custom", "options": { "apiKey": "xxx" } } ] } ``` ## Environment Variables Key environment variables for configuring OpenCode. ```bash # Server authentication export OPENCODE_SERVER_PASSWORD="mysecretpassword" export OPENCODE_SERVER_USERNAME="admin" # Provider API keys export ANTHROPIC_API_KEY="sk-ant-xxx" export OPENAI_API_KEY="sk-xxx" export GOOGLE_API_KEY="xxx" # Custom installation directory export OPENCODE_INSTALL_DIR="/usr/local/bin" # Data directory (default: ~/.local/share/opencode) export XDG_DATA_HOME="$HOME/.local/share" # Config directory (default: ~/.config/opencode) export XDG_CONFIG_HOME="$HOME/.config" # Enable auto-sharing of sessions export OPENCODE_AUTO_SHARE=1 # Run without external plugins export OPENCODE_PURE=1 ``` ## Summary OpenCode serves as a versatile AI coding assistant supporting both interactive terminal sessions and programmatic API access. The primary use cases include interactive code development with AI assistance, automated code review and refactoring pipelines, CI/CD integration for AI-powered code generation, building custom AI coding workflows through the SDK, and extending functionality with MCP servers and plugins. Integration patterns typically involve either the CLI for interactive development or the JavaScript SDK for building automated tools and custom interfaces. The client/server architecture enables remote development scenarios where OpenCode runs on a development machine while being controlled from a mobile app or web interface. The permission system allows fine-grained control over what operations the AI can perform, making it suitable for enterprise environments with strict security requirements. MCP integration enables connecting to external tools and services, while the plugin system allows customization of the AI's behavior and integration with existing development workflows.