qwen-code/docs/users/features/lsp.md
易良 ba77ddd81b
fix(lsp): expose status and startup diagnostics (#3649)
* feat(lsp): add /lsp slash command to show server status

Implements the /lsp command that displays the status of all configured
LSP servers. Previously this was documented in the FAQ but never
implemented, leaving users with no way to check if their language
servers started successfully.

Changes:
- Add LspServerStatusInfo interface to lsp/types.ts
- Add getServerStatus() to LspClient and NativeLspClient
- Expose getServerHandles() from NativeLspService
- Create lspCommand.ts with status table output
- Register /lsp in BuiltinCommandLoader (only when LSP is enabled)

The command shows: server name, command, languages, and status
(NOT_STARTED / IN_PROGRESS / READY / FAILED + error message).

* fix(lsp): expose status and startup diagnostics

* fix(lsp): harden status command diagnostics

* fix(lsp): add stderr error listener and harden initialization error handling

- Add stderr 'error' event listener in LspConnectionFactory to prevent
  unhandled stream errors from crashing the process
- Wrap setLspInitializationError calls in try-catch in config.ts to guard
  against post-initialization state changes that would throw
2026-05-17 01:42:28 +08:00

15 KiB

Language Server Protocol (LSP) Support

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.

Overview

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:

  • Navigate to symbol definitions
  • Find all references to a symbol
  • Get hover information (documentation, type info)
  • View diagnostic messages (errors, warnings)
  • Access code actions (quick fixes, refactorings)
  • Analyze call hierarchies

Quick Start

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.

Prerequisites

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

Configuration

.lsp.json File

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"
    }
  }
}

C/C++ (clangd) configuration

Dependencies:

  • clangd (LLVM) must be installed and available in PATH.
  • A compile database (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"
    ]
  }
}

Java (jdtls) configuration

Dependencies:

  • JDK installed and available in PATH (java).
  • JDTLS installed and available in PATH (jdtls).

Example:

{
  "java": {
    "command": "jdtls",
    "args": ["-configuration", ".jdtls-config", "-data", ".jdtls-workspace"]
  }
}

Configuration Options

Required Fields

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)

Optional Fields

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

TCP/Socket Transport

For servers that use TCP or Unix socket transport:

{
  "remote-lsp": {
    "transport": "tcp",
    "socket": {
      "host": "127.0.0.1",
      "port": 9999
    },
    "extensionToLanguage": {
      ".custom": "custom"
    }
  }
}

Available LSP Operations

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.

Code Navigation

Go to Definition

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 References

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)

Go to Implementation

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)

Symbol Information

Hover

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)

Document Symbols

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)

Call Hierarchy

Prepare Call Hierarchy

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)

Incoming Calls

Find all functions that call the given function.

Operation: incomingCalls
Parameters:
  - callHierarchyItem: Item from prepareCallHierarchy

Outgoing Calls

Find all functions called by the given function.

Operation: outgoingCalls
Parameters:
  - callHierarchyItem: Item from prepareCallHierarchy

Diagnostics

File Diagnostics

Get diagnostic messages (errors, warnings) for a file.

Operation: diagnostics
Parameters:
  - filePath: Path to the file

Workspace Diagnostics

Get all diagnostic messages across the workspace.

Operation: workspaceDiagnostics
Parameters:
  - limit: Maximum results (optional)

Code Actions

Get Code Actions

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/warnings
  • refactor - Refactoring operations
  • refactor.extract - Extract to function/variable
  • refactor.inline - Inline function/variable
  • source - Source code actions
  • source.organizeImports - Organize imports
  • source.fixAll - Fix all auto-fixable issues

Security

LSP servers are only started in trusted workspaces by default. This is because language servers run with your user permissions and can execute code.

Trust Controls

  • Trusted Workspace: LSP servers start if configured
  • Untrusted Workspace: LSP servers won't start unless trustRequired: false is set in the server configuration

To mark a workspace as trusted, use the /trust command.

Per-Server Trust Override

You can override trust requirements for specific servers in their configuration:

{
  "safe-server": {
    "command": "safe-language-server",
    "args": ["--stdio"],
    "trustRequired": false,
    "extensionToLanguage": {
      ".safe": "safe"
    }
  }
}

Troubleshooting

Server Not Starting

  1. Verify --experimental-lsp flag: Make sure you're using the flag when starting Qwen Code
  2. Check if the server is installed: Run the command manually (e.g. clangd --version) to verify
  3. Check the command: The server binary must be in your system PATH, or specified as an absolute path (e.g. /opt/llvm/bin/clangd). Relative paths that escape the workspace are blocked
  4. Check workspace trust: The workspace must be trusted for LSP (use /trust)
  5. Check logs: Start Qwen Code with --debug, then search for LSP-related entries in the debug log (see Debugging section below)
  6. Check the process: Run ps aux | grep <server-name> to verify the server process is running

Slow Performance

  1. Large projects: Consider excluding node_modules and other large directories
  2. Server timeout: Increase startupTimeout in server configuration for slow servers

No Results

  1. Server not ready: The server may still be indexing. For C/C++ projects with clangd, ensure --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 subdirectory
  2. File not saved: Save your file for the server to pick up changes
  3. Wrong language: Check if the correct server is running for your language
  4. Check the process: Run ps aux | grep <server-name> to verify the server is actually running

Debugging

LSP 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.

Extension LSP Configuration

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.

Best Practices

  1. Install language servers globally: This ensures they're available in all projects
  2. Use project-specific settings: Configure server options per project when needed via .lsp.json
  3. Keep servers updated: Update your language servers regularly for best results
  4. Trust wisely: Only trust workspaces from trusted sources

FAQ

Q: How do I enable LSP?

Use the --experimental-lsp flag when starting Qwen Code:

qwen --experimental-lsp

Q: How do I know which language servers are running?

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.

Q: Can I use multiple language servers for the same file type?

Yes, but only one will be used for each operation. The first server that returns results wins.

Q: Does LSP work in sandbox mode?

LSP servers run outside the sandbox to access your code. They're subject to workspace trust controls.