AphrodyBun GitHub

Runtime docs · Runtime · Core Runtime

Language server

One language server for TypeScript, JavaScript, Python, Rust, C and C++ with bun lsp

bun lsp is a language server for editors and a command line for agents and scripts. It speaks the Language Server Protocol and passes each request to the server of the document's language. It starts that server the first time a file of that language needs it.

LanguageServerDiagnostics
TypeScript, JavaScripttsgo (@typescript/native-preview), else typescript-language-server, else bun x downloads tsgobun check, in the same process
Pythonty, else basedpyright, else pyright, else ty through bun uvthe server, plus ruff server if it is installed
Rustrust-analyzerthe server
C, C++, Objective-Cclangd, else clangd from PyPI through bun uvthe server

bun lsp finds servers in node_modules/.bin, in the .venv of the project, and on PATH.

Editors

Configure bun lsp as the language server of every language it handles. It reads requests on stdin and writes answers on stdout.

Zed settings.json
{
  "lsp": {
    "bun": { "binary": { "path": "bun", "arguments": ["lsp"] } }
  }
}
Neovim
vim.lsp.config("bun", {
  cmd = { "bun", "lsp" },
  filetypes = { "typescript", "javascript", "typescriptreact", "python", "rust", "c", "cpp" },
  root_markers = { ".git" },
})
vim.lsp.enable("bun")

The editor gets the diagnostics of all of a document's servers in one list. Completions, code actions, inlay hints, code lenses and document links are resolved by the server that returned them. workspace/symbol asks every running server.

Queries from the command line

bun lsp query asks one question and prints the answer. The first query of a workspace starts a daemon for it, which keeps the servers running between queries. Later queries take milliseconds instead of the seconds a server needs to load a project.

bun lsp query diagnostics src/index.ts
bun lsp query definition src/index.ts:12:8
bun lsp query references src/index.ts:12:8
bun lsp query hover src/index.ts:12:8
bun lsp query symbols src/index.ts
bun lsp query workspace-symbols . Router
bun lsp query rename src/index.ts:12:8 newName --apply
src/index.ts:3:7: error TS2322: Type 'string' is not assignable to type 'number'.

Lines and columns start at 1, and columns count characters. bun lsp query diagnostics exits with code 1 if there is an error.

FlagDescription
--jsonPrint the answer as JSON
--limit <n>Print at most n items. Defaults to 100
--timeout <ms>How long a server may take. Defaults to 30000
--applyWith rename, write the edits to the files
--no-daemonStart the servers in this process, and stop them after the answer

The other commands manage the daemon of the workspace in the current directory, or in the given directory:

bun lsp warm            # start the daemon and the servers of each language in the workspace
bun lsp warm --lang typescript,rust
bun lsp status          # the running servers
bun lsp stop
bun lsp servers         # the server that each language would start, or what to install

The daemon of a workspace exits after 30 minutes without a query. A server stops after 15 minutes without a request. When more than 6 servers would run, the least recently used one stops.

C and C++

clangd needs a compile_commands.json. bun lsp looks for it in the project root, then in build/, out/ and cmake-build-debug/ and their subdirectories, with build/debug first. If there is none, it writes one with ninja -t compdb from the build.ninja it finds there, keeping only the compile commands. In a Linux kernel tree, it runs scripts/clang-tools/gen_compile_commands.py after a build.

bun lsp compdb          # write compile_commands.json now

clangd keeps its background index next to compile_commands.json, in .cache/clangd, so it survives restarts. bun lsp starts it with --background-index, --limit-results=100, -j set to half the CPU cores (at most 4), and --pch-storage=disk. On Windows, when INCLUDE is not set, it gives clangd the MSVC and Windows SDK environment from bun msvc env so that clang-cl command lines find their headers.

Configuration

Environment variableDescription
BUN_LSP_TYPESCRIPTThe TypeScript server command, such as "tsgo --lsp --stdio" or a JSON array of arguments
BUN_LSP_PYTHONThe Python server command
BUN_LSP_RUSTThe Rust server command
BUN_LSP_CPPThe C and C++ server command. Its arguments replace those that bun lsp adds
BUN_LSP_TS_DIAGNOSTICSserver to take TypeScript diagnostics from the server instead of bun check
BUN_LSP_OFFLINE1 to never download a server with bun x or bun uv
BUN_LSP_LIMITThe most items in an answer, and clangd --limit-results. Defaults to 100
BUN_LSP_JOBSThreads of clangd and rust-analyzer. Defaults to half the CPU cores, at most 4
BUN_LSP_MAX_SERVERSThe most servers that run at once. Defaults to 6
BUN_LSP_SERVER_IDLE_MSHow long an unused server keeps running. Defaults to 15 minutes
BUN_LSP_IDLE_MSHow long the daemon waits for a query before it exits. Defaults to 30 minutes
BUN_LSP_TIMEOUT_MSHow long a server may take to answer. Defaults to 30 seconds

rust-analyzer starts with checkOnSave off, so it does not run cargo check after each save.