Independent Neovim utility modules for browsing, editing and UI. Install the plugin once, then enable only the modules and integrations you want.
Neovim 0.12 or newer is required. With vim.pack, add the plugin before requiring a module:
vim.pack.add({ { src = 'https://github.com/halkn/kago.nvim' } })
local explorer = require('kago.explorer')
explorer.setup()
vim.keymap.set('n', '<Leader>e', explorer.toggle)This example opens and closes Explorer with <Leader>e. Installing the plugin alone does not
register mappings, commands or provider replacements.
Other executables are needed only for the features that use them:
| Dependency | Feature |
|---|---|
git |
Explorer git status and picker.git() |
rg (ripgrep) |
picker.files() and picker.grep() |
fd |
Explorer path filter (/) |
Icon providers are optional. Explorer uses nvim-web-devicons
for file icons when available and generic glyphs otherwise. Picker prefers
mini.icons, falls back to nvim-web-devicons, and
omits icons when neither is available.
There is no top-level require('kago').setup(). Each module can be required and configured without
loading or setting up unrelated kago.* modules.
Modules do not replace vim.ui.input, vim.ui.select or vim.notify, and they do not create user
commands. Loading a module or calling setup() without mappings does not add global mappings.
Editing modules install only mappings supplied through setup({ mappings = ... }). Modules own the
buffer-local mappings and autocmds needed for their own UI.
| Module | Purpose |
|---|---|
kago.explorer |
Persistent filesystem sidebar with filtering, git status and preview |
kago.picker |
Floating fuzzy picker over files, buffers, grep, buffer lines, tree and git |
kago.input |
vim.ui.input compatible floating prompt |
kago.notify |
vim.notify compatible floating notifications with history |
kago.terminal |
Floating terminal toggle |
kago.yankring |
Yank ring with paste cycling |
kago.surround |
Add / delete / replace surrounding brackets and quotes |
kago.pairs |
Auto-pairing for brackets and quotes |
kago.replace |
Operator that replaces a motion range with a register |
The quick start configures Explorer and its entrypoint mapping. Call
explorer.open() to open it at the current working directory, or pass a root explicitly:
require('kago.explorer').open({ root = vim.fn.getcwd() })explorer.close() and explorer.toggle() control the sidebar. Navigation, filtering and preview
keys work only inside its buffer.
local picker = require('kago.picker')
picker.setup({
debounce_ms = 150,
height_ratio = 0.8,
width_ratio = 0.9,
exclude_globs = { '!**/.git/*' },
})
vim.keymap.set('n', '<Leader>f', picker.files)Open other built-in sources with picker.buffers(), picker.grep(), picker.buf_lines() or
picker.git(). picker.open('files') accepts a source name, and picker.close() closes the
current picker. To use Picker for vim.ui.select, assign its standalone adapter explicitly:
vim.ui.select = picker.ui_selectNo setup. input is a standalone vim.ui.input compatible function:
vim.ui.input = require('kago.input').inputlocal notify = require('kago.notify')
notify.setup()
vim.notify = notify.notify
vim.api.nvim_create_user_command('NotifyHistory', notify.show_history, {
desc = 'Show notification history',
})local terminal = require('kago.terminal')
terminal.setup()
vim.keymap.set({ 'n', 't' }, '<C-t>', terminal.toggle)require('kago.yankring').setup({
highlight_ms = 200,
max_size = 30,
mappings = {
paste_after = 'p',
paste_before = 'P',
paste_after_end = 'gp',
paste_before_end = 'gP',
cycle_prev = '<C-p>',
cycle_next = '<C-n>',
show = '<Leader>y',
},
})require('kago.surround').setup({
mappings = { add = 'sa', delete = 'sd', replace = 'sr' },
})require('kago.pairs').setup({
mappings = {
pairs = { ['('] = ')', ['['] = ']', ['{'] = '}' },
quotes = { '"', "'", '`' },
backspace = { '<BS>', '<C-h>' },
cr = '<CR>',
},
})require('kago.replace').setup({ mappings = { replace = 'R' } })Run make check before submitting changes. See Contributing for local setup,
test conventions and CI behavior.
MIT