summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2026-01-31 14:42:36 -0500
committerDax Raad <[email protected]>2026-01-31 14:42:36 -0500
commite70d984320571597f89421d85c2f74009951027c (patch)
tree68d7523c911c2ca01926b4a4960a85a5d330489d
parentda7c874808b82544a9eb5981eb9ba83106b74378 (diff)
downloadopencode-e70d984320571597f89421d85c2f74009951027c.tar.gz
opencode-e70d984320571597f89421d85c2f74009951027c.zip
tui: enable password authentication for remote session attachment
Allow users to authenticate when attaching to a remote OpenCode session by supporting basic auth via a password flag or OPENCODE_SERVER_PASSWORD environment variable
-rw-r--r--packages/opencode/src/cli/cmd/tui/app.tsx2
-rw-r--r--packages/opencode/src/cli/cmd/tui/attach.ts21
-rw-r--r--packages/opencode/src/cli/cmd/tui/context/sdk.tsx9
3 files changed, 27 insertions, 5 deletions
diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx
index 10d7a25f8..713def2e5 100644
--- a/packages/opencode/src/cli/cmd/tui/app.tsx
+++ b/packages/opencode/src/cli/cmd/tui/app.tsx
@@ -104,6 +104,7 @@ export function tui(input: {
args: Args
directory?: string
fetch?: typeof fetch
+ headers?: RequestInit["headers"]
events?: EventSource
onExit?: () => Promise<void>
}) {
@@ -130,6 +131,7 @@ export function tui(input: {
url={input.url}
directory={input.directory}
fetch={input.fetch}
+ headers={input.headers}
events={input.events}
>
<SyncProvider>
diff --git a/packages/opencode/src/cli/cmd/tui/attach.ts b/packages/opencode/src/cli/cmd/tui/attach.ts
index f641ff098..e852cb73d 100644
--- a/packages/opencode/src/cli/cmd/tui/attach.ts
+++ b/packages/opencode/src/cli/cmd/tui/attach.ts
@@ -19,21 +19,34 @@ export const AttachCommand = cmd({
alias: ["s"],
type: "string",
describe: "session id to continue",
+ })
+ .option("password", {
+ alias: ["p"],
+ type: "string",
+ describe: "basic auth password (defaults to OPENCODE_SERVER_PASSWORD)",
}),
handler: async (args) => {
- let directory = args.dir
- if (args.dir) {
+ const directory = (() => {
+ if (!args.dir) return undefined
try {
process.chdir(args.dir)
- directory = process.cwd()
+ return process.cwd()
} catch {
// If the directory doesn't exist locally (remote attach), pass it through.
+ return args.dir
}
- }
+ })()
+ const headers = (() => {
+ const password = args.password ?? process.env.OPENCODE_SERVER_PASSWORD
+ if (!password) return undefined
+ const auth = `Basic ${Buffer.from(`opencode:${password}`).toString("base64")}`
+ return { Authorization: auth }
+ })()
await tui({
url: args.url,
args: { sessionID: args.session },
directory,
+ headers,
})
},
})
diff --git a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx
index 3339e7b00..7fa7e05c3 100644
--- a/packages/opencode/src/cli/cmd/tui/context/sdk.tsx
+++ b/packages/opencode/src/cli/cmd/tui/context/sdk.tsx
@@ -9,13 +9,20 @@ 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
+ headers?: RequestInit["headers"]
+ events?: EventSource
+ }) => {
const abort = new AbortController()
const sdk = createOpencodeClient({
baseUrl: props.url,
signal: abort.signal,
directory: props.directory,
fetch: props.fetch,
+ headers: props.headers,
})
const emitter = createGlobalEmitter<{