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.

The contract

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.

Managing extras

: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 " run :Lazy sync after changes

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 sync lazy.nvim, 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.

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 or :Lazy sync if plugins were added.
  3. Run :BlakToolsInstall to install any new Mason tools required.
  4. Run :BlakDoctor to confirm everything resolved.

After disabling an extra, the state file updates immediately. Restart Blak 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.

Dedicated pages

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

GroupExtras
Languageslang.lua, lang.typescript, lang.typescript-tsgo, lang.python, lang.python-pro, lang.rust, lang.go, lang.markdown, lang.c, lang.bash, lang.web, lang.docker, lang.yaml, lang.json, lang.terraform, lang.nix, lang.zig
Debugdebug.dap
Testtest.neotest
UIui.animations, ui.base46, ui.comfy-line-numbers, ui.dim, ui.image-preview, ui.indent, ui.lualine, ui.zen
Gitgit.lazygit, git.diffview, git.gitbrowse, git.neogit
AIai.claudecode, ai.copilot, ai.sidekick, ai.supermaven
Editoreditor.aerial, 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

Languages

lang.lua

Lua development — what Blak itself is written in.

AddsValue
Treesitterlua, luadoc
Masonstylua
LSPlua_ls
Formatstylua for .lua

lang.typescript

TypeScript and JavaScript with ESLint + Prettier.

AddsValue
Treesitterjavascript, typescript, tsx, jsdoc, json
Masonprettier, prettierd, eslint_d
LSPts_ls, eslint
Formatprettierd (fallback prettier) for js/ts/jsx/tsx/json
Linteslint_d for js/ts/jsx/tsx

lang.typescript-tsgo

TypeScript and JavaScript with the experimental native tsgo LSP, ESLint, and Prettier.

Enable this instead of lang.typescript when you want to try TypeScript’s Go-based language server. If both are enabled and this extra applies after lang.typescript, it removes ts_ls from the merged config for future setup. Restart after switching if ts_ls already attached in the current session.

AddsValue
Treesitterjavascript, typescript, tsx, jsdoc, json
Masonprettier, prettierd, eslint_d
LSPtsgo, eslint
Formatprettierd (fallback prettier) for js/ts/jsx/tsx/json
Linteslint_d for js/ts/jsx/tsx

lang.python

Python with Pyright + Ruff + Black + isort.

AddsValue
Treesitterpython
Masonblack, isort, ruff
LSPpyright, ruff
Formatisort, then black
Lintruff

lang.python-pro

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

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

AddsValue
Treesitterpython, requirements
Masonruff, debugpy
LSPbasedpyright, ruff
Formatruff_organize_imports, then ruff_format
Pluginsvenv-selector.nvim
Keys<leader>cv for :VenvSelect

lang.rust

Rust with rust-analyzer and TOML support.

AddsValue
Treesitterrust, toml
Masoncodelldb
LSPrust_analyzer (with cargo.allFeatures + Clippy), taplo
Formatrustfmt (LSP fallback), taplo (LSP fallback)
Pluginssaecki/crates.nvim

lang.go

Go with gopls and golangci-lint.

AddsValue
Treesittergo, gomod, gosum, gowork
Masongoimports, gofumpt, golangci-lint
LSPgopls
Formatgoimports, gofumpt
Lintgolangcilint

lang.markdown

Markdown with Marksman LSP and Prettier.

AddsValue
Treesittermarkdown, markdown_inline
Masonprettier, prettierd, markdownlint
LSPmarksman
Formatprettierd (fallback prettier) for markdown
Lintmarkdownlint

lang.c

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

AddsValue
Treesitterc, cpp
Masonclang-format
LSPclangd
Formatclang_format for c, cpp, objc, objcpp, cuda

lang.bash

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

AddsValue
Treesitterbash
Masonshellcheck
LSPbashls
Lintshellcheck for sh, bash

lang.web

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

AddsValue
Treesitterhtml, css, scss
Masonprettier, prettierd
LSPhtml, cssls, tailwindcss, emmet_language_server
Formatprettierd (fallback prettier) for html, css, scss, less

lang.docker

Dockerfile and Docker Compose with hadolint linting.

AddsValue
Treesitterdockerfile
Masonhadolint
LSPdockerls, docker_compose_language_service
Linthadolint for dockerfile
Filetyperegisters yaml.docker-compose for Compose files

lang.yaml

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

AddsValue
Treesitteryaml
Masonprettier, prettierd
LSPyamlls with SchemaStore schemas
Formatprettierd (fallback prettier) for yaml
Pluginb0o/SchemaStore.nvim

lang.json

JSON with jsonls, SchemaStore schemas, and Prettier.

AddsValue
Treesitterjson, jsonc
Masonprettier, prettierd
LSPjsonls with SchemaStore schemas
Formatprettierd (fallback prettier) for json, jsonc
Pluginb0o/SchemaStore.nvim

lang.terraform

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

AddsValue
Treesitterterraform, hcl
Masontflint
LSPterraformls
Formatterraform_fmt for terraform, terraform-vars (needs the terraform CLI)
Linttflint for terraform

lang.nix

Nix with the nil language server and nixfmt.

AddsValue
Treesitternix
Masonnixfmt
LSPnil_ls
Formatnixfmt for nix

lang.zig

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

AddsValue
Treesitterzig
LSPzls

UI

ui.animations

Smooth scroll and cursor animations via Snacks.

AddsValue
Snacksanimate.enabled = true, scroll.enabled = true

ui.base46

AvengeMedia/base46, the NvChad Base46 colorscheme collection as regular Neovim colorschemes.

AddsValue
PluginAvengeMedia/base46

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

ui.comfy-line-numbers

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

AddsValue
Pluginmluders/comfy-line-numbers.nvim
Keymaplabel + j or k motions
Keymaplabel + <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.

ui.dim

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

AddsValue
Snacksdim.enabled = true

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

ui.image-preview

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

AddsValue
Snacksimage.enabled = true

ui.indent

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

AddsValue
Snacksindent.enabled = true
Keymap<leader>ug → toggle indent guides

ui.lualine

lualine.nvim as an opt-in statusline.

AddsValue
Pluginnvim-lualine/lualine.nvim
Depsmini.icons
Configglobal 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.

ui.zen

Distraction-free editing mode.

AddsValue
Snackszen.enabled = true
Keymap<leader>uz → toggle zen

Debug

debug.dap

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

AddsValue
Pluginsmfussenegger/nvim-dap, rcarriga/nvim-dap-ui
Depsnvim-nio
Keymaps<leader>d* debug actions

Language adapters and launch configurations stay explicit in user.lua.

Test

test.neotest

neotest as a base test runner framework.

AddsValue
Pluginnvim-neotest/neotest
Depsnvim-nio, plenary.nvim, FixCursorHold.nvim, nvim-treesitter
Keymaps<leader>T* test actions

Language-specific adapters stay explicit in plugins.specs.

Git

git.lazygit

LazyGit floating window via Snacks.

AddsValue
Snackslazygit.enabled = true
Keymap<leader>gg → LazyGit float

Requires lazygit in $PATH.

git.diffview

sindrets/diffview.nvim for richer diffs and file history.

AddsValue
Pluginsindrets/diffview.nvim
Keymap<leader>gD:DiffviewOpen
Keymap<leader>gH → file history

git.gitbrowse

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

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

git.neogit

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

AddsValue
PluginNeogitOrg/neogit
Depsplenary.nvim
Treesittergit_config, git_rebase, gitcommit, diff
Keymap<leader>gn → open Neogit

AI

ai.claudecode

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

AddsValue
Plugincoder/claudecode.nvim
Depsfolke/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.

ai.copilot

GitHub Copilot integration via zbirenbaum/copilot.lua.

AddsValue
Pluginzbirenbaum/copilot.lua

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

ai.sidekick

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

AddsValue
Pluginfolke/sidekick.nvim
Snackspicker.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

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.

ai.supermaven

supermaven-nvim inline AI completion.

AddsValue
Pluginsupermaven-inc/supermaven-nvim
Commands:Supermaven* command family
Keymap<leader>aS -> toggle Supermaven
Keymap<M-l> -> accept the inline suggestion
Keymap<M-w> -> accept one word
Keymap<M-]> -> clear the inline suggestion

Blak disables Supermaven’s built-in plugin keymaps and registers the mappings above through :BlakKeys instead. That keeps the extra discoverable and avoids quietly taking over <Tab>.

Supermaven options are passed through ai.supermaven:

return {
extras = { enabled = { "ai.supermaven" } },
ai = {
supermaven = {
log_level = "info",
ignore_filetypes = {
markdown = true,
},
},
},
}

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

Editor

editor.aerial

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

AddsValue
Pluginstevearc/aerial.nvim
Depsmini.icons
Keymap<leader>co → toggle outline

editor.flash

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

AddsValue
Pluginfolke/flash.nvim
Keymapss jump, S Treesitter, r/R remote/search, <C-s> toggle in search

editor.grug-far

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

AddsValue
PluginMagicDuck/grug-far.nvim
Keymap<leader>sr → search and replace (normal and visual)

editor.scratch

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

AddsValue
Keymap<leader>. → toggle scratch buffer
Keymap<leader>S → select scratch buffer

editor.harpoon

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

AddsValue
PluginThePrimeagen/harpoon on branch harpoon2
Depsplenary.nvim
Configcalls require("harpoon"):setup({})
Keymaps<leader>h* Harpoon file actions

editor.mini

nvim-mini modules as opt-in editor pieces.

AddsValue
Pluginsone nvim-mini/mini.<module> spec for each configured non-core, non-conflicting mini.modules entry
Configcalls 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.

editor.overseer

overseer.nvim for project task running and job management.

AddsValue
Pluginstevearc/overseer.nvim
Keymaps<leader>oo, <leader>or, <leader>oq

editor.refactoring

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

AddsValue
PluginThePrimeagen/refactoring.nvim
Depsplenary.nvim, nvim-treesitter
Keymaps<leader>r* refactor actions

editor.render-markdown

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

AddsValue
PluginMeanderingProgrammer/render-markdown.nvim
Depsnvim-treesitter, mini.icons
Treesittermarkdown, markdown_inline
Keymap<leader>um → toggle Markdown rendering

editor.todo-comments

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

AddsValue
Pluginfolke/todo-comments.nvim
Depsplenary.nvim
Keymaps]t, [t, <leader>xT

editor.trouble

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

AddsValue
Pluginfolke/trouble.nvim
Depsmini.icons
Keymaps<leader>xX, <leader>xQ, <leader>xL, <leader>cO, <leader>cR

editor.window-navigation

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

AddsValue
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> redraws the screen in stock Neovim. Opting in keeps the shortcut explicit and reversible.

editor.neotree

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

AddsValue
Pluginnvim-neo-tree/neo-tree.nvim (v3.x)
Depsplenary.nvim, mini.icons, nui.nvim
Keymap<leader>E → toggle Neo-tree

editor.snacks-explorer

Snacks explorer as the configured file explorer.

AddsValue
Configsets explorer.provider = "snacks"
Snacksexplorer.enabled = true; explorer picker auto_close = true
Binaryfd 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.

editor.snacks-terminal

Snacks terminal as the configured terminal provider.

AddsValue
Configsets terminal.provider = "snacks"
Snacksterminal.enabled = true
Command:BlakTerminal [cmd] uses Snacks.terminal.toggle()
Keymapterminal.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.

editor.telescope

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

AddsValue
Pluginnvim-telescope/telescope.nvim
Depsplenary.nvim, mini.icons
Configsets picker.provider = "telescope"

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

editor.fzf-lua

ibhagwan/fzf-lua as the picker backend.

AddsValue
Pluginibhagwan/fzf-lua
Depsmini.icons
Configsets picker.provider = "fzf_lua"

Anatomy of an extra

-- lua/blak/extras/lang/rust.lua
return {
id = "lang.rust",
label = "Rust",
description = "rust-analyzer + treesitter",
treesitter = { "rust", "toml" },
mason = { "codelldb" },
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", opts = {} },
},
apply = function(config) -- optional, runs after merge
config.snacks.dim = { enabled = true }
end,
}

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