Self-hosted service
manateelazycat/lsp-bridge avatar
manateelazycat/lsp-bridge

lsp-bridge: Emacs LSP client that runs language server traffic through a Python subprocess

A blazingly fast LSP client for Emacs

1,754 stars241 forksEmacs LispGPL-3.0

At a glance

What is it?
lsp-bridge moves LSP requests and data analysis out of Emacs and into an external Python process, avoiding the GC pauses that arrive when large responses trigger garbage collection. It ships with remote SSH completion and a multi-server fusion system, but requires disabling every other completion plugin before it works.
Who is it for?
lsp-bridge suits Emacs users who face GC stalls on large LSP responses, or who need built-in SSH remote completion without patching eglot or lsp-mode separately. Anyone with an existing corfu, company, lsp-mode, or eglot setup has to tear it out before lsp-bridge works, and that replacement cost is the first thing to decide.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 36 days ago.
What is it written in?
Mainly Emacs Lisp, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • manateelazycat/lsp-bridge1,754 ★ · +2
Star history
Repository2026-10-112026-10-22
manateelazycat/lsp-bridge1.8k1.8k

2 Stars in the last 11 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

An external Python process handles LSP traffic so Emacs avoids GC stalls on large responses

Emacs is a single-threaded editor. When an LSP server returns a large completion payload, Emacs either processes it on the main thread, risking a garbage collection pause, or drops it. lsp-bridge avoids this by running all LSP communication and response analysis in a separate Python process. Emacs sends a request and keeps accepting keystrokes; the Python side returns results asynchronously.

Multi-threading lives in the Python layer, not in Emacs Lisp. Offloading to a subprocess prevents Emacs from freezing when large completion data would otherwise trigger garbage collection. That design differs from eglot, which handles LSP communication inside Emacs and shares the same GC exposure on heavy workloads.

An EmacsConf 2022 talk linked from the README covers the subprocess model in more depth than the README itself. That talk is the primary technical explanation of how the architecture works.

Eight pip packages with version floors, Python 3.13 only for the uv path, and an orjson contradiction

The Python layer needs eight packages. Install them with:

bash
pip3 install epc orjson sexpdata six setuptools paramiko rapidfuzz watchdog packaging

The README calls orjson optional, noting it provides faster JSON parsing performance because it is written in Rust. That description is not consistent with pyproject.toml, which lists orjson as a required dependency at version 3.10.18 or higher alongside paramiko 3.5.1 or higher, epc 0.0.5 or higher, and six 1.17.0 or higher. Anyone who installs via the uv-based python-lsp-bridge wrapper will always receive orjson; the optionality applies only to the manual pip3 route.

The pyproject.toml also specifies `requires-python = ">=3.13,<3.14"`, restricting the wrapper path to exactly Python 3.13. The pip3 manual path is not bound by that file. Verify your Python minor version before setting up the uv wrapper; any version outside the >=3.13,<3.14 range will be rejected by pyproject.toml.

The python-lsp-bridge wrapper lives at the repository root. Create a symbolic link to it in a directory on your PATH; copying the file is explicitly warned against in the README.

straight.el and doom-emacs configs need :build (:not compile) to stay in sync with the Python layer

Byte-compiling or native-compiling lsp-bridge produces an Elisp API snapshot that diverges from the Python side after any upgrade. Compilation is not just unnecessary: it creates a mismatch that breaks completion silently or visibly depending on what changed. For straight.el users, the configuration that prevents this is:

elisp
(use-package lsp-bridge
  :straight '(lsp-bridge :type git :host github :repo "manateelazycat/lsp-bridge"
            :files (:defaults "*.el" "*.py" "acm" "core" "langserver" "multiserver" "resources")
            :build (:not compile))
  :init
  (global-lsp-bridge-mode))

Doom-emacs users add the same `:build (:not compile)` flag in packages.el along with markdown-mode and yasnippet as separate package declarations, then run `doom sync`. Both installation paths rely on that flag to skip compilation.

For a plain git clone without a package manager, load the package by adding the clone directory to `load-path`, requiring yasnippet and activating `yas-global-mode 1`, then requiring lsp-bridge and calling `global-lsp-bridge-mode`.

Root detection climbs to .git or .dir-locals.el; without either, completion covers only the open file

lsp-bridge determines completion scope at startup by scanning upward from the open file. Finding a .git or .dir-locals.el directory triggers project-wide completion across the entire tree. Without either marker, completion narrows to the single open file only.

For monorepos or projects that use neither marker, the `lsp-bridge-get-project-path-by-filepath` function provides a third path. Implement that function in your init file to accept a file path string and return the desired project root. No other root-detection override is documented.

Completion also extends into org-mode source blocks. That coverage matters for literate programming workflows where a plain LSP client typically stops working at block boundaries.

Multi-server fusion: Pyright and Ruff for Python through one JSON configuration

A single language can draw from multiple LSP servers simultaneously. For Python, a single JSON configuration can route completion requests to Pyright and formatting or diagnostic requests to Ruff, both active in the same buffer. Expressing that arrangement requires only a JSON file rather than separate mode hooks or adapter code.

Beyond LSP, lsp-bridge includes backends for capf, file words, file paths, Yas/Tempel snippets, TabNine, Codeium, Copilot, Tabby, Citre, Ctags, and Org Roam. These appear alongside LSP results in the completion popup. Adding a backend to a specific mode requires listing that mode in `lsp-bridge-default-mode-hooks`. Ordering of backends in the popup is controlled through `acm-backend-order`.

Per-project overrides require only a few additional lines in the project-level JSON file. That keeps language server customization outside the Emacs init file, which can reduce init complexity for teams with many projects.

SSH remote completion includes tramp, jump servers, and Docker, where eglot and lsp-mode require extra configuration

Remote completion is where lsp-bridge's built-in scope differs most from eglot and lsp-mode. Both of those handle LSP communication locally; remote support requires external configuration or plugins. lsp-bridge ships remote SSH support including password and public key auth, the Emacs tramp protocol, jump servers, and Docker containers, placing it closer to VSCode's remote development capability without additional extensions.

For developers who edit files on a remote machine from a local Emacs instance, that built-in coverage removes a setup step. The paramiko dependency at version 3.5.1 or higher is what handles the SSH transport in the Python layer. The remote usage section in the README is truncated and provides no configuration example for tramp or Docker; those details are in the extended documentation outside the README.

Replacing an existing completion stack requires full removal of every competing plugin

lsp-bridge replaces the entire completion stack: backend, frontend, and multi-backend integration. Running lsp-mode, eglot, company, or corfu alongside it causes conflicts. Disabling those is a prerequisite, not a preference. For users with years of configuration in those tools, that trade-off is the real cost of switching.

No compatibility layer or gradual migration path is documented. Either lsp-bridge owns the completion stack, or it does not run properly.

No GitHub releases exist; updates come from the master branch, which was last pushed on 2026-09-17. Each pull from master requires restarting Emacs to keep the Elisp and Python layers in sync, with no tagged version available to pin.

Editorial conclusion

lsp-bridge suits Emacs users who face GC stalls on large LSP responses, or who need built-in SSH remote completion without patching eglot or lsp-mode separately. Anyone with an existing corfu, company, lsp-mode, or eglot setup has to tear it out before lsp-bridge works, and that replacement cost is the first thing to decide. Python 3.13 is the only supported minor version for the pyproject.toml install path, so check your Python version before committing. orjson is listed as optional in the README but required in pyproject.toml at version 3.10.18 or higher, so expect it regardless of which install route you take.

Frequently asked questions

What is lsp-bridge for Emacs?

lsp-bridge is an LSP client for Emacs that offloads language server communication to an external Python process, preventing Emacs garbage collection from blocking the editor on large responses. It also includes built-in remote SSH completion and a multi-server fusion system.

How do I install lsp-bridge?

Install Emacs 28 or higher, install the Python dependencies with pip3, clone the repository, and add the load-path configuration to your Emacs init file. straight.el and doom-emacs paths are documented in the README with recipe configurations that include :build (:not compile).

Can lsp-bridge run alongside lsp-mode or eglot?

No. Disabling lsp-mode, eglot, company, corfu, and similar plugins is a prerequisite. lsp-bridge provides its own backend, frontend, and integration layer, and running competing plugins causes conflicts.

Does lsp-bridge support remote development over SSH?

Yes. Built-in support covers SSH connections with passwords or public keys, the Emacs tramp protocol, jump servers, and Docker containers. Remote mode is separate from local usage and relies on the paramiko package for SSH transport.

Why must I avoid byte-compiling lsp-bridge?

Byte-compiling or native-compiling lsp-bridge produces an Elisp API snapshot that diverges from the Python side after any upgrade, breaking completion. The multi-threading design does not require compilation to run efficiently.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. manateelazycat/lsp-bridge on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/manateelazycat-lsp-bridge.svg)](https://hysenlabs.com/projects/manateelazycat-lsp-bridge)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/manateelazycat-lsp-bridge.svg)](https://hysenlabs.com/projects/manateelazycat-lsp-bridge)