Skip to content
vic

joaotavora/eglot

A client for Language Server Protocol servers

joaotavora/eglot.json
{
"createdAt": "2017-08-16T01:41:16Z",
"defaultBranch": "master",
"description": "A client for Language Server Protocol servers",
"fullName": "joaotavora/eglot",
"homepage": null,
"language": "Emacs Lisp",
"name": "eglot",
"pushedAt": "2025-10-29T15:47:20Z",
"stargazersCount": 2436,
"topics": [],
"updatedAt": "2025-11-26T20:16:15Z",
"url": "https://github.com/joaotavora/eglot"
}

[Build status][build-status] GNU ELPA MELPA

Emacs Polyglot is the Emacs [LSP][lsp] client that stays out of your way:

  • 📽 Scroll down this README for some pretty gifs
  • 📚 Read Eglot’s [manual][manual] and [release notes][release-notes]
  • 🏆 Folks over at Google [seem to like it][gospb]. Thanks!
  • ✨ Get the stable or the latest version
  • 👾 Eglot now lives in Emacs itself! Learn how to contribute!

Also see [eglot-x][eglot-x] for non-standard protocol extensions support.

Just type M-x package-install RET eglot RET into Emacs 26.3+.

Now find some source file, any source file, and type M-x eglot.

That’s it. If you’re lucky, this guesses the LSP program to start for the language you’re using. Otherwise, it prompts you to enter one.

Get latest [GNU-Devel ELPA][gnudevelelpa] version

Section titled “Get latest [GNU-Devel ELPA][gnudevelelpa] version”

First, configure GNU-Devel ELPA as your ELPA source repository.

(add-to-list 'package-archives '("gnu-devel" . "https://elpa.gnu.org/devel/"))

Then, use M-x package-install or M-x package-update as before install an ELPA package from the latest upstream. You will be running the same Eglot version as if you were running Emacs master!

M-x eglot-upgrade-eglot should also work if you have already installed it.

These are just some of the servers that M-x eglot can use out of the box. The full list can be consulted in the eglot-server-programs variable, where you can [easily add your own servers][manual].

  • Ada’s [ada_language_server][ada_language_server]
  • Bash’s [bash-language-server][bash-language-server]
  • C/C++‘s [clangd][clangd] or [ccls][ccls]
  • C#‘s [omnisharp][omnisharp]
  • Clojure’s [clojure-lsp][clojure-lsp]
  • CMake’s [cmake-language-server][cmake-language-server]
  • CSS’s [css-languageserver][css-languageserver]
  • Dart’s [analysis_server][dart-analysis-server]
  • Dockerfile’s [docker-langserver][docker-langserver]
  • Elixir’s [elixir-ls][elixir-ls]
  • Elm’s [elm-language-server][elm-language-server]
  • Erlang’s [erlang_ls][erlang_ls]
  • Fortran’s [fortls][fortls]
  • Futhark’s [futhark lsp][futhark-lsp]
  • Go’s [gopls][gopls]
  • Godot Engine’s [built-in LSP][godot]
  • HTML [html-languageserver][html-languageserver]
  • Haskell’s [haskell-language-server][haskell-language-server]
  • JSON’s [vscode-json-languageserver][vscode-json-languageserver]
  • Java’s [Eclipse JDT Language Server][eclipse-jdt]
  • Javascript’s [TS & JS Language Server][typescript-language-server]
  • Kotlin’s [kotlin-language-server][kotlin-language-server]
  • Lua’s [lua-lsp][lua-lsp]
  • Markdown’s [marksman][marksman]
  • Mint’s [mint-ls][mint-ls]
  • Nix’s [rnix-lsp][rnix-lsp]
  • Ocaml’s [ocaml-lsp][ocaml-lsp]
  • Perl’s [Perl::LanguageServer][perl-language-server]
  • PHP’s [php-language-server][php-language-server]
  • PureScript’s [purescript-language-server][purescript-language-server]
  • Python’s [pylsp][pylsp], [pyls][pyls] [pyright][pyright], or [jedi-language-server][jedi-language-server]
  • R’s [languageserver][r-languageserver]
  • Racket’s [racket-langserver][racket-langserver]
  • Ruby’s [solargraph][solargraph]
  • Rust’s [rust-analyzer][rust-analyzer]
  • Scala’s [metals][metals]
  • TeX/LaTeX’s [Digestif][digestif] ot [texlab][texlab]
  • VimScript’s [vim-language-server][vim-language-server]
  • YAML’s [yaml-language-server][yaml-language-server]
  • Zig’s [zls][zls]

Eglot is in Emacs’s core since Emacs 29!

Section titled “Eglot is in Emacs’s core since Emacs 29!”

⚠️ This repository is not the development upstream anymore ⚠️

It’s not dead (yet 🧟)

  • Pull requests won’t be merged. You can still use them to show ideas for patches. See below for how to properly contribute.

  • You can start a [discussion][discussion]

    Say what is on your mind. It’s possible discussion or bug report will be moved to [Emacs’s bug tracker][emacs-bug-tracker-eglot]. You may jump straight to that forum using M-x report-emacs-bug or simply sending mail to bug-gnu-emacs@gnu.org.

    Please the [Eglot-specific bug-reporting instructions][bug-reporting].

  • The [eglot.el][eglot.el] file here is periodically updated to mirror the [Emacs upstream][upstream-eglot.el]

  • The existing tests of [eglot-tests.el][eglot-tests.el], also periodically updated, may be used to rehearse and validate patches using [GitHub CI infrastructure][build-status].

Contributing to Eglot is done by contributing to the Emacs project. Read below for how Eglot fits in and how to quickly submit a patch.

From a development perspective, moving to core allows us to work on Eglot in tandem with other related packages already in Emacs, such as [Flymake][flymake], [ElDoc][eldoc], [Xref][xref], [Project][project].

This means adding or tweaking an Emacs LSP feature is a matter of submitting a single patch to Emacs targetting multiple relevant packages, not just Eglot. You may even propose a new package altogether.

These — Eglot included — are so-called :core packages. They are released periodically to GNU ELPA, so users of older Emacs versions can get all the goodies via M-x package-install.

The recommended way to experiment with changes to the code is to compile Emacs from a Git repo like this one or this one. Here are [three][compile-emacs1] [separate][compile-emacs2] [guides][compile-emacs3-official] for doing so.

When you are content with your tweaks to Eglot (and/or its sibling :core packages), submit your patch 💪via email💪 to bug-gnu-emacs@gnu.org. You may CC the authors/maintainers of packages if you know their emails, but it isn’t strictly necessary. We’ll guide you if any more steps are needed (like copyright assignments, etc).

![eglot-completions]!(./gif-examples/eglot-completions.gif)

The animation shows [company-mode][company] presenting the completion candidates to the user, but Eglot works with the built-in completion-at-point function as well, which is usually bound to C-M-i.

![eglot-snippets-on-completion]!(./gif-examples/eglot-snippets-on-completion.gif)

Eglot provides template based completion if the server supports snippet completion and [yasnippet][yasnippet] is enabled before Eglot connects to the server. The animation shows [company-mode][company], but completion-at-point also works with snippets.

![eglot-diagnostics]!(./gif-examples/eglot-diagnostics.gif)

Eglot relays the diagnostics information received from the LSP server to Emacs’s [Flymake][flymake], which annotates/underlines the problematic parts of the buffer. The information is shared with the [ElDoc][eldoc] system, meaning that the commands eldoc and eldoc-doc-buffer (the latter bound to C-h-. for convenience) show diagnostics along with other documentation under point.

[Flymake][flymake] provides other convenient ways to view and manage diagnostic errors. These are described in its [manual][flymake].

When Eglot manages a buffer, it disables pre-existing Flymake backends. See variable eglot-stay-out-of to change that.

![eglot-code-actions]!(./gif-examples/eglot-code-actions.gif)

The LSP server may provide code actions, for example, to fix a diagnostic error or to suggest refactoring edits. The commands are frequently associating with Flymake diagnostic annotations, so that left-clicking them shows a menu. Additionally, the command eglot-code-actions asks the server for any code spanning a given region.

Sometimes, these code actions are initiated by the server. See eglot-confirm-server-initiated-edits to control that behaviour.

![eglot-hover-on-symbol]!(./gif-examples/eglot-hover-on-symbol.gif)

Here, too, the LSP server’s view of a given symbol or function signature is relayed to the [ElDoc][eldoc] system. The commands eldoc and eldoc-doc-buffer commands access that information.

There are customization variables to help adjust [ElDoc][eldoc]‘s liberal use of the lower “echo area”, among other options. If you still find the solicitous nature of this LSP feature too distracing, you can use eglot-ignored-server-capabilities to turn it off.

![eglot-rename]!(./gif-examples/eglot-rename.gif)

Type M-x eglot-rename RET to rename the symbol at point.

![eglot-xref-find-definition]!(./gif-examples/eglot-xref-find-definition.gif)

To jump to the definition of a symbol, use the built-in xref-find-definitions command, which is bound to M-..

![eglot-xref-find-references]!(./gif-examples/eglot-xref-find-references.gif)

Eglot here relies on Emacs’ built-in functionality as well. xref-find-references is bound to M-?. Additionally, Eglot provides the following similar commands: eglot-find-declaration, eglot-find-implementation, eglot-find-typeDefinition.

Around May 2018, I wrote a comparison of Eglot to lsp-mode.el, and was discussed with its then-maintainer. That mode has since been refactored/rewritten and now purports to support a lot of features that differentiated Eglot from it. It may now be very different or very similar to Eglot, or even sing with the birds in the trees, so [go check it out][emacs-lsp]. That said, here’s the original comparison, which I will not be updating any more.

“Eglot is considerably less code and hassle than lsp-mode.el. In most cases, there’s nothing to configure. It’s a minimalist approach focused on user experience and performance.

User-visible differences:

  • The single most visible difference is the friendly entry point M-x eglot, not M-x eglot-<language>. Also, there are no eglot-<language> extra packages.

  • There’s no “whitelisting” or “blacklisting” directories to languages. M-x eglot starts servers to handle file of a major mode inside a specific project, using Emacs’s built-in project.el library to discover projects. Then it automatically detects current and future opened files under that project and syncs with server;

  • Easy way to quit/restart a server, just middle/right click on the connection name;

  • Pretty interactive mode-line section for live tracking of server communication;

  • Automatically restarts frequently crashing servers;

  • Slow-to-start servers start asynchronously in the background;

  • Server-initiated edits are confirmed with the user;

  • Diagnostics work out-of-the-box (no flycheck.el needed);

  • Smoother/more responsive (read below).

Under the hood:

  • Message parser is much simpler.
  • Defers signature requests like textDocument/hover until server is ready.
  • Sends textDocument/didChange for groups of edits, not one per each tiny change.
  • Easier to read and maintain elisp. Yeah I know, very subjective, so judge for yourself.
  • Doesn’t require anything other than Emacs, but will automatically upgrade to work with stuff outside Emacs, like company, markdown-mode, if you happen to have these installed.
  • Has automated tests that check against actual LSP servers.”

Eglot is subject to the same [copyright assignment][copyright-assignment] policy as GNU Emacs.

Any [legally significant][legally-significant] contributions can only be merged after the author has completed their paperwork. Please ask for the request form, and we’ll send it to you.

[ada_language_server] !: https://github.com/AdaCore/ada_language_server [bash-language-server] !: https://github.com/mads-hartmann/bash-language-server [clangd] !: https://clang.llvm.org/extra/clangd.html [omnisharp] !: https://github.com/OmniSharp/omnisharp-roslyn [clojure-lsp] !: https://clojure-lsp.io [cmake-language-server] !: https://github.com/regen100/cmake-language-server [css-languageserver] !: https://github.com/hrsh7th/vscode-langservers-extracted [dart-analysis-server] !: https://github.com/dart-lang/sdk/blob/master/pkg/analysis_server/tool/lsp_spec/README.md [elixir-ls] !: https://github.com/elixir-lsp/elixir-ls [elm-language-server] !: https://github.com/elm-tooling/elm-language-server [fortls] !: https://github.com/hansec/fortran-language-server [futhark-lsp] !: https://futhark-lang.org [gopls] !: https://github.com/golang/tools/tree/master/gopls [godot] !: https://godotengine.org [html-languageserver] !: https://github.com/hrsh7th/vscode-langservers-extracted [haskell-language-server] !: https://github.com/haskell/haskell-language-server [jedi-language-server] !: https://github.com/pappasam/jedi-language-server [vscode-json-languageserver] !: https://github.com/hrsh7th/vscode-langservers-extracted [eclipse-jdt] !: https://github.com/eclipse/eclipse.jdt.ls [typescript-language-server] !: https://github.com/theia-ide/typescript-language-server [kotlin-language-server] !: https://github.com/fwcd/KotlinLanguageServer [lua-lsp] !: https://github.com/Alloyed/lua-lsp [marksman] !: https://github.com/artempyanykh/marksman [mint-ls] !: https://www.mint-lang.com/ [rnix-lsp] !: https://github.com/nix-community/rnix-lsp [ocaml-lsp] !: https://github.com/ocaml/ocaml-lsp/ [perl-language-server] !: https://github.com/richterger/Perl-LanguageServer [php-language-server] !: https://github.com/felixfbecker/php-language-server [purescript-language-server] !: https://github.com/nwolverson/purescript-language-server [pyls] !: https://github.com/palantir/python-language-server [pylsp] !: https://github.com/python-lsp/python-lsp-server [pyright] !: https://github.com/microsoft/pyright [r-languageserver] !: https://cran.r-project.org/package=languageserver [racket-langserver] !: https://github.com/jeapostrophe/racket-langserver [solargraph] !: https://github.com/castwide/solargraph [rust-analyzer] !: https://github.com/rust-analyzer/rust-analyzer [metals] !: https://scalameta.org/metals/ [digestif] !: https://github.com/astoff/digestif [texlab] !: https://github.com/latex-lsp/texlab [vim-language-server] !: https://github.com/iamcco/vim-language-server [yaml-language-server] !: https://github.com/redhat-developer/yaml-language-server [zls] !: https://github.com/zigtools/zls

[manual] !: https://elpa.gnu.org/devel/doc/eglot.html [lsp] !: https://microsoft.github.io/language-server-protocol/ [company-mode] !: https://github.com/company-mode/company-mode [ccls] !: https://github.com/MaskRay/ccls [cquery] !: https://github.com/cquery-project/cquery [docker-langserver] !: https://github.com/rcjsuen/dockerfile-language-server-nodejs [emacs-lsp-plugins] !: https://github.com/emacs-lsp [emacs-lsp] !: https://github.com/emacs-lsp/lsp-mode [erlang_ls] !: https://github.com/erlang-ls/erlang_ls [gnuelpa] !: https://elpa.gnu.org/packages/eglot.html [gnudevelelpa] !: https://elpa.gnu.org/devel/eglot.html [melpa] !: https://melpa.org/#/eglot [news] !: https://github.com/joaotavora/eglot/blob/master/NEWS.md [windows-subprocess-hang] !: https://www.gnu.org/software/emacs/manual/html_node/efaq-w32/Subprocess-hang.html [company] !: https://elpa.gnu.org/packages/company.html [flymake] !: https://www.gnu.org/software/emacs/manual/html_node/flymake/index.html#Top [xref] !: https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html [imenu] !: https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html [eldoc] !: https://github.com/emacs-mirror/emacs/blob/master/lisp/emacs-lisp/eldoc.el [yasnippet] !: https://elpa.gnu.org/packages/yasnippet.html [markdown] !: https://github.com/defunkt/markdown-mode [gospb] !: https://opensource.googleblog.com/2020/10/announcing-latest-google-open-source.html [copyright-assignment] !: https://www.fsf.org/licensing/contributor-faq [legally-significant] !: https://www.gnu.org/prep/maintain/html_node/Legally-Significant.html#Legally-Significant [dir-locals-emacs-manual] !: https://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html [configuration-request] !: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_configuration [did-change-configuration] !: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeConfiguration [json-serialize] !: https://www.gnu.org/software/emacs/manual/html_node/elisp/Parsing-JSON.html [plist] !: https://www.gnu.org/software/emacs/manual/html_node/elisp/Property-Lists.html [discussion] !: https://github.com/joaotavora/eglot/discussions [upstream-eglot.el] !: https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/eglot.el [eglot.el] !: https://github.com/joaotavora/eglot/blob/master/eglot.el [eglot-tests.el] !: https://github.com/joaotavora/eglot/blob/master/eglot-tests.el [announcement] !: https://github.com/joaotavora/eglot/discussions [compile-emacs1] !: https://lars.ingebrigtsen.no/2014/11/13/welcome-new-emacs-developers/ [compile-emacs2] !: https://batsov.com/articles/2021/12/19/building-emacs-from-source-with-pgtk/ [compile-emacs3-official] !: https://github.com/emacs-mirror/emacs/blob/master/INSTALL [emacs-bug-tracker-eglot] !: https://debbugs.gnu.org/cgi/pkgreport.cgi?include=subject%3Aeglot;package=emacs [bug-reporting] !: https://joaotavora.github.io/eglot/#Troubleshooting-Eglot [project] !: https://www.gnu.org/software/emacs/manual/html_node/emacs/Projects.html [emacs-upstream] !: https://github.com/emacs-mirror/emacs [release-notes] !: https://github.com/emacs-mirror/emacs/blob/master/etc/EGLOT-NEWS [build-status] !: https://github.com/joaotavora/eglot/actions/workflows/test.yml [eglot-x] !: https://github.com/nemethf/eglot-x