SYLEN
AboutNewsConferenceMembershipDonate

Email updates

Conference, news, and membership updates by email.

Site

  • About
  • News
  • Membership
  • Waitlist
  • Donate

Conference

  • Conference 2027
  • Call for papers

Account

  • Create account
  • Membership details

SYLEN

  • Guidelines
  • Privacy
  • Terms

© 2026 Systems Leadership and Engineering Network. sylen.org.

Membership details →
Back to news
General SESource: jointhefreeworld.orgJuly 21, 2026

Decoupling JVM Development from IntelliJ: Production-Grade Scala and Kotlin via Emacs Eglot

Emacs 29's native LSP client, Eglot, offers a lightweight, protocol-first alternative to resource-heavy JVM IDEs. By leveraging Elisp advice and custom workspace configurations, systems engineers can resolve LSP deviations in Metals and the Kotlin language server to achieve seamless, multi-language navigation.

Architectural Motivation

The conventional approach to JVM development relies on monolithic IDEs like IntelliJ IDEA, which routinely demand upward of 8GB of RAM and degrade system responsiveness during binary indexing. By contrast, an Emacs-based setup using Eglot adheres to the Unix philosophy by decoupling transport from processing.

Eglot functions as a minimal, protocol-first transport layer that communicates with backend language servers via JSON-RPC. This architecture provides a unified interface for text manipulation, cross-referencing, and autocompletion while remaining lightweight and hackable.

Server Provisioning and Initialization

Eglot is configured as a built-in package (`:ensure nil`) initialized via `use-package` hooks linked to major tree-sitter modes such as `scala-ts-mode` and `kotlin-ts-mode`. To optimize performance and lifecycle management, settings like `eglot-autoshutdown` automatically terminate server processes when their managing buffers are closed, while `eglot-extend-to-xref` enables cross-referencing to resolve symbols outside the immediate workspace directory.

For Scala development, the Metals server is initiated with specific JVM tuning parameters: a 4GB heap limit (`-Xmx4G`) and the low-latency Z Garbage Collector (`-XX:+UseZGC`). Metals HTTP communication is explicitly enabled. For Kotlin, the setup bypasses standard tools in favor of the JetBrains-backed Kotlin Language Server (`intellij-server --stdio`).

Fine-Tuning Workspace Settings

Customizing downstream variables is managed via `eglot-workspace-configuration`. For Metals, this controls inlay hint density—enabling hints for inferred types and type parameters while disabling them for implicit arguments and conversions to prevent visual clutter in code buffers. Additionally, Bloop JVM properties are configured with a 4GB heap.

The global workspace configuration also maps distinct YAML schemas to remote URLs based on filename pattern matches. This ensures real-time structural validation of configurations directly in the editor.

Engineering Workarounds for Eldoc and URI Translation

Because minimal LSP clients do not provide complex out-of-the-box toggles for non-conforming servers, developers must use Emacs Lisp to address protocol quirks.

First, to prevent Eldoc from becoming saturated by generic hover data, Flymake diagnostics are prioritized. This is achieved by prepending `flymake-eldoc-function` to `eldoc-documentation-functions` and setting `eldoc-documentation-strategy` to `eldoc-documentation-compose`.

Second, during dependency navigation, the Kotlin language server returns file references formatted as `jar:///path/to/library.jar!/File.kt`. Because Emacs cannot natively resolve this URI scheme, jumping to definitions fails.

The solution wraps Eglot's URI translators with advice to rewrite the protocol prefix. By advising `eglot-uri-to-path` and `eglot-path-to-uri` with `:around` filters, custom Lisp functions map `jar:///` to `jar:file:///`. This translation enables companion packages like `jarchive` to correctly extract and open read-only dependency files.

Read the original article at jointhefreeworld.org.