import yargs from "yargs" import { hideBin } from "yargs/helpers" import { RunCommand } from "./cli/cmd/run" import { GenerateCommand } from "./cli/cmd/generate" import { ConsoleCommand } from "./cli/cmd/account" import { ProvidersCommand } from "./cli/cmd/providers" import { AgentCommand } from "./cli/cmd/agent" import { UpgradeCommand } from "./cli/cmd/upgrade" import { UninstallCommand } from "./cli/cmd/uninstall" import { ModelsCommand } from "./cli/cmd/models" import { UI } from "./cli/ui" import { InstallationVersion } from "@opencode-ai/core/installation/version" import { FormatError } from "./cli/error" import { ServeCommand } from "./cli/cmd/serve" import { DebugCommand } from "./cli/cmd/debug" import { StatsCommand } from "./cli/cmd/stats" import { McpCommand } from "./cli/cmd/mcp" import { GithubCommand } from "./cli/cmd/github" import { ExportCommand } from "./cli/cmd/export" import { ImportCommand } from "./cli/cmd/import" import { V2ServeCommand } from "./cli/cmd/v2-serve" import { AcpCommand } from "./cli/cmd/acp" import { EOL } from "os" import { WebCommand } from "./cli/cmd/web" import { PrCommand } from "./cli/cmd/pr" import { SessionCommand } from "./cli/cmd/session" import { DbCommand } from "./cli/cmd/db" import { errorMessage } from "./util/error" import { PluginCommand } from "./cli/cmd/plug" import { Heap } from "./cli/heap" const args = hideBin(process.argv) function show(out: string) { const text = out.trimStart() if (!text.startsWith("opencode ")) { process.stderr.write(UI.logo() + EOL + EOL) process.stderr.write(text + EOL) return } process.stderr.write(out) } const cli = yargs(args) .parserConfiguration({ "populate--": true }) .scriptName("opencode") .wrap(100) .help("help", "show help") .alias("help", "h") .version("version", "show version number", InstallationVersion) .alias("version", "v") .option("print-logs", { describe: "print logs to stderr", type: "boolean", }) .option("log-level", { describe: "log level", type: "string", choices: ["DEBUG", "INFO", "WARN", "ERROR"], }) .option("pure", { describe: "run without external plugins", type: "boolean", }) .middleware(async (opts) => { if (opts.printLogs) process.env.OPENCODE_PRINT_LOGS = "1" if (opts.logLevel) process.env.OPENCODE_LOG_LEVEL = opts.logLevel if (opts.pure) { process.env.OPENCODE_PURE = "1" } Heap.start() process.env.AGENT = "1" process.env.OPENCODE = "1" process.env.OPENCODE_PID = String(process.pid) }) .usage("") .completion("completion", "generate shell completion script") .command(AcpCommand) .command(McpCommand) .command(V2ServeCommand) .command(RunCommand) .command(GenerateCommand) .command(DebugCommand) .command(ConsoleCommand) .command(ProvidersCommand) .command(AgentCommand) .command(UpgradeCommand) .command(UninstallCommand) .command(ServeCommand) .command(WebCommand) .command(ModelsCommand) .command(StatsCommand) .command(ExportCommand) .command(ImportCommand) .command(GithubCommand) .command(PrCommand) .command(SessionCommand) .command(PluginCommand) .command(DbCommand) .fail((msg, err) => { if ( msg?.startsWith("Unknown argument") || msg?.startsWith("Not enough non-option arguments") || msg?.startsWith("Invalid values:") ) { if (err) throw err cli.showHelp(show) } if (err) throw err process.exit(1) }) .strict() try { if (args.includes("-h") || args.includes("--help")) { await cli.parse(args, (err: Error | undefined, _argv: unknown, out: string) => { if (err) throw err if (!out) return show(out) }) } else { await cli.parse() } } catch (e) { const formatted = FormatError(e) if (formatted) UI.error(formatted) if (formatted === undefined) { UI.error("Unexpected error" + EOL) process.stderr.write(errorMessage(e) + EOL) } process.exitCode = 1 } finally { // Some subprocesses don't react properly to SIGTERM and similar signals. // Most notably, some docker-container-based MCP servers don't handle such signals unless // run using `docker run --init`. // Explicitly exit to avoid any hanging subprocesses. process.exit() }