lsp-proxy

command module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 22, 2026 License: MIT Imports: 14 Imported by: 0

README

lsp-proxy

Proof of Concept — exploratory project, not production-ready.

A transparent stdio proxy for Language Server Protocol (LSP) servers. Sits between an editor and any stdio-based language server, forwarding JSON-RPC messages in both directions and allowing them to be inspected and modified in transit.

Currently supports saving and enriching hover documentation (markdown) per symbol, then injecting the modified content back into hover responses.

Table of contents

Screenshots

Go

Go hover

Go hover

Rust

Rust hover

Rust hover

How it works

Transparent proxy — forwards all messages unchanged:

┌────────┐              ┌───────────┐              ┌────────────┐
│ Editor │─ requests ──►│ lsp-proxy │─ requests ──►│ LSP server │
│        │◄─ responses ─│           │◄─ responses ─│            │
└────────┘              └───────────┘              └────────────┘

With hover documentation (-save-md / -read-md) — intercepts hover responses, saves the markdown to a file, and optionally injects your edited version on the next hover:

┌────────┐              ┌───────────┐              ┌────────────┐
│ Editor │─ requests ──►│ lsp-proxy │─ requests ──►│ LSP server │
│        │◄─ responses ─│           │◄─ responses ─│            │
└────────┘              └─────┬─────┘              └────────────┘
                              │ reads / writes
                         ┌────▼──────┐
                         │  *.md     │
                         └───────────┘

Getting the binary

Download a pre-built release

Pre-built binaries for all platforms are attached to each release on Codeberg.

Download the binary for your platform:

Platform File
macOS (Apple Silicon) lsp-proxy-darwin-arm64
macOS (Intel) lsp-proxy-darwin-amd64
Linux (arm64) lsp-proxy-linux-arm64
Linux (amd64) lsp-proxy-linux-amd64
Windows (amd64) lsp-proxy-windows-amd64.exe

Make it executable on macOS / Linux:

chmod +x lsp-proxy-darwin-arm64
Install with Go

If you have Go installed, you can install directly without cloning the repo:

go install codeberg.org/poctastic/lsp-proxy@latest

The binary is placed in $GOPATH/bin (usually ~/go/bin). Make sure that directory is on your $PATH.

Usage

# macOS / Linux
./lsp-proxy -lsp-path <path-to-lsp-server> [flags]

# Windows
.\lsp-proxy.exe -lsp-path <path-to-lsp-server> [flags]
Flags
Flag Required Description
-lsp-path yes Path to the upstream LSP server binary
-save-md no Save hover markdown per symbol to -md-path (only on first encounter)
-read-md no Read back markdown from -md-path and inject into hover responses
-md-path when -save-md or -read-md Directory where hover markdown files are saved/read
Examples

Transparent pass-through (no modification):

macOS / Linux:

./lsp-proxy -lsp-path /usr/local/bin/gopls

Windows:

.\lsp-proxy.exe -lsp-path C:\path\to\gopls.exe

Save hover docs as markdown files:

macOS / Linux:

./lsp-proxy -lsp-path /usr/local/bin/gopls \
  -save-md \
  -md-path ./docs/

Windows:

.\lsp-proxy.exe -lsp-path C:\path\to\gopls.exe `
  -save-md `
  -md-path .\docs\

Save and inject modified docs:

macOS / Linux:

./lsp-proxy -lsp-path /usr/local/bin/gopls \
  -save-md \
  -read-md \
  -md-path ./docs/

Windows:

.\lsp-proxy.exe -lsp-path C:\path\to\gopls.exe `
  -save-md `
  -read-md `
  -md-path .\docs\

Markdown files are named {hash}_{symbol}.md (e.g. a3f1c2d0_Atoi.md). Each file includes an Edit here link at the bottom — click it to open the file directly. Edit it freely; on the next hover, your version is returned to the editor instead of the server's original response.

Zed configuration

Point Zed's LSP binary at the proxy and pass the real server as -lsp-path.

1. Open the Zed settings file directly:

Platform Path
macOS ~/.config/zed/settings.json
Linux ~/.config/zed/settings.json
Windows %APPDATA%\Zed\settings.json

Or open it from inside Zed: cmd-shift-p (macOS / Linux) / ctrl-shift-p (Windows) → zed: open settings.

2. Add an lsp block (or extend the existing one) with the languages you want to proxy:

{
  "lsp": {
    "gopls": {
      "binary": {
        "path": "/path/to/lsp-proxy",
        "arguments": [
          "-lsp-path", "/path/to/gopls",
          "-save-md",
          "-read-md",
          "-md-path", "/path/to/markdown/dir/"
        ]
      }
    },
    "rust-analyzer": {
      "binary": {
        "path": "/path/to/lsp-proxy",
        "arguments": [
          "-lsp-path", "/path/to/rust-analyzer",
          "-save-md",
          "-read-md",
          "-md-path", "/path/to/markdown/dir/"
        ]
      }
    }
  }
}

3. Fill in the paths:

Placeholder macOS Linux Windows
/path/to/lsp-proxy ./lsp-proxy ./lsp-proxy .\lsp-proxy.exe
/path/to/gopls ~/Library/Application Support/Zed/languages/gopls/gopls_<version> ~/.local/share/zed/languages/gopls/gopls_<version> %APPDATA%\Zed\languages\gopls\gopls_<version>.exe
/path/to/rust-analyzer ~/Library/Application Support/Zed/languages/rust-analyzer/rust-analyzer-<date> ~/.local/share/zed/languages/rust-analyzer/rust-analyzer-<date> %APPDATA%\Zed\languages\rust-analyzer\rust-analyzer-<date>.exe
/path/to/markdown/dir/ any writable directory any writable directory any writable directory

4. Restart the language server for the changes to take effect — no need to restart Zed.

Open a code file, then open the command palette (cmd-shift-p / ctrl-shift-p) and run editor: restart language server.

The proxy works with any editor that launches an LSP server over stdio — the Zed configuration above is the reference setup.

Inspecting LSP logs in Zed

Zed exposes the full JSON-RPC traffic between the editor and the language server (i.e. the proxy in this case).

Open a code file, then open the command palette (cmd-shift-p / ctrl-shift-p) and run dev: open language server logs.

A panel opens showing:

  • Logs tab — stderr output from the language server (and the proxy, since the proxy forwards the server's stderr directly).
  • RPC Messages tab — the raw JSON-RPC messages exchanged between Zed and the proxy, useful for verifying that messages are being forwarded and modified correctly.

This is the primary tool for debugging when something isn't working — check the RPC messages tab to confirm the proxy is running (you'll see initialize / initialized) and the logs tab for any errors the proxy or the server emits.

Development

Requirements
  • Go 1.26.2+
  • Make
Build
make build         # build for host platform → bin/lsp-proxy
make build-all     # cross-compile for macOS / Linux / Windows
Testing without an editor

During development you can drive the proxy directly from the terminal using a shell function that prepends the Content-Length header to a JSON-RPC message (mimicking what an editor sends):

lsp_frame() {
    local msg="$1"
    printf "Content-Length: %d\r\n\r\n%s" "${#msg}" "$msg"
}

Then pipe a sequence of LSP messages into the proxy:

{
    lsp_frame '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":null,"rootUri":null,"capabilities":{}}}'
    sleep 0.5
    lsp_frame '{"jsonrpc":"2.0","method":"initialized","params":{}}'
    sleep 0.2
    lsp_frame '{"jsonrpc":"2.0","id":"2x","method":"shutdown"}'
    sleep 0.2
    lsp_frame '{"jsonrpc":"2.0","method":"exit"}'
} | go run . -lsp-path "/path/to/lsp-server" -save-md -read-md -md-path "./debug/"

The sleep calls give the language server time to process each message before the next one arrives. The proxy's responses are written to stdout, so you'll see the full JSON-RPC exchange in the terminal.

Replace go run . with ./bin/lsp-proxy if you've already built the binary.

Other targets
make vet           # run go vet
make test          # run tests
make run           # build and run (requires -lsp-path set via environment)
make help          # list all targets

License

MIT

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL