Tabnine client for Neovim
Table of Contents
- Install
- Activate (mandatory)
- Activate Tabnine Pro
- Tabnine Agent
- Commands
<Tab>andnvim-cmp- lualine integration
- Other statusline integrations
- Tabnine Enterprise customers (self hosted only)
- Keymaps examples
Install
Note this plugin requires having Neovim version >= v0.7
The Unix build script requires curl and unzip to be available in your $PATH
Unix (Linux, MacOS)
Using vim-plug
- Add the following in your
init.vim
call plug#begin() Plug 'codota/tabnine-nvim', { 'do': './dl_binaries.sh' } call plug#end()
- Restart Neovim and run
:PlugInstall
Using packer
- Add the following in your
init.lua:
require("packer").startup(function(use) use { 'codota/tabnine-nvim', run = "./dl_binaries.sh" } end)
- Restart Neovim and run
:PackerInstall
Using lazy.nvim
- Add the following in your
init.lua:
require("lazy").setup({ { 'codota/tabnine-nvim', build = "./dl_binaries.sh" }, })
- Restart Neovim and run
:Lazy
Windows
The build script needs a set execution policy. Here is an example on how to set it
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
For more information visit the official documentation
Windows installations need to be adjusted to utilize PowerShell. This can be accomplished by changing the do/run/build parameter in your plugin manager's configuration from ./dl_binaries.sh to pwsh.exe -file .\\dl_binaries.ps1
-- Example using lazy.nvim -- pwsh.exe for PowerShell Core -- powershell.exe for Windows PowerShell require("lazy").setup({ { 'codota/tabnine-nvim', build = "pwsh.exe -file .\\dl_binaries.ps1" }, })
If you need to use Tabnine on Windows and Unix you can change the config as follows
-- Get platform dependant build script local function tabnine_build_path() -- Replace vim.uv with vim.loop if using NVIM 0.9.0 or below if vim.uv.os_uname().sysname == "Windows_NT" then return "pwsh.exe -file .\\dl_binaries.ps1" else return "./dl_binaries.sh" end end require("lazy").setup({ { 'codota/tabnine-nvim', build = tabnine_build_path()}, })
Activate (mandatory)
Add this later in your init.lua:
require('tabnine').setup({ disable_auto_comment=true, accept_keymap="<Tab>", dismiss_keymap = "<C-]>", debounce_ms = 800, suggestion_color = {gui = "#808080", cterm = 244}, exclude_filetypes = {"TelescopePrompt", "NvimTree"}, log_file_path = nil, -- absolute path to Tabnine log file ignore_certificate_errors = false, -- workspace_folders = { -- paths = { "/your/project" }, -- get_paths = function() -- return { "/your/project" } -- end, -- }, })
init.vim users - the activation script is lua code. Make sure to have it inside lua block:
lua <<EOF " activate tabnine here EOF
Advanced use cases:
You can set accept_keymap and dismiss_keymap to false to disable them, then you can create mappings using require('tabnine.keymaps')
--- Example integration with Tabnine and LuaSnip; falling back to inserting tab if neither has a completion vim.keymap.set("i", "<tab>", function() if require("tabnine.keymaps").has_suggestion() then return require("tabnine.keymaps").accept_suggestion() elseif require("luasnip").jumpable(1) then return require("luasnip").jump(1) else return "<tab>" end end, { expr = true })
Activate Tabnine Pro
:TabnineHub- to open Tabnine Hub and log in to your account:TabnineLoginWithAuthToken- to log in using auth token (for headless environments, where no browser is available)
Sometimes Tabnine may fail to open the browser on Tabnine Hub, in this case use :TabnineHubUrl to get Tabnine Hub URL
Tabnine Agent
Tabnine Agent requires a webview component and a Node.js server to run.
Building the Webview
- Install the required dependencies:
# Debian/Ubuntu sudo apt-get install -y libgtk-3-dev libglib2.0-dev libjavascriptcoregtk-4.1-dev libsoup-3.0-dev libwebkit2gtk-4.1-dev # Arch pacman -S --needed gtk3 glib2 webkit2gtk-4.1 libsoup3 # macOS (dependencies included with system)
- Build the webview binary (requires Rust stable):
cd webview/ cargo build --release # Or if using nightly by default: rustup run stable cargo build --release
This creates the tabnine_webview binary in webview/target/release/.
Project Structure
tabnine-nvim/
├── node/
│ ├── installer/ # Node.js runtime installer (per-platform binaries)
│ └── server/ # Node.js proxy server for chat communication
├── webview/ # Rust webview binary source (wry-based)
├── binaries/ # TabNine completion engine (downloaded)
└── lua/tabnine/ # Neovim plugin Lua code
Commands
:TabnineStatus- to print Tabnine status:TabnineDisable- to disable Tabnine:TabnineEnable- to enable Tabnine:TabnineToggle- to toggle enable/disable:TabnineAgent- to launch Tabnine Agent:TabnineLoginWithAuthToken- to log in using auth token (for headless environments, where no browser is available):TabnineAccept- accept apply changes:TabnineReject- reject apply changes
Tabnine Agent commands
:TabnineAgent- to open Tabnine Agent:TabnineAgentClose- to close Tabnine Agent:TabnineAgentClear- to clear the current conversation:TabnineAgentNew- to start a new conversation:TabnineFix- to fix the function in scope:TabnineTest- to generate tests for function in scope:TabnineExplain- to explain the function in scope:TabnineAccept- accept apply changes:TabnineReject- reject apply changes
Note: The old
TabnineChat*commands are deprecated and will show a warning. Please use the newTabnineAgent*commands instead.
<Tab> and nvim-cmp
nvim-cmp maps <Tab> to navigating through pop menu items (see here) This conflicts with Tabnine <Tab> for inline completion. To get this sorted you can either:
- Bind Tabnine inline completion to a different key using
accept_keymap - Bind
cmp.select_next_item()&cmp.select_prev_item()to different keys, e.g:<C-k>&<C-j>
lualine integration
This plugin exposes a lualine tabnine component. e.g:
require('lualine').setup({ tabline = { lualine_a = {}, lualine_b = {'branch'}, lualine_c = {'filename'}, lualine_x = {}, lualine_y = {}, lualine_z = {} }, sections = {lualine_c = {'lsp_progress'}, lualine_x = {'tabnine'}} })
Other statusline integrations
To render tabnine status widget use:
require('tabnine.status').status()
Tabnine Enterprise customers (self hosted only)
In your init.lua:
these instructions are made for packer, but are pretty much the same with all package managers
local tabnine_enterprise_host = "https://tabnine.customer.com" require("packer").startup(function(use) use { 'codota/tabnine-nvim', run = "./dl_binaries.sh " .. tabnine_enterprise_host .. "/update" } end) require('tabnine').setup({ disable_auto_comment=true, accept_keymap="<Tab>", dismiss_keymap = "<C-]>", debounce_ms = 800, suggestion_color = {gui = "#808080", cterm = 244}, codelens_color = { gui = "#808080", cterm = 244 }, codelens_enabled = true, exclude_filetypes = {"TelescopePrompt", "NvimTree"}, log_file_path = nil, -- absolute path to Tabnine log file, tabnine_enterprise_host = tabnine_enterprise_host, ignore_certificate_errors = false, })
Keymaps examples
api.nvim_set_keymap("x", "<leader>q", "", { noremap = true, callback = require("tabnine.chat").open }) api.nvim_set_keymap("i", "<leader>q", "", { noremap = true, callback = require("tabnine.chat").open }) api.nvim_set_keymap("n", "<leader>q", "", { noremap = true, callback = require("tabnine.chat").open })

