Language servers
Diagnostics, hover, completion, go-to-definition and formatting in editor panes — from language servers you install, never bundled.
On this page
An editor pane on its own gives you syntax highlighting and the usual editing moves. Point a language server at it and it also gives you:
- Diagnostics — errors and warnings as live squiggles
- Hover — types and documentation under the pointer
- Completion — suggestions that know your project, not just words in the file
- Go to definition — cross-file, landing the cursor on the target
- Parameter hints — the signature of the call you are inside, with the argument you are on underlined
- Occurrence highlights — every other place the symbol under your cursor appears, reading told apart from writing
- Formatting — see below
TermHQ ships no language servers
Not as a limitation — as the design. A bundled server is one you cannot upgrade, one that disagrees with your project’s toolchain, and one that ships to everyone who does not write that language. TermHQ launches the servers you install, on your machine, at your version.
Nothing here is required. With no servers installed, editor panes work exactly as described on the editor page.
What is set up out of the box
Five entries ship as configuration, ready for the day you install the binary they name:
| Language | Server | Install it with |
|---|---|---|
| TypeScript / JavaScript | typescript-language-server |
npm i -g typescript-language-server typescript |
| Rust | rust-analyzer |
rustup component add rust-analyzer |
| Go | gopls |
go install golang.org/x/tools/gopls@latest |
| Python | pyright-langserver |
npm i -g pyright |
| C / C++ | clangd |
Your platform’s LLVM package |
Install one and it starts working the next time you open a file of that language. Install none and nothing breaks.
Adding your own
Open Settings → Editor → Language server setup, then choose Add a server; the new entry goes at the end of the list. (The setup section is hidden while Language intelligence is off.) TermHQ accepts servers that speak the Language Server Protocol over standard input and output. Each entry has:
- Name — the field at the top of the entry, which labels it in the list
- Command — the program name on your
PATH, or its full path - Arguments — space-separated options passed to that program, such as
--stdio. Quoted arguments containing spaces are not supported by this field. - Languages — comma-separated language IDs for the file types it should
handle, such as
typescript, javascript - Root markers — comma-separated filenames that mark the top of a project,
such as
tsconfig.json, package.json - Enabled — a switch, so you can park one without deleting it
In Arguments, Languages and Root markers, spaces and commas stay in place while you type. Press Enter, press Tab to move to the next field, or click elsewhere to apply that field’s value. There is no separate Save button.
To delete an entry, press its ×; it turns into Remove?, and only a second click removes the entry.
Restore default servers replaces the entire list with the five above, exactly as a fresh install has them. It does not ask first, and any server you added yourself is deleted along with your changes to the five.
How servers start and stop
You do not start them. A server launches when you open a file it handles, and one
runs per project — the project being whatever folder the nearest root marker
sits in, walking upward from your file. A monorepo with three Cargo.toml files
gets three, each seeing only its own crate.
A server stops about half a minute after the last file using it closes, restarts itself if it crashes (at most twice in five minutes, so a server that cannot start does not spin), and shuts down with the window.
When a server is not working
Every entry under Settings → Editor → Language server setup carries a status chip that tells you the truth rather than a green light:
| Status | What it means |
|---|---|
| running | Working, serving one project |
| running · 2 roots | Working, serving two projects |
| starting… | Launched, still coming up |
| checking… | Still looking for the command on your PATH |
its path, such as /usr/local/bin/gopls |
Installed; it starts when you open a file it handles |
| not installed | The command is not on your PATH — install it |
| would not start | It is there, but it failed. Hover for its own last words |
| restarting… | Recovering from a crash |
| disabled | Its Enabled switch is off, so it never launches |
The dot beside each entry’s name says the same at a glance: lit while the server runs, hollow when it is missing, failing or switched off.
Hover any status for the full story, including whatever the server itself said on the way down — “not found on PATH”, “initialize: no answer after 30s”, or the exit code that killed it. Each entry also keeps the server’s own log under Logs, which is the first thing worth reading when something is wrong.
Restart shows its work: a spinner while a relaunch is genuinely in flight, and a plain answer when there is nothing to relaunch (“cleared — no open file uses this server yet”) rather than a button that looks broken.
One deliberate detail: a missing binary keeps saying not installed even after you press Restart, because the fix is to install it, not to press the button again.
Formatting
Shift+Alt+F formats the document, and Ctrl+K then Ctrl+F formats just the selection. Settings → Editor → Format on save (off by default) does it on every save.
TermHQ never reformats anything itself. The request goes to your language
server, so it is rustfmt behind rust-analyzer and gofmt behind gopls, already
obeying your project’s own configuration. There is no formatter of ours in the
middle to disagree with your repo.
Using a different formatter
The first server in the list that offers formatting owns it. So to format with
Prettier, Black, shfmt or Ruff, add a formatting-only server — efm-langserver,
diagnostic-languageserver, or ruff server — and put it above the
language’s main server. That one formats; the main server keeps diagnostics,
hover and completion.
Settings cannot reorder the list, and Add a server puts a new entry at the
end. To move it up, close TermHQ and edit config.json:
servers are listed in the languageServers array, in order, and the formatter’s
entry has to come before the main server’s.
Format on save never waits more than two seconds for a formatter, and never applies edits computed against a version of the document you have already typed past.
When a server wants to change your files
Some servers offer refactors that touch more than the file you are in — a rename across a project, an import added somewhere else.
When that happens, the changes land in buffers, not on disk. Files already open are edited in place; closed ones open as tabs. Everything arrives unsaved and undoable, and nothing is written until you save it. One Ctrl+Z takes back a server’s whole edit for a file.
The edit is all-or-nothing. If anything about it does not fit — a file that moved on while it was being computed, overlapping changes, a file that will not open — the whole thing is refused and the server is told why, rather than half a refactor being applied to your project.
File operations — creating, renaming or deleting files as part of a refactor — are not supported yet, and a refactor that needs one is refused rather than partly done.
Turning it off
Settings → Editor → Language intelligence is the master switch. Off, no server ever launches, editor panes behave exactly as they do with nothing installed, and Language server setup is hidden until you turn it back on.
Individual entries have their own Enabled switch, which is the lighter version of the same idea.
Note that occurrence highlighting keeps working with the whole layer off — it falls back to matching words rather than understanding symbols, which is worth more than nothing while a server is missing, disabled, or still starting.