go-lsp-bridge relays JSON-RPC Language Server Protocol traffic between a
WebSocket and a language-server subprocess's stdio. It owns the
Content-Length framing on the stdio side so each WS text frame carries one bare JSON
object — exactly what browser LSP clients like codemirror-languageserver and
@open-rpc/codemirror-lsp expect. A web editor gets real completions, hovers,
diagnostics and go-to-definition from an actual server (texlab, gopls, pyright,
typescript-language-server, rust-analyzer, …) behind a single HTTP handler — pure Go, no cgo,
with per-connection subprocesses and both global and per-user concurrency caps.
server → client : one JSON-RPC object per WS text frame
client → server : one JSON-RPC object per WS text frame
Transport framing bridge ready
Relays JSON-RPC untouched between a WebSocket and a language server’s stdio, adding + stripping the Content-Length framing so each WS text frame carries one bare JSON object — exactly what codemirror-languageserver / @open-rpc/codemirror-lsp expect.
Per-connection subprocesses ready
Every WebSocket spawns its own language server (exec.CommandContext) and kills it on close. A missing binary or a failed spawn is reported back as a JSON-RPC error frame, so the editor surfaces one visible failure instead of silently dropping completions.
Configurable server registry ready
DefaultServers() ships launchers for latex / go / python / typescript / javascript / rust, each overridable per-deployment via a neutral LSPBRIDGE_* env var. The registry is a plain map — bring your own, or extend the defaults in place; adding a language is one line.
Concurrency caps ready
Two layers keep the host safe: a process-wide ceiling so it can’t be saturated, and a per-subject ceiling (WithSubject) so one runaway editor with a reconnect loop can’t starve everyone else. The per-user counter keys by authenticated identity, not raw token.
Coverage & six arches ready
A hermetic WS → subprocess → WS round-trip against a bundled fake-lsp stub, plus unit tests for every framing / registry / concurrency / error branch — 100% coverage, gofmt + go vet clean, green across all six 64-bit Go arches (exec/WS tests gated off the qemu lanes).
Server pooling & metrics planned
Future work: optional warm-subprocess pooling to amortise language-server startup, and Prometheus-style counters for spawns, rejections and frame throughput. Not required for the core bridge, which stays dependency-light.
- ready capability complete (exit criteria met, nothing material left)
- active in progress (substantial work shipped, not yet finished)
- planned not started yet (or downstream by design)
A bridge, not a client: it transports JSON-RPC untouched, translating only the
transport framing (WebSocket text frames ↔ stdio Content-Length). The launcher registry
is a plain map with neutral LSPBRIDGE_* environment overrides — no host-application
naming baked in — so it is reusable by any Go program. Validated by a hermetic
WS→subprocess→WS round-trip against a bundled stub, at 100% coverage across
github.com/go-lsp-bridge.