К этому моменту вы умеете собирать конфиг руками: знаете init.lua и разумные дефолты (глава 20), маппинги и which-key (глава 21), менеджеры плагинов и lazy-loading (глава 23), нативный LSP (глава 25), автодополнение (глава 26), Treesitter (глава 27), пикеры (глава 28) и Git внутри редактора (глава 29). Эта глава отвечает на три практических вопроса, которые встают перед каждым, кто перерос "голый" Neovim:
- С чего начать? Собирать конфиг с нуля - мощно, но долго. Готовые дистрибутивы (kickstart.nvim, LazyVim, NvChad, AstroNvim) дают рабочую IDE за минуты. Разберём, кому что подходит в 2026 и где их границы.
- Как отлаживать код прямо в редакторе? nvim-dap превращает Neovim в полноценный отладчик с точками останова, шагами и инспекцией переменных - без выхода в IDE.
- Как жить в терминале изнутри редактора и снаружи? Встроенный :terminal, toggleterm, бесшовная навигация с tmux и удалённое управление через neovim-remote.
1. Дистрибутивы: готовый конфиг vs свой
Зачем вообще дистрибутив
"Голый" Neovim из коробки - это редактор, а не среда разработки. Чтобы получить LSP, автодополнение, файловый менеджер, нечёткий поиск, Git-интеграцию и согласованные кейбинды, нужно установить и настроить десяток плагинов. На сборку зрелого личного конфига уходят недели итераций.
Дистрибутив - это готовый, поддерживаемый сообществом конфиг поверх lazy.nvim (см. главу 23). Вы устанавливаете его в ~/.config/nvim, и у вас сразу рабочая IDE. Цена - вы принимаете чужие соглашения: структуру файлов, дефолтные кейбинды, выбор плагинов. Ключевое решение 2026 года звучит так: либо вы понимаете каждую строку своего конфига (путь kickstart), либо осознанно принимаете соглашения дистрибутива (LazyVim/NvChad/AstroNvim) и учитесь их переопределять. Худший вариант - смешивать: лезть в дистрибутив с ручными правками, не понимая его слоёв мёржа opts. Это ломает каскад настроек и приводит к загадочным багам.
Четыре варианта в 2026
kickstart.nvim - учебный, один файл
kickstart.nvim (nvim-lua/kickstart.nvim) - это не дистрибутив, а стартовая площадка. Один хорошо прокомментированный init.lua (плюс опциональные модули в kickstart/), который показывает, как устроены LSP, Treesitter, автодополнение и пикеры. Идея авторов: вы читаете и понимаете каждую строку, форкаете репозиторий и дальше пилите конфиг под себя.
- Плюсы: прозрачность, ноль магии, идеален для обучения и как основа своего конфига. Обновлён под нативный LSP 0.11 и blink.cmp.
- Минусы: это минимум; всё сверх базы вы достраиваете сами.
- Кому: тем, кто хочет понимать внутренности и в итоге иметь свой конфиг.
LazyVim (folke/LazyVim) - по разным оценкам самый популярный дистрибутив 2026 года: на нём построена значительная часть пользовательских Neovim-конфигов (точных верифицируемых цифр доли рынка нет - это грубая оценка по активности репозитория и упоминаниям в сообществе). Рабочий IDE-сетап из коробки на lazy.nvim, со слоистой системой переопределения opts и системой Extras (:LazyExtras), которой вы включаете готовые модули - языковые паки (lang.*), альтернативы движков и т.д. - без ручного конфига.
Важные дефолты 2026: движок автодополнения по умолчанию - blink.cmp (не nvim-cmp), пикер и ряд UI-компонентов - из snacks.nvim. Вернуться на nvim-cmp можно через :LazyExtras -> включить coding.nvim-cmp; одновременно работает только один движок.
- Плюсы: крупнейшее сообщество, рабочая IDE сразу, аккуратная система override через opts, Extras для языков.
- Минусы: нужно понимать слои мёржа, иначе override не работает интуитивно; "магия" дистрибутива скрывает детали.
- Кому: тем, кто хочет быстрый старт с возможностью тонко переопределять. Дефолтный выбор для большинства в 2026.
NvChad делает упор на быстрый старт и эстетику: собственная система тем base46 (компилируется в байткод ради скорости), минималистичный, отполированный UI. Поверх ставится слой NvChad/ui и конфиг пользователя.
- Плюсы: очень быстрый старт, красивый UI "из коробки", своя система тем.
- Минусы: более своеобразная архитектура (base46, кастомные абстракции), кастомизация требует знакомства именно с соглашениями NvChad.
- Кому: тем, для кого важны визуал и скорость, и кто готов разобраться в base46.
AstroNvim - модульный community-дистрибутив с системой плагинов-"packs" (community-репозиторий с готовыми наборами под языки и инструменты).
- Плюсы: богатая модульность, community-паки, продуманная структура.
- Минусы: больше слоёв абстракции; как и у любого дистрибутива - нужно принять его соглашения.
- Кому: тем, кто любит модульный, "собранный из блоков" подход.
Прежде чем ставить LazyVim/NvChad/AstroNvim поверх существующего ~/.config/nvim, защититесь от потери своей настройки. Neovim хранит состояние в нескольких местах, и затереть нужно не только конфиг:
Код: Выделить всё
Путь | Что лежит
---------------------+---------------------------------------------------
~/.config/nvim | сам конфиг (init.lua, lua-модули)
~/.local/share/nvim | данные плагинов, парсеры Treesitter, Mason и т.д.
~/.local/state/nvim | состояние: шейды, undo, swap, логи
~/.cache/nvim | кеши (можно просто удалять)
Код: Выделить всё
# Бэкап (не удаляем - переименовываем, чтобы вернуть одной командой)
mv ~/.config/nvim{,.bak}
mv ~/.local/share/nvim{,.bak}
mv ~/.local/state/nvim{,.bak}
mv ~/.cache/nvim{,.bak} 2>/dev/null
# Теперь ставим дистрибутив в чистый ~/.config/nvim, например LazyVim:
git clone https://github.com/LazyVim/starter ~/.config/nvim
rm -rf ~/.config/nvim/.git
# Вернуть свой конфиг: удалить .bak-каталоги обратно на место.
Код: Выделить всё
git clone https://github.com/LazyVim/starter ~/.config/lazyvim
NVIM_APPNAME=lazyvim nvim # запуск LazyVim рядом с обычным `nvim`
Дистрибутив vs свой конфиг
Код: Выделить всё
Критерий | Свой конфиг (с нуля) | Дистрибутив
-------------------------+------------------------+---------------------------
Время до рабочей IDE | дни-недели | минуты
Понимание внутренностей | полное | частичное (скрыто слоями)
Контроль | абсолютный | в рамках соглашений
Поддержка/обновления | на вас | на сообществе
Риск "магии" | нет | есть (каскад opts)
Кривая обучения | круче | положе на старте
Практичный приём, на котором сходится сообщество: жить на LazyVim (рабочая IDE сразу, не теряете время), а в свободное время разобрать kickstart.nvim - прочитать его построчно, чтобы понимать, как всё устроено, и не зависеть от магии дистрибутива. Опытным Vim-пользователям, у которых уже есть рабочий конфиг, мигрировать на дистрибутив без причины не нужно.
2. Отладка: nvim-dap и dap-uiВнимание (nvim-treesitter 2026). nvim-treesitter пережил несовместимый rewrite: старый код заморожен в ветке master (для Neovim 0.11), новый - в main (требует 0.12). На Neovim 0.12 базовая подсветка Treesitter уже в ядре. Дистрибутивы это учитывают в своих пресетах - ещё один аргумент не собирать Treesitter-часть руками, если не хотите вникать. Подробнее в главе 27.
Зачем отладчик в редакторе
Печать print() по всему коду - это отладка прошлого века. Полноценный отладчик даёт точки останова (breakpoints), пошаговое выполнение, инспекцию переменных, стек вызовов и REPL - не покидая Neovim и не теряя контекст. Раньше за этим уходили в IDE; теперь это есть нативно через DAP.
nvim-dap (mfussenegger/nvim-dap) - клиент Debug Adapter Protocol (DAP). Это тот же подход, что у LSP: единый протокол, а конкретику языка обеспечивает внешний debug adapter (отдельная программа). Neovim говорит на DAP, адаптер транслирует это в отладчик конкретного языка (debugpy для Python, delve для Go, codelldb для C/C++/Rust и т.д.).
Архитектура:
Код: Выделить всё
Neovim (nvim-dap) < - - DAP - - > debug adapter < - - > отладчик языка / процесс
Код: Выделить всё
Компонент | Роль
---------------------------------------------+------------------------------------------
nvim-dap | DAP-клиент: точки останова, шаги, сессии
nvim-dap-ui (rcarriga/nvim-dap-ui) | UI: панели scopes, watches, стек, REPL
nvim-dap-virtual-text | inline-значения переменных прямо в коде
debug adapter (debugpy, delve, codelldb...) | мост к отладчику конкретного языка
mason-nvim-dap (опц.) | установка адаптеров через Mason
Код: Выделить всё
local dap, dapui = require("dap"), require("dapui")
dapui.setup()
dap.listeners.before.attach.dapui_config = function() dapui.open() end
dap.listeners.before.launch.dapui_config = function() dapui.open() end
dap.listeners.before.event_terminated.dapui_config = function() dapui.close() end
dap.listeners.before.event_exited.dapui_config = function() dapui.close() end
В nvim-dap нет навязанных кейбиндов - вы биндите функции сами. Типовая раскладка (близкая к F-клавишам IDE; именно она встречается в каноничных примерах nvim-dap - <S-F11> под step out, как в большинстве IDE):
Код: Выделить всё
Клавиша / вызов | Действие
------------------------------------------+--------------------------------
<F5> -> dap.continue() | старт / продолжить выполнение
<F10> -> dap.step_over() | шаг через (step over)
<F11> -> dap.step_into() | шаг внутрь (step into)
<S-F11> -> dap.step_out() | шаг наружу (step out)
<leader>b -> dap.toggle_breakpoint() | поставить/снять точку останова
<leader>B -> dap.set_breakpoint(условие) | условная точка останова
<leader>dr -> dap.repl.open() | открыть REPL отладчика
<leader>du -> dapui.toggle() | показать/скрыть панели dap-ui
Код: Выделить всё
vim.keymap.set("n", "<F5>", function() require("dap").continue() end, { desc = "Debug: continue" })
vim.keymap.set("n", "<F10>", function() require("dap").step_over() end, { desc = "Debug: step over" })
vim.keymap.set("n", "<F11>", function() require("dap").step_into() end, { desc = "Debug: step into" })
vim.keymap.set("n", "<S-F11>", function() require("dap").step_out() end, { desc = "Debug: step out" })
vim.keymap.set("n", "<leader>b", function() require("dap").toggle_breakpoint() end, { desc = "Debug: toggle breakpoint" })
Установлен debugpy (например, через Mason или pip install debugpy в окружении проекта), настроен адаптер:
Код: Выделить всё
local dap = require("dap")
dap.adapters.python = {
type = "executable",
command = "python",
args = { "-m", "debugpy.adapter" },
}
dap.configurations.python = {
{
type = "python",
request = "launch",
name = "Launch file",
program = "${file}", -- текущий файл
-- Интерпретатор, которым debugpy ЗАПУСКАЕТ ваш код.
-- Без него debugpy цепляется к системному python, а не к venv проекта
-- (типичная причина "не находит мои пакеты").
pythonPath = function()
-- активный venv, если есть; иначе python из PATH
local venv = os.getenv("VIRTUAL_ENV")
if venv then return venv .. "/bin/python" end
return vim.fn.exepath("python3") or vim.fn.exepath("python") or "python"
end,
},
}
Сессия отладки шаг за шагом:Про окружение проекта. Поле command адаптера - это python, которым запускается сам debugpy.adapter; а pythonPath в configurations - это интерпретатор, которым debugpy запускает ваш код. Чтобы отладчик видел зависимости проекта, pythonPath должен указывать на python из активного venv (как выше). Если опустить pythonPath, отладка пойдёт через системный python - пакеты из окружения проекта будут "не видны".
Код: Выделить всё
Открыт buggy.py, курсор на строке 12
Нажимаем <leader>b -> на строке 12 появился знак точки останова (●)
Нажимаем <F5> -> dap.continue(): код стартует, dap-ui раскрывает панели,
выполнение замирает на строке 12
Смотрим панель Scopes -> видим локальные переменные и их значения
Нажимаем <F10> -> step over: перешли на строку 13, значения обновились
Печатаем в REPL: my_var -> отладчик вернул текущее значение my_var
Нажимаем <F5> -> продолжили до следующего breakpoint или конца
launch vs attach: подключение к работающему процессу
Выше request = "launch" - отладчик сам запускает программу. Но в реальной работе процесс часто уже крутится: веб-сервер (Django/Flask/uvicorn), воркер, тесты под pytest, удалённый или контейнерный процесс. Для этого есть request = "attach" - DAP подключается к уже работающему процессу, не перезапуская его.
Сценарий: запускаете приложение под debugpy в режиме ожидания отладчика, затем цепляетесь из Neovim к нужному хосту/порту:
Код: Выделить всё
# В терминале/контейнере: процесс ждёт подключения отладчика на порту 5678
python -m debugpy --listen 0.0.0.0:5678 --wait-for-client -m uvicorn app:app
Код: Выделить всё
-- В dap.configurations.python добавляем конфигурацию attach рядом с launch:
table.insert(dap.configurations.python, {
type = "python",
request = "attach",
name = "Attach :5678",
connect = { host = "127.0.0.1", port = 5678 },
-- сопоставление путей, если код в контейнере/на другом хосте:
pathMappings = {
{ localRoot = "${workspaceFolder}", remoteRoot = "." },
},
})
Точки останова посложнее
dap.set_breakpoint(condition, hit_condition, log_message) принимает до трёх аргументов - все опциональны, ненужные передавайте как nil. Отсюда три вида "умных" точек:
- Условная (condition): dap.set_breakpoint(vim.fn.input("Condition: ")) - останавливается, только когда выражение истинно (например, i == 42). Незаменимо в циклах.
- По счётчику срабатываний (hit_condition): останов не на конкретном значении, а на N-м проходе через строку - когда индекс цикла вам не виден или неудобен, но нужно "поймать 100-ю итерацию". Передаётся вторым аргументом:
Код: Выделить всё
-- остановиться на 100-м срабатывании этой точки
require("dap").set_breakpoint(nil, "100")
-- комбинируется с условием: считать только подходящие срабатывания
require("dap").set_breakpoint("user.id == 7", "3") -- 3-й раз, когда id == 7
- Logpoint (log_message): точка, которая не останавливает выполнение, а печатает сообщение в REPL; выражения в {...} интерполируются: dap.set_breakpoint(nil, nil, "iter={i} value={total}") - "принт без принтов" прямо в исходнике, без правки кода.
В LazyVim DAP подключается через Extra: :LazyExtras -> включить dap.core. Это ставит nvim-dap, nvim-dap-ui, virtual text и Mason-интеграцию для адаптеров плюс разумные кейбинды на <leader>d. Языковые Extras (lang.python, lang.go и т.д.) часто подтягивают и нужный адаптер. Если вы на дистрибутиве - начинайте отсюда, а не собирайте DAP руками.
3. Терминал внутри редактора
Встроенный :terminal
Neovim несёт настоящий терминальный эмулятор внутри буфера. Команда :terminal (или :term) открывает буфер, в котором запущена интерактивная оболочка - туда можно гнать сборку, тесты, git, что угодно, не выходя из редактора.
Ключевая особенность - режим терминала (Terminal mode). Когда вы "внутри" терминального буфера, нажатия идут в оболочку, а не в Neovim. Чтобы выйти в Normal-режим (для прокрутки, копирования, прыжков по буферу), нажмите <C-\><C-n>. Это самая частая точка спотыкания у новичков.
Код: Выделить всё
Команда / клавиша | Действие
-------------------+-------------------------------------------------+----------------------------------
:terminal | открыть терминал в текущем окне
:split | terminal | терминал в горизонтальном сплите
:vsplit | terminal | терминал в вертикальном сплите
<C-\><C-n> | выйти из Terminal-режима в Normal
i / a | вернуться в Terminal-режим (ввод) из Normal
:terminal <cmd> | запустить команду сразу (например :term make)
Код: Выделить всё
vim.keymap.set("t", "<Esc>", [[<C-\><C-n>]], { desc = "Terminal: to normal mode" })
-- Навигация из терминала в соседние окна без выхода вручную:
vim.keymap.set("t", "<C-h>", [[<C-\><C-n><C-w>h]])
vim.keymap.set("t", "<C-j>", [[<C-\><C-n><C-w>j]])
vim.keymap.set("t", "<C-k>", [[<C-\><C-n><C-w>k]])
vim.keymap.set("t", "<C-l>", [[<C-\><C-n><C-w>l]])
Автокоманда, чтобы терминальные буферы открывались сразу в режиме ввода и без номеров строк:Не вешайте <Esc> на выход из Terminal-режима глобально, если внутри терминала работаете в программах, которым нужен сам <Esc> (например, ещё один Vim или TUI). Делайте маппинг буфер-локальным через autocmd на TermOpen для конкретных оболочек.
Код: Выделить всё
vim.api.nvim_create_autocmd("TermOpen", {
group = vim.api.nvim_create_augroup("term-open", { clear = true }),
callback = function()
vim.opt_local.number = false
vim.opt_local.relativenumber = false
vim.cmd.startinsert()
end,
})
Встроенный :terminal примитивен: один буфер на окно, ручное управление. toggleterm.nvim (akinsho/toggleterm.nvim) делает работу с терминалом цивилизованной:
- Тоггл по горячей клавише - терминал "выезжает" (плавающим окном, сплитом или снизу) и прячется одним нажатием.
- Несколько пронумерованных терминалов - 2<C-\> открывает терминал №2. Число-префикс перед <C-\> работает только из Normal-режима и при заданном open_mapping; в Terminal-режиме (когда вы "внутри" терминала) счётчик набрать нельзя - сначала выйдите в Normal через <C-\><C-n>.
- Именованные кастомные терминалы для конкретных инструментов (например, lazygit - см. главу 29; node REPL; htop).
- Отправка текущей строки/выделения в терминал (ToggleTermSendCurrentLine, ToggleTermSendVisualSelection).
Код: Выделить всё
require("toggleterm").setup({
open_mapping = [[<c-\>]], -- Ctrl-\ открывает/прячет терминал
direction = "float", -- float | horizontal | vertical | tab
float_opts = { border = "rounded" },
})
Код: Выделить всё
local Terminal = require("toggleterm.terminal").Terminal
local lazygit = Terminal:new({ cmd = "lazygit", direction = "float", hidden = true })
vim.keymap.set("n", "<leader>gg", function() lazygit:toggle() end, { desc = "Lazygit" })
Код: Выделить всё
Возможность | :terminal | toggleterm
----------------------------------+-------------+------------
Тоггл одной клавишей | нет | да
Плавающее окно | вручную | да
Несколько именованных терминалов | вручную | да
Отправка строки/выделения | нет | да
Интеграция (lazygit и пр.) | вручную | из коробки
4. Интеграция с tmux
Зачем
Многие живут в tmux: несколько панелей, в одной - Neovim, в других - серверы, логи, REPL. Проблема в том, что у Neovim своя система окон (сплитов), а у tmux - своя система панелей, и переключаться приходится разными хоткеями: <C-w>h/j/k/l внутри Neovim и <prefix> + стрелки в tmux. Граница между "окном Neovim" и "панелью tmux" постоянно сбивает.
vim-tmux-navigator
vim-tmux-navigator (christoomey/vim-tmux-navigator) стирает эту границу. Вы ставите плагин в Neovim и добавляете парные привязки в ~/.tmux.conf. После этого <C-h>/<C-j>/<C-k>/<C-l> перемещают фокус сквозь границу: если рядом окно Neovim - прыгаем в него, если панель tmux - в неё. Один набор клавиш на всю сетку.
Сторона tmux (~/.tmux.conf):
Код: Выделить всё
# Умное переключение панелей, понимающее сплиты Vim/Neovim
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
| grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|l?n?vim?x?|fzf)(diff)?$'"
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h' 'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j' 'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k' 'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l' 'select-pane -R'
Код: Выделить всё
Курсор в окне кода (левый сплит Neovim)
Нажимаем <C-l> -> перешли в правый сплит Neovim (терминал)
Нажимаем <C-l> -> справа окон Neovim больше нет -> перешли в панель tmux с логами
Нажимаем <C-h> -> вернулись обратно в Neovim, в нужный сплит
5. neovim-remote: один Neovim снаружиПомните про clipboard и OSC52: tmux может ломать авто-детект OSC52 для системного буфера. Если копирование "молча" не работает по SSH, включите set -g allow-passthrough on в tmux или сконфигурируйте провайдер явно. Подробнее про регистры и clipboard - в главе 8.
Проблема
Вы внутри Neovim, открыли терминал (или работаете в tmux-панели рядом) и хотите из shell открыть файл в уже запущенном Neovim, а не плодить вложенные экземпляры. Классический случай - git commit: Git запускает $EDITOR для сообщения коммита, и если EDITOR=nvim, вы получаете Neovim внутри Neovim. Неприятно.
Решение
Neovim умеет слушать сокет. Запущенный экземпляр публикует адрес в переменной $NVIM (для дочерних процессов терминала это работает автоматически), либо его можно задать явно: nvim --listen /tmp/nvim.sock.
Управлять им снаружи можно двумя способами:
- neovim-remote (nvr) - отдельная утилита (pip install neovim-remote). Команды nvr файл, nvr -cc split файл, nvr --remote-wait (для редакторов коммитов - вернуть управление только после закрытия буфера).
- Нативно, без nvr - у nvim есть флаг --remote и семейство --remote-*: nvim --server $NVIM --remote файл открывает файл в уже запущенном сервере.
Код: Выделить всё
# В shell-профиле, например ~/.zshrc:
if [ -n "$NVIM" ]; then
export EDITOR='nvr --remote-wait' # вариант с neovim-remote
# либо нативно:
# export EDITOR="nvim --server $NVIM --remote-wait"
fi
Код: Выделить всё
Внутри :terminal набираем git commit
-> сообщение коммита открывается БУФЕРОМ в текущем Neovim (не вложенный nvim)
Редактируем, :wq
-> nvr возвращает управление git, коммит создан
6. Лучшие практики 2026
- Новичку - LazyVim как основа, kickstart.nvim параллельно для обучения. Рабочая IDE сразу плюс прозрачный однофайловый конфиг, чтобы понимать внутренности. Не выбирайте "или-или" - берите оба, но в разных ролях.
- Не смешивайте дистрибутив с хаотичными ручными правками. В LazyVim переопределяйте через слой opts (и :LazyExtras), а не правкой файлов дистрибутива. В kickstart, наоборот, слоёв нет - правьте файл напрямую.
- DAP начинайте с языкового Extra/готового адаптера, а не с ручной сборки. В LazyVim - dap.core + lang.*. Адаптеры ставьте через Mason (mason-nvim-dap), чтобы не возиться с путями.
- Условные точки, hit-condition и logpoints вместо print. Условие (i == 42), останов на N-м срабатывании (hit_condition) и логпоинты с интерполяцией экономят часы в циклах и горячих путях.
- Для уже запущенного процесса - request = "attach". Веб-сервер, воркер, тесты, код в Docker/на удалённом хосте отлаживаются подключением к работающему debugpy --listen, а не перезапуском через launch.
- Терминал - через toggleterm (или встроенный toggle LazyVim), а не голый :terminal. Тоггл одной клавишей, именованные терминалы под lazygit/REPL, отправка выделения.
- <C-\><C-n> - мышечная память для выхода из Terminal-режима. Замапьте <Esc> буфер-локально, но осторожно с вложенными TUI.
- Единый набор <C-h/j/k/l> через vim-tmux-navigator. Одни клавиши на сплиты Neovim и панели tmux - меньше когнитивной нагрузки.
- Один Neovim, а не матрёшка. Настройте EDITOR на nvr --remote-wait (или нативный --remote-wait) внутри терминала, чтобы git commit и подобное открывались буфером.
- Опытным Vim-юзерам не мигрировать без причины. Если ваш конфиг работает - дистрибутив не обязателен. На серверах, где нельзя ставить софт, держите беглость в чистом Vim (см. главу 24).
- Лезть в файлы дистрибутива вместо слоя override. Правки внутри LazyVim/NvChad затираются при обновлении и ломают каскад opts. Используйте предусмотренный механизм переопределения.
- Ждать, что nvim-dap сам поставит точки останова без адаптера. DAP - только клиент; без установленного debug adapter (debugpy/delve/codelldb) и конфигурации dap.configurations.<lang> ничего не запустится.
- Забыть request/program в конфиге DAP. Конфигурация требует как минимум type, request (launch/attach) и точки входа (program/${file}).
- "Залипнуть" в Terminal-режиме. Нажатия уходят в оболочку; команды Neovim не работают, пока не нажмёте <C-\><C-n>.
- Глобальный <Esc> на выход из терминала ломает вложенные TUI. Внутри терминала может крутиться программа, которой нужен сам <Esc> - делайте маппинг буфер-локальным.
- Поставить vim-tmux-navigator только в Neovim. Без парных привязок в ~/.tmux.conf сквозная навигация не работает - нужны обе стороны.
- EDITOR=nvim внутри терминала Neovim. git commit запустит вложенный Neovim. Решение - --remote-wait через nvr или нативно.
- Забыть --remote-wait (взять просто --remote). Git не дождётся текста коммита и завершится с пустым/незаполненным сообщением.
- Полагаться на OSC52-copy через tmux без allow-passthrough. Копирование в системный буфер по SSH "молча" не сработает (см. главу 8).
- Поставьте kickstart.nvim в песочнице. Используйте отдельный конфиг через переменную окружения NVIM_APPNAME (например, NVIM_APPNAME=kickstart nvim), чтобы не трогать основной ~/.config/nvim. Прочитайте init.lua целиком и найдите, где включается LSP, а где - пикер.
- Соберите минимальный DAP под свой язык. Установите адаптер (Python - debugpy, Go - delve), настройте dap.adapters и dap.configurations, привяжите <F5>/<F10>/<leader>b. Поставьте точку останова, запустите и пройдите три шага, наблюдая переменные в dap-ui.
- Условный breakpoint и hit-condition. В цикле на 100 итераций поставьте условную точку останова, срабатывающую только на i == 42. Затем уберите условие и поставьте точку с hit_condition = "42" (dap.set_breakpoint(nil, "42")) - убедитесь, что она тоже замирает на 42-м проходе, не зная про переменную i. Сравните оба подхода.
- Терминальный workflow. Настройте toggleterm с тогглом на <C-\> и отдельным плавающим терминалом под любой TUI (htop/lazygit). Отправьте текущую строку кода в терминал через ToggleTermSendCurrentLine.
- Сквозная навигация. Установите vim-tmux-navigator в Neovim и добавьте парные привязки в ~/.tmux.conf. В сессии tmux с панелью Neovim и панелью с tail -f логом пройдите <C-h/j/k/l> через границу редактора и tmux, ни разу не используя <prefix>.
- Никакой матрёшки. Настройте EDITOR на --remote-wait так, чтобы при git commit из встроенного :terminal сообщение открывалось буфером в текущем Neovim. Проверьте, что без --remote-wait Git завершается с пустым сообщением, а с ним - ждёт :wq.
- Attach к работающему процессу. Запустите простой веб-сервер или скрипт под python -m debugpy --listen 5678 --wait-for-client .... Добавьте в dap.configurations.python конфигурацию request = "attach" с connect = { host, port } и подключитесь из Neovim к живому процессу. Поставьте breakpoint в обработчике и поймайте реальный запрос.
- Изоляция конфига. Через NVIM_APPNAME поставьте LazyVim рядом со своим основным конфигом (~/.config/lazyvim + NVIM_APPNAME=lazyvim nvim), не трогая ~/.config/nvim. Убедитесь, что оба запускаются независимо и делят только бинарь Neovim. Заведите алиас для быстрого запуска.
- Дистрибутивы экономят недели. В 2026 практичный путь: жить на LazyVim (рабочая IDE из коробки, blink.cmp и snacks по умолчанию, Extras через :LazyExtras) и параллельно изучить kickstart.nvim построчно, чтобы понимать внутренности. NvChad - за скорость и UI (base46), AstroNvim - за модульность. Свой конфиг даёт полный контроль ценой времени.
- Не смешивайте правки дистрибутива со слоями его конфигурации - override идёт через opts, а не правку файлов.
- Отладка нативна. nvim-dap (DAP-клиент) + nvim-dap-ui (панели) + debug adapter под язык дают breakpoints, шаги, инспекцию и REPL без выхода в IDE. Условные точки, останов по счётчику срабатываний (hit_condition) и logpoints заменяют print. Для уже работающего процесса (веб-сервер, тесты, контейнер) - request = "attach", а не launch. Для Python указывайте pythonPath на интерпретатор venv, иначе debugpy не увидит зависимости проекта.
- Терминал под рукой. Встроенный :terminal плюс <C-\><C-n> для выхода из Terminal-режима; toggleterm - тоггл одной клавишей, именованные терминалы и отправка выделения.
- Бесшовные интеграции. vim-tmux-navigator объединяет сплиты Neovim и панели tmux под <C-h/j/k/l>; neovim-remote (nvr --remote-wait) и нативный --remote-wait избавляют от вложенных Neovim в git commit.