Code intelligence with language servers

Let the agent see real compiler diagnostics instead of guessing, and learn the cases where the language server misleads it.

Automatic detection

OpenCode starts a language server for the languages it recognises in your project and feeds the diagnostics back to the model. The practical effect is large: instead of inferring that a rename broke three call sites, the agent reads the actual type error and fixes it in the same turn.

# check which servers are running in a session
/lsp

# the same information appears in the log output
opencode run --print-logs "add a required field to the Order type and fix the fallout"
  • Servers are detected from file extensions and project markers such as package.json, go.mod or Cargo.toml.
  • A server must be installed on the machine - OpenCode orchestrates it, it does not bundle a compiler.
  • Diagnostics are cheaper than a test run, so they give the agent a fast feedback signal on every edit.
LanguageServerGives the agent
TypeScript / JavaScripttypescript-language-serverType errors, unused imports
Pythonpyright or basedpyrightType and import errors
GogoplsCompile errors, unused variables
Rustrust-analyzerBorrow-check and type errors
JavajdtlsCompiler diagnostics

Per-language configuration

{
  "$schema": "https://opencode.ai/config.json",
  "lsp": {
    "typescript": { "disabled": true },
    "eslint": {
      "command": ["npx", "vscode-eslint-language-server", "--stdio"],
      "extensions": [".js", ".jsx", ".ts", ".tsx"]
    },
    "custom-lang": {
      "command": ["my-langserver", "--stdio"],
      "extensions": [".foo"]
    }
  }
}
  • Disable a server that is slow, noisy or wrong for the project - a bad diagnostic channel is worse than none.
  • Add a server for a language OpenCode does not know, or to bring in a linter as an extra diagnostic source.
  • Keep the command to something already in the project's toolchain so every developer gets the same diagnostics.
💡
Diagnostics are a filter, not a verdict. They catch type and import errors cheaply, which is most of what an agent gets wrong mechanically. They say nothing about whether the behaviour is correct - the test suite is still the gate that decides that.

When the server misleads

SymptomCauseFix
Errors in code that compiles fineServer reading a stale or wrong tsconfigPoint the server at the right project file
Thousand of errors on openMonorepo: server started at the wrong rootConfigure per-package roots or disable the root server
Agent loops on a phantom errorGenerated files in the include pathExclude build output and generated directories
Diagnostics never appearNo server installed on this machineInstall it, then restart the session
Slow responses on every editHeavy server on a very large treeDisable it and rely on the type-check command
# reproduce what the agent sees, outside the agent
npx tsc --noEmit
npx tsc --noEmit -p packages/core/tsconfig.json

# if the compile is clean but the agent insists otherwise, the server
# is reading a different project - that is a config problem, not a code one

The rule is simple: if tsc --noEmit is clean and the agent keeps reporting errors, the diagnostic channel is wrong. Fix the configuration or disable that server; do not let the agent argue with a broken oracle.

FAQ

Does OpenCode require language servers?
No. Everything works without them, but the agent then has to infer types and imports from reading source, which is slower and more error-prone. When a supported language server is installed, the quality of mechanical edits improves noticeably.
Why did enabling a linter as a language server help?
It turns lint rules into diagnostics the agent can read and act on immediately, in the same turn as the edit. That is faster and cheaper than discovering the same problem in a later CI run.

Plan mode versus build mode MCP servers and custom tools

Last refreshed 2026-09-18.