A fast, low-memory LSP server for Kotlin, Java, and Swift, written in Rust.
Built with tree-sitter — instant startup, no JVM.
cargo install kotlin-lspNo Cargo? Get it at rustup.rs. After install,
kotlin-lspis at~/.cargo/bin/— make sure it's on yourPATH.
Optional: Install fd and rg (ripgrep) for faster file discovery and cross-file search.
One-liner (Linux / macOS) — installs both kotlin-lsp and the native JAR indexer:
curl -fsSL https://raw.githubusercontent.com/Hessesian/kotlin-lsp/main/install.sh | shcargo-binstall — downloads the pre-built binary (no compilation):
cargo binstall kotlin-lspmise — via the aqua backend:
mise use -g aqua:Hessesian/kotlin-lspmason.nvim (Neovim) — once listed in the registry:
require("mason").setup()
require("mason-lspconfig").setup({ ensure_installed = { "kotlin_ls" } })For full JAR/library type information (Compose, AndroidX, Kotlin stdlib docs), the native sidecar is needed. The install.sh and mise/aqua channels install both binaries automatically. cargo-binstall and mason.nvim install only kotlin-lsp — in those cases, download the matching tarball manually to get the sidecar too:
# Linux x86_64 example — both binaries extracted from one tarball
tar -xzf kotlin-lsp-linux-x86_64.tar.gz
mv kotlin-lsp ~/.cargo/bin/
mv kotlin-jar-indexer ~/.cargo/bin/The sidecar is a self-contained native binary — no JVM required. Starts in ~4 ms.
Fallback: if the native sidecar is absent but
javais on your PATH,kotlin-lspautomatically falls back to the JAR version.
VS Code — download and install the .vsix from the latest release:
code --install-extension kotlin-lsp-linux-x64-vX.Y.Z.vsix # Linux
code --install-extension kotlin-lsp-darwin-arm64-vX.Y.Z.vsix # macOS Apple SiliconThe extension bundles syntax highlighting and launches kotlin-lsp automatically.
Zed — install the bundled extension (registers kotlin-lsp from $PATH, no manual wiring):
zed --install-dev-extension contrib/zed-extensionThen add to ~/.config/zed/settings.json:
{
"languages": {
"Kotlin": {
"language_servers": ["kotlin-lsp", "!kotlin-language-server"],
"format_on_save": "off",
"show_completions_on_input": true
},
"Java": { "language_servers": ["kotlin-lsp"], "format_on_save": "off" },
"Swift": { "language_servers": ["kotlin-lsp"], "format_on_save": "off" }
}
}Full Zed setup + manual wiring option →
Helix — add to ~/.config/helix/languages.toml:
[[language]]
name = "kotlin"
language-servers = ["kotlin-lsp"]
[[language]]
name = "java"
language-servers = ["kotlin-lsp"]
[language-server.kotlin-lsp]
command = "kotlin-lsp"Once your editor is wired up:
- Open a Kotlin/Java file — hover, go-to-definition, and completions work immediately via
rgfallback while the index builds in the background. - Library sources are discovered automatically — no configuration needed in most cases:
- Android SDK (
Activity,Context,View, …) — detected fromlocal.properties→$ANDROID_HOME→$ANDROID_SDK_ROOT - Gradle library sources (Compose, coroutines, AndroidX, …) — run once to unpack
*-sources.jarfrom the Gradle cache:
- Android SDK (
kotlin-lsp extract-sources # one-time; restart editor after- IntelliJ/Android Studio projects —
workspace.jsonsource roots are picked up automatically, including anysourcePathsyou've configured there.
| Capability | Notes |
|---|---|
| Go-to-definition | Index → superclass hierarchy → rg fallback. Multi-hop chains, lambda params, this/super |
| Hover | Declaration signature, lambda param types, Kotlin stdlib docs |
| Completion | Dot-completion with type resolution, auto-import, scored ranking, stdlib entries |
| References | Project-wide rg --word-regexp + open buffers; scoped to declaring class for fields/properties |
| Document/workspace symbol | Outline view, fuzzy search, dot-qualified extension function queries |
| Rename | Project-wide via WorkspaceEdit |
| Inlay hints | Lambda it, named params, this, untyped val/var; enriched async via background rg pass |
| Semantic tokens | Full syntax highlighting via tree-sitter CST + cross-file resolution |
| Diagnostics | Syntax errors (tree-sitter), missing when branches (sealed/enum), missing call arguments |
| Go-to-implementation | Interface methods and abstract functions; transitive subtype BFS; scoped by declaring class |
| Signature help | Active parameter highlighting |
| Code actions | Fill missing when branches for sealed classes and enums |
| Folding | Brace regions + consecutive comment blocks |
| CLI mode | find, refs, hover, index, complete, tokens, tree, sources, extract-sources — scriptable, no daemon |
All features work immediately — rg fallback handles symbols before indexing finishes.
| Language | Symbols |
|---|---|
| Kotlin | class, interface, object, fun, val, var, typealias, constructor params, enum entries |
| Java | class, interface, enum, method, field, enum_constant |
| Swift | class, struct, enum, protocol, func, let, var, typealias, extension, init, enum cases |
kotlin-lsp works standalone — no editor, no daemon.
kotlin-lsp find MyViewModel # search declarations
kotlin-lsp refs MyViewModel # find all references
kotlin-lsp hover src/Foo.kt 42 10 # hover info at line 42, col 10
kotlin-lsp complete src/Foo.kt 42 --dot # completions after last '.' on line 42
kotlin-lsp index --root ./android # pre-build cache
kotlin-lsp sources --root ./android # list detected source roots
kotlin-lsp extract-sources # unpack library sources from Gradle cache| Flag | Behaviour |
|---|---|
| (none) | Auto: use cached index if available, fall back to fast rg/fd |
--fast |
Always use rg/fd; instant, no index needed |
--smart |
Require index; build it if missing |
--json |
Machine-readable output |
--root <dir> |
Workspace root (default: nearest .git dir) |
complete returns JSON [{label, kind, detail?, import?}]. Use --dot / --eol to auto-place the cursor; --no-stdlib skips ~/.kotlin-lsp/sources for ~5× faster project-only results.
Resolved in order:
KOTLIN_LSP_WORKSPACE_ROOTenv var- LSP client
rootUri/workspaceFolders ~/.config/kotlin-lsp/workspacefile (for clients that send no root)
# ~/.config/helix/languages.toml
[language-server.kotlin-lsp.config.indexingOptions]
ignorePatterns = ["bazel-*", "build/**", "third-party/**"]Patterns follow gitignore glob rules and apply to both fd and walkdir fallback.
Library sources are resolved automatically — no manual config needed in most cases:
| Source | How it's discovered |
|---|---|
Android SDK (Activity, Context, …) |
sdk.dir in local.properties → $ANDROID_HOME → $ANDROID_SDK_ROOT |
| Gradle library sources (Compose, coroutines, …) | ~/.kotlin-lsp/sources after running kotlin-lsp extract-sources |
| IntelliJ/Android Studio project roots | workspace.json at project root (exported by IDE) |
| Standard Gradle/Maven layouts | src/main/kotlin, src/test/kotlin, per-module subprojects |
workspace.json — JetBrains IDEs export this file to the project root. It describes every module's source roots and lets you override library source directories:
{
"sourcePaths": [
"<WORKSPACE>/custom-stubs",
"/absolute/path/to/generated-sources"
]
}When sourcePaths is present (even as []), it overrides the ~/.kotlin-lsp/sources default. Use [] to disable all library sources for a specific project.
Manual override via LSP config (for custom stubs or generated code):
# ~/.config/helix/languages.toml
[language-server.kotlin-lsp.config.indexingOptions]
sourcePaths = ["buildSrc/src", "/path/to/generated-stubs"]Source path files are indexed for hover and completions but excluded from findReferences and rename.
Full configuration reference →
- No type inference for generic lambda parameters — use explicit annotations for unresolvable cases
- No type checking — syntax errors only; use Gradle/Xcode/CI for semantic diagnostics
- Swift support is structural — all symbols indexed; no module boundaries or closure type inference
- Java completion is less refined than Kotlin
findReferenceson common names returns noise — name-based search viarg, no import filtering yet- Binary
.aar/.jar— only the public API surface is available; full source navigation requires a*-sources.jar(usekotlin-lsp extract-sources). Direct class-file indexing is planned.
| kotlin-lsp | Kotlin/kotlin-lsp (JetBrains) | |
|---|---|---|
| Runtime | Native Rust, no JVM | JVM 17+, ~500 MB |
| Startup | Instant | Gradle import (slow) |
| Memory | < 200 MB | 1+ GB |
| Accuracy | Syntactic (tree-sitter) | Full IntelliJ Analysis API |
| Editor support | Any LSP editor | VS Code (official) |
| Swift | ✓ | ✗ |
They can coexist — use kotlin-lsp for fast navigation, the official one for type-checked diagnostics.
- Feature details — resolution chain, completion, CLI reference
- Editor setup — Helix, Neovim, VS Code, Zed
- GitHub Copilot CLI — agent integration, skill extension, Serena MCP setup
- Architecture & performance — source layout, memory model
- Performance & profiling — benchmarks, flamegraph setup
- Changelog
Superclass hierarchy resolution, this/super qualifier handling, and lambda parameter recognition were inspired by code-compass.nvim by Emmanuel Touzery.

