Skip to content

refactor(lsp): default project toolchains off - #51

Merged
potsrevennil merged 3 commits into
masterfrom
refactor/project-scoped-toolchains
Oct 20, 2026
Merged

potsrevennil merged 3 commits into
masterfrom
refactor/project-scoped-toolchains

Conversation

@potsrevennil

@potsrevennil potsrevennil commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

packages.default installed every language toolchain globally (python, clang, rustup, go + gopls + golangci-lint), and kapi-sysconf additionally turned on haskell and lean. Those tools have to match each project's own compiler, runtime and CI: HLS ↔ GHC, gopls ↔ go, black/clang-format ↔ the versions CI checks with. So a global copy is often the wrong version, and it only gets used when no project shell is active. It is also expensive: nixpkgs' HLS alone is a ~9 GiB closure that every nixpkgs bump re-downloads.

Project toolchains (python, c, rust, go, haskell, lean) now default to off. Editor-wide tooling (config, shell, typst, js/nodejs) stays on. Projects provide their server, formatter and linter from their flake devShell, and direnv puts them first on PATH. The Lua config only names tools, so it picks up whichever binary that is, and it now stays quiet when one is missing:

  • Servers: Neovim 0.12's can_start skips a config whose cmd isn't executable. It writes a line to lsp.log and shows no notification.

  • Formatters: no change needed. conform skips unavailable formatters, and since codespell (formatters_by_ft["*"]) is always available it never reaches its "Formatters unavailable" warning.

  • Linters: none-ls golangci_lint is gated on a runtime_condition, so it is skipped instead of throwing "command golangci-lint is not executable".

  • Look at: lua/plugins/none-ls.lua. The runtime_condition is checked on every run, so it also works if PATH changes mid-session (e.g. direnv.vim).

  • Verify: nix build .#default no longer pulls in go, gopls, golangci-lint, python, clang-tools or rustup. packages.lite and packages.bundle set every toggle explicitly, so CI's KAPI_VIM_LANGS=shell,go bundle still tests go.

  • Re-enable on a machine without project flakes: kapi-vim.override { enable_go = true; }, or KAPI_VIM_LANGS=go nix run --impure .#bundle.

  • Docs: README has a new "Language toolchains" section.

  • Out of scope: a CI fixture that exercises project-provided tools, which we decided wasn't worth the runtime.

🤖 Generated with Claude Code

potsrevennil and others added 3 commits October 20, 2026 14:07
Split the language toggles into editor-wide tooling (config, shell,
typst: on) and project toolchains (python, c, rust, go, js, haskell,
lean: off). A project's language server has to match its own compiler
or runtime, so it comes from the project's flake devShell via direnv;
lua/plugins/lsp.lua only names the servers and picks up whatever is
first on PATH. Installing them globally was mostly redundant, and some
(HLS) carry multi-GiB closures that every nixpkgs bump re-downloads.

Neovim skips a server whose cmd is not executable (logged to lsp.log,
no notification), so opening such a file outside a project shell just
runs without that LSP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow-up to defaulting project toolchains off: those toggles also
carry the per-language formatters and linters, which now come from the
project's devShell too. Make the config treat them like servers:

- conform: notify_no_formatters = false, so a .go/.py/.c buffer outside
  a project shell doesn't warn about goimports/black/clang-format.
- none-ls: gate golangci_lint on a runtime_condition, so it is skipped
  instead of erroring on spawn when golangci-lint isn't on PATH.
- js back on by default: it is just nodejs, which commitlint already
  pulls into the closure, so turning it off saved nothing.
- Fix comments still calling packages.default the every-language build,
  and document `.override { enable_<lang> = true; }` for re-enabling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop notify_no_formatters = false: it was never needed. Every buffer
also gets codespell (formatters_by_ft["*"]), which is always installed,
and conform only warns when none of a buffer's formatters are available.
A missing goimports/black/clang-format is skipped quietly, and the
warning stays for genuinely broken setups (e.g. editor-wide formatters
missing).

README: explain that per-language toolchains come from the project's
devShell via direnv, and how to turn them on without project flakes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@potsrevennil
potsrevennil marked this pull request as ready for review October 20, 2026 06:51
@potsrevennil
potsrevennil merged commit 29896bf into master Oct 20, 2026
5 checks passed
@potsrevennil
potsrevennil deleted the refactor/project-scoped-toolchains branch October 20, 2026 06:52
potsrevennil added a commit that referenced this pull request Oct 20, 2026
Regenerated with `:Lazy! sync` on top of master (#47, #51 merged).
Same 44-entry plugin set; 13 pins bumped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant