A language server gives the editor completion, hover, go to definition, rename, code actions and the compiler’s own diagnostics. Settings > LSP has a card for every one Tori knows, split into three tabs:
- Ready: bundled with Tori, or found on your machine.
- Installable: Tori can fetch it for you.
- Manual: your own toolchain installs it; the card shows the command.
Each card has a status dot, a version, Install, Update or Remove where they apply, and an on or off switch.
Installing a server
Open a file in a language whose server Tori can install, and a banner over the file offers it: Install, Not now (asked again next session), or Never for this language. The card in Settings > LSP has the same Install button.
Tori installs a pinned version, either from npm or from a GitHub release
whose checksum it checks before writing anything, into
~/.config/tori/servers/<id>/. A failed download leaves the previous install
in place. When a Tori release pins a newer version, the card offers Update.
For a Manual server, Install runs the command shown on the card in a terminal inside Settings, using your login shell’s PATH. Reopen Tori after installing one by hand outside of Settings so it is picked up.
If you already have a server on your PATH, Tori uses yours, even for one it could install itself.
Every server
Ready, no install
| Language | Server | Notes |
|---|---|---|
| TypeScript, JavaScript | typescript-language-server |
Bundled. Needs node on your PATH. Uses the project’s own TypeScript. |
| JSON | vscode-json-languageserver |
Bundled. Validates against SchemaStore, so package.json, tsconfig.json and friends get checked. |
| YAML | yaml-language-server |
Bundled. SchemaStore validation for GitHub workflows, compose files and the like. |
| CSS, SCSS, Less | vscode-css-language-server |
Bundled. |
| HTML | vscode-html-language-server |
Bundled. |
| Rust | rust-analyzer |
Not bundled, so it always matches your toolchain: rustup component add rust-analyzer. |
ESLint, Biome, oxlint and Ruff also run as language servers; they are on the linters page.
Installable from Tori
| Language | Server | Source |
|---|---|---|
| Python | pyright | npm |
| Bash, sh | bash-language-server |
npm |
| Svelte | svelte-language-server |
npm |
| Astro | @astrojs/language-server |
npm. Type checks with the project’s own TypeScript when it has one, else the copy Tori bundles. |
| PHP | Intelephense | npm |
| Vim script | vim-language-server |
npm |
| Elm | elm-language-server |
npm (needs elm installed) |
| Prisma | @prisma/language-server |
npm |
| Perl | Perl Navigator | npm |
| GraphQL | graphql-language-service-cli |
npm |
| Fish | fish-lsp |
npm (needs fish installed) |
| C, C++, Objective-C | clangd | GitHub release. Xcode’s command line tools already ship one. |
| Lua | lua-language-server |
GitHub release |
| Markdown | marksman | GitHub release |
| LaTeX | texlab | GitHub release |
| XML | LemMinX | GitHub release |
| Typst | tinymist | GitHub release |
| TOML | tombi | GitHub release |
| Clojure | clojure-lsp |
GitHub release |
Install it yourself
| Language | Server | Install |
|---|---|---|
| Go | gopls | go install golang.org/x/tools/gopls@latest |
| Ruby | ruby-lsp | gem install ruby-lsp |
| Java | jdtls | brew install jdtls |
| Kotlin | kotlin-language-server |
brew install kotlin-language-server |
| Swift | sourcekit-lsp | Ships with Xcode and the Swift toolchain |
| C# | csharp-ls |
dotnet tool install --global csharp-ls |
| Zig | zls | The release that matches your Zig |
| Haskell | haskell-language-server |
ghcup install hls |
| OCaml | ocaml-lsp-server |
opam install ocaml-lsp-server |
| Elixir | elixir-ls |
brew install elixir-ls. Starts only under a mix.exs. |
| Dart, Flutter | dart language-server |
Ships with the Dart and Flutter SDKs |
| Terraform | terraform-ls |
brew install hashicorp/tap/terraform-ls |
| Scala | Metals | cs install metals |
| Nix | nil | nix profile install nixpkgs#nil |
When a server does not start
- The project is not trusted. Most servers run project code, so they wait until you trust the project. Tori offers it the first time; see trusted projects.
- It is not on your PATH. The card says not found. If you installed it somewhere your login shell does not look, point Tori at it with your own TOML (below).
- It is switched off. Check the card’s switch, and the project’s own
.tori/settings.json.
A server starts per project root: the nearest folder above the file with a
tsconfig.json, go.mod, Cargo.toml or whatever that language uses. In a
monorepo, each package gets its own server.
Adding or replacing a server
Each server is a TOML file. Add one from the catalog with Add a
language in Settings > LSP, or drop one into ~/.config/tori/packs/lsp/ and
restart Tori. A file may not reuse a built in id, so to replace a built in
server, give your file its own id and switch the built in one off on its card.
This one runs Python through a pyright you installed yourself, in place of the
built in python:
schema_version = 1id = "python-pyright"label = "Python (pyright)"root_markers = ["pyproject.toml", "setup.py", "requirements.txt", ".git"]
[languages]py = "python"pyi = "python"
[launch]kind = "path"program = "pyright-langserver"args = ["--stdio"]Keep every top level key above the first [table]: in TOML a key written
after a table header belongs to that table. A replacement is whole, so list
every extension you still want served. A file that fails to load is listed
under Needs fixing in Settings > LSP, and the server it would have
replaced keeps running.
Missing a language?
Request a language server. Say which server, how you install it today, and paste your TOML if you already have one working.