summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorAiden Cline <[email protected]>2025-12-26 11:43:52 -0600
committerAiden Cline <[email protected]>2025-12-26 11:43:52 -0600
commit505068d5a6cccc732aed76580f9bec6a5dbca507 (patch)
tree21b0bf70c21f89f6813075d5c4901d4d6080809d /packages
parent2e10ffac6b4ffe6ff183a485d847e26641f8a1bc (diff)
downloadopencode-505068d5a6cccc732aed76580f9bec6a5dbca507.tar.gz
opencode-505068d5a6cccc732aed76580f9bec6a5dbca507.zip
Revert "feat(core): optional mdns service (#6192)"
This reverts commit 26e7043718fbf5fbf08eecd04ff8ed5edd82e33e.
Diffstat (limited to 'packages')
-rw-r--r--packages/opencode/package.json1
-rw-r--r--packages/opencode/src/cli/cmd/acp.ts30
-rw-r--r--packages/opencode/src/cli/cmd/serve.ts25
-rw-r--r--packages/opencode/src/cli/cmd/tui/spawn.ts28
-rw-r--r--packages/opencode/src/cli/cmd/tui/thread.ts22
-rw-r--r--packages/opencode/src/cli/cmd/tui/worker.ts2
-rw-r--r--packages/opencode/src/cli/cmd/web.ts31
-rw-r--r--packages/opencode/src/cli/network.ts42
-rw-r--r--packages/opencode/src/config/config.ts12
-rw-r--r--packages/opencode/src/server/mdns.ts57
-rw-r--r--packages/opencode/src/server/server.ts33
-rw-r--r--packages/web/src/content/docs/cli.mdx18
-rw-r--r--packages/web/src/content/docs/config.mdx25
-rw-r--r--packages/web/src/content/docs/server.mdx9
14 files changed, 112 insertions, 223 deletions
diff --git a/packages/opencode/package.json b/packages/opencode/package.json
index 55656660e..bf45966d8 100644
--- a/packages/opencode/package.json
+++ b/packages/opencode/package.json
@@ -88,7 +88,6 @@
"@standard-schema/spec": "1.0.0",
"@zip.js/zip.js": "2.7.62",
"ai": "catalog:",
- "bonjour-service": "1.3.0",
"bun-pty": "0.4.2",
"chokidar": "4.0.3",
"clipboardy": "4.0.0",
diff --git a/packages/opencode/src/cli/cmd/acp.ts b/packages/opencode/src/cli/cmd/acp.ts
index 2db64e3b1..c607e5f5b 100644
--- a/packages/opencode/src/cli/cmd/acp.ts
+++ b/packages/opencode/src/cli/cmd/acp.ts
@@ -3,10 +3,8 @@ import { bootstrap } from "../bootstrap"
import { cmd } from "./cmd"
import { AgentSideConnection, ndJsonStream } from "@agentclientprotocol/sdk"
import { ACP } from "@/acp/agent"
-import { Config } from "@/config/config"
import { Server } from "@/server/server"
import { createOpencodeClient } from "@opencode-ai/sdk/v2"
-import { withNetworkOptions, resolveNetworkOptions } from "../network"
const log = Log.create({ service: "acp-command" })
@@ -21,17 +19,29 @@ export const AcpCommand = cmd({
command: "acp",
describe: "start ACP (Agent Client Protocol) server",
builder: (yargs) => {
- return withNetworkOptions(yargs).option("cwd", {
- describe: "working directory",
- type: "string",
- default: process.cwd(),
- })
+ return yargs
+ .option("cwd", {
+ describe: "working directory",
+ type: "string",
+ default: process.cwd(),
+ })
+ .option("port", {
+ type: "number",
+ describe: "port to listen on",
+ default: 0,
+ })
+ .option("hostname", {
+ type: "string",
+ describe: "hostname to listen on",
+ default: "127.0.0.1",
+ })
},
handler: async (args) => {
await bootstrap(process.cwd(), async () => {
- const config = await Config.get()
- const opts = resolveNetworkOptions(args, config)
- const server = Server.listen(opts)
+ const server = Server.listen({
+ port: args.port,
+ hostname: args.hostname,
+ })
const sdk = createOpencodeClient({
baseUrl: `http://${server.hostname}:${server.port}`,
diff --git a/packages/opencode/src/cli/cmd/serve.ts b/packages/opencode/src/cli/cmd/serve.ts
index 0fd7aa88f..3af3316a9 100644
--- a/packages/opencode/src/cli/cmd/serve.ts
+++ b/packages/opencode/src/cli/cmd/serve.ts
@@ -1,16 +1,29 @@
-import { Config } from "../../config/config"
import { Server } from "../../server/server"
import { cmd } from "./cmd"
-import { withNetworkOptions, resolveNetworkOptions } from "../network"
export const ServeCommand = cmd({
command: "serve",
- builder: (yargs) => withNetworkOptions(yargs),
+ builder: (yargs) =>
+ yargs
+ .option("port", {
+ alias: ["p"],
+ type: "number",
+ describe: "port to listen on",
+ default: 0,
+ })
+ .option("hostname", {
+ type: "string",
+ describe: "hostname to listen on",
+ default: "127.0.0.1",
+ }),
describe: "starts a headless opencode server",
handler: async (args) => {
- const config = await Config.get()
- const opts = resolveNetworkOptions(args, config)
- const server = Server.listen(opts)
+ const hostname = args.hostname
+ const port = args.port
+ const server = Server.listen({
+ port,
+ hostname,
+ })
console.log(`opencode server listening on http://${server.hostname}:${server.port}`)
await new Promise(() => {})
await server.stop()
diff --git a/packages/opencode/src/cli/cmd/tui/spawn.ts b/packages/opencode/src/cli/cmd/tui/spawn.ts
index 7ab846428..fa6795298 100644
--- a/packages/opencode/src/cli/cmd/tui/spawn.ts
+++ b/packages/opencode/src/cli/cmd/tui/spawn.ts
@@ -1,23 +1,33 @@
import { cmd } from "@/cli/cmd/cmd"
-import { Config } from "@/config/config"
import { Instance } from "@/project/instance"
import path from "path"
import { Server } from "@/server/server"
import { upgrade } from "@/cli/upgrade"
-import { withNetworkOptions, resolveNetworkOptions } from "@/cli/network"
export const TuiSpawnCommand = cmd({
command: "spawn [project]",
builder: (yargs) =>
- withNetworkOptions(yargs).positional("project", {
- type: "string",
- describe: "path to start opencode in",
- }),
+ yargs
+ .positional("project", {
+ type: "string",
+ describe: "path to start opencode in",
+ })
+ .option("port", {
+ type: "number",
+ describe: "port to listen on",
+ default: 0,
+ })
+ .option("hostname", {
+ type: "string",
+ describe: "hostname to listen on",
+ default: "127.0.0.1",
+ }),
handler: async (args) => {
upgrade()
- const config = await Config.get()
- const opts = resolveNetworkOptions(args, config)
- const server = Server.listen(opts)
+ const server = Server.listen({
+ port: args.port,
+ hostname: "127.0.0.1",
+ })
const bin = process.execPath
const cmd = []
let cwd = process.cwd()
diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts
index f75e3bd65..3cf8937a9 100644
--- a/packages/opencode/src/cli/cmd/tui/thread.ts
+++ b/packages/opencode/src/cli/cmd/tui/thread.ts
@@ -6,8 +6,6 @@ import path from "path"
import { UI } from "@/cli/ui"
import { iife } from "@/util/iife"
import { Log } from "@/util/log"
-import { withNetworkOptions, resolveNetworkOptions } from "@/cli/network"
-import { Config } from "@/config/config"
declare global {
const OPENCODE_WORKER_PATH: string
@@ -17,7 +15,7 @@ export const TuiThreadCommand = cmd({
command: "$0 [project]",
describe: "start opencode tui",
builder: (yargs) =>
- withNetworkOptions(yargs)
+ yargs
.positional("project", {
type: "string",
describe: "path to start opencode in",
@@ -38,12 +36,23 @@ export const TuiThreadCommand = cmd({
describe: "session id to continue",
})
.option("prompt", {
+ alias: ["p"],
type: "string",
describe: "prompt to use",
})
.option("agent", {
type: "string",
describe: "agent to use",
+ })
+ .option("port", {
+ type: "number",
+ describe: "port to listen on",
+ default: 0,
+ })
+ .option("hostname", {
+ type: "string",
+ describe: "hostname to listen on",
+ default: "127.0.0.1",
}),
handler: async (args) => {
// Resolve relative paths against PWD to preserve behavior when using --cwd flag
@@ -78,9 +87,10 @@ export const TuiThreadCommand = cmd({
process.on("unhandledRejection", (e) => {
Log.Default.error(e)
})
- const config = await Config.get()
- const networkOpts = resolveNetworkOptions(args, config)
- const server = await client.call("server", networkOpts)
+ const server = await client.call("server", {
+ port: args.port,
+ hostname: args.hostname,
+ })
const prompt = await iife(async () => {
const piped = !process.stdin.isTTY ? await Bun.stdin.text() : undefined
if (!args.prompt) return piped
diff --git a/packages/opencode/src/cli/cmd/tui/worker.ts b/packages/opencode/src/cli/cmd/tui/worker.ts
index 3ffc45ae8..76f78f3fa 100644
--- a/packages/opencode/src/cli/cmd/tui/worker.ts
+++ b/packages/opencode/src/cli/cmd/tui/worker.ts
@@ -30,7 +30,7 @@ process.on("uncaughtException", (e) => {
let server: Bun.Server<BunWebSocketData>
export const rpc = {
- async server(input: { port: number; hostname: string; mdns?: boolean }) {
+ async server(input: { port: number; hostname: string }) {
if (server) await server.stop(true)
try {
server = Server.listen(input)
diff --git a/packages/opencode/src/cli/cmd/web.ts b/packages/opencode/src/cli/cmd/web.ts
index adede0385..3d3036b1b 100644
--- a/packages/opencode/src/cli/cmd/web.ts
+++ b/packages/opencode/src/cli/cmd/web.ts
@@ -1,8 +1,6 @@
-import { Config } from "../../config/config"
import { Server } from "../../server/server"
import { UI } from "../ui"
import { cmd } from "./cmd"
-import { withNetworkOptions, resolveNetworkOptions } from "../network"
import open from "open"
import { networkInterfaces } from "os"
@@ -30,17 +28,32 @@ function getNetworkIPs() {
export const WebCommand = cmd({
command: "web",
- builder: (yargs) => withNetworkOptions(yargs),
+ builder: (yargs) =>
+ yargs
+ .option("port", {
+ alias: ["p"],
+ type: "number",
+ describe: "port to listen on",
+ default: 0,
+ })
+ .option("hostname", {
+ type: "string",
+ describe: "hostname to listen on",
+ default: "127.0.0.1",
+ }),
describe: "starts a headless opencode server",
handler: async (args) => {
- const config = await Config.get()
- const opts = resolveNetworkOptions(args, config)
- const server = Server.listen(opts)
+ const hostname = args.hostname
+ const port = args.port
+ const server = Server.listen({
+ port,
+ hostname,
+ })
UI.empty()
UI.println(UI.logo(" "))
UI.empty()
- if (opts.hostname === "0.0.0.0") {
+ if (hostname === "0.0.0.0") {
// Show localhost for local access
const localhostUrl = `http://localhost:${server.port}`
UI.println(UI.Style.TEXT_INFO_BOLD + " Local access: ", UI.Style.TEXT_NORMAL, localhostUrl)
@@ -57,10 +70,6 @@ export const WebCommand = cmd({
}
}
- if (opts.mdns) {
- UI.println(UI.Style.TEXT_INFO_BOLD + " mDNS: ", UI.Style.TEXT_NORMAL, "opencode.local")
- }
-
// Open localhost in browser
open(localhostUrl.toString()).catch(() => {})
} else {
diff --git a/packages/opencode/src/cli/network.ts b/packages/opencode/src/cli/network.ts
deleted file mode 100644
index 661688572..000000000
--- a/packages/opencode/src/cli/network.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import type { Argv, InferredOptionTypes } from "yargs"
-import type { Config } from "../config/config"
-
-const options = {
- port: {
- type: "number" as const,
- describe: "port to listen on",
- default: 0,
- },
- hostname: {
- type: "string" as const,
- describe: "hostname to listen on",
- default: "127.0.0.1",
- },
- mdns: {
- type: "boolean" as const,
- describe: "enable mDNS service discovery (defaults hostname to 0.0.0.0)",
- default: false,
- },
-}
-
-export type NetworkOptions = InferredOptionTypes<typeof options>
-
-export function withNetworkOptions<T>(yargs: Argv<T>) {
- return yargs.options(options)
-}
-
-export function resolveNetworkOptions(args: NetworkOptions, config?: Config.Info) {
- const portExplicitlySet = process.argv.includes("--port")
- const hostnameExplicitlySet = process.argv.includes("--hostname")
- const mdnsExplicitlySet = process.argv.includes("--mdns")
-
- const mdns = mdnsExplicitlySet ? args.mdns : (config?.server?.mdns ?? args.mdns)
- const port = portExplicitlySet ? args.port : (config?.server?.port ?? args.port)
- const hostname = hostnameExplicitlySet
- ? args.hostname
- : mdns && !config?.server?.hostname
- ? "0.0.0.0"
- : (config?.server?.hostname ?? args.hostname)
-
- return { hostname, port, mdns }
-}
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 3350cf8f6..802c5db92 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -587,17 +587,6 @@ export namespace Config {
.describe("Control diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column"),
})
- export const Server = z
- .object({
- port: z.number().int().positive().optional().describe("Port to listen on"),
- hostname: z.string().optional().describe("Hostname to listen on"),
- mdns: z.boolean().optional().describe("Enable mDNS service discovery"),
- })
- .strict()
- .meta({
- ref: "ServerConfig",
- })
-
export const Layout = z.enum(["auto", "stretch"]).meta({
ref: "LayoutConfig",
})
@@ -646,7 +635,6 @@ export namespace Config {
keybinds: Keybinds.optional().describe("Custom keybind configurations"),
logLevel: Log.Level.optional().describe("Log level"),
tui: TUI.optional().describe("TUI specific settings"),
- server: Server.optional().describe("Server configuration for opencode serve and web commands"),
command: z
.record(z.string(), Command)
.optional()
diff --git a/packages/opencode/src/server/mdns.ts b/packages/opencode/src/server/mdns.ts
deleted file mode 100644
index 45e61d361..000000000
--- a/packages/opencode/src/server/mdns.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { Log } from "@/util/log"
-import Bonjour from "bonjour-service"
-
-const log = Log.create({ service: "mdns" })
-
-export namespace MDNS {
- let bonjour: Bonjour | undefined
- let currentPort: number | undefined
-
- export function publish(port: number, name = "opencode") {
- if (currentPort === port) return
- if (bonjour) unpublish()
-
- try {
- bonjour = new Bonjour()
- const service = bonjour.publish({
- name,
- type: "http",
- port,
- txt: { path: "/" },
- })
-
- service.on("up", () => {
- log.info("mDNS service published", { name, port })
- })
-
- service.on("error", (err) => {
- log.error("mDNS service error", { error: err })
- })
-
- currentPort = port
- } catch (err) {
- log.error("mDNS publish failed", { error: err })
- if (bonjour) {
- try {
- bonjour.destroy()
- } catch {}
- }
- bonjour = undefined
- currentPort = undefined
- }
- }
-
- export function unpublish() {
- if (bonjour) {
- try {
- bonjour.unpublishAll()
- bonjour.destroy()
- } catch (err) {
- log.error("mDNS unpublish failed", { error: err })
- }
- bonjour = undefined
- currentPort = undefined
- log.info("mDNS service unpublished")
- }
- }
-}
diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts
index 65393e128..c74dbbb41 100644
--- a/packages/opencode/src/server/server.ts
+++ b/packages/opencode/src/server/server.ts
@@ -45,11 +45,9 @@ import { Snapshot } from "@/snapshot"
import { SessionSummary } from "@/session/summary"
import { SessionStatus } from "@/session/status"
import { upgradeWebSocket, websocket } from "hono/bun"
-import type { BunWebSocketData } from "hono/bun"
import { errors } from "./error"
import { Pty } from "@/pty"
import { Installation } from "@/installation"
-import { MDNS } from "./mdns"
// @ts-ignore This global is needed to prevent ai-sdk from logging warnings to stdout https://github.com/vercel/ai/blob/2dc67e0ef538307f21368db32d5a12345d98831b/packages/ai/src/logger/log-warnings.ts#L85
globalThis.AI_SDK_LOG_WARNINGS = false
@@ -2625,41 +2623,20 @@ export namespace Server {
return result
}
- export function listen(opts: { port: number; hostname: string; mdns?: boolean }) {
+ export function listen(opts: { port: number; hostname: string }) {
const args = {
hostname: opts.hostname,
idleTimeout: 0,
fetch: App().fetch,
websocket: websocket,
} as const
- const tryServe = (port: number) => {
+ if (opts.port === 0) {
try {
- return Bun.serve({ ...args, port })
+ return Bun.serve({ ...args, port: 4096 })
} catch {
- return undefined
+ // port 4096 not available, fall through to use port 0
}
}
- const server = opts.port === 0 ? (tryServe(4096) ?? tryServe(0)) : tryServe(opts.port)
- if (!server) throw new Error(`Failed to start server on port ${opts.port}`)
-
- const shouldPublishMDNS =
- opts.mdns &&
- server.port &&
- opts.hostname !== "127.0.0.1" &&
- opts.hostname !== "localhost" &&
- opts.hostname !== "::1"
- if (shouldPublishMDNS) {
- MDNS.publish(server.port!)
- } else if (opts.mdns) {
- log.warn("mDNS enabled but hostname is loopback; skipping mDNS publish")
- }
-
- const originalStop = server.stop.bind(server)
- server.stop = async (closeActiveConnections?: boolean) => {
- if (shouldPublishMDNS) MDNS.unpublish()
- return originalStop(closeActiveConnections)
- }
-
- return server
+ return Bun.serve({ ...args, port: opts.port })
}
}
diff --git a/packages/web/src/content/docs/cli.mdx b/packages/web/src/content/docs/cli.mdx
index 4a826e5b3..e4e40ac7a 100644
--- a/packages/web/src/content/docs/cli.mdx
+++ b/packages/web/src/content/docs/cli.mdx
@@ -335,11 +335,10 @@ This starts an HTTP server that provides API access to opencode functionality wi
#### Flags
-| Flag | Description |
-| ------------ | --------------------- |
-| `--port` | Port to listen on |
-| `--hostname` | Hostname to listen on |
-| `--mdns` | Enable mDNS discovery |
+| Flag | Short | Description |
+| ------------ | ----- | --------------------- |
+| `--port` | `-p` | Port to listen on |
+| `--hostname` | | Hostname to listen on |
---
@@ -429,11 +428,10 @@ This starts an HTTP server and opens a web browser to access OpenCode through a
#### Flags
-| Flag | Description |
-| ------------ | --------------------- |
-| `--port` | Port to listen on |
-| `--hostname` | Hostname to listen on |
-| `--mdns` | Enable mDNS discovery |
+| Flag | Short | Description |
+| ------------ | ----- | --------------------- |
+| `--port` | `-p` | Port to listen on |
+| `--hostname` | | Hostname to listen on |
---
diff --git a/packages/web/src/content/docs/config.mdx b/packages/web/src/content/docs/config.mdx
index d7f803178..ebaff36bb 100644
--- a/packages/web/src/content/docs/config.mdx
+++ b/packages/web/src/content/docs/config.mdx
@@ -120,31 +120,6 @@ Available options:
---
-### Server
-
-You can configure server settings for the `opencode serve` and `opencode web` commands through the `server` option.
-
-```json title="opencode.json"
-{
- "$schema": "https://opencode.ai/config.json",
- "server": {
- "port": 4096,
- "hostname": "0.0.0.0",
- "mdns": true
- }
-}
-```
-
-Available options:
-
-- `port` - Port to listen on.
-- `hostname` - Hostname to listen on. When `mdns` is enabled and no hostname is set, defaults to `0.0.0.0`.
-- `mdns` - Enable mDNS service discovery. This allows other devices on the network to discover your OpenCode server.
-
-[Learn more about the server here](/docs/server).
-
----
-
### Tools
You can manage the tools an LLM can use through the `tools` option.
diff --git a/packages/web/src/content/docs/server.mdx b/packages/web/src/content/docs/server.mdx
index c63917f79..427d8f505 100644
--- a/packages/web/src/content/docs/server.mdx
+++ b/packages/web/src/content/docs/server.mdx
@@ -18,11 +18,10 @@ opencode serve [--port <number>] [--hostname <string>]
#### Options
-| Flag | Description | Default |
-| ------------ | --------------------- | ----------- |
-| `--port` | Port to listen on | `4096` |
-| `--hostname` | Hostname to listen on | `127.0.0.1` |
-| `--mdns` | Enable mDNS discovery | `false` |
+| Flag | Short | Description | Default |
+| ------------ | ----- | --------------------- | ----------- |
+| `--port` | `-p` | Port to listen on | `4096` |
+| `--hostname` | `-h` | Hostname to listen on | `127.0.0.1` |
---