anomalyco / anomalyco/opencode
[Feature] Document & expose global LSP activation (a custom server id bypasses NearestRoot gating)
@kitlangton is already working on this.
Since Sep 13, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
opencode's built-in LSP servers are repo-root gated (NearestRoot([...markers...]), walk stops at ctx.directory), but a custom lsp entry whose id is not a built-in gets root = ctx.directory ΓÇö i.e. it activates globally, with no marker file required. This behaviour is undocumented and there is no explicit way to request it.
Mechanism (source, dev)
packages/opencode/src/lsp/lsp.ts ΓÇö config entries are merged into the server map:
if (cfg.lsp !== true) {
for (const [name, item] of Object.entries(cfg.lsp)) {
const existing = servers[name]
if (item.disabled) { delete servers[name]; continue }
servers[name] = {
...existing,
id: name,
root: existing?.root ?? (async (_file, ctx) => ctx.directory), // <-- key line
extensions: item.extensions ?? existing?.extensions ?? [],
spawn: async (root) => ({ process: lspspawn(item.command[0], item.command.slice(1), { cwd: root, env: { ...process.env, ...item.env } }), initialization: item.initialization }),
}
}
}
- New id →
existing === undefined→root = ctx.directory(global; no markers). - Built-in id (e.g.
biome,csharp) → inherits the built-inNearestRoot(...)→ marker-gated.
The config schema (packages/core/src/config/lsp.ts) exposes only command, extensions, disabled, env, initialization ΓÇö there is no root or global field, and this behaviour is not in the docs (https://opencode.ai/docs/lsp/).
Verified globally (marker-free directory)
With ~/.config/opencode/opencode.jsonc entries using non-built-in ids:
"global-python": { "command": ["basedpyright-langserver","--stdio"], "extensions": [".py",".pyi"] },
"global-csharp": { "command": ["cmd","/c","roslyn-language-server","--stdio","--autoLoadProjects"], "extensions": [".cs",".csx"] },
"global-biome-code": { "command": ["cmd","/c","biome","lsp-proxy","--stdio"], "extensions": [".js",".jsx",".ts",".tsx",".mjs",".cjs",".mts",".cts"] },
"global-shell": { "command": ["cmd","/c","bash-language-server","start"], "extensions": [".sh",".bash",".zsh",".ksh"] },
In a bare temp dir with no lockfile/biome.json/.slnx anywhere on the walk path, writing broken files produced diagnostics (write-tool <diagnostics> block):
<diagnostics file="...\global-lsp-probe\probe2.py">
ERROR [1:6] "(" was not closed
ERROR [1:7] Expected parameter name
...
ERROR [1:37] Invalid expression term ';' # .cs
ERROR [1:19] Expected an expression, or an assignment but instead found ';'. # .ts
ERROR [1:11] Expected an expression, or an assignment but instead found ';'. # .js
(The same directory yields nothing for .sh and .json ΓÇö separate issues, not this request.)
Request
- Document the rule: "a custom server id that does not match a built-in is launched with the workspace directory as its root, so it is not marker-gated."
- Optionally expose it explicitly, e.g.
"root": "workspace"or"global": trueon a server entry, so users don't have to discover a name-collision side effect. - Consider the inverse too: a documented way to force marker-gating for a custom server.
Verified 2026-09-13 on opencode 1.18.30 (Windows 10 Pro 19045).
Environment (software)
| item | value |
|---|---|
| OS | Microsoft Windows 10 Pro — 10.0.19045 (Build 19045), 64-bit |
| Shell | PowerShell 7.6.6 (+ Windows Terminal) |
| opencode | 1.18.30 |
| plugins | oh-my-openagent 4.19.4 · @cortexkit/opencode-antigravity-auth 2.2.1 |
| runtimes | Node v24.19.0 · npm 11.17.0 · Bun 1.4.2 |
| LSP binaries | biome 2.5.13 · basedpyright 1.40.1 · roslyn-language-server 5.12.0-1.26426.8 · bash-language-server 5.6.0 · shellcheck 0.11.0 · vscode-langservers-extracted 4.10.0 · PowerShellEditorServices 4.7.0 · PSScriptAnalyzer 1.25.0 |
| logs | ~/.local/share/opencode/log/opencode.log · ~/.omo/agent/OmO-debug.log · ~/.omo/agent/logs/config-reload.log |
OS facts collected with:
Get-CimInstance Win32_OperatingSystem | Select-Object Caption,Version,BuildNumber,OSArchitecture
No hardware, hostname, username, or credentials included.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.