From 98b6bb218b45b3c2a8a7a1a69e2e715a21321de2 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 1 Aug 2025 14:51:58 -0400 Subject: [PATCH] configurable lsp --- packages/opencode/src/config/config.ts | 17 +++++ packages/opencode/src/lsp/index.ts | 29 +++++++- packages/web/src/content/docs/docs/lsp.mdx | 79 ++++++++++++++++++++++ packages/web/src/pages/s/[id].astro | 7 ++ 4 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 packages/web/src/content/docs/docs/lsp.mdx diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 3d933a15..acce3b61 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -289,6 +289,23 @@ export namespace Config { }), ) .optional(), + lsp: z + .record( + z.string(), + z.union([ + z.object({ + disabled: z.literal(true), + }), + z.object({ + command: z.array(z.string()), + extensions: z.array(z.string()).optional(), + disabled: z.boolean().optional(), + env: z.record(z.string(), z.string()).optional(), + initialization: z.record(z.string(), z.any()).optional(), + }), + ]), + ) + .optional(), instructions: z.array(z.string()).optional().describe("Additional instruction files or patterns to include"), layout: Layout.optional().describe("@deprecated Always uses stretch layout."), permission: z diff --git a/packages/opencode/src/lsp/index.ts b/packages/opencode/src/lsp/index.ts index 8f6c1c9c..09e3c55c 100644 --- a/packages/opencode/src/lsp/index.ts +++ b/packages/opencode/src/lsp/index.ts @@ -4,6 +4,8 @@ import { LSPClient } from "./client" import path from "path" import { LSPServer } from "./server" import { z } from "zod" +import { Config } from "../config/config" +import { spawn } from "child_process" export namespace LSP { const log = Log.create({ service: "lsp" }) @@ -55,6 +57,31 @@ export namespace LSP { "lsp", async () => { const clients: LSPClient.Info[] = [] + const servers: Record = LSPServer + const cfg = await Config.get() + for (const [name, item] of Object.entries(cfg.lsp ?? {})) { + const existing = servers[name] + if (item.disabled) { + delete servers[name] + continue + } + servers[name] = { + ...existing, + extensions: item.extensions ?? existing.extensions, + spawn: async (_app, root) => { + return { + process: spawn(item.command[0], item.command.slice(1), { + cwd: root, + env: { + ...process.env, + ...item.env, + }, + }), + initialization: item.initialization, + } + }, + } + } return { broken: new Set(), clients, @@ -76,7 +103,7 @@ export namespace LSP { const extension = path.parse(file).ext const result: LSPClient.Info[] = [] for (const server of Object.values(LSPServer)) { - if (!server.extensions.includes(extension)) continue + if (server.extensions.length && !server.extensions.includes(extension)) continue const root = await server.root(file, App.info()) if (!root) continue if (s.broken.has(root + server.id)) continue diff --git a/packages/web/src/content/docs/docs/lsp.mdx b/packages/web/src/content/docs/docs/lsp.mdx new file mode 100644 index 00000000..791f4f28 --- /dev/null +++ b/packages/web/src/content/docs/docs/lsp.mdx @@ -0,0 +1,79 @@ +--- +title: LSP Servers +description: Language Server Protocol integration with opencode +--- + +opencode integrates with Language Server Protocol (LSP) to enhance how the LLM interacts with your codebase. LSP servers provide intelligent code analysis and editing capabilities for different programming languages. + +## Built-in LSP Servers + +opencode comes with several built-in LSP servers for popular languages: + +| LSP Server | Languages/Extensions | Requirements | +| ---------- | -------------------------------------------- | ----------------------------------- | +| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` dependency in project | +| gopls | .go | `go` command available | +| ruby-lsp | .rb, .rake, .gemspec, .ru | `ruby` and `gem` commands available | +| pyright | .py, .pyi | `pyright` dependency installed | +| elixir-ls | .ex, .exs | `elixir` command available | +| zls | .zig, .zon | `zig` command available | +| csharp | .cs | `.NET SDK` installed | + +LSP servers are automatically enabled when their requirements are met in your project environment. + +## Configuration + +You can customize LSP servers through the `lsp` section in your `opencode.json` configuration file. + +### Disabling LSP Servers + +To disable a specific LSP server, set its configuration to `{ "disabled": true }`: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "typescript": { + "disabled": true + } + } +} +``` + +### Custom LSP Servers + +You can add custom LSP servers by specifying the command and file extensions: + +```json title="opencode.json" +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "custom-lsp": { + "command": ["custom-lsp-server", "--stdio"], + "extensions": [".custom"] + } + } +} +``` + +### Configuration Options + +Each LSP server configuration supports these properties: + +| Property | Type | Description | +| ---------------- | -------- | ------------------------------------------------- | +| `disabled` | boolean | Set to `true` to disable the LSP server | +| `command` | string[] | The command to start the LSP server | +| `extensions` | string[] | File extensions this LSP server should handle | +| `env` | object | Environment variables to set when starting server | +| `initialization` | object | Initialization options to send to the LSP server | + +## How It Works + +When opencode opens a file, it: + +1. Checks the file extension against all enabled LSP servers +2. Starts the appropriate LSP server if not already running +3. Provides intelligent code analysis and editing capabilities + +This integration allows the LLM to better understand your codebase through features like diagnostics, go-to-definition, and find-references. diff --git a/packages/web/src/pages/s/[id].astro b/packages/web/src/pages/s/[id].astro index fadf0eb0..0e0170b6 100644 --- a/packages/web/src/pages/s/[id].astro +++ b/packages/web/src/pages/s/[id].astro @@ -67,6 +67,13 @@ const ogImage = `${config.socialCard}/opencode-share/${encodedTitle}.png?model=$ content: "opencode - The AI coding agent built for the terminal.", }, }, + { + tag: "meta", + attrs: { + name: "robots", + content: "noindex", + } + }, { tag: "meta", attrs: {