docs/users/features/lsp.md
Qwen Code provides native Language Server Protocol (LSP) support, enabling advanced code intelligence features like go-to-definition, find references, diagnostics, and code actions. This integration allows the AI agent to understand your code more deeply and provide more accurate assistance.
LSP support in Qwen Code works by connecting to language servers that understand your code. Once you configure servers via .lsp.json (or extensions), Qwen Code can start them and use them to:
LSP is an experimental feature in Qwen Code. To enable it, use the --experimental-lsp command line flag:
qwen --experimental-lsp
LSP servers are configuration-driven. You must define them in .lsp.json (or via extensions) for Qwen Code to start them.
You need to have the language server for your programming language installed:
| Language | Language Server | Install Command |
|---|---|---|
| TypeScript/JavaScript | typescript-language-server | npm install -g typescript-language-server typescript |
| Python | pylsp | pip install python-lsp-server |
| Go | gopls | go install golang.org/x/tools/gopls@latest |
| Rust | rust-analyzer | Installation guide |
| C/C++ | clangd | Install LLVM/clangd via your package manager |
| Java | jdtls | Install JDTLS and a JDK |
You can configure language servers using a .lsp.json file in your project root. Each top-level key is a language identifier, and its value is the server configuration object.
Basic format:
{
"typescript": {
"command": "typescript-language-server",
"args": ["--stdio"],
"extensionToLanguage": {
".ts": "typescript",
".tsx": "typescriptreact",
".js": "javascript",
".jsx": "javascriptreact"
}
}
}
Dependencies:
compile_commands.json) or compile_flags.txt is required for accurate results.Example:
{
"cpp": {
"command": "clangd",
"args": [
"--background-index",
"--clang-tidy",
"--header-insertion=iwyu",
"--completion-style=detailed"
]
}
}
Dependencies:
java).jdtls).Example:
{
"java": {
"command": "jdtls",
"args": ["-configuration", ".jdtls-config", "-data", ".jdtls-workspace"]
}
}
| Option | Type | Description |
|---|---|---|
command | string | Command to start the LSP server. Supports bare command names resolved via PATH (e.g. clangd) and absolute paths (e.g. /opt/llvm/bin/clangd) |
| Option | Type | Default | Description |
|---|---|---|---|
args | string[] | [] | Command line arguments |
transport | string | "stdio" | Transport type: stdio, tcp, or socket |
env | object | - | Environment variables |
initializationOptions | object | - | LSP initialization options |
settings | object | - | Server settings via workspace/didChangeConfiguration |
extensionToLanguage | object | - | Maps file extensions to language identifiers |
workspaceFolder | string | - | Override workspace folder (must be within project root) |
startupTimeout | number | 10000 | Startup timeout in milliseconds |
shutdownTimeout | number | 5000 | Shutdown timeout in milliseconds |
restartOnCrash | boolean | false | Auto-restart on crash |
maxRestarts | number | 3 | Maximum restart attempts |
trustRequired | boolean | true | Require trusted workspace |
For servers that use TCP or Unix socket transport:
{
"remote-lsp": {
"transport": "tcp",
"socket": {
"host": "127.0.0.1",
"port": 9999
},
"extensionToLanguage": {
".custom": "custom"
}
}
}
Qwen Code exposes LSP functionality through the unified lsp tool. Here are the available operations:
Location-based operations (goToDefinition, findReferences, hover, goToImplementation, and prepareCallHierarchy) require an exact filePath + line + character position. If you do not know the exact position, use workspaceSymbol or documentSymbol first to locate the symbol.
Find where a symbol is defined.
Operation: goToDefinition
Parameters:
- filePath: Path to the file
- line: Line number (1-based)
- character: Column number (1-based)
Find all references to a symbol.
Operation: findReferences
Parameters:
- filePath: Path to the file
- line: Line number (1-based)
- character: Column number (1-based)
- includeDeclaration: Include the declaration itself (optional)
Find implementations of an interface or abstract method.
Operation: goToImplementation
Parameters:
- filePath: Path to the file
- line: Line number (1-based)
- character: Column number (1-based)
Get documentation and type information for a symbol.
Operation: hover
Parameters:
- filePath: Path to the file
- line: Line number (1-based)
- character: Column number (1-based)
Get all symbols in a document.
Operation: documentSymbol
Parameters:
- filePath: Path to the file
Search for symbols across the workspace.
Operation: workspaceSymbol
Parameters:
- query: Search query string
- limit: Maximum results (optional)
Get the call hierarchy item at a position.
Operation: prepareCallHierarchy
Parameters:
- filePath: Path to the file
- line: Line number (1-based)
- character: Column number (1-based)
Find all functions that call the given function.
Operation: incomingCalls
Parameters:
- callHierarchyItem: Item from prepareCallHierarchy
Find all functions called by the given function.
Operation: outgoingCalls
Parameters:
- callHierarchyItem: Item from prepareCallHierarchy
Get diagnostic messages (errors, warnings) for a file.
Operation: diagnostics
Parameters:
- filePath: Path to the file
Get all diagnostic messages across the workspace.
Operation: workspaceDiagnostics
Parameters:
- limit: Maximum results (optional)
Get available code actions (quick fixes, refactorings) at a location.
Operation: codeActions
Parameters:
- filePath: Path to the file
- line: Start line number (1-based)
- character: Start column number (1-based)
- endLine: End line number (optional, defaults to line)
- endCharacter: End column (optional, defaults to character)
- diagnostics: Diagnostics to get actions for (optional)
- codeActionKinds: Filter by action kind (optional)
Code action kinds:
quickfix - Quick fixes for errors/warningsrefactor - Refactoring operationsrefactor.extract - Extract to function/variablerefactor.inline - Inline function/variablesource - Source code actionssource.organizeImports - Organize importssource.fixAll - Fix all auto-fixable issuesLSP servers are only started in trusted workspaces by default. This is because language servers run with your user permissions and can execute code.
trustRequired: false is set in the server configurationTo mark a workspace as trusted, use the /trust command.
You can override trust requirements for specific servers in their configuration:
{
"safe-server": {
"command": "safe-language-server",
"args": ["--stdio"],
"trustRequired": false,
"extensionToLanguage": {
".safe": "safe"
}
}
}
--experimental-lsp flag: Make sure you're using the flag when starting Qwen Codeclangd --version) to verifyPATH, or specified as an absolute path (e.g. /opt/llvm/bin/clangd). Relative paths that escape the workspace are blocked/trust)--debug, then search for LSP-related entries in the debug log (see Debugging section below)ps aux | grep <server-name> to verify the server process is runningnode_modules and other large directoriesstartupTimeout in server configuration for slow servers--background-index is in the args and a compile_commands.json (or compile_flags.txt) exists in the project root or a parent directory. Use --compile-commands-dir=<path> if it is in a build subdirectoryps aux | grep <server-name> to verify the server is actually runningLSP does not have a separate debug flag. Use Qwen Code's normal debug mode together with the LSP feature flag:
qwen --experimental-lsp --debug
Debug logs are written to the session debug log directory. To check LSP-related entries:
# Default runtime directory
rg "LSP|Native LSP|clangd|connection closed" ~/.qwen/debug/latest
# Or, without ripgrep:
grep -E "LSP|Native LSP|clangd|connection closed" ~/.qwen/debug/latest
# If QWEN_RUNTIME_DIR is configured
rg "LSP|Native LSP|clangd|connection closed" "$QWEN_RUNTIME_DIR/debug/latest"
Useful entries include:
[LSP] ...: Logs emitted by the native LSP service and server manager.[CONFIG] Native LSP status after discovery: ...: LSP server configuration discovered for the session.[CONFIG] Native LSP status after startup: ...: Server startup result, including ready/failed counts.[STATUS] LSP status snapshot for /status: ...: Status snapshot printed when running /status in debug mode.You can also run /status in the CLI to see a short LSP summary:
LSP: disabled
LSP: enabled, 1/1 ready
LSP: enabled, 0/1 ready (1 failed)
LSP: enabled, no servers configured
LSP: enabled, status unavailable
For per-server details, run /lsp:
**LSP Server Status**
| Server | Command | Languages | Status |
|--------|---------|-----------|--------|
| clangd | `clangd` | c, cpp | READY |
| pyright | `pyright-langserver` | python | FAILED - startup failed |
Common error messages to look for:
command path is unsafe -> relative path escapes workspace, use absolute path or add to PATH
command not found -> server binary not installed or not in PATH
requires trusted workspace -> run /trust first
LSP connection closed -> server started but exited or closed stdio before replying to initialize
For clangd startup failures, verify the server directly from the project root:
clangd --version
clangd --check=/path/to/file.cpp --log=verbose
C/C++ projects should usually provide a compile_commands.json or compile_flags.txt. If the compile database is in a build directory, pass it to clangd:
{
"cpp": {
"command": "clangd",
"args": ["--background-index", "--compile-commands-dir=build"]
}
}
ps aux | grep clangd # or typescript-language-server, jdtls, etc.
Extensions can provide LSP server configurations through the lspServers field in their plugin.json. This can be either an inline object or a path to a .lsp.json file. Qwen Code loads these configs when the extension is enabled. The format is the same language-keyed layout used in project .lsp.json files.
.lsp.jsonUse the --experimental-lsp flag when starting Qwen Code:
qwen --experimental-lsp
Start Qwen Code with LSP and debug mode enabled:
qwen --experimental-lsp --debug
Then run /status for a short summary, /lsp for per-server status, or inspect the debug log:
# Default runtime directory
rg "LSP|Native LSP|<server-name>" ~/.qwen/debug/latest
# Or:
grep -E "LSP|Native LSP|<server-name>" ~/.qwen/debug/latest
# If QWEN_RUNTIME_DIR is configured
rg "LSP|Native LSP|<server-name>" "$QWEN_RUNTIME_DIR/debug/latest"
LSP uses Qwen Code's normal --debug mode; there is no separate LSP debug flag.
Yes, but only one will be used for each operation. The first server that returns results wins.
LSP servers run outside the sandbox to access your code. They're subject to workspace trust controls.