▸ What is GitHub Copilot?

GitHub Copilot is an AI code completion tool that suggests entire lines or blocks of code as you type, based on context from your current file and comments. In Neovim, suggestions appear as greyed-out ghost text — press Tab to accept or keep typing to ignore.

Free tier available: Individual developers get a limited free plan. Enable it at your GitHub account settings under Copilot, then follow the authentication steps below.

▸ Prerequisites

GitHub Copilot Access

Free or paid plan activated at github.com/settings/copilot.

Node.js 18+

Required by the language server backend. Check with node --version.

Neovim 0.9+

copilot.lua requires 0.9+. The official copilot.vim works from 0.6+.

A plugin manager

Examples below use lazy.nvim. Adapt as needed for packer or other managers.

▸ Installation

There are two plugins to choose from. copilot.lua is recommended for modern Neovim setups — it is written in pure Lua and integrates cleanly with nvim-cmp.

copilot.vim
Official · Vimscript · Simpler, fewer options
-- lazy.nvim
{
  "github/copilot.vim",
  -- keymaps are set automatically:
  -- Tab         → accept
  -- Ctrl+]      → dismiss
  -- Alt+] / Alt+[ → next/prev
}
Tab conflict: copilot.vim maps Tab globally in insert mode, which often conflicts with snippet and completion plugins. See the Tab section below.

▸ Authentication

1

Run :Copilot setup

Neovim prints a one-time device code and opens (or tells you to open) github.com/login/device.

2

Enter the code in your browser

Paste the code shown in Neovim into the GitHub device page and click Authorise GitHub Copilot.

3

Verify with :Copilot status

Should print Copilot: Ready. If not, confirm Node.js is on your PATH (node --version) and your subscription is active.

▸ How It Works in the Editor

After a brief pause while typing, Copilot sends your file context to GitHub's servers and streams back a suggestion, shown as ghost text after your cursor.

Ghost text

The suggestion appears inline in grey. Press Tab to accept the full suggestion or Ctrl+Right to accept word by word.

Multiple suggestions

Copilot generates several alternatives. Cycle through them with Alt+] / Alt+[. Press Ctrl+] to dismiss all.

Context window

Copilot reads the content of your current file, open buffers, and comments. Descriptive comments and function signatures give better results.

Suggestions panel

Run :Copilot panel (copilot.vim) to open a split showing up to 10 alternative completions at once.

▸ Keybindings

Suggestion keys (insert mode)
TabAccept full suggestion
Ctrl+RightAccept next word only (copilot.lua)
Ctrl+Alt+]Accept next word only (copilot.vim)
Alt+]Next suggestion
Alt+[Previous suggestion
Ctrl+]Dismiss suggestion
Commands (normal mode)
:Copilot setupAuthenticate with GitHub
:Copilot statusCheck connection status
:Copilot enableEnable globally
:Copilot disableDisable globally
:Copilot panelOpen alternatives panel

▸ nvim-cmp Integration

Add copilot-cmp to surface Copilot suggestions inside the nvim-cmp popup menu alongside LSP and snippet completions.

-- lazy.nvim — add alongside copilot.lua
{
  "zbirenbaum/copilot-cmp",
  dependencies = "zbirenbaum/copilot.lua",
  config = true,
},

-- In your cmp config, add "copilot" as a source:
require("cmp").setup({
  sources = cmp.config.sources({
    { name = "copilot",  group_index = 2 },
    { name = "nvim_lsp", group_index = 2 },
    { name = "luasnip",  group_index = 2 },
    { name = "buffer",   group_index = 3 },
  }),
})
Tip: When using copilot-cmp, disable inline ghost text to avoid showing the same suggestion twice — set suggestion = { enabled = false } in your copilot.lua opts.

▸ Resolving Tab Conflicts

Copilot, LuaSnip, and nvim-cmp all compete for Tab. This mapping checks each in priority order and falls back to a literal tab.

vim.keymap.set("i", "<Tab>", function()
  local copilot  = require("copilot.suggestion")
  local luasnip  = require("luasnip")
  if copilot.is_visible() then
    copilot.accept()
  elseif luasnip.expand_or_jumpable() then
    luasnip.expand_or_jump()
  else
    return "<Tab>"
  end
end, { expr = true, silent = true })

▸ Disabling for Specific Filetypes

-- In copilot.lua opts:
filetypes = {
  markdown  = false,  -- avoid leaking prose
  yaml      = false,
  [".env"]  = false,  -- never suggest in env files
  ["*"]     = true,   -- enable everywhere else
},
Security: Always disable Copilot for .env files, secrets, and private configs. File contents are sent to GitHub's API with each request.

▸ Tips for Better Suggestions

Write descriptive comments

A comment like -- parse ISO date string and return table produces far better completions than an empty function body.

Name things clearly

Copilot infers intent from variable and function names. parseUserInput produces more relevant suggestions than foo.

Open related files

Copilot uses open buffers as context. Keeping interface or type definition files open helps it match your project's patterns.

Use the panel for exploration

:Copilot panel shows up to 10 alternatives at once — useful when you want to see different approaches to a problem.