Skip to main content
OpenCode integrates with Language Server Protocol (LSP) to provide code intelligence features across multiple programming languages. The AI assistant can access diagnostics, errors, and warnings to help you write better code.

What is LSP?

The Language Server Protocol (LSP) is a standardized protocol that provides language-specific intelligence features:
  • Diagnostics: Real-time error and warning detection
  • Type checking: Static analysis and type errors
  • Linting: Code style and quality issues
  • Semantic analysis: Language-specific code understanding
OpenCode’s LSP client implementation is based on the mcp-language-server project.

Supported features

OpenCode’s LSP integration currently exposes diagnostics to the AI assistant:

Error detection

  • Syntax errors
  • Type errors
  • Compilation errors
  • Import/reference errors

Warnings

  • Unused variables
  • Deprecated APIs
  • Potential bugs
  • Code smells

Hints

  • Optimization suggestions
  • Style improvements
  • Best practices
  • Refactoring opportunities

Real-time feedback

  • Instant analysis on file open
  • Updates on file changes
  • Persistent across session
  • Multi-file awareness
While the LSP client supports the full protocol (completions, hover, go-to-definition, etc.), only diagnostics are currently exposed to the AI assistant.

Configuration

LSP servers are configured in .opencode.json under the lsp key:
{
  "lsp": {
    "language-id": {
      "disabled": false,
      "command": "path-to-language-server",
      "args": ["--stdio"]
    }
  },
  "debugLSP": false
}

Configuration fields

disabled
boolean
default:false
Whether this language server is disabled
command
string
required
Path to the language server executable
args
array
Command-line arguments to pass to the server (e.g., ["--stdio"])
debugLSP
boolean
default:false
Enable debug logging for LSP operations (top-level config)

Language-specific configuration

Go (gopls)

{
  "lsp": {
    "go": {
      "disabled": false,
      "command": "gopls"
    }
  }
}
Installation:
go install golang.org/x/tools/gopls@latest
Features:
  • Type checking
  • Import errors
  • Unused variables
  • Build errors
  • Module issues

TypeScript (typescript-language-server)

{
  "lsp": {
    "typescript": {
      "disabled": false,
      "command": "typescript-language-server",
      "args": ["--stdio"]
    }
  }
}
Installation:
npm install -g typescript-language-server typescript
Features:
  • Type errors
  • Missing imports
  • Unused code
  • Strict mode violations
  • TSConfig issues
OpenCode automatically opens tsconfig.json and package.json to help TypeScript servers initialize properly.

JavaScript (typescript-language-server)

{
  "lsp": {
    "javascript": {
      "disabled": false,
      "command": "typescript-language-server",
      "args": ["--stdio"]
    }
  }
}
Same server as TypeScript, works with jsconfig.json.

Python (pyright)

{
  "lsp": {
    "python": {
      "disabled": false,
      "command": "pyright-langserver",
      "args": ["--stdio"]
    }
  }
}
Installation:
npm install -g pyright
Features:
  • Type checking (with type hints)
  • Import resolution
  • Undefined variables
  • Syntax errors
Alternative: pylsp
{
  "lsp": {
    "python": {
      "command": "pylsp"
    }
  }
}

Rust (rust-analyzer)

{
  "lsp": {
    "rust": {
      "disabled": false,
      "command": "rust-analyzer"
    }
  }
}
Installation:
rustup component add rust-analyzer
Features:
  • Borrow checker errors
  • Type mismatches
  • Lifetime errors
  • Cargo build issues
  • Macro expansion

Java (jdtls)

{
  "lsp": {
    "java": {
      "disabled": false,
      "command": "/path/to/jdtls",
      "args": ["-data", "/path/to/workspace"]
    }
  }
}
Installation: Download Eclipse JDT Language Server from eclipse.org/jdtls

C/C++ (clangd)

{
  "lsp": {
    "c": {
      "disabled": false,
      "command": "clangd"
    },
    "cpp": {
      "disabled": false,
      "command": "clangd"
    }
  }
}
Installation:
# macOS
brew install llvm

# Ubuntu
sudo apt install clangd

How LSP integration works

1

Server initialization

When OpenCode starts:
  1. Reads LSP configuration from .opencode.json
  2. Launches configured language servers
  3. Sends initialize request with workspace info
  4. Waits for server to be ready
2

File operations

When AI tools interact with files:
  1. textDocument/didOpen sent when file is first accessed
  2. textDocument/didChange sent when file is modified
  3. textDocument/didClose sent when no longer needed
3

Diagnostic collection

Language servers send diagnostics:
  1. textDocument/publishDiagnostics received asynchronously
  2. Diagnostics cached per file URI
  3. Available to AI via diagnostics tool
  4. Automatically included after file modifications
4

Diagnostic display

Diagnostics shown in tool responses:
  1. After view tool (if file has issues)
  2. After write tool (new errors/warnings)
  3. After edit tool (validation)
  4. On-demand via diagnostics tool

File lifecycle management

Automatic file opening

OpenCode intelligently manages file state:
AI: view src/main.ts
→ File opened in LSP if not already open
→ Diagnostics collected
→ Shown in response:

<file>
...
</file>

<file_diagnostics>
Error: src/main.ts:42:5 [typescript][2304] Cannot find name 'foo'
</file_diagnostics>

Persistent sessions

Files remain open across multiple operations:
1. AI: view src/utils.ts
   → Opens file in LSP
   
2. AI: edit src/utils.ts ...
   → File already open
   → Sends didChange notification
   → New diagnostics published
   
3. AI: write src/utils.ts ...
   → Updates open file
   → Fresh diagnostics

Smart initialization

For TypeScript/JavaScript projects, OpenCode:
  1. Opens configuration files first:
    • tsconfig.json
    • package.json
    • jsconfig.json
  2. Opens sample source files to help server index:
    • Finds up to 5 .ts/.tsx/.js/.jsx files
    • Skips node_modules and build directories
    • Accelerates initial diagnostics

Server detection and optimization

OpenCode detects server types and optimizes accordingly:
Detected by: Command contains typescript, vtsls, or tsserverOptimizations:
  • Opens key config files (tsconfig.json, package.json)
  • Opens sample source files to help with indexing
  • Uses document symbol requests for readiness checks
  • Waits longer for initial diagnostics

Diagnostic format

Diagnostics are displayed in a structured format:
<file_diagnostics>
Error: /path/to/file.ts:42:10 [typescript][2304] Cannot find name 'variableName'
Warn: /path/to/file.ts:56:5 [typescript][6133] 'unused' is declared but never used
Hint: /path/to/file.ts:12:8 [typescript] Parameter 'x' can be simplified
</file_diagnostics>

<project_diagnostics>
Error: /path/to/other.ts:12:1 [gopls] expected declaration, found 'IDENT'
</project_diagnostics>

<diagnostic_summary>
Current file: 1 errors, 1 warnings
Project: 1 errors, 0 warnings
</diagnostic_summary>

Severity levels

Error

Code will not compile or has serious issuesExamples:
  • Syntax errors
  • Type mismatches
  • Undefined references
  • Import failures
Potential issues or questionable codeExamples:
  • Unused variables
  • Deprecated APIs
  • Type assertions
  • Missing error handling
Informational messagesExamples:
  • Documentation
  • Suggestions
  • Code metrics
Improvement suggestionsExamples:
  • Simplifications
  • Performance tips
  • Style consistency

Diagnostic tags

Additional metadata:
  • Unnecessary: Code that can be removed (e.g., unused imports)
  • Deprecated: Using deprecated APIs or features

AI tool integration

The AI assistant accesses diagnostics through the diagnostics tool:

Get file diagnostics

{
  "tool": "diagnostics",
  "parameters": {
    "file_path": "/path/to/file.ts"
  }
}

Get project diagnostics

{
  "tool": "diagnostics",
  "parameters": {
    "file_path": ""
  }
}

Automatic inclusion

Diagnostics are automatically shown:
  1. After view: If file has errors/warnings
  2. After write: Shows new diagnostics
  3. After edit: Validates changes
  4. After patch: Shows diagnostics for all modified files

Common workflows

Debugging errors

1

Get diagnostics

AI: Use diagnostics tool to see all errors
2

Examine code

AI: Use view on files with errors
3

Fix issues

AI: Use edit or write to correct errors
4

Verify fix

New diagnostics automatically shown after file modification

Type error resolution

User: Fix the type errors in src/api.ts

AI workflow:
1. diagnostics tool → identify specific errors
2. view src/api.ts → understand code context
3. edit src/api.ts → fix type issues
4. Diagnostics automatically updated
5. If errors remain, iterate

Pre-commit validation

User: Check for errors before committing

AI workflow:
1. diagnostics tool (no file_path) → project-wide scan
2. Report errors by severity
3. Suggest fixes for critical issues
4. Verify no errors remain

Troubleshooting

Check:
  • Command path is correct: which gopls
  • Server is installed and in PATH
  • No conflicting servers running
  • Enable debug logging: "debugLSP": true
  • Check logs: opencode -d
Verify:
  • Server initialized successfully (check logs)
  • File is in workspace directory
  • File type matches language ID
  • Server has finished indexing (may take time for large projects)
  • Try closing and reopening file
Possible causes:
  • File modified outside OpenCode
  • Server hasn’t processed changes yet
  • Cache not updated
Solutions:
  • Wait for server to process (5-10 seconds)
  • Use diagnostics tool to refresh
  • Restart OpenCode if persistent
TypeScript can be slow on large projects:
  • Initial indexing takes time
  • Configure smaller include in tsconfig.json
  • Exclude node_modules explicitly
  • Use project references for monorepos
  • Consider increasing system resources
If you have multiple configs for same language:
  • Last configured server wins
  • Disable unused servers: "disabled": true
  • Use different language IDs if needed

Performance considerations

Lazy file opening

OpenCode opens files on-demand:
  • Only when AI tools access them
  • Reduces memory usage
  • Faster startup
  • Less server load

File closing

Files remain open until:
  • Session ends
  • Explicit close
  • OpenCode shutdown
Keeps diagnostics fresh

Diagnostic caching

Diagnostics are cached:
  • Per-file URI
  • Updated on publishDiagnostics
  • Shared across tools
  • Memory-efficient

Async updates

Diagnostics arrive asynchronously:
  • Non-blocking operations
  • Background processing
  • Timeout after 5 seconds
  • Graceful degradation

Limitations

Current limitations of LSP integration:
  • Diagnostics only: Other LSP features (completions, hover, etc.) not exposed to AI
  • Single workspace: One workspace root per session
  • File-based: Works with file:// URIs only
  • No refactoring: Code actions not yet available
  • Limited customization: Server-specific options not configurable

Future enhancements

Planned improvements:
  • Code actions: Enable AI to apply quick fixes
  • Completions: Suggest completions to AI
  • Hover information: Provide type info and docs
  • Go to definition: Navigate code references
  • Workspace symbols: Better code navigation
  • Semantic tokens: Enhanced code understanding
  • Server-specific configs: Per-server initialization options

Best practices

Install recommended servers

Use official language servers:
  • They’re well-maintained
  • Best diagnostic quality
  • Regular updates
  • Good documentation

Configure project properly

Ensure project config files exist:
  • tsconfig.json for TypeScript
  • go.mod for Go
  • Cargo.toml for Rust
  • Helps servers understand project

Monitor performance

Watch for slow servers:
  • Enable debug logging temporarily
  • Check initialization time
  • Monitor memory usage
  • Tune server settings

Use diagnostics proactively

Check regularly during development:
  • Before commits
  • After major changes
  • When debugging
  • During code review

Keep servers updated

Update regularly:
go install golang.org/x/tools/gopls@latest
npm update -g typescript-language-server
rustup update

Debug systematically

When issues arise:
  1. Enable debugLSP: true
  2. Run opencode -d
  3. Check server logs
  4. Test server independently
  5. Review configuration

Debug mode

Enable detailed LSP logging:
{
  "debugLSP": true,
  "debug": true
}
Then run:
opencode -d
Debug output includes:
  • Server initialization
  • File open/close events
  • Diagnostic publications
  • Server responses
  • Error messages
Debug logs are written to ~/.opencode/logs/ and shown in the logs page (Ctrl+L)

Next steps

Diagnostics tool

Learn how to use the diagnostics tool

Configuration

Complete configuration reference

AI tools

Explore all available AI tools

LSP Specification

Official LSP documentation

Build docs developers (and LLMs) love