opencode icon indicating copy to clipboard operation
opencode copied to clipboard

feat(serve): add CORS origins configuration support

Open braden-w opened this issue 5 months ago • 8 comments

Add --cors-origins flag to serve command allowing specification of allowed CORS origins for cross-origin requests. When no origins are specified, defaults to same-origin only for security.

Usage:

opencode serve --cors-origins "http://localhost:3000" "https://myapp.com"
opencode serve -c "http://localhost:3000"

braden-w avatar Jul 22 '25 15:07 braden-w

Hey! I understand this might be considered a core feature, and I saw in the README that you don't accept PRs for those.

Feel free to close this if it doesn't align with the project's direction, totally okay! I built this because I was encountering CORS issues when tunneling the server, but I completely understand if this doesn't align with the vision.

Thanks for the amazing project!

braden-w avatar Jul 22 '25 15:07 braden-w

I second this one. Really useful to have Opencode as a Backend service only.

alexandermariduena avatar Jul 30 '25 13:07 alexandermariduena

Would be very useful. If you try to build a browser client you will not be able to make any requests without this feature.

andreigiura avatar Aug 01 '25 08:08 andreigiura

fix conflicts and i'll merge - ty!

thdxr avatar Aug 04 '25 16:08 thdxr

@braden-w Do you need some help with this?

alexandermariduena avatar Aug 04 '25 17:08 alexandermariduena

Hey everyone! 👋

I fixed conflicts, but had some issues since the lazy wrapper around app didn't support args, and I want to start a discussion here.

After looking through the codebase, I'm not sure we need the lazy wrapper around app. The Server.app() function is only called in three places:

  1. Server.listen() - called once when the server starts
  2. Server.openapi() - called once during OpenAPI spec generation (opencode generate command)
  3. Plugin system - called once during plugin initialization

Each of these happens in completely different execution contexts and typically only once per command. So the expensive app creation (setting up ~30 routes, OpenAPI specs, middleware, etc.) only happens once anyway; the lazy caching isn't really providing any performance benefit.

For this PR, I ended up just removing the lazy wrapper entirely. That said, if we do want to keep lazy, there are a few options we could explore:

  1. Make lazy accept arguments - essentially turning it into a memoization function
  2. Use a closure pattern: capture CORS config in the outer scope
  3. Parameterized cache: cache app instances by their configuration

But honestly, given the call patterns, I think the simplest solution (no caching) is probably the right one here.

What do you all think? Am I missing some use case where the app gets created multiple times in the same process?

braden-w avatar Aug 04 '25 18:08 braden-w

Hey @thdxr , sorry for the ping, but just wanted to check in and get some feedback on the proposed changes. Is there a solution we could make so that app remains lazy while supporting CORS as parameters?

braden-w avatar Aug 05 '25 21:08 braden-w

Would be very useful +1 for this.

ajmariduena avatar Aug 11 '25 04:08 ajmariduena

It looks like CORS support has already been added to the main branch in a simpler way. The server now uses Hono's CORS middleware with permissive defaults:

packages/opencode/src/server/server.ts (line 125)

import { cors } from "hono/cors"

// ...

.use(cors())

This allows all origins by default, unlike this configurable origins approach. One less feature but simpler.

I think this PR can be closed since the feature is already implemented. Thank you @thdxr !

braden-w avatar Nov 21 '25 22:11 braden-w