import { Argument, Flag } from "effect/unstable/cli" import { Spec } from "../framework/spec" declare const OPENCODE_CLI_NAME: string | undefined const ServerParams = { standalone: Flag.boolean("standalone").pipe( Flag.withDescription("Run with a private server instead of the background service"), Flag.withDefault(false), ), server: Flag.string("server").pipe( Flag.withDescription("Connect to a server URL instead of the background service"), Flag.optional, ), } export const Commands = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCODE_CLI_NAME : "opencode", { description: "OpenCode 2.0 preview command line interface", params: { ...ServerParams, directory: Argument.string("directory").pipe( Argument.withDescription("Directory to start OpenCode in"), Argument.optional, ), continue: Flag.boolean("continue").pipe( Flag.withAlias("c"), Flag.withDescription("Continue the last session"), Flag.withDefault(false), ), session: Flag.string("session").pipe( Flag.withAlias("s"), Flag.withDescription("Session ID to continue"), Flag.optional, ), }, commands: [ Spec.make("api", { description: "Make a request to the running server", params: { ...ServerParams, request: Argument.string("operation | method path").pipe( Argument.withDescription("OpenAPI operation ID, or an HTTP method followed by a path"), Argument.variadic({ min: 1, max: 2 }), ), data: Flag.string("data").pipe(Flag.withAlias("d"), Flag.withDescription("Request body"), Flag.optional), header: Flag.string("header").pipe( Flag.withAlias("H"), Flag.withDescription("Request header in name:value form"), Flag.atMost(100), ), param: Flag.keyValuePair("param").pipe(Flag.withDescription("OpenAPI path or query parameter"), Flag.optional), }, }), Spec.make("debug", { description: "Debugging and troubleshooting tools", commands: [Spec.make("agents", { description: "List all agents" })], }), Spec.make("console", { description: "Manage OpenCode Console access", commands: [ Spec.make("login", { description: "Log in to OpenCode Console", params: { url: Argument.string("url").pipe(Argument.withDescription("Console server URL"), Argument.optional), }, }), ], }), Spec.make("auth", { description: "Manage authentication", commands: [ Spec.make("connect", { description: "Connect to a wellknown authentication provider", params: { url: Argument.string("url").pipe(Argument.withDescription("Wellknown provider URL")), }, }), ], }), Spec.make("mcp", { description: "Manage MCP (Model Context Protocol) servers", commands: [ Spec.make("list", { description: "List configured MCP servers and their status" }), Spec.make("add", { description: "Add an MCP server to your configuration", params: { name: Argument.string("name").pipe(Argument.withDescription("Name of the MCP server")), command: Argument.string("command").pipe( Argument.withDescription("Command and arguments for a local server, passed after --"), Argument.variadic({ min: 0 }), ), url: Flag.string("url").pipe(Flag.withDescription("URL for a remote MCP server"), Flag.optional), header: Flag.keyValuePair("header").pipe( Flag.withDescription("HTTP header for a remote server, as name=value"), Flag.optional, ), env: Flag.keyValuePair("env").pipe( Flag.withDescription("Environment variable for a local server, as name=value"), Flag.optional, ), global: Flag.boolean("global").pipe( Flag.withDescription("Write to the global config instead of the project config"), Flag.withDefault(false), ), }, }), Spec.make("auth", { description: "Authenticate with an OAuth-capable remote MCP server", params: { name: Argument.string("name").pipe(Argument.withDescription("Name of the MCP server")) }, }), Spec.make("logout", { description: "Remove stored OAuth credentials for an MCP server", params: { name: Argument.string("name").pipe(Argument.withDescription("Name of the MCP server")) }, }), ], }), Spec.make("plugin", { description: "Manage plugins", commands: [Spec.make("list", { description: "List active plugins" })], }), Spec.make("migrate", { description: "Migrate v1 data to v2" }), Spec.make("mini", { description: "Start the minimal interactive interface", params: { ...ServerParams, continue: Flag.boolean("continue").pipe( Flag.withAlias("c"), Flag.withDescription("Continue the last session"), Flag.withDefault(false), ), session: Flag.string("session").pipe( Flag.withAlias("s"), Flag.withDescription("Session ID to continue"), Flag.optional, ), fork: Flag.boolean("fork").pipe( Flag.withDescription("Fork the session when continuing"), Flag.withDefault(false), ), replay: Flag.boolean("replay").pipe( Flag.withDescription("Replay session history on resume and after resize"), Flag.withDefault(true), ), replayLimit: Flag.integer("replay-limit").pipe( Flag.withDescription("Cap visible replay to the newest N messages"), Flag.optional, ), model: Flag.string("model").pipe( Flag.withAlias("m"), Flag.withDescription("Model to use in the format provider/model"), Flag.optional, ), agent: Flag.string("agent").pipe(Flag.withDescription("Agent to use"), Flag.optional), prompt: Flag.string("prompt").pipe(Flag.withDescription("Prompt to use"), Flag.optional), demo: Flag.boolean("demo").pipe(Flag.withDefault(false), Flag.withHidden), }, }), Spec.make("run", { description: "Run OpenCode with a message", params: { ...ServerParams, message: Argument.string("message").pipe( Argument.withDescription("Message to send"), Argument.variadic({ min: 0 }), ), continue: Flag.boolean("continue").pipe( Flag.withAlias("c"), Flag.withDescription("Continue the last session"), Flag.withDefault(false), ), session: Flag.string("session").pipe( Flag.withAlias("s"), Flag.withDescription("Session ID to continue"), Flag.optional, ), fork: Flag.boolean("fork").pipe( Flag.withDescription("Fork the session before continuing"), Flag.withDefault(false), ), model: Flag.string("model").pipe( Flag.withAlias("m"), Flag.withDescription("Model to use in the format provider/model#variant"), Flag.optional, ), agent: Flag.string("agent").pipe(Flag.withDescription("Agent to use"), Flag.optional), format: Flag.choice("format", ["default", "json"]).pipe( Flag.withDescription("Output format"), Flag.withDefault("default"), ), file: Flag.string("file").pipe( Flag.withAlias("f"), Flag.withDescription("File to attach to the message"), Flag.atMost(100), ), title: Flag.string("title").pipe(Flag.withDescription("Session title"), Flag.optional), thinking: Flag.boolean("thinking").pipe(Flag.withDescription("Show thinking blocks"), Flag.withDefault(false)), auto: Flag.boolean("auto").pipe( Flag.withDescription("Auto-approve permissions that are not explicitly denied"), Flag.withDefault(false), ), yolo: Flag.boolean("yolo").pipe(Flag.withDefault(false), Flag.withHidden), }, }), Spec.make("service", { description: "Manage the background server", commands: [ Spec.make("start", { description: "Start the background server" }), Spec.make("restart", { description: "Restart the background server" }), Spec.make("status", { description: "Show background server status" }), Spec.make("stop", { description: "Stop the background server" }), Spec.make("get", { description: "Get service configuration", params: { key: Argument.string("key").pipe(Argument.optional) }, }), Spec.make("set", { description: "Set service configuration", params: { key: Argument.string("key"), value: Argument.string("value") }, }), Spec.make("unset", { description: "Unset service configuration", params: { key: Argument.string("key") }, }), ], }), Spec.make("pair", { description: "Show server pairing information" }), Spec.make("serve", { description: "Start the v2 API server", params: { hostname: Flag.string("hostname").pipe(Flag.optional), port: Flag.integer("port").pipe(Flag.optional), service: Flag.boolean("service").pipe(Flag.withDefault(false)), stdio: Flag.boolean("stdio").pipe(Flag.withDefault(false)), }, }), ], })