Browse Source

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
Dax Raad 3 weeks ago
parent
commit
e70d984320

+ 2 - 0
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>

+ 17 - 4
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,
     })
   },
 })

+ 8 - 1
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<{