OpenCode CLI commands wire through packages/opencode/src/index.ts as a yargs parser with global flags for logging (--log-level, --print-logs) and behavior (--pure for plugin-free mode), and top-level subcommands for interactive (tui, attach), non-interactive (run, serve), and IDE-integrated (acp) modes. The TUI starts by default and supports session resume/fork, custom models/agents, and server binding; serve runs a headless HTTP API; attach connects to remote backends; and acp integrates with editors via JSON-RPC—all sharing OpenCode's tools, MCP servers, and agent permission system. MCP (Model Context Protocol) servers are external processes that expose additional tools and context to OpenCode agents.
packages/opencode/src/index.ts is the CLI entry point, wiring all subcommands into a yargs parser with --print-logs, --log-level, and --pure global flags.[1] The --log-level flag in packages/opencode/src/index.ts accepts DEBUG, INFO, WARN, or ERROR and propagates the choice via process.env.OPENCODE_LOG_LEVEL.[1] The --pure flag in packages/opencode/src/index.ts sets process.env.OPENCODE_PURE = "1" to run without external plugins.[1] The CLI middleware in packages/opencode/src/index.ts always sets process.env.AGENT = "1", process.env.OPENCODE = "1", and process.env.OPENCODE_PID to the current process PID before any command runs.[1]
packages/opencode/src/index.ts registers the following top-level CLI commands: acp, mcp, tui, attach, run, generate, debug, account, providers, agent, upgrade, uninstall, serve, web, models, stats, export, import, github, pr, session, plugin, and db.[1] The cmd helper in packages/opencode/src/cli/cmd/cmd.ts is a typed identity function that wraps a yargs CommandModule and enriches its argument type with WithDoubleDash<U>, which adds optional "--" (passthrough args) and _ (positional args) fields.[2]
The opencode CLI starts the TUI by default when run without arguments; passing a prompt via opencode run enables non-interactive (programmatic) usage.[3] The opencode run command runs OpenCode non-interactively by accepting a prompt directly, useful for scripting and automation without launching the TUI.[3] The opencode TUI command supports flags including --continue/-c (resume last session), --session/-s (resume by session ID), --fork (fork when continuing), --prompt, --model/-m (in provider/model format), --agent, --auto (auto-approve non-denied permissions), --port, --hostname, --mdns, --mdns-domain, and --cors.[3] The TUI randomly assigns a port and hostname by default; passing explicit --hostname and --port flags allows external clients to connect to the TUI's server.[4]
opencode serve runs a headless HTTP server exposing an OpenAPI endpoint that opencode clients can use programmatically, defaulting to port 4096 and hostname 127.0.0.1.[4] mDNS discovery for the opencode server is disabled by default (--mdns defaults to false); the default mDNS service domain is opencode.local (--mdns-domain).[4] The --cors flag on opencode serve allows additional browser origins and can be passed multiple times to allow several origins.[4] Set the OPENCODE_SERVER_PASSWORD environment variable to protect the opencode server with HTTP basic auth; the username defaults to opencode and can be overridden with OPENCODE_SERVER_USERNAME. This applies to both opencode serve and opencode web.[4]
Example: Enable HTTP basic auth on the opencode server by setting OPENCODE_SERVER_PASSWORD:
OPENCODE_SERVER_PASSWORD=your-password opencode serve
opencode attach [url] attaches a TUI to an already-running OpenCode backend server (started via serve or web commands), enabling TUI use with a remote backend.[3] Using opencode attach with a separately started opencode serve avoids MCP server cold boot times when running opencode run repeatedly.[3] The --password flag for opencode attach defaults to the OPENCODE_SERVER_PASSWORD environment variable; --username defaults to OPENCODE_SERVER_USERNAME or opencode.[3] Example: attaching the TUI to a remote OpenCode backend started with opencode web.[3]
opencode acp starts OpenCode as an ACP-compatible subprocess that communicates with a host editor over JSON-RPC via stdio.[5] When using OpenCode via ACP, all features work identically to the terminal — including built-in tools, custom tools and slash commands, MCP servers, AGENTS.md rules, and the agents/permissions system — except some built-in slash commands (/undo, /redo) which are currently unsupported.[5]
Example: Configure Zed to use a custom OpenCode executable via ACP by adding to ~/.config/zed/settings.json:
{
"agent_servers": {
"OpenCode": {
"type": "custom",
"command": "opencode",
"args": ["acp"]
}
}
}
Example: Configure OpenCode as an ACP agent in JetBrains IDEs via acp.json:
{
"agent_servers": {
"OpenCode": {
"command": "/absolute/path/bin/opencode",
"args": ["acp"]
}
}
}
ACP (Agent Communication Protocol) is a JSON-RPC–based protocol enabling host editors (such as Zed or JetBrains IDEs) to communicate with an external AI agent subprocess over stdio.
Running /init inside the OpenCode TUI analyzes the project and creates an AGENTS.md file in the project root; this file should be committed to Git.[6] The /share command creates a shareable link to the current conversation and copies it to the clipboard; conversations are not shared by default.[6] The /redo command re-applies changes that were previously undone with /undo.[6] The @ key in the TUI opens a fuzzy file search to include files in the prompt.[6] Images can be added to an OpenCode prompt by dragging and dropping them into the terminal.[6]
On unknown arguments, missing required arguments, or invalid values, packages/opencode/src/index.ts calls cli.showHelp() rather than printing a bare error message.[1] When --help / -h is passed, packages/opencode/src/index.ts prepends the UI.logo() banner to help output when the text does not already start with "opencode ".[1] On a caught error, packages/opencode/src/index.ts calls FormatError(e) and, if the result is undefined (unrecognized error), falls back to printing "Unexpected error" plus the raw error message, then sets process.exitCode = 1.[1] packages/opencode/src/index.ts always calls process.exit() in the finally block after command completion, forcefully terminating any subprocesses (such as Docker-based MCP servers) that do not handle SIGTERM.[1]
Sources