simple-lsp-cli
v1.6.0
Published
Agent-friendly CLI for invoking Language Server Protocol (LSP) methods
Maintainers
Readme
simple-lsp-cli
A lightweight CLI tool for invoking Language Server Protocol methods. Designed for AI Agent tool calls.
Features
- Agent-friendly: All output is structured JSON, easy to parse
- Minimal dependencies: Only
cross-spawn+vscode-jsonrpc, requires Node.js ≥ 18 - Cross-platform: Full support for Windows / macOS / Linux
- Auto-detection: Automatically selects the language server based on file extension
- Daemon mode: Background persistent process, avoids repeated initialization, greatly speeds up consecutive calls
- Full LSP coverage: hover / definition / references / completion / diagnostics / symbols / rename / format / code-actions / signature-help / type-definition
- Built-in support: Python (Pyright), TypeScript/JavaScript (typescript-language-server), Rust (rust-analyzer)
- User/project config: Add language-first LSP mappings with
slsp.config.json - Capability discovery:
slsp servers -f <file>tells Agents which commands are supported before calling them
Prerequisites
simple-lsp-clidoes not bundle any language server. After installing this CLI, you still need to install at least one LSP server for your target language.
# Python (Pyright recommended)
npm install -g pyright
# TypeScript / JavaScript
npm install -g typescript typescript-language-server
# Or pylsp for Python
pip install python-lsp-server
# Rust
rustup component add rust-analyzerInstallation
As an npm package
npm install -g simple-lsp-cliOnce installed, use either alias:
slsp --help
simple-lsp-cli --helpLocal development
cd simple-lsp-cli
npm install
npm run build
npm linkQuick Start
slsp servers -f src/main.py --format json # Inspect selected server + capabilities
slsp hover -f src/main.py -l 10 -c 5 # Type info + docs
slsp definition -f src/app.ts -l 42 -c 12 # Go to definition
slsp diagnostics -f src/main.py # Errors / warnings
slsp symbols -f src/utils.ts # Document symbols
slsp references -f src/main.py -l 15 -c 8 # Find references
slsp completion -f src/main.py -l 10 -c 5 # Completion suggestions
slsp rename -f src/main.py -l 5 -c 8 -n newFunc # Rename symbolCommands
All positional arguments are 1-based.
Position-based (require --file --line --col)
| Command | Description |
|---------|-------------|
| hover | Type info and documentation |
| definition | Go to definition |
| type-definition | Go to type definition |
| references | Find all references |
| completion | Completion suggestions |
| signature-help | Function signature info |
| rename | Rename symbol (requires --new-name) |
| code-actions | Code actions |
File-based (require --file only)
| Command | Description |
|---------|-------------|
| diagnostics | Errors, warnings, hints |
| symbols | Document symbols |
| format | Format document |
Management
| Command | Description |
|---------|-------------|
| servers | List configured language servers |
| servers -f <file> | Inspect selected server and command capabilities |
| languages | List configured languages, extensions, and candidate servers |
| config | Show loaded config layers and effective config summary |
| daemon start | Start background daemon |
| daemon stop | Stop daemon |
| daemon status | Daemon status |
Options
-f, --file <path> Target file (required)
-l, --line <n> Line number (1-based)
-c, --col <n> Column number (1-based)
-r, --root <path> Project root (auto-detected by default)
-s, --server <name> Force server (pyright|pylsp|typescript|rust-analyzer)
-n, --new-name <name> New name (for rename)
-w, --wait <ms> Diagnostics wait time (default 5000)
-v, --verbose Output LSP logs to stderr
-h, --help Show help (use with a command for command help)
-V, --version Show version
--format <fmt> Output format: text (default) or json
--no-daemon Force inline mode (skip daemon)Configuration
Add slsp.config.json globally at ~/.config/simple-lsp-cli/slsp.config.json (or $XDG_CONFIG_HOME/simple-lsp-cli/slsp.config.json) or in a project. Merge order is built-in < global < project.
{
"$schema": "https://raw.githubusercontent.com/frostime/simple-lsp-cli/main/schema/slsp.schema.json",
"schemaVersion": "2.0",
"languages": {
"latex": {
"extensions": ["tex", "cls", "sty"],
"languageId": "latex",
"servers": ["texlab"]
},
"bibtex": {
"extensions": ["bib"],
"languageId": "bibtex",
"servers": ["texlab"]
}
},
"servers": {
"texlab": {
"name": "TexLab",
"command": "texlab",
"args": [],
"transport": "stdio",
"rootMarkers": [".latexmkrc", "Tectonic.toml", ".git"],
"initializationOptions": {},
"env": {}
}
}
}Rules: schemaVersion should be "2.0"; v1 configs are migrated in memory; languages.*.servers[0] is the default server; bad config fails fast with config_error.
Agent-first Capability Discovery
slsp servers -f src/main.py --format json{
"success": true,
"command": "servers",
"result": {
"selected": { "id": "pyright", "languageId": "python", "root": "/project" },
"commands": { "hover": "supported", "format": "unsupported", "diagnostics": "unknown" }
}
}Agents should call supported commands only. If a command is unsupported, fall back to rg/read or another supported semantic command.
Output Format
{
"success": true,
"command": "hover",
"file": "/abs/path/file.py",
"position": { "line": 10, "character": 5 },
"result": { "contents": "(variable) name: str", "range": { "..." : "..." } }
}Daemon Mode (Auto-managed)
On the first LSP command call, the daemon starts automatically. Subsequent calls reuse the session (~0.7s vs 2-3s cold start). Exits automatically after 15 minutes of inactivity — no manual management needed.
slsp hover -f src/main.py -l 10 -c 5 # Auto-starts daemon
slsp hover -f src/main.py -l 20 -c 3 # Reuses session, fast response
# Auto-exits after 15 minutesManual control is still available:
slsp daemon start # Start immediately
slsp daemon status # View status + idle time
slsp daemon stop # Stop immediately
slsp hover --no-daemon -f ... # Force inline modeAgent Integration
import subprocess, json
def lsp(action, file, line=None, col=None, **kw):
cmd = ["slsp", action, "-f", file]
if line: cmd += ["-l", str(line)]
if col: cmd += ["-c", str(col)]
for k, v in kw.items():
cmd += [f"--{k.replace('_', '-')}", str(v)]
return json.loads(subprocess.run(cmd, capture_output=True, text=True).stdout)Architecture
CLI → Daemon(optional) → LspClient → JsonRpcConnection → Language Server (stdio)License
GPL-V3
