theme: ricetheme
New palette
New palette

How to change the colorscheme in Neovim

Try a scheme with :colorscheme, install it with vim.pack, lazy.nvim or LazyVim, make it stick in init.lua, and match Neovim to the palette of your terminal.

Interface drawing of a split terminal: Neovim with Lua code in a deep blue night palette on the left, a shell prompt in the same colors on the right, sixteen color swatches beneath both
One palette for the editor and the terminal around it.

tl;dr the short answer

Type :colorscheme and a name to try a scheme, then put vim.cmd.colorscheme(‘name’) in init.lua after the line that loads its plugin, so it survives a restart. With lazy.nvim, give the scheme lazy = false and priority = 1000, and in LazyVim set the colorscheme option on LazyVim/LazyVim instead.

To try a colorscheme, type :colorscheme and its name: :colorscheme habamax recolors Neovim on the spot. To keep one, install the plugin that provides it and add vim.cmd.colorscheme('name') to your init.lua, after the line that loads the plugin; typed at the command line, a scheme only lasts until you quit. This guide was written against Neovim 0.12 and uses tokyonight.nvim as the example. It covers the built-in vim.pack, lazy.nvim and LazyVim, then matches the editor to the terminal around it so the whole rice shares one palette.

Try a scheme with :colorscheme

Neovim ships with more than two dozen schemes, so you can try the command before installing anything:

  • :colorscheme on its own prints the name of the scheme in use.
  • :colorscheme followed by a space and Tab cycles through every scheme Neovim can find, built-in and installed. Press Enter to apply one.
  • :set background=light (or dark) switches a scheme that has both versions. Changing it reloads the scheme.

Built-in ones worth a look are default (Neovim’s own since 0.10), habamax, retrobox, sorbet and unokai. Neovim 0.12 also ships Vim’s port of catppuccin, Latte on a light background and Mocha on a dark one, and :colorscheme vim brings back the colors from before 0.10.

Install one with vim.pack

Neovim 0.12 added a plugin manager of its own, so a colorscheme no longer needs a third-party one. The vim.pack documentation still calls it experimental, “yet should be stable enough for daily use”. Add this to ~/.config/nvim/init.lua:

vim.pack.add({ 'https://github.com/folke/tokyonight.nvim' })

require('tokyonight').setup({ style = 'night' })
vim.cmd.colorscheme('tokyonight')
  1. Restart Neovim. vim.pack asks you to confirm the first install, then downloads the plugin into ~/.local/share/nvim/site/pack/core/opt/.
  2. Run :colorscheme; it should print tokyonight-night.
  3. Commit ~/.config/nvim/nvim-pack-lock.json along with init.lua. vim.pack records the exact commit of every plugin there, so a new machine gets the same version.
  4. To update later, run :lua vim.pack.update(), read the changes in the tab it opens, then :write to accept them or :quit to skip.

Call setup() before the colorscheme line, as the tokyonight.nvim README asks: the options are read when the scheme loads. Its styles are storm, moon, night and day, and each is also a scheme name of its own, such as tokyonight-night.

Install one with lazy.nvim or LazyVim

lazy.nvim

Give the scheme its own spec, in a file under lua/plugins/ if your setup imports that folder, or in the list you pass to require('lazy').setup():

return {
  {
    'folke/tokyonight.nvim',
    lazy = false,
    priority = 1000,
    config = function()
      require('tokyonight').setup({ style = 'night' })
      vim.cmd.colorscheme('tokyonight')
    end,
  },
}

lazy = false loads it at startup instead of on demand, and priority = 1000 loads it before the other startup plugins (the default is 50), so plugins that read highlight groups when they start see the right colors. The lazy.nvim plugin spec recommends a high priority for colorschemes for this reason.

LazyVim

LazyVim already loads tokyonight in its moon style, comes with catppuccin installed too, and falls back to habamax if the scheme you pick fails to load. To switch, add the plugin and point LazyVim at it in lua/plugins/colorscheme.lua:

return {
  { 'ellisonleao/gruvbox.nvim' },
  {
    'LazyVim/LazyVim',
    opts = { colorscheme = 'gruvbox' },
  },
}

To keep tokyonight and only change its style, give its spec opts = { style = 'night' } instead. The LazyVim colorscheme page has the full specs for both bundled schemes.

Make it stick in init.lua

The colorscheme line has to run after the plugin is available, or Neovim stops with E185: Cannot find color scheme and keeps the default. Keep exactly one place that sets it: with LazyVim that’s the option above, anywhere else it’s one line in init.lua.

A guard keeps a fresh machine readable before its plugins have installed:

local ok = pcall(vim.cmd.colorscheme, 'tokyonight')
if not ok then
  vim.cmd.colorscheme('habamax')
end

A scheme you made yourself needs no plugin at all. Any .lua or .vim file in ~/.config/nvim/colors/ is found by name, so ~/.config/nvim/colors/mytheme.lua loads with vim.cmd.colorscheme('mytheme'). Keep the whole ~/.config/nvim folder, lockfile included, in your dotfiles; our guide to managing dotfiles with GNU Stow sets that up.

Preview schemes before you pick

  • Built in: the Tab cycling above. Apply one, look at a real file for a minute, try the next.
  • Telescope: :Telescope colorscheme enable_preview=true recolors the editor as you move through the list.
  • LazyVim: <leader>uC opens its colorscheme picker, which previews each scheme live.

To shortlist, install three or four, live with each for a day, then remove the rest. With vim.pack, take a plugin out of vim.pack.add() first, then run :lua vim.pack.del({ 'tokyonight.nvim' }) with its name; with lazy.nvim, delete its spec and run :Lazy clean. Catppuccin, Rosé Pine, Dracula and the Base16 schemes are in the palettes section of our Toolkit, each with ports for most of a rice.

Match Neovim to your terminal and desktop

A scheme looks its best when the terminal around Neovim wears the same colors.

  1. Check true color. :set termguicolors? should print termguicolors. Since 0.10, Neovim turns it on by itself when the terminal reports 24-bit color; if it prints notermguicolors, add vim.o.termguicolors = true to init.lua and check the tmux fix below.
  2. Use the scheme’s port in the terminal. tokyonight’s repository has an extras folder with themes for kitty, foot, Alacritty, Ghostty, tmux, fish and dozens more. For kitty, copy extras/kitty/tokyonight_night.conf into ~/.config/kitty/ and add include tokyonight_night.conf to kitty.conf.
  3. Line up the backgrounds. A terminal background one shade off from Neovim’s shows as a frame around the editor. Use the port with the same style, or make Neovim’s background transparent: tokyonight takes transparent = true in setup(), and the terminal’s own opacity setting, such as kitty’s background_opacity, decides what shows through.
  4. Or start from one palette. The Generator builds a palette from your wallpaper and writes a Neovim colorscheme and theme files for kitty, Alacritty and Ghostty from it. To build one by hand, how to make your own terminal color scheme gives every color its job. Inside Neovim’s own :terminal, most schemes set the sixteen colors through vim.g.terminal_color_0 to _15.

Tweak a few highlight groups

Put the cursor on anything and run :Inspect to see which highlight groups color it. If the scheme has a hook for overrides, like tokyonight’s on_highlights, use that. For any scheme, a ColorScheme autocommand reapplies your tweaks every time a scheme loads. Put it above the colorscheme line so the first load runs it too:

vim.api.nvim_create_autocmd('ColorScheme', {
  callback = function()
    vim.api.nvim_set_hl(0, 'Comment', { italic = false, update = true })
    for _, group in ipairs({ 'Normal', 'NormalFloat', 'SignColumn' }) do
      vim.api.nvim_set_hl(0, group, { bg = 'NONE', update = true })
    end
  end,
})

vim.cmd.colorscheme('tokyonight')

update = true, new in 0.12, changes only the attributes you name. Without it, nvim_set_hl replaces the whole group, so a lone { bg = 'NONE' } on Normal would wipe its text color as well.

Tip: keep overrides few and specific. Three lines that fix what bugs you survive a scheme update; fifty lines are a scheme of your own, and at that point it’s tidier to write one in ~/.config/nvim/colors/.

When the colors look wrong

  • E185 at startup. The name is misspelled or the plugin isn’t loaded yet. Tab-complete :colorscheme to see the exact names, and check that the line comes after vim.pack.add() or inside the lazy.nvim spec.
  • Washed out or off inside tmux. Add these to tmux.conf, with your own $TERM from outside tmux in place of xterm-kitty (tmux 3.2 or later), then restart tmux:
    set -g default-terminal "tmux-256color"
    set -as terminal-features ",xterm-kitty:RGB"
    :checkhealth run inside tmux has a tmux section that flags a wrong $TERM and missing true color.
  • A light scheme when you wanted dark. At startup Neovim sets background from the terminal’s own color, and schemes like tokyonight pick their light style from it. Load the dark style by name, such as tokyonight-night, or check your terminal’s background.
  • catppuccin doesn’t look like the plugin. That name now loads Vim’s built-in port, which isn’t maintained by the Catppuccin team. The catppuccin/nvim README loads the plugin as catppuccin-nvim, or by flavor, such as catppuccin-mocha.
  • A sidebar or statusline doesn’t match. The scheme has no colors for that plugin. tokyonight and catppuccin list the plugins they support in their READMEs; for the rest, a few groups in the autocommand above do it.
  • Another scheme wins. Something later in your config loads a different one. :colorscheme names the scheme in use; search your config for every colorscheme line and keep one.

There’s more on editors and how they fit a rice in Editors.

Questions

Why does my colorscheme reset when I restart Neovim?

A scheme typed at the command line only lasts for that session. Put vim.cmd.colorscheme(‘name’) in init.lua, after the line that installs or loads the plugin; if it runs before the plugin is available, Neovim stops with E185 and keeps the default. If the line is there and the scheme still changes, something later in your config loads another one.

Why do colors look wrong in Neovim inside tmux?

tmux has to be told that the terminal outside it supports 24-bit color, or Neovim falls back to fewer colors. Add set -g default-terminal “tmux-256color” and set -as terminal-features “,xterm-kitty:RGB” to tmux.conf, with your own $TERM in place of xterm-kitty, then restart tmux. Running :checkhealth inside tmux reports when true color isn’t detected.

How do I make Neovim’s background transparent?

Many schemes have an option for it, such as transparent = true in tokyonight or transparent_background = true in catppuccin. For any other scheme, clear the background of Normal, NormalFloat and SignColumn in a ColorScheme autocommand. The terminal then shows through, so its own opacity setting decides what you see.

How do I see which colorschemes I have installed?

Type :colorscheme followed by a space and press Tab to cycle through every scheme Neovim can find, built-in ones included, or Ctrl-D to list them all at once. From Lua, vim.fn.getcompletion(‘’, ‘color’) returns the same list.

Sources

  1. Syntax and highlighting: :colorscheme, Neovim user documentation
  2. vim.pack: the built-in plugin manager, Neovim user documentation
  3. Plugin spec, lazy.nvim documentation
  4. tmux FAQ: How do I use RGB colour?, tmux wiki