From ab25fba6e570b5662196f6b2a0365d753812cda9 Mon Sep 17 00:00:00 2001 From: OpeOginni Date: Tue, 13 Jan 2026 23:33:54 +0100 Subject: [PATCH 1/3] feat(tui): add username and password options for authentication in TUI attach command --- packages/opencode/src/cli/cmd/tui/app.tsx | 2 ++ packages/opencode/src/cli/cmd/tui/attach.ts | 13 ++++++++++++- packages/opencode/src/cli/cmd/tui/context/args.tsx | 2 ++ packages/opencode/src/cli/cmd/tui/context/sdk.tsx | 7 ++++++- 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 1fea3f4b305..881722612cc 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -131,6 +131,8 @@ export function tui(input: { directory={input.directory} fetch={input.fetch} events={input.events} + username={input.args.username} + password={input.args.password} > diff --git a/packages/opencode/src/cli/cmd/tui/attach.ts b/packages/opencode/src/cli/cmd/tui/attach.ts index 3f9285f631c..1d3006a598f 100644 --- a/packages/opencode/src/cli/cmd/tui/attach.ts +++ b/packages/opencode/src/cli/cmd/tui/attach.ts @@ -19,12 +19,23 @@ export const AttachCommand = cmd({ alias: ["s"], type: "string", describe: "session id to continue", + }) + .option("username", { + alias: ["u"], + type: "string", + default: "opencode", + describe: "username to authenticate with", + }) + .option("password", { + alias: ["p"], + type: "string", + describe: "password to authenticate with", }), handler: async (args) => { if (args.dir) process.chdir(args.dir) await tui({ url: args.url, - args: { sessionID: args.session }, + args: { sessionID: args.session, username: args.username, password: args.password }, directory: args.dir ? process.cwd() : undefined, }) }, diff --git a/packages/opencode/src/cli/cmd/tui/context/args.tsx b/packages/opencode/src/cli/cmd/tui/context/args.tsx index ffd43009a41..480c21c278f 100644 --- a/packages/opencode/src/cli/cmd/tui/context/args.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/args.tsx @@ -1,6 +1,8 @@ import { createSimpleContext } from "./helper" export interface Args { + username?: string + password?: string model?: string agent?: string prompt?: string diff --git a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx index 3339e7b00d2..96b6d7b0c8c 100644 --- a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx @@ -9,13 +9,18 @@ export type EventSource = { export const { use: useSDK, provider: SDKProvider } = createSimpleContext({ name: "SDK", - init: (props: { url: string; directory?: string; fetch?: typeof fetch; events?: EventSource }) => { + init: (props: { url: string; directory?: string; fetch?: typeof fetch; events?: EventSource, username?: string; password?: string }) => { const abort = new AbortController() const sdk = createOpencodeClient({ baseUrl: props.url, signal: abort.signal, directory: props.directory, fetch: props.fetch, + headers: props.password && props.username + ? { + Authorization: `Basic ${Buffer.from(`${props.username}:${props.password}`).toString("base64")}` + } + : undefined, }) const emitter = createGlobalEmitter<{ From 3c81ab4f95cdc5a5cc2378042b3a5e94153d6aeb Mon Sep 17 00:00:00 2001 From: OpeOginni Date: Wed, 14 Jan 2026 00:16:48 +0100 Subject: [PATCH 2/3] feat(server): move CORS before auth configuration and include authentication status in health check response --- packages/opencode/src/server/server.ts | 45 +++++++++++++------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index 52457515b8e..0a23b552771 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -97,7 +97,29 @@ export namespace Server { status: 500, }) }) + .use( + cors({ + origin(input) { + if (!input) return + + if (input.startsWith("http://localhost:")) return input + if (input.startsWith("http://127.0.0.1:")) return input + if (input === "tauri://localhost" || input === "http://tauri.localhost") return input + + // *.opencode.ai (https only, adjust if needed) + if (/^https:\/\/([a-z0-9-]+\.)*opencode\.ai$/.test(input)) { + return input + } + if (_corsWhitelist.includes(input)) { + return input + } + + return + }, + }), + ) .use((c, next) => { + if (c.req.path === "/global/health") return next() const password = Flag.OPENCODE_SERVER_PASSWORD if (!password) return next() const username = Flag.OPENCODE_SERVER_USERNAME ?? "opencode" @@ -120,27 +142,6 @@ export namespace Server { timer.stop() } }) - .use( - cors({ - origin(input) { - if (!input) return - - if (input.startsWith("http://localhost:")) return input - if (input.startsWith("http://127.0.0.1:")) return input - if (input === "tauri://localhost" || input === "http://tauri.localhost") return input - - // *.opencode.ai (https only, adjust if needed) - if (/^https:\/\/([a-z0-9-]+\.)*opencode\.ai$/.test(input)) { - return input - } - if (_corsWhitelist.includes(input)) { - return input - } - - return - }, - }), - ) .get( "/global/health", describeRoute({ @@ -159,7 +160,7 @@ export namespace Server { }, }), async (c) => { - return c.json({ healthy: true, version: Installation.VERSION }) + return c.json({ healthy: true, version: Installation.VERSION, authenticated: !!Flag.OPENCODE_SERVER_PASSWORD }) }, ) .get( From 95caf9141dc59d429c6e4e32522cce925f287d5f Mon Sep 17 00:00:00 2001 From: OpeOginni Date: Wed, 14 Jan 2026 00:19:21 +0100 Subject: [PATCH 3/3] docs(cli): add username and password options for basic authentication in CLI documentation --- packages/web/src/content/docs/cli.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/web/src/content/docs/cli.mdx b/packages/web/src/content/docs/cli.mdx index d1d11ed70d9..59df5b67bc2 100644 --- a/packages/web/src/content/docs/cli.mdx +++ b/packages/web/src/content/docs/cli.mdx @@ -368,6 +368,8 @@ This starts an HTTP server that provides API access to opencode functionality wi | `--hostname` | Hostname to listen on | | `--mdns` | Enable mDNS discovery | | `--cors` | Additional browser origin(s) to allow CORS | +| `--username | Username set on server for basic auth | +| `--password | Password set on server for basic auth | ---