summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorKit Langton <[email protected]>2026-05-02 22:35:20 -0400
committerGitHub <[email protected]>2026-05-02 22:35:20 -0400
commit7409dcc6bdd2329c12b7053d0476bd8802747e7f (patch)
tree270fe033f559d862a2d4399bfaf5ae518fdf816b /packages
parent2829943ad15da5cd736a7f70f45f54daf488bcdd (diff)
downloadopencode-7409dcc6bdd2329c12b7053d0476bd8802747e7f.tar.gz
opencode-7409dcc6bdd2329c12b7053d0476bd8802747e7f.zip
refactor(cli): convert run command to effectCmd (#25519)
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/src/cli/cmd/cmd.ts2
-rw-r--r--packages/opencode/src/cli/cmd/run.ts37
-rw-r--r--packages/opencode/src/cli/effect-cmd.ts6
3 files changed, 25 insertions, 20 deletions
diff --git a/packages/opencode/src/cli/cmd/cmd.ts b/packages/opencode/src/cli/cmd/cmd.ts
index fe6d62d7b..05af009b8 100644
--- a/packages/opencode/src/cli/cmd/cmd.ts
+++ b/packages/opencode/src/cli/cmd/cmd.ts
@@ -1,6 +1,6 @@
import type { CommandModule } from "yargs"
-type WithDoubleDash<T> = T & { "--"?: string[] }
+export type WithDoubleDash<T> = T & { "--"?: string[] }
export function cmd<T, U>(input: CommandModule<T, WithDoubleDash<U>>) {
return input
diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts
index f73ca6717..72096dba3 100644
--- a/packages/opencode/src/cli/cmd/run.ts
+++ b/packages/opencode/src/cli/cmd/run.ts
@@ -1,10 +1,10 @@
import type { Argv } from "yargs"
import path from "path"
import { pathToFileURL } from "url"
+import { Effect } from "effect"
import { UI } from "../ui"
-import { cmd } from "./cmd"
+import { effectCmd } from "../effect-cmd"
import { Flag } from "@opencode-ai/core/flag/flag"
-import { bootstrap } from "../bootstrap"
import { EOL } from "os"
import { Filesystem } from "@/util/filesystem"
import { createOpencodeClient, type OpencodeClient, type ToolPart } from "@opencode-ai/sdk/v2"
@@ -203,11 +203,17 @@ function normalizePath(input?: string) {
return input
}
-export const RunCommand = cmd({
+export const RunCommand = effectCmd({
command: "run [message..]",
describe: "run opencode with a message",
- builder: (yargs: Argv) => {
- return yargs
+ // --attach connects to a remote server (no local instance needed); the
+ // default path runs an in-process server and needs the project instance.
+ instance: (args) => !args.attach,
+ // For --dir without --attach, load instance for the resolved target dir.
+ // The handler also chdirs (preserving the legacy order: chdir → file resolution).
+ directory: (args) => (args.dir && !args.attach ? path.resolve(process.cwd(), args.dir) : process.cwd()),
+ builder: (yargs: Argv) =>
+ yargs
.positional("message", {
describe: "message to send",
type: "string",
@@ -291,9 +297,9 @@ export const RunCommand = cmd({
type: "boolean",
describe: "auto-approve permissions that are not explicitly denied (dangerous!)",
default: false,
- })
- },
- handler: async (args) => {
+ }),
+ handler: Effect.fn("Cli.run")(function* (args) {
+ yield* Effect.promise(async () => {
let message = [...args.message, ...(args["--"] || [])]
.map((arg) => (arg.includes(" ") ? `"${arg.replace(/"/g, '\\"')}"` : arg))
.join(" ")
@@ -661,13 +667,12 @@ export const RunCommand = cmd({
return await execute(sdk)
}
- await bootstrap(process.cwd(), async () => {
- const fetchFn = (async (input: RequestInfo | URL, init?: RequestInit) => {
- const request = new Request(input, init)
- return Server.Default().app.fetch(request)
- }) as typeof globalThis.fetch
- const sdk = createOpencodeClient({ baseUrl: "http://opencode.internal", fetch: fetchFn })
- await execute(sdk)
+ const fetchFn = (async (input: RequestInfo | URL, init?: RequestInit) => {
+ const request = new Request(input, init)
+ return Server.Default().app.fetch(request)
+ }) as typeof globalThis.fetch
+ const sdk = createOpencodeClient({ baseUrl: "http://opencode.internal", fetch: fetchFn })
+ await execute(sdk)
})
- },
+ }),
})
diff --git a/packages/opencode/src/cli/effect-cmd.ts b/packages/opencode/src/cli/effect-cmd.ts
index ceb52d07a..b0f6de16b 100644
--- a/packages/opencode/src/cli/effect-cmd.ts
+++ b/packages/opencode/src/cli/effect-cmd.ts
@@ -3,7 +3,7 @@ import { Effect, Schema } from "effect"
import { AppRuntime, type AppServices } from "@/effect/app-runtime"
import { InstanceStore } from "@/project/instance-store"
import { InstanceRef } from "@/effect/instance-ref"
-import { cmd } from "./cmd/cmd"
+import { cmd, type WithDoubleDash } from "./cmd/cmd"
/**
* User-visible command failure. Throw via `fail("...")` from an effectCmd handler
@@ -47,7 +47,7 @@ interface EffectCmdOpts<Args, A> {
instance?: boolean | ((args: Args) => boolean)
/** Defaults to process.cwd(). Override for commands that take a directory positional. */
directory?: (args: Args) => string
- handler: (args: Args) => Effect.Effect<A, CliError, AppServices | InstanceStore.Service>
+ handler: (args: WithDoubleDash<Args>) => Effect.Effect<A, CliError, AppServices | InstanceStore.Service>
}
/**
@@ -75,7 +75,7 @@ export const effectCmd = <Args, A>(opts: EffectCmdOpts<Args, A>) =>
builder: opts.builder as never,
async handler(rawArgs) {
// yargs typing wraps Args in ArgumentsCamelCase<WithDoubleDash<...>>; cast at the boundary.
- const args = rawArgs as unknown as Args
+ const args = rawArgs as unknown as WithDoubleDash<Args>
const useInstance = typeof opts.instance === "function" ? opts.instance(args) : opts.instance !== false
if (!useInstance) {
await AppRuntime.runPromise(opts.handler(args))