pi-lspconfig
v0.0.1
Published
Language Server Protocol support for pi — out-of-the-box per-language LSP configs, user-overridable, behind one unified tool.
Maintainers
Readme
pi-lspconfig
Language Server Protocol support for pi — out-of-the-box LSP configs for common languages, overridable from a single config file, exposed through one unified tool.
Built on nvim-lspconfig's config model and pi-lens's tool surface.
Status: usable. Milestones M0–M6 are complete: the tools, diagnostics,
/lsp-*commands, reload hardening, real-server smoke tests, packaging, and the generated language docs are live. SeeROADMAP.md.
Why
An agent that only has grep cannot tell a function's definition from a mention
in a comment, a string, or an unrelated same-named symbol. A language server can.
This extension puts one in reach of the model without asking the user to
configure anything.
Design
Built-in configs, overridable. Each supported language ships a declarative
server spec — command, language ids, root markers, settings — in the spirit of
nvim-lspconfig's server tables. A pi-lspconfig.config.ts file deep-merges over
them, and the user's value always wins.
One tool, not eighteen. definition, references, hover,
documentSymbol, workspaceSymbol, codeAction, rename, and the call
hierarchy are all operations of a single lsp tool. The model learns one input
shape and pays for one tool description.
Honest failure. A missing binary, an unsupported capability, and a real crash return distinct statuses with actionable hints — never a silent empty list.
Tools
| Tool | Purpose |
| ---- | ------- |
| lsp | Navigation, symbols, hover, code actions, rename, call hierarchy |
| lsp_diagnostics | Errors and warnings for a file or the workspace |
lsp takes path plus either a 1-based line/character or a symbol name —
naming the symbol is usually more reliable than guessing a column.
Configuration
Create pi-lspconfig.config.ts in your project root (or ~/.pi/ for all
projects):
import { defineConfig } from "pi-lspconfig";
export default defineConfig({
servers: {
// Override a built-in server.
pyright: {
settings: { python: { analysis: { typeCheckingMode: "strict" } } },
},
// Add a server that is not built in.
mylang: {
cmd: ["mylang-ls", "--stdio"],
filetypes: ["mylang"],
rootMarkers: [".mylangrc", ".git"],
},
},
disabledServers: ["gopls"],
});Override rules: objects merge recursively with the user's keys winning; arrays
and functions replace the default; undefined keeps the default; null deletes
the key.
See docs/configuration.md for search paths,
precedence, and the full reference.
Auto-install
Off by default. Installing a toolchain is a supply-chain decision, so pi-lspconfig reports a missing binary rather than acting on it. When you do want it, opt in per server:
export default defineConfig({
servers: {
gopls: { autoInstall: true },
},
});On the first missing binary for that server, its installCommand runs once (120
second deadline, output captured) and the launch is retried once. A failed
install still returns status: "binary_missing", with the installer's last line
as a note. Servers you define yourself need both installCommand and
autoInstall: true.
Commands
| Command | Purpose |
| ------- | ------- |
| /lsp-status | Running servers, roots, and diagnostic counts |
| /lsp-restart [server] | Restart one server, or all of them |
| /lsp-list | Configured servers |
| /lsp-config <server> | Resolved spec for one server |
Flags
| Flag | Purpose |
| ---- | ------- |
| --lsp-disable | Turn the extension off for one invocation |
| --lsp-log <level> | stderr log level: off, error, warn, info, debug, verbose |
Install
pi install npm:pi-lspconfigFrom a checkout (the extension is plain TypeScript, there is no build step):
npm install
pi install ./pi-lspconfig # or: pi -e ./src/index.ts for one invocationLanguage servers are not installed for you. Put vtsls, pyright-langserver,
rust-analyzer, or gopls on your PATH as needed; a missing binary is
reported with its install command. To have pi-lspconfig run that command for
you, opt in per server — see Auto-install.
Supported languages
TypeScript/JavaScript (vtsls), Python (pyright), Rust (rust-analyzer), and
Go (gopls). See docs/languages.md.
Documentation
docs/architecture.md— layers, lifecycle, and the two invariants that are easy to get wrongdocs/configuration.md— config referencedocs/languages.md— built-in serversdocs/adr/— decision recordsROADMAP.md— milestonesAGENTS.md— conventions for contributors and agents
Development
npm run typecheck
npm testThe default suite uses a fake language server and needs no toolchain. Smoke
tests against the real vtsls, pyright, rust-analyzer, and gopls are
gated behind PI_LSP_REAL=1 and skip per language when a binary is absent:
PI_LSP_REAL=1 npx vitest run tests/integration/real-serversRequires Node >= 22.19.
License
MIT
