Skip to content

Extras

Extras are how Blak says “yes” to language support, optional tools, and personal preference — without bloating core for everyone.

All extras live under lua/blak/extras/, registered in lua/blak/extras/init.lua.

An extra is a single Lua module that can contribute any of:

  • Treesitter parsers (ensure_installed)
  • Mason tools (mason.ensure_installed)
  • LSP servers via vim.lsp.config()
  • Formatters and linters by filetype
  • Snacks module options
  • Keymaps (auto-shown in :BlakKeys)
  • Plugin specs for lazy.nvim

When you disable an extra and restart, Blak stops registering that extra’s plugin specs, keymaps, tools, parsers, and config contributions. Run :BlakExtras sync afterward to let lazy.nvim clean up removed plugins.

:BlakExtras " open the extras UI
:BlakExtras list " same UI, explicit
:BlackExtras list " same command, typo-friendly
:BlakExtras enable lang.rust
:BlakExtras disable git.lazygit
:BlakExtras sync " install missing plugins, remove unused ones

The UI groups enabled extras and available extras, shows the tools and plugins each one contributes, and lets you toggle the row under the cursor with x or <CR>. Press s to run :BlakExtras sync, r to refresh, and q to close. Extras from lua/blak/user.lua are marked [config]; remove them there when you want the UI to stop treating them as enabled.

An extra’s description and tool lines select the same extra. Headings and blank lines do nothing. The floating menu fits the current terminal and adjusts when you resize it.

State persists outside the repo in stdpath('state')/blak/extras.json. That means:

  • A fresh clone with the same NVIM_APPNAME reuses the same enabled extras.
  • A fresh install under a new NVIM_APPNAME starts from your config defaults.
  • Multiple checkouts (blak, blak-dev) can have different enabled sets.
  • user.lua and extras.json compose: anything in extras.enabled in user.lua is added on top of the state file.

If an extra was renamed or removed, :BlakDoctor reports it as unknown. Run :BlakExtras disable <id> to remove that stale state entry.

After enabling an extra:

  1. Blak applies its config to the current session.
  2. Run :BlakExtras sync if plugins were added. It installs missing plugins at the commits Blak ships pins for and removes unused ones, but never updates installed plugins; :Lazy sync would also update every plugin past its pin. Newly installed plugins load in the current session; no restart is needed.
  3. Run :BlakToolsInstall to install any new Mason tools required.
  4. Run :BlakDoctor to check reported dependencies, then exercise the feature.

After disabling an extra, the state file updates immediately. Run :restart when you want already-loaded plugins, keymaps, and runtime hooks to disappear from the current session, then run :BlakExtras sync if plugin specs were removed.

Each supported extra has a dedicated page with its user.lua enable snippet, configuration examples, install notes, and verification path.

Group Extras
Languages lang.lua, lang.typescript, lang.typescript-legacy, lang.typescript-tsgo, lang.python, lang.python-pro, lang.rust, lang.go, lang.markdown, lang.c, lang.bash, lang.web, lang.tailwind, lang.docker, lang.yaml, lang.json, lang.terraform, lang.nix, lang.zig
Debug debug.dap
Test test.neotest
UI ui.animations, ui.base46, ui.comfy-line-numbers, ui.dim, ui.image-preview, ui.indent, ui.lualine, ui.zen
Git git.lazygit, git.diffview, git.gitbrowse, git.neogit
AI ai.claudecode, ai.copilot, ai.sidekick
Editor editor.aerial, editor.emmet, editor.flash, editor.grug-far, editor.scratch, editor.harpoon, editor.mini, editor.overseer, editor.refactoring, editor.render-markdown, editor.todo-comments, editor.trouble, editor.window-navigation, editor.neotree, editor.snacks-explorer, editor.snacks-terminal, editor.telescope, editor.fzf-lua

Lua development — what Blak itself is written in.

Adds Value
Treesitter lua, luadoc
Mason stylua
LSP lua_ls
Format stylua for .lua

TypeScript and JavaScript with the native TypeScript 7 tsc LSP, ESLint, and Prettier.

Adds Value
Treesitter javascript, typescript, tsx, jsdoc, json
Mason prettier, prettierd
LSP tsc, eslint
Format prettierd (fallback prettier) for js/ts/jsx/tsx/json
Lint ESLint diagnostics come from the eslint language server

Run :BlakToolsInstall, wait, and restart after upgrading. Explicit lsp.servers.ts_ls entries remain; remove them to use only the native server.

The optional ts_ls stack with compatible workspace SDK resolution and Mason fallback. It has the same parsers, formatters, and ESLint integration as the standard extra. Use it for projects that need the older server or its plugins.

Disable lang.typescript and its beta alias when selecting legacy TypeScript. If both stacks are enabled, native replaces only unchanged defaults contributed by legacy, regardless of activation order. Explicit user servers and formatter settings remain in effect. Restart after switching.

Compatibility alias for lang.typescript. Existing saved IDs keep working and lsp.servers.tsgo settings are carried into tsc, with explicit tsc settings winning. Enabling the alias and standard extra applies the stack once. Use lang.typescript in new configurations.

Python with Pyright + Ruff + Black + isort.

Adds Value
Treesitter python
Mason black, isort, ruff
LSP pyright, ruff
Format isort, then black
Lint Ruff language server diagnostics
With debug.dap debugpy through nvim-dap-python
With test.neotest neotest-python

Python with BasedPyright, Ruff-first formatting, and venv selection.

Enable this instead of lang.python when you want the richer Python stack.

Adds Value
Treesitter python, requirements
Mason ruff
LSP basedpyright, ruff
Format ruff_organize_imports, then ruff_format
Plugins venv-selector.nvim
Keys <leader>cv for :VenvSelect
With debug.dap, test.neotest Same adapters as lang.python

Rust with rust-analyzer and TOML support.

Adds Value
Treesitter rust, toml
LSP rust_analyzer (with cargo.allFeatures + Clippy), taplo
Format rustfmt (LSP fallback), taplo (LSP fallback)
Plugins saecki/crates.nvim (in-process LSP in Cargo.toml: hover, code actions, completion)
With debug.dap CodeLLDB (Mason codelldb), cargo build launch config

Go with gopls and golangci-lint.

Adds Value
Treesitter go, gomod, gosum, gowork
Mason goimports, gofumpt, golangci-lint
LSP gopls
Format goimports, gofumpt
Lint golangcilint
With debug.dap Delve (Mason delve) adapter and launch configs
With test.neotest neotest-golang, debugging through Delve

Markdown with Marksman LSP and Prettier.

Adds Value
Treesitter markdown, markdown_inline
Mason prettier, prettierd, markdownlint
LSP marksman
Format prettierd (fallback prettier) for markdown
Lint markdownlint

C and C++ with clangd and clang-format.

Adds Value
Treesitter c, cpp
Mason clang-format
LSP clangd
Format clang_format for c, cpp, objc, objcpp, cuda

Shell scripting with the bash language server and shellcheck. Shell formatting with shfmt already ships in Blak core.

Adds Value
Treesitter bash
Mason shellcheck
LSP bashls (runs shellcheck)

Frontend HTML, CSS, Tailwind, and Emmet with Prettier.

Adds Value
Treesitter html, css, scss
Mason prettier, prettierd
LSP html, cssls, tailwindcss, emmet_language_server
Format prettierd (fallback prettier) for html, css, scss, less

tailwindcss uses the same server config as lang.tailwind, so it attaches only in Tailwind projects.

Standalone Tailwind CSS language server: class completion, hovers, and lint without the rest of the web stack. Already included in lang.web, which shares this server config.

Adds Value
LSP tailwindcss with classAttributes and classFunctions tuned for React and class-variance helpers
Root attaches only in Tailwind projects (project detection)

Dockerfile and Docker Compose with hadolint linting.

Adds Value
Treesitter dockerfile
Mason hadolint
LSP dockerls, docker_compose_language_service
Lint hadolint for dockerfile
Filetype registers yaml.docker-compose for Compose files

YAML with yaml-language-server, SchemaStore schemas, and Prettier.

Adds Value
Treesitter yaml
Mason prettier, prettierd
LSP yamlls with SchemaStore schemas
Format prettierd (fallback prettier) for yaml
Plugin b0o/SchemaStore.nvim

JSON with jsonls, SchemaStore schemas, and Prettier.

Adds Value
Treesitter json (also highlights JSONC)
Mason prettier, prettierd
LSP jsonls with SchemaStore schemas
Format prettierd (fallback prettier) for json, jsonc
Plugin b0o/SchemaStore.nvim

Terraform and HCL with terraform-ls, terraform fmt, and tflint.

Adds Value
Treesitter terraform, hcl
LSP terraformls, tflint (runs as a language server)
Format terraform_fmt for terraform, terraform-vars (needs the terraform CLI)

Nix with the nil language server and nixfmt.

Adds Value
Treesitter nix
LSP nil_ls
Format nixfmt for nix

Install nixfmt with Nix (nix profile install nixpkgs#nixfmt); Mason only ships it for Linux x64. Formatting skips nixfmt until it is on $PATH.

Zig with the zls language server (formatting via built-in zig fmt).

Adds Value
Treesitter zig
LSP zls

Smooth scrolling via Snacks.

Adds Value
Snacks scroll.enabled = true

duxlabs-dev/base46 (formerly AvengeMedia/base46), the NvChad Base46 colorscheme collection as Neovim colorschemes.

Adds Value
Plugin duxlabs-dev/base46

Enable the extra, sync plugins, then set ui.colorscheme to a Base46 scheme such as base46-gruvchad.

mluders/comfy-line-numbers.nvim shows relative line labels using left-hand digits and maps those labels back to vertical motions.

Adds Value
Plugin mluders/comfy-line-numbers.nvim
Keymap label + j or k motions
Keymap label + <Down> or <Up> motions

Enable the extra, sync plugins, then use the displayed labels with j, k, <Down>, or <Up>. For example, 11j and 11<Down> both move to the line whose comfy label is 11.

Snacks dim highlights the active scope by dimming the surrounding lines.

Adds Value
Snacks dim.enabled = true

Snacks already ships in core, so this extra enables the dim module without adding a plugin spec.

Image previews in pickers and floats — works in Kitty, WezTerm, and Ghostty.

Adds Value
Snacks image.enabled = true

Indent guides with animated active-scope highlighting via Snacks. Core ships the module disabled; this extra flips it on.

Adds Value
Snacks indent.enabled = true
Keymap <leader>ug → toggle indent guides

lualine.nvim as an opt-in statusline.

Adds Value
Plugin nvim-lualine/lualine.nvim
Deps mini.icons
Config global statusline, Blak theme auto-detection, ASCII separators

This extra turns off native showmode while lualine is enabled because the statusline already displays the current mode. Disable the extra, restart Blak, then run :BlakExtras sync to remove the plugin spec.

Distraction-free editing mode.

Adds Value
Snacks zen.enabled = true
Keymap <leader>uz → toggle zen

nvim-dap and nvim-dap-ui for Debug Adapter Protocol workflows.

Adds Value
Plugins mfussenegger/nvim-dap, rcarriga/nvim-dap-ui
Deps nvim-nio
Keymaps <leader>d* debug actions

lang.go, lang.python, lang.python-pro, and lang.rust add their debug adapters and launch configurations when enabled alongside it. Other languages go in the nvim-dap spec’s opts.adapters and opts.configurations.

neotest as a base test runner framework.

Adds Value
Plugin nvim-neotest/neotest
Deps nvim-nio, plenary.nvim
Keymaps <leader>T* test actions

lang.go, lang.python, and lang.python-pro add their test adapters when enabled alongside it. Other adapters go in the neotest spec’s opts.adapters.

LazyGit floating window via Snacks.

Adds Value
Snacks lazygit.enabled = true
Keymap <leader>gg → LazyGit float

Requires lazygit in $PATH.

diffview-plus.nvim, the maintained fork of sindrets/diffview.nvim, for richer diffs and file history.

Adds Value
Plugin dlyongemallo/diffview-plus.nvim (tagged releases)
Deps mini.icons
Keymap <leader>gD → :DiffviewOpen
Keymap <leader>gH → file history

Open the current file, line, or repository on its Git remote (GitHub, GitLab, Bitbucket, sourcehut) using Snacks gitbrowse. No new plugin.

Adds Value
Keymap <leader>gB → open on remote (normal and visual)

NeogitOrg/neogit, a Magit-style interactive Git interface. Pairs with git.diffview and uses the core Snacks picker.

Adds Value
Plugin NeogitOrg/neogit
Treesitter git_config, git_rebase, gitcommit, diff
Keymap <leader>gn → open Neogit

claudecode.nvim integration for Claude Code CLI sessions and native diff review.

Adds Value
Plugin coder/claudecode.nvim
Deps folke/snacks.nvim
Commands :ClaudeCode* command family
Keymap <leader>ac -> toggle Claude Code
Keymap <leader>aF -> focus Claude Code
Keymap <leader>ar -> resume Claude Code
Keymap <leader>aC -> continue Claude Code
Keymap <leader>am -> select model
Keymap <leader>ab -> add current buffer
Keymap <leader>as -> send visual selection
Keymap <leader>aA -> accept diff
Keymap <leader>aD -> deny diff

Claude Code options are passed through ai.claudecode. Blak sets terminal.provider = "snacks" because Snacks is already part of core:

return {
extras = { enabled = { "ai.claudecode" } },
ai = {
claudecode = {
log_level = "info",
terminal = {
provider = "snacks",
},
},
},
}

Never enabled by default. Opt in with :BlakExtras enable ai.claudecode.

GitHub Copilot inline suggestions through copilot-language-server and native vim.lsp.inline_completion. No Copilot plugin.

Adds Value
LSP copilot (Mason installs copilot-language-server)
Keymap <M-l> (insert) -> accept the suggestion
Keymap <M-]> / <M-[> (insert) -> next / previous suggestion

Sign in with :LspCopilotSignIn in any buffer the server attached to.

Never enabled by default. Opt in with :BlakExtras enable ai.copilot.

sidekick.nvim AI CLI terminals and optional Copilot Next Edit Suggestions.

Adds Value
Plugin folke/sidekick.nvim
Snacks picker.actions.sidekick_send
Keymap <C-.> → focus the Sidekick CLI
Keymap <leader>aa → toggle the CLI
Keymap <leader>as → select an AI CLI
Keymap <leader>ad → detach the current CLI session
Keymap <leader>af → send the current file
Keymap <leader>at → send {this} context
Keymap <leader>av → send the visual selection
Keymap <leader>ap → pick a prompt
Keymap <leader>an -> jump to or apply the next edit suggestion

Next Edit Suggestions need the Copilot language server, so enable ai.copilot too when you turn on nes.enabled.

Enable it, sync plugins, then install at least one AI CLI supported by Sidekick, such as Codex, Claude, Gemini, or OpenCode:

:BlakExtras enable ai.sidekick
:BlakExtras sync
:checkhealth sidekick

Blak keeps ai.sidekick.nes.enabled = false by default so the extra remains a terminal-based AI workflow unless you opt into Copilot Next Edit Suggestions:

return {
extras = { enabled = { "ai.sidekick" } },
ai = {
sidekick = {
nes = { enabled = true },
cli = {
mux = { enabled = true, backend = "tmux" },
},
},
},
}

The extra registers a Snacks picker action named sidekick_send. If you want a picker-local key for sending file/search selections to Sidekick, add it yourself so it remains part of your visible config:

return {
extras = { enabled = { "ai.sidekick" } },
snacks = {
picker = {
win = {
input = {
keys = {
["<a-a>"] = { "sidekick_send", mode = { "n", "i" } },
},
},
},
},
},
}

Never enabled by default. Disable it, restart Blak, then run :BlakExtras sync to remove the plugin spec.

aerial.nvim for an opt-in code outline window.

Adds Value
Plugin stevearc/aerial.nvim
Deps mini.icons
Keymap <leader>co → toggle outline

VS Code-style Emmet: type .block and accept the completion to get <div className="block"></div> in JSX, <div class="block"></div> in HTML. Already included in lang.web.

Adds Value
LSP emmet_language_server for HTML, CSS, JSX/TSX, Vue, Svelte, and Astro

flash.nvim for label-based jump motions and Treesitter selection. Deliberately shadows native s/S; opt-in and visible in :BlakKeys.

Adds Value
Plugin folke/flash.nvim
Keymaps s jump, S Treesitter, r/R remote/search, <C-s> toggle in search

grug-far.nvim for buffer-based, ripgrep-powered project-wide find and replace.

Adds Value
Plugin MagicDuck/grug-far.nvim
Keymap <leader>sr → search and replace (normal and visual)

Snacks scratch buffers: persistent, context-aware throwaway notepads. No new plugin.

Adds Value
Keymap <leader>. → toggle scratch buffer
Keymap <leader>S → select scratch buffer

Harpoon v2 for project-local file marks and a small editable quick menu.

Adds Value
Plugin ThePrimeagen/harpoon on branch harpoon2
Deps plenary.nvim
Config calls require("harpoon"):setup({})
Keymaps <leader>h* Harpoon file actions

nvim-mini modules as opt-in editor pieces.

Adds Value
Plugins one nvim-mini/mini.<module> spec for each configured non-core, non-conflicting mini.modules entry
Config calls require("mini.<module>").setup(mini.opts.<module> or {})

This extra does not enable any optional Mini module by default. mini.icons and pair handling ship in core; put the other Mini modules you want in mini.modules, enable editor.mini, then run :BlakExtras sync.

overseer.nvim for project task running and job management.

Adds Value
Plugin stevearc/overseer.nvim
Keymaps <leader>oo, <leader>or, <leader>oq

refactoring.nvim for Treesitter-powered extract, inline, and print-debug refactors.

Adds Value
Plugin ThePrimeagen/refactoring.nvim
Deps lewis6991/async.nvim
Keymaps <leader>r* refactor actions

render-markdown.nvim for richer in-buffer Markdown rendering.

Adds Value
Plugin MeanderingProgrammer/render-markdown.nvim
Deps nvim-treesitter, mini.icons
Treesitter markdown, markdown_inline
Keymap <leader>um → toggle Markdown rendering

todo-comments.nvim for highlighted and searchable TODO-style comments.

Adds Value
Plugin folke/todo-comments.nvim
Deps plenary.nvim
Keymaps ]t, [t, <leader>xT

]t/[t replace Neovim’s native tag-matchlist maps (:tnext/:tprevious) while the extra is enabled.

trouble.nvim for richer diagnostics, references, symbols, quickfix, and location list views.

Adds Value
Plugin folke/trouble.nvim
Deps mini.icons
Keymaps <leader>xX, <leader>xQ, <leader>xL, <leader>cO, <leader>cR

Native window movement on Ctrl-h/j/k/l.

Adds Value
Keymaps <C-h> left, <C-j> down, <C-k> up, <C-l> right

This is an extra instead of a core default because <C-l> already means :nohlsearch | diffupdate | redraw in stock Neovim, and this extra replaces it. Blak’s <Esc> still clears search highlighting. Opting in keeps the shortcut explicit and reversible.

nvim-neo-tree/neo-tree.nvim as an alternative file explorer alongside Oil.

Adds Value
Plugin nvim-neo-tree/neo-tree.nvim (v3.x)
Deps plenary.nvim, mini.icons, nui.nvim
Keymap <leader>E → toggle Neo-tree

Snacks explorer as the configured file explorer.

Adds Value
Config sets explorer.provider = "snacks"
Snacks explorer.enabled = true; explorer picker auto_close = true
Binary fd on $PATH for fast file discovery
Keymap <leader>e → toggle Snacks explorer

Snacks already ships in core for dashboard/input/notifier/picker support, so this extra enables the explorer module instead of adding a new plugin. Blak also toggles an already-open Snacks explorer instead of opening a second one.

Snacks terminal as the configured terminal provider.

Adds Value
Config sets terminal.provider = "snacks"
Snacks terminal.enabled = true
Command :BlakTerminal [cmd] uses Snacks.terminal.toggle()
Keymap terminal.toggle_key toggles Snacks terminal

Snacks already ships in core, so this extra enables the terminal module and keeps the existing Blak command and keymap surface.

nvim-telescope/telescope.nvim as the picker backend.

Adds Value
Plugin nvim-telescope/telescope.nvim
Deps plenary.nvim, mini.icons
Config sets picker.provider = "telescope"

Enabling this swaps :BlakPick and all <leader>f* mappings to Telescope.

ibhagwan/fzf-lua as the picker backend.

Adds Value
Plugin ibhagwan/fzf-lua
Deps mini.icons
Config sets picker.provider = "fzf_lua"
-- lua/blak/extras/lang/rust.lua
return {
id = "lang.rust",
label = "Rust",
description = "rust-analyzer + treesitter",
treesitter = { "rust", "toml" },
lsp = {
servers = {
rust_analyzer = {
settings = {
["rust-analyzer"] = { check = { command = "clippy" } },
},
},
},
},
format = {
formatters_by_ft = { rust = { lsp_format = "fallback" } },
},
keys = {
{ lhs = "<leader>cc", rhs = ":!cargo check<CR>", desc = "cargo check" },
},
plugins = { -- optional, lazy.nvim spec list
{ "owner/plugin.nvim", cmd = "Example", opts = {} },
},
integrations = { -- optional, added only while another extra is enabled too
["debug.dap"] = { mason = { "codelldb" }, plugins = { --[[ nvim-dap opts ]] } },
},
apply = function(config) -- optional, runs before declarative contributions
config.snacks.dim = { enabled = true }
end,
}

That’s the entire surface. See Writing an extra for the full guide.