Вайб-кодинг в Neovim: настройка CodeCompanion.nvim через RouterAI (Claude, Qwen, DeepSeek)
CodeCompanion.nvim — AI-плагин для Neovim (Apache-2.0, около 6,9 тыс. звёзд на GitHub): чат прямо в буфере, inline-правки с diff, командный режим и агент с инструментами (tools) для чтения и правки файлов. В этой статье мы подключим его к RouterAI через адаптер openai_compatible: один ключ для Claude, Qwen, DeepSeek и GLM, работа из России без VPN и оплата в рублях.
Статья написана для версии плагина v20.0.1 (октябрь 2026) и Neovim 0.12.6.
Требования
- Neovim 0.12 или новее (так сказано в документации установки);
-
curlв системе; - плагины plenary.nvim и nvim-treesitter (последний нужен для
yaml-парсера — разбора markdown-промптов и skills); - менеджер плагинов, в примерах — lazy.nvim;
- ключ RouterAI: зарегистрируйтесь на routerai.ru, пополните баланс и создайте ключ в разделе «Ключи API». Ключ показывают один раз, скопируйте его сразу.
Установка
Добавьте плагин в конфигурацию lazy.nvim. Документация рекомендует закрепить версию, чтобы обновления не ломали конфиг:
{
"olimorris/codecompanion.nvim",
version = "^20.0.0",
opts = {},
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-treesitter/nvim-treesitter",
},
},
Перезапустите Neovim, выполните :Lazy sync и проверьте зависимости командой :checkhealth codecompanion.

Предупреждения (WARNING) о yaml parser, markitdown и sqlite3 относятся к необязательным зависимостям: они нужны для markdown-промптов, загрузки веб-страниц и токенов Copilot и на работу с RouterAI не влияют.
Подключение к RouterAI
В CodeCompanion HTTP-адаптеры лежат в adapters.http. Для любого OpenAI-совместимого сервиса расширяют openai_compatible под собственным именем.
Шаг 1. Ключ в переменной окружения
Не храните ключ в конфиге: адаптер читает его из переменной окружения при каждом запросе.
export ROUTERAI_API_KEY="sk-xxxxxxxxxxxxxxxx"
Добавьте строку в ~/.bashrc или ~/.zshrc и запускайте Neovim из этого же окружения.
Шаг 2. Адаптер routerai
Создайте файл ~/.config/nvim/lua/plugins/codecompanion.lua:
return {
"olimorris/codecompanion.nvim",
version = "^20.0.0",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-treesitter/nvim-treesitter",
},
opts = {
adapters = {
http = {
routerai = function()
return require("codecompanion.adapters").extend("openai_compatible", {
formatted_name = "RouterAI",
env = {
url = "https://routerai.ru/api",
api_key = "ROUTERAI_API_KEY",
},
schema = {
model = {
default = "anthropic/claude-sonnet-5.5",
},
},
})
end,
},
},
interactions = {
chat = { adapter = "routerai" },
inline = { adapter = "routerai" },
cmd = { adapter = "routerai" },
},
},
}

Что здесь важно:
| Поле | Значение | Пояснение |
|---|---|---|
formatted_name |
RouterAI |
Название в заголовке чата и в списке адаптеров |
env.url |
https://routerai.ru/api |
Без /v1 — см. ниже |
env.api_key |
ROUTERAI_API_KEY |
Имя переменной окружения, а не сам ключ |
schema.model.default |
anthropic/claude-sonnet-5.5 |
Модель по умолчанию, id из каталога |
interactions.*.adapter |
routerai |
Чат, inline и cmd используют этот адаптер |
Почему url без /v1. Адаптер собирает адрес как url + chat_url, а chat_url по умолчанию равен /v1/chat/completions. Мы проверили: с url = "https://routerai.ru/api" запросы уходят на https://routerai.ru/api/v1/chat/completions и https://routerai.ru/api/v1/models. Если указать https://routerai.ru/api/v1, получится /api/v1/v1/chat/completions и ответ 404. В других инструментах Base URL RouterAI — https://routerai.ru/api/v1, но здесь /v1 добавляет сам адаптер.
Если не задать api_key, адаптер отправит значение OPENAI_API_KEY — ваш ключ OpenAI уйдёт не туда. Всегда задавайте api_key явно.
Команды и режимы
Ни одна команда по умолчанию не привязана к клавишам; список — в справочнике команд.
| Команда | Что делает |
|---|---|
:CodeCompanionChat |
Открывает чат-буфер |
:CodeCompanionChat Toggle |
Показывает или скрывает последний чат |
:CodeCompanionChat adapter=routerai model=qwen/qwen3-coder |
Чат с конкретным адаптером и моделью |
:CodeCompanion <запрос> |
Inline-правка текущего буфера или выделения |
:CodeCompanionCmd <запрос> |
Генерирует команду для командной строки Neovim |
:CodeCompanionActions |
Палитра действий и библиотека промптов |
Режимы (interactions) настраиваются отдельно: chat, inline и cmd. Так можно отдать чат мощной модели, а cmd — быстрой:
interactions = {
chat = { adapter = { name = "routerai", model = "anthropic/claude-sonnet-5.5" } },
inline = { adapter = { name = "routerai", model = "qwen/qwen3-coder" } },
cmd = { adapter = { name = "routerai", model = "z-ai/glm-5.3-flash" } },
},
Чат
Откройте файл и выполните :CodeCompanionChat. Сообщение отправляется по <C-s> в режиме вставки или <CR> в нормальном режиме. Чтобы модель увидела код, добавьте контекст #{buffer} — без него модель отвечает только по тексту сообщения (в нашей проверке на вопрос «какие функции экспортирует этот файл?» без #{buffer} модель попросила прислать код):
Какие функции экспортирует #{buffer:invoices.js}? Ответь коротко, списком.

Inline
Выделите код и выполните:
:'<,'>CodeCompanion Добавь JSDoc к totalAmount
Модель правит выделение, а изменения показываются как diff по блокам (hunk): ga принимает блок, gr отклоняет, g2 принимает все оставшиеся, g3 отклоняет все оставшиеся. Список клавиш открывается по ? в diff. Для inline модель обязана поддерживать tool calling — именно через него она правит буфер.

Агентный режим и подтверждения
Чтобы модель могла читать и менять файлы, добавьте в сообщение инструменты: @{files} даёт чтение, создание и правку файлов, @{agent} — полный набор, включая запуск команд:
@{files} Добавь docstring к каждой функции в #{buffer}
По умолчанию каждый чат стартует в режиме Ask (описано в руководстве по подтверждениям):
| Инструмент | До выполнения | После выполнения |
|---|---|---|
read_file, grep_search
|
Спрашивает | — |
run_command |
Спрашивает для каждой команды | — |
delete_file |
Спрашивает для каждого файла | — |
create_file, edit_file
|
Выполняется | Просит подтвердить изменение (diff) |
Ответы на запрос: g1 — всегда разрешать в этом чате, g2 — разрешить один раз, g3 — отклонить с причиной, g4 — отменить всё. Режим чата меняется клавишей gty: Ask, Auto (всё, кроме run_command и защищённых инструментов вроде delete_file) и YOLO (всё без вопросов). Режим Auto пишет правки сразу на диск, поэтому проверяйте результат командой :CodeCompanionCodeReview и держите проект под git.
Режим по умолчанию меняется так:
interactions = {
chat = {
tools = { opts = { approval_mode = "ask" } }, -- "ask", "auto" или "yolo"
},
},
Выбор модели
Идентификаторы сверены с каталогом RouterAI; все пять моделей отвечают через /api/v1/chat/completions и объявляют поддержку tools. Цены смотрите в каталоге — они зависят от модели и объёма контекста.
| Модель | Для чего |
|---|---|
anthropic/claude-sonnet-5.5 |
Рефакторинг и сложные многофайловые правки, основной вариант |
anthropic/claude-haiku-5.5 |
Быстрые ответы и мелкие правки |
qwen/qwen3-coder |
Генерация и правка кода, inline-запросы |
deepseek/deepseek-v4.1-flash-1017 |
Дешёвые массовые задачи: тесты, комментарии, мелкие правки |
z-ai/glm-5.3-flash |
Недорогие быстрые запросы, например для cmd
|
Модель в чате переключается клавишей ga (адаптер и модель), а при пустом default адаптер возьмёт первую модель из /v1/models. Чтобы список был коротким и не зависел от каталога, задайте его вручную:
schema = {
model = {
default = "anthropic/claude-sonnet-5.5",
choices = {
"anthropic/claude-sonnet-5.5",
"qwen/qwen3-coder",
"deepseek/deepseek-v4.1-flash-1017",
"z-ai/glm-5.3-flash",
},
},
},
Проверка подключения
- Запустите
nvimв каталоге проекта из того же терминала, где заданROUTERAI_API_KEY. - Выполните
:CodeCompanionChat— в заголовке ответа должно быть CodeCompanion (RouterAI). - Отправьте
Привет! Какая ты модель? #{buffer}по<C-s>. - Через несколько секунд придёт ответ. Если его нет, откройте
:checkhealth codecompanionи лог (stdpath("log"), файлcodecompanion.log).
Решение проблем
-
404 на запросе. В
env.urlстоитhttps://routerai.ru/api/v1. Уберите/v1: адаптер добавляет его сам. -
Ответ не приходит. Возможно, Neovim не видит переменную
ROUTERAI_API_KEY(например, запущен из GUI-ярлыка). Проверьте:lua print(vim.env.ROUTERAI_API_KEY ~= nil)(должно вывестиtrue; сам ключ не печатается) и запускайте Neovim из терминала с экспортированной переменной. -
Модель «не видит» файл. Добавьте
#{buffer}или#{buffer:имя_файла}; для правок —@{files}. - Inline не вносит правки. Модель должна поддерживать tool calling. Выберите одну из моделей из таблицы выше.
-
В списке моделей не те варианты или адаптер ждёт
/v1/modelsслишком долго. Задайтеschema.model.choicesвручную. Если определены два адаптера наopenai_compatible, у каждого задайтеdefaultиchoices: кэш моделей у них общий. -
Нужен подробный лог. Включите
opts = { log_level = "DEBUG" }вsetup(), повторите запрос и посмотритеcodecompanion.log; после отладки вернитеERROR.
Чем отличается от Avante
CodeCompanion шире по режимам: чат, inline, cmd, агент с инструментами и подтверждениями, библиотека промптов и подключение ACP-агентов. Цена — ручная конфигурация на Lua: адаптер, модели и подтверждения вы задаёте сами. Если нужен другой подход к AI в Neovim, посмотрите гайд по Avante.
Что дальше
- Каталог моделей RouterAI — актуальные id и контекст;
- Вайб-кодинг в Neovim с Avante — альтернативный плагин;
- Вайб-кодинг в Zed — другой редактор с нативным AI;
- Что такое вайб-кодинг;
- Документация CodeCompanion — rules, skills, MCP и prompt library.