# Language servers

> Diagnostics, hover and go-to-definition from language servers, plus toolchain selection.

Rexa runs language servers for diagnostics, hover information and code navigation. Each server is off until you turn it on, except JSON, which is on by default.

## Turn a server on

The first time you open a file whose language has a server, Rexa offers **Enable**. You can also turn servers on in **Settings → Language servers**, or in `settings.json`:

```json [settings.json]
{
  "lsp": { "enabled_servers": ["rust-analyzer", "typescript-language-server"] }
}
```

Enabling a server applies to every project.

## Built-in servers

| Name                           | Languages                | Command                               |
| ------------------------------ | ------------------------ | ------------------------------------- |
| `rust-analyzer`                | Rust                     | `rust-analyzer`                       |
| `typescript-language-server`   | TypeScript, JavaScript   | `typescript-language-server --stdio`  |
| `pyright`                      | Python                   | `pyright-langserver --stdio`          |
| `gopls`                        | Go                       | `gopls`                               |
| `clangd`                       | C, C++                   | `clangd`                              |
| `zls`                          | Zig                      | `zls`                                 |
| `lua-language-server`          | Lua                      | `lua-language-server`                 |
| `vscode-json-language-server`  | JSON, JSONC              | `vscode-json-language-server --stdio` |

Rexa looks for each command on your `PATH`, including the `PATH` your login shell sets. The JSON and TypeScript servers need no install: when the command is missing, Rexa runs a pinned copy and caches it in `~/Library/Caches/deno`.

## Features

| Feature              | How                                                                    |
| -------------------- | ---------------------------------------------------------------------- |
| Diagnostics          | Underlines and gutter dots. Counts in the status bar.                  |
| Hover                | Rest the pointer for 300 ms, or <Kbd>K</Kbd> in Vim normal mode.       |
| Go to definition     | <Kbd>F12</Kbd> or <Kbd>⌘</Kbd>-click                                   |
| Go to declaration    | <Kbd>⌃</Kbd> <Kbd>F12</Kbd>                                            |
| Go to type definition | <Kbd>⌘</Kbd> <Kbd>F12</Kbd> or <Kbd>⌘</Kbd> <Kbd>⇧</Kbd>-click        |
| Go to implementation | <Kbd>⇧</Kbd> <Kbd>F12</Kbd>                                            |

The jumps also work from git diffs and the right-click menu.

<Callout type="note">
  Completion, rename, find references, code actions and formatting are not available yet.
</Callout>

## Problems

| Action                       | Shortcut                                           |
| ---------------------------- | -------------------------------------------------- |
| Problems tab                 | <Kbd>⌘</Kbd> <Kbd>⇧</Kbd> <Kbd>M</Kbd>             |
| Problems palette             | <Kbd>⌃</Kbd> <Kbd>⇧</Kbd> <Kbd>M</Kbd>             |
| Next / previous problem      | <Kbd>F8</Kbd> / <Kbd>⇧</Kbd> <Kbd>F8</Kbd>         |

The Problems tab lists errors and warnings for the worktree, grouped by file, with filters for each. Click the counts in the status bar for the same list as a popup.

## Server status

Each running server has a status bar item with its name and progress, such as `Rust: Indexing (42%)`. A trailing `…` means starting, yellow means not installed, and red means it failed.

Click the item for its details and a menu: Restart, Stop or Start, Show Logs, the server's own commands (such as **Reload Workspace** for Rust), the toolchain picker, and **Restart All Language Servers**.

## Toolchains

Rexa picks a toolchain per server root: the TypeScript version, Python interpreter, Node version, Rust toolchain or Go toolchain. It prefers the one closest to the project, never a machine-wide install.

- **TypeScript** uses the project's `node_modules/typescript`. Without one, Rexa uses a bundled TypeScript 7, or TypeScript 5.9 for projects that declare TypeScript 6 or older.
- **Python** uses the project's `.venv`.
- **Node** follows `.nvmrc`, `.node-version` or `volta.node`. Write a version number; aliases such as `lts/*` are not resolved.

Change it from the server's status item (**TypeScript Version…**, **Python Interpreter…**), or pin it per project in [`.rexa/config.json`](/docs/reference/project-config#toolchains). New terminals and agents in the worktree get the same Python and Node first on `PATH`.

## Add or replace a server

`lsp.servers` adds a server, or replaces a built-in one with the same name:

```json [settings.json]
{
  "lsp": {
    "enabled_servers": ["ruby-lsp"],
    "servers": {
      "ruby-lsp": {
        "label": "Ruby",
        "languages": ["ruby"],
        "command": "ruby-lsp",
        "args": [],
        "root_markers": ["Gemfile"]
      }
    }
  }
}
```

Each server also accepts `env`, `initialization_options` and `settings`. Zed extensions can provide servers too; see [Themes and extensions](/docs/customize/themes-and-extensions).

## From the command line

`rexa lsp` reports and controls servers in the running app:

```bash [Terminal]
rexa lsp                          # status of every server
rexa lsp diagnostics src/main.rs  # diagnostics for a file
rexa lsp restart rust-analyzer    # restart one server
rexa lsp toolchain python .venv   # pick a toolchain
```

Each server's log is in `~/Library/Logs/rexa/lsp/`.
