Code intelligence (language servers)
When a language server for the project's language is installed, Houston uses it the way an editor would: to check the agent's edits, and to give the agent type-aware navigation. It's on by default whenever a server is installed.
Checking edits
After the agent writes a file a server covers, the tool result lists the errors the edit introduced (and up to five new warnings), so the agent can fix them in the same turn.
- Problems the file already had before the edit are left out.
- A clean edit adds nothing.
- The first check in a conversation starts the server (a large project can take several seconds to load). After that, files the agent reads are opened in the running server in the background, so later checks are usually quick.
Diagnostics on save (Settings > Tools) picks what runs after an edit:
- the language server, when one covers the file (the default)
- the language server, or else a fast checker (
eslint,ruff/pyflakes,gofmt) for other files - no check at all
Navigation tools
These are offered only when a server is installed for a language the project uses, so a project without one pays nothing for them.
| Tool | Gives the agent |
|---|---|
lsp_definition | where a symbol is defined (following imports through to the declaration) |
lsp_references | every real use of a symbol across the project |
lsp_hover | a symbol's type, signature, and documentation |
lsp_document_symbols | a file's outline |
lsp_workspace_symbols | symbols by name across the project |
lsp_rename | renames a symbol everywhere it's used |
- Read-only and fast. All but
lsp_renameare read-only, need no approval, and run in parallel with other reads. - Contained. Results never include files outside the project, and lines from credential files aren't quoted.
- Renames are ordinary patches. The server's edits are applied as one
apply_patch, so a rename asks for approval like any patch (with a diff of every file), follows yourapply_patchpermission rules file by file, and is undone by Revert like any other change. A rename that would touch a file outside the project, or create, move, or delete files, is refused.
Supported servers
None are bundled; install the ones you want.
| Language | Server |
|---|---|
| TypeScript, JavaScript | typescript-language-server or vtsls (a copy in the project's node_modules/.bin is preferred over one on PATH) |
| Python | pyright-langserver (from pyright) or basedpyright-langserver |
| Go | gopls |
| Rust | rust-analyzer |
| C, C++ | clangd |
Adding others. In Settings > Tools > Language servers, add a JSON list of { "id", "command", "extensions" } entries (plus optional args, languageId, rootMarkers). Reusing a built-in id (typescript, python, go, rust, clangd) replaces it.
What's installed: Settings > Tools > Optional integrations and /doctor both show it.
How servers run
- They start on demand, one per language and project, are reused across turns, and stop after ten idle minutes or when Houston quits.
- They run in the same sandbox as shell commands, with no network.
- With no network, a server can't download the project's dependencies, so Go and Rust servers read them from your own caches: your Go module cache (
GOMODCACHE, or~/go/pkg/mod) and your Cargo home (CARGO_HOME, or~/.cargo), the ones your own builds fill. They can read them but not change them. If a dependency isn't there, the agent is told which, and/doctorwarns; rungo mod downloadorcargo fetchin the project yourself, and Houston restarts the server once they're there. - A server can run code from the project (a TypeScript plugin named in
tsconfig.json, a Rust build script). So on a host where the sandbox can't confine it, servers stay off unless you set Run language servers to Always. Never turns them off everywhere. - Setting
HOUSTON_LSP=offin the environment also turns them off for that process.