A maintained fork of ~detegr/bqnlsp (upstream has been quiet since May 2026). This fork turns the language server from "diagnostics only" into a real analysis tool: interprocedural shape/type inference, semantic tokens, a Zed extension, and a deterministic CLI report you can gate CI on.
+----------------- bqnlsp knows ------------------+
| ∘ 3‿2⍴1 2 3 → shape 3‿2, atom cells |
your .bqn → | ∘ Scan/Rank/Valences/Catch/Repeat → shapes | → hover, outline,
| ∘ arithmetic checks element types | semantic tokens,
+--------------------------------------------------+ diagnostics
| Area | What you get |
|---|---|
| Static analysis | Interprocedural shape & type inference (lsp/src/infer.rs, shape.rs): inferred shapes for Scan, Rank, Valences, Catch, Repeat; element-type checks in arithmetic; primitive coverage 40/44 monadic, 42/44 dyadic modifiers 8/9 and 8/11 |
| Hover | Inferred types rendered in BQN notation — including inside block bodies |
| Editor | Zed extension (editors/zed/): outline, hover types, rename, references, semantic tokens over tree-sitter-bqn |
| LSP plumbing | Semantic tokens; nested document outline with deduped definitions; did_change debounced; document analysis moved off the reactor thread; a DashMap guard no longer held across awaits; block-internal errors reported once |
| CLI | check / symbols / probe one-shot modes with real exit codes (drop into pre-commit/CI); --check JSON report with a stable schema; --no-trace stable subset |
| Testing | Golden-file corpus (lsp/tests/cases/*.bqn + .expected.json) validated against CBQN as ground truth |
Everything below this line is also true of upstream; build and usage docs kept from the original project.
- Zed: install the extension from
editors/zed/— see editors/zed/README.md. - Neovim / VS Code: rough templates live in
editors/.
Besides serving LSP over stdio, the binary has one-shot modes for checking and debugging:
bqnlsp # speak LSP on stdin/stdout (what editors run)
bqnlsp check FILE... # text summary of a program's diagnostics
bqnlsp check --json FILE # the machine-readable report
bqnlsp check - # read the program from stdin
bqnlsp symbols FILE # the document outline
bqnlsp probe FILE # bytecode dump
bqnlsp --help
check exits 0 when nothing is wrong, 1 when a file fails to compile or has
diagnostics, and 2 for bad arguments or an unreadable file, so it drops straight
into a pre-commit hook or CI step. Diagnostics read as file: line:col: message.
--check compiles the program and reports what the static analysis infers, as
{compile_ok, diagnostics, constraints, signatures} plus a per-instruction
trace unless --no-trace is given. It exits 0 even when the program fails to
compile, so callers should read the JSON rather than the exit status; exit 2
means the arguments were bad or the file was unreadable. --no-trace yields the
stable subset, which is what the golden-file tests under lsp/tests/ compare.
Nix is the preferred way to build the project. Install the Nix package manager and run:
nix --extra-experimental-features nix-command --extra-experimental-features flakes build 'sourcehut:~detegr/bqnlsp'
After the build, there will be a symlink to the Nix store called result which
will contain the binary in result/bin/bqnlsp.
- Update submodules of this repository with
git submodule update --init --recursive. - Clone CBQN and build it with
make shared-o3. - Run
build.bqn /path/to/CBQNfor automated build of the project where/path/to/CBQNcontains the prebuilt CBQN shared object.
- Update submodules of this repository with
git submodule update --init --recursive. - Clone CBQN and build it with
make shared-o3. - Set following environment variables:
RUSTFLAGS="-L /path/to/CBQN"LD_LIBRARY_PATH="/path/to/CBQN"(useDYLD_LIBRARY_PATHon MacOS)
- Generate help files with:
cargo run --release --bin genhelp ./BQN ./lsp/src/help - Build bqnlsp with:
cargo build --release --bin bqnlsp
When installing the bqnlsp binary, distribute the CBQN shared object to the
same directory and it'll load without messing with LD_LIBRARY_PATH.
The help-generation step is not optional: lsp/src/help/mod.rs embeds those
files with include_str!, and they are not committed, so a fresh checkout
cannot build until genhelp has produced them.
The cbqn dependency is selected by feature:
native(default) links a CBQN shared object (libcbqn.so/.dylib/cbqn.dll), which requires a C toolchain and a CBQN built withmake shared-o3.wasiruns CBQN compiled to WebAssembly through wasmer, so no C toolchain orlibcbqnis needed. It embedslsp/BQN.wasmat compile time, soBQN_WASMmust point at that file when building with--features wasi.
Run the test corpus against a CBQN shared object:
LD_LIBRARY_PATH=/path/to/CBQN cargo test -p bqnlsp
The tests spawn the built binary, and it links libcbqn when it is loaded. If
no CBQN is reachable the corpus reports that it is skipping rather than failing.
PLAN.md tracks the analysis milestones; AGENTS.md documents the build
recipe and harness constraints.
genhelp— helper that walks the BQN help files, runs the BQN code in them and places the evaluated expression results into the files.lsp— the language server implementation.editors— a Zed extension and rough templates for nvim-lspconfig and vscode.
Original project by Antti Keränen (~detegr);
this fork starts at upstream commit Update BQN submodule (2026-05-31) and is
GPL-3 like the original. The fork exists because upstream is quiet and the
analysis work didn't fit in issue reports — see git log for the 37 commits of
divergence, all documented.