⚙️ Configurable GitHub Copilot blink.cmp source for Neovim
![Completion Sample][title-image]
blink-copilot
⚙️ Configurable GitHub Copilot [blink.cmp][blink-cmp-github] source
Table of Contents
maxcompletions
- maxattempts
- kindname
- kindicon
- kindhl
- debounce
- autorefresh
📋 Requirements
- Neovim >= 0.11.0
- GitHub Copilot LSP Provider (choose one of the following)
🌟 Features
- Compliant with the blink.cmp async specification.
- Automatically detects the LSP client during buffer switches.
- Supports multiple completion candidates.
- Refreshes Copilot suggestion items dynamically as the cursor moves.
- Implemented entirely in Lua using the latest GitHub Copilot LSP APIs.
- Offers an improved preview with auto-indentation for completion items.
- Compatible with both copilot.lua and the official copilot.vim LSP providers.
- Easily configurable icon and kind settings.
🥘 Recipes
Here are some example configuration for using blink-copilot with [lazy.nvim][lazy-nvim-github].
blink-copilot + Copilot Language Server
Sign in to Copilot, or use the :LspCopilotSignIn command from https://github.com/neovim/nvim-lspconfig.
Option 1: Mason-lspconfig
Using
mason-lspconfig.nvim (simpler)
{
"williamboman/mason-lspconfig.nvim", --No manual LSP configuration needed
opts = {
ensure_installed = { "copilot" },
},
dependencies = { "williamboman/mason.nvim" },
},
{
"saghen/blink.cmp",
dependencies = { "fang2hou/blink-copilot" },
opts = {
sources = {
default = { "lsp", "path", "snippets", "buffer", "copilot" },
providers = {
copilot = {
name = "copilot",
module = "blink-copilot",
async = true,
},
},
},
},
},
Option 2: Mason + Custom lspconfig
Using
mason.nvim + nvim-lspconfig (more control)
{
"neovim/nvim-lspconfig",
opts = {
servers = {
copilot = {}, -- manual LSP configuration
},
},
},
{
"mason-org/mason.nvim",
opts = { ensure_installed = { "copilot" } },
},
{
"saghen/blink.cmp",
dependencies = { "fang2hou/blink-copilot" },
opts = {
sources = {
default = { "lsp", "path", "snippets", "buffer", "copilot" },
providers = {
copilot = {
name = "copilot",
module = "blink-copilot",
async = true,
},
},
},
},
},
blink-copilot + zbirenbaum/copilot.lua
{
"zbirenbaum/copilot.lua",
cmd = "Copilot",
event = "InsertEnter",
opts = {
suggestion = { enabled = false },
panel = { enabled = false },
filetypes = {
markdown = true,
help = true,
},
},
},
{
"saghen/blink.cmp",
optional = true,
dependencies = { "fang2hou/blink-copilot" },
opts = {
sources = {
default = { "copilot" },
providers = {
copilot = {
name = "copilot",
module = "blink-copilot",
score_offset = 100,
async = true,
},
},
},
},
}
blink-copilot + github/copilot.vim
{
"github/copilot.vim",
cmd = "Copilot",
event = "BufWinEnter",
init = function()
vim.g.copilotnomaps = true
end,
config = function()
-- Block the normal Copilot suggestions
vim.api.nvimcreateaugroup("github_copilot", { clear = true })
vim.api.nvimcreateautocmd({ "FileType", "BufUnload" }, {
group = "github_copilot",
callback = function(args)
vim.fn["copilot#On" .. args.event]()
end,
})
vim.fn["copilot#OnFileType"]()
end,
},
{
"saghen/blink.cmp",
dependencies = { "fang2hou/blink-copilot" },
opts = {
sources = {
default = { "copilot" },
providers = {
copilot = {
name = "copilot",
module = "blink-copilot",
score_offset = 100,
async = true,
},
},
},
},
}
blink-copilot + copilotlsp-nvim/copilot-lsp
You can check the [official documentation][copilot-lsp-github].
{
"copilotlsp-nvim/copilot-lsp",
init = function()
vim.g.copilotnesdebounce = 500
vim.lsp.enable("copilot_ls")
vim.keymap.set("n", "<tab>", function()
local bufnr = vim.api.nvimgetcurrent_buf()
local state = vim.b[bufnr].nes_state
if state then
local = require("copilot-lsp.nes").walkcursorstartedit()
or (
require("copilot-lsp.nes").applypendingnes()
and require("copilot-lsp.nes").walkcursorend_edit()
)
return nil
else
return "<C-i>"
end
end, { desc = "Accept Copilot NES suggestion", expr = true })
end,
}
{
"saghen/blink.cmp",
dependencies = { "fang2hou/blink-copilot" },
opts = {
sources = {
default = { "copilot" },
providers = {
copilot = {
name = "copilot",
module = "blink-copilot",
score_offset = 100,
async = true,
},
},
},
keymap = {
preset = "super-tab",
["<Tab>"] = {
function(cmp)
if vim.b[vim.api.nvimgetcurrentbuf()].nesstate then
cmp.hide()
return (
require("copilot-lsp.nes").applypendingnes()
and require("copilot-lsp.nes").walkcursorend_edit()
)
end
if cmp.snippet_active() then
return cmp.accept()
else
return cmp.selectandaccept()
end
end,
"snippet_forward",
"fallback",
},
},
},
}
With 💤 LazyVim [copilot][lazyvim-copilot-extra] extra
-- Import copilot extra (you can also use :LazyExtras to install it)
{ import = "lazyvim.plugins.extras.ai.copilot" },
(Optional)
copilot.lua ➡️ Copilot Language Server
{
"zbirenbaum/copilot.lua",
enabled = false,
},
{
"neovim/nvim-lspconfig",
opts = {
servers = {
-- LazyVim Extra disabled it for copilot.lua
copilot = { enabled = true },
},
},
},
{
"mason-org/mason.nvim",
opts = { ensure_installed = { "copilot" } },
},
(Optional)
copilot.lua ➡️ copilot.vim
{
"zbirenbaum/copilot.lua",
enabled = false,
},
{
"github/copilot.vim",
cmd = "Copilot",
event = "BufWinEnter",
init = function()
vim.g.copilotnomaps = true
end,
config = function()
-- Block the normal Copilot suggestions
vim.api.nvimcreateautocmd({ "FileType", "BufUnload" }, {
group = "github_copilot",
callback = function(args)
vim.fn["copilot#On" .. args.event]()
end,
})
vim.fn["copilot#OnFileType"]()
end,
}
⚙️ Configuration
blink-copilot seamlessly integrates with both blink.cmp source options and Neovim plugin configurations. For most users, simply configuring the options within blink options sources.provider.copilot.opts is sufficient.
{
"saghen/blink.cmp",
optional = true,
dependencies = {
"fang2hou/blink-copilot",
opts = {
max_completions = 1, -- Global default for max completions
max_attempts = 2, -- Global default for max attempts
}
},
opts = {
sources = {
default = { "copilot" },
providers = {
copilot = {
name = "copilot",
module = "blink-copilot",
score_offset = 100,
async = true,
opts = {
-- Local options override global ones
maxcompletions = 3, -- Override global maxcompletions
-- Final settings: -- * max_completions = 3 -- * max_attempts = 2 -- * all other options are default } }, }, }, }, }
Here is the default configuration for blink-copilot:
{
max_completions = 3,
max_attempts = 4,
kind_name = "Copilot", ---@type string | false
kind_icon = " ", ---@type string | false
kind_hl = false, ---@type string | false
debounce = 200, ---@type integer | false
auto_refresh = {
backward = true,
forward = true,
},
}
max_completions
Maximum number of completions to show.
[!NOTE]
Sometimes Copilot do not provide any completions, even you set max_completions
to a large number. This is a limitation of Copilot itself, not the plugin.
Default: 3
max_attempts
Maximum number of attempts to fetch completions.
[!NOTE]
Each attempt will fetch 0 ~ 10 completions. Considering the possibility of failure,
it is generally recommended to set it to max_completions+1.
Default: 4
kind_name
Specifies the type of completion item to display. Some distros may automatically set icon from the kind_name.
Set to false to disable the kind_name in completion items.
Default: "Copilot"
kind_icon
Specifies the icon of completion item to display.
Set to false to disable the kind_icon in completion items.
Default: " " (![default-icon][copilot-icon-image])
kind_hl
Specifies the highlight group of completion item to display.
Set to false to disable the kind_hl in completion items.
Default: false
debounce
[!NOTE]
Debounce is a feature that limits the number of requests sent to Copilot.
You can customize the debounce time in milliseconds or set it to false to
disable it.
[!IMPORTANT]
If you disable debounce and enable auto_refresh, the copilot suggestion
items will be refreshed every time the cursor moves.
Excessive refreshing may temporarily block your Copilot.
Default: 200
auto_refresh
Automatically refreshes the completion list when the cursor moves.
[!NOTE]
If you enable backward, the completion list will be refreshed when the cursor
moves backward. If you enable forward, the completion list will be refreshed
when the cursor moves forward.
Default: { backward = true, forward = true }
📚 Frequently Asked Questions
The number of completions does not match my settings.
This is because the number of completions provided by Copilot is not fixed. The max_completions setting is only an upper limit, and the actual number of completions may be less than this value.
What's the difference betweenblink-copilotandblink-cmp-copilot?
- Completion Preview is now correctly deindented.
- Support both
copilot.luaandcopilot.vimas a backend. - Support multiple completions, and it is configurable.
- LSP interaction no longer relies on
copilot.lua, ensuring improved
- Auto refresh copilot suggestion items when cursor moves.
The completion isn't working after restarting Copilot. What should I do?
The Copilot plugin doesn't automatically attach the new LSP client to buffers. To resolve this, manually reopen your current buffer to attach the LSP client. blink-copilot will automatically detect the new client and resume completions.
Why aren't blink completions showing up?
Blink intentionally pauses completions during macro recording. If you see recording @x in your statusline, press q to stop recording.
🔄 Alternatives and Related Projects
- [hrsh7th/cmp-copilot][cmp-copilot-github] -
nvim-cmp.
- [zbirenbaum/copilot-cmp][copilot-cmp-github] -
nvim-cmp.
- [giuxtaposition/blink-cmp-copilot][blink-cmp-copilot-github] -
blink.cmp.
🪪 License
MIT
[title-image]: https://github.com/user-attachments/assets/dbe4dee4-811f-4f46-be89-4d58dfea9433 [copilot-icon-image]: https://github.com/user-attachments/assets/06330b50-2386-4fc1-8dbd-8040ec4cb2df [copilot-language-server]: https://github.com/github/copilot-language-server-release [copilot-vim-github]: https://github.com/github/copilot.vim [copilot-lua-github]: https://github.com/zbirenbaum/copilot.lua [copilot-lsp-github]: https://github.com/copilotlsp-nvim/copilot-lsp [lazyvim-copilot-extra]: https://www.lazyvim.org/extras/ai/copilot [lazy-nvim-github]: https://github.com/folke/lazy.nvim [blink-cmp-github]: https://github.com/Saghen/blink.cmp [cmp-copilot-github]: https://github.com/hrsh7th/cmp-copilot [copilot-cmp-github]: https://github.com/zbirenbaum/copilot-cmp [blink-cmp-copilot-github]: https://github.com/giuxtaposition/blink-cmp-copilot