Skip to content

Config schema

Blak validates its merged config on load. Invalid values throw on startup with a clear list of every problem, not the first one. The validation rules live in lua/blak/config/schema.lua.

Top-level keys

All present after merging with the defaults. Keys marked validated are checked by schema.lua on load; the rest are deep-merged and passed to the modules that consume them without per-field validation.

KeyTypeNotes
versionstringBlak’s own version string. Informational; do not set it in user.lua
leaderstringDefault " ". Validated
localleaderstringDefault "\\". Validated
packagetableSee below. Validated
uitableSee below. Validated
editortableSee below. Validated
completiontableSee below. Validated
performancetableSee below
pickertableSee below. Validated
explorertableSee below. Validated
terminaltableSee below. Validated
keymapstableList of user keymap specs. Validated
pluginstablePersonal lazy.nvim specs. Validated
hookstableLua hooks for pre-validation and post-setup customization. Validated
aitableSee below. Validated
minitableSee below. Validated
snackstableSee below
treesittertableSee below
lsptableSee below
masontableSee below
formattableSee below
linttableSee below
extrastableSee below. Validated

package

KeyTypeAllowed
backendstring"lazy"
channelstring"stable", "edge", or "nightly"
check_updatesboolean

Setting an unsupported channel raises:

Blak config validation failed:
- package.channel must be stable, edge, or nightly

ui

KeyTypeAllowed
colorschemestringAny installed colorscheme name
transparentbooleantrue or false
themetableOptions passed to a colorscheme Lua setup() function when available

Set ui.transparent = true to clear editor background highlights after the active colorscheme loads. Use ui.theme for colorscheme-native setup options. Blak tries the colorscheme name first, then the name before the final dash. Configure custom themes with unusual setup rules through plugins.specs.

editor

KeyTypeNotes
clipboardbooleanUse the system clipboard when available
confirmbooleanPrompt before commands abandon unsaved changes
relative_numberbooleanToggle relative line numbers
scrolloffnumberContext lines above and below the cursor
sidescrolloffnumberContext columns beside the cursor
tabstopnumberWidth used to display a tab character
shiftwidthnumberIndent width for operators and new lines
expandtabbooleanInsert spaces instead of tab characters

Disable confirm prompts in user.lua:

return {
editor = {
confirm = false,
},
}

picker

KeyTypeAllowed
providerstring"fff", "snacks", "telescope", or "fzf_lua"

Switching providers swaps the implementation behind :BlakPick without changing the keymaps. If you want a provider that doesn’t exist yet, add it under lua/blak/providers/picker.lua and submit a PR.

completion

KeyTypeAllowed
super_tabbooleantrue or false

Set completion.super_tab = true to use the completion engine’s SuperTab-style keymap preset where Blak can delegate to one. The default is false, so stable updates do not change completion muscle memory.

explorer

KeyTypeAllowed
providerstring"oil" or "snacks"

Switching providers swaps the implementation behind <leader>e and directory-buffer takeover. The usual path is :BlakExtras enable editor.snacks-explorer, which sets this option and enables the Snacks explorer module for you.

terminal

KeyTypeAllowed
providerstring"native" or "snacks"
toggle_keystring or falseAny key accepted by vim.keymap.set(), or false to skip the keymap

The usual path for Snacks terminal is :BlakExtras enable editor.snacks-terminal, which sets terminal.provider = "snacks" and enables the Snacks terminal module for you. Set terminal.toggle_key when you want a different toggle mapping:

return {
extras = { enabled = { "editor.snacks-terminal" } },
terminal = {
toggle_key = "<C-/>",
},
}

keymaps

keymaps is a list of user mappings applied after core and enabled extras.

KeyTypeNotes
modestring or string[]Optional; defaults to "n"
modesstring or string[]Alias for mode; use one or the other
keystringRequired key to map
actionstring, function, or falseRequired action; false disables this key
descriptionstringRequired for active mappings so :BlakKeys can show it
disablebooleanSet true to remove this key from Blak
optstableOptional vim.keymap.set() options
return {
keymaps = {
{ key = "<leader>sg", action = "<cmd>BlakPick grep<cr>", description = "Grep" },
{
mode = { "n", "x" },
key = "<leader>y",
action = '"+y',
description = "Yank to clipboard",
},
{
key = "<leader>rn",
action = function()
vim.lsp.buf.rename()
end,
description = "Rename symbol",
},
{ key = "<leader>/", disable = true },
},
}

To move a default action, disable the old key and add the new one. This keeps user muscle memory explicit without hiding mappings from :BlakKeys.

Blak still accepts lhs, rhs, and desc as aliases for users already familiar with Vim terminology, but the documented user.lua shape uses the more direct names above.

plugins

KeyTypeNotes
specstableList of lazy.nvim specs appended after Blak core and enabled extras
return {
plugins = {
specs = {
{ "tpope/vim-sleuth", event = "BufReadPost" },
},
},
}

Use this for personal plugins. If the behavior is broadly useful and reversible, prefer a documented extra so other users can enable and disable it through :BlakExtras.

hooks

KeyTypeNotes
beforefunction or function[]Runs after merge, before validation and extras
afterfunction or function[]Runs after startup and after successful user.lua reloads
return {
hooks = {
after = function(config)
vim.opt.cursorline = false
end,
},
}

Hooks receive (config, blak). config is the merged Blak config table, and blak.util is available on the second argument.

ai

KeyTypeNotes
claudecodetableOptions passed to coder/claudecode.nvim when ai.claudecode is enabled. Blak sets terminal.provider = "snacks" by default.
sidekicktableOptions passed to folke/sidekick.nvim when ai.sidekick is enabled. Blak sets nes.enabled = false by default.
supermaventableOptions passed to supermaven-inc/supermaven-nvim when ai.supermaven is enabled. Blak always disables the plugin’s built-in keymaps.

Use this table for Claude Code configuration:

return {
extras = { enabled = { "ai.claudecode" } },
ai = {
claudecode = {
terminal = {
provider = "snacks",
},
diff_opts = {
layout = "vertical",
},
},
},
}

Use ai.sidekick for Sidekick CLI and NES configuration:

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

Use ai.supermaven to tune Supermaven without enabling its hidden keymaps:

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

mini

KeyTypeNotes
modulesstring[]Mini module slugs to install and set up when editor.mini is enabled. Use ai, surround, or mini.ai; mini.icons and pair handling already ship in core.
optstable<string, table>Per-module options passed to require("mini.<module>").setup()

The Mini extra is intentionally inert until you choose modules:

return {
extras = { enabled = { "editor.mini" } },
mini = {
modules = { "ai", "surround", "pairs" },
opts = {
surround = { n_lines = 80 },
},
},
}

performance

KeyTypeNotes
bigfile_sizenumberSize in bytes above which Snacks bigfile mode trims heavy features. Default 1.5 MiB
max_treesitter_linesnumberBuffers with more lines than this skip Treesitter highlighting. Default 10000

snacks

A table deep-merged over Blak’s own snacks.nvim options, last-write-wins. Use it to tune or disable individual Snacks modules:

return {
snacks = {
words = { enabled = false },
},
}

The full option surface is the upstream snacks.nvim config; Blak validates only that the value is mergeable.

treesitter

KeyTypeNotes
ensure_installedstring[]Parsers installed at startup

Per the deep merge semantics below, setting ensure_installed in the simple table form replaces the default parser list. Use the function form or an extra to append.

lsp

KeyTypeNotes
automatic_enablebooleanEnable configured servers automatically through vim.lsp.enable()
serverstable<string, table>Per-server options passed to vim.lsp.config()
diagnosticstablePassed to vim.diagnostic.config()
return {
lsp = {
servers = {
gopls = {},
},
diagnostics = {
virtual_text = false,
},
},
}

Language extras add their servers to lsp.servers for you; use this table directly when you want a server without the rest of an extra. Validation only checks that lsp is a table.

mason

KeyTypeNotes
automatic_installbooleanInstall ensure_installed tools through Mason on startup
ensure_installedstring[]Mason package names

format

KeyTypeNotes
enabledbooleanFormat on save. vim.g.blak_disable_autoformat and vim.b.blak_disable_autoformat override per session or buffer
timeout_msnumberFormatter timeout per save
lsp_formatstringConform’s lsp_format mode; default "fallback"
formatters_by_fttable<string, string[]>Conform formatters per filetype

lint

KeyTypeNotes
eventsstring[]Autocmd events that trigger nvim-lint; empty list disables event-driven linting
linters_by_fttable<string, string[]>nvim-lint linters per filetype

extras

KeyTypeNotes
enabledblak.ExtraId[]List of extra IDs. lua_ls completes known IDs like lang.typescript, editor.mini, and git.lazygit. Validation only checks that entries are strings — unknown IDs surface as a warning at runtime, not a hard error.

The runtime warning gives you a chance to keep using your config after renaming an extra in the repo.

Deep merge semantics

The simple user.lua form returns a table that is deep-merged into the defaults via vim.tbl_deep_extend("force", defaults, user):

  • Scalars in your table replace defaults.
  • Tables are merged key by key.
  • Lists are replaced wholesale. If you write treesitter = { ensure_installed = { "rust" } }, you lose the entire default list.

To append to default lists, use an extra or return a function:

return function(config)
table.insert(config.treesitter.ensure_installed, "rust")
end

The function form receives the config table Blak is building. Mutate it in place and return nothing, or return a table of final overrides.

Error handling

If validation fails on startup, require("blak").setup() raises and Blak does not load. You’ll see the original Neovim banner and the error message in :messages.

If validation or evaluation fails during an automatic user.lua reload, Blak warns and keeps the previous in-session config active. Fix user.lua and save it again.

The error message is verbose on purpose:

Blak config validation failed:
- package.channel must be stable, edge, or nightly
- picker.provider must be fff, snacks, telescope, or fzf_lua
- completion.super_tab must be boolean, got string
- explorer.provider must be oil or snacks
- terminal.provider must be native or snacks
- extras.enabled entries must be strings

Multiple problems are reported in one pass so you don’t fix one and immediately hit the next.