Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

code-2026

code-2026

code-2026.nvim

A dark and light Neovim colorscheme ported from VS Code's Dark Modern 2026 theme — red keywords, purple functions, teal types and light-blue strings.

Based on D0nw0r/dark2026.nvim, rebuilt as a configurable plugin.

The code-2026 family

Target Repository
Neovim code-2026-theme/nvim this repo
Ghostty code-2026-theme/ghostty terminal theme
kitty code-2026-theme/kitty terminal theme
Xcode code-2026-theme/xcode editor theme
Obsidian code-2026-theme/obsidian app theme
Yazi code-2026-theme/yazi file manager

Every port shares one palette, so :terminal inside Neovim renders identically to the host terminal. See Matching your terminal for the values.

Features

  • 638 highlight groups — editor UI, legacy syntax, tree-sitter, LSP semantic tokens, diagnostics, diffs, and 28 plugins.
  • Transparency for the editor, with floating windows controlled separately.
  • Per-token styling — bold/italic/underline for 20 semantic token families.
  • Palette overrides, static (palette) or programmatic (on_colors).
  • Highlight overrides, static (highlights) or programmatic (on_highlights).
  • Per-plugin opt-out for every plugin integration.
  • Terminal colors (vim.g.terminal_color_*) and a lualine theme.
  • No dependencies. Config errors warn instead of breaking your session.

Requirements

  • Neovim 0.9+
  • A true-color terminal ('termguicolors' is set by the theme)

Installation

vim.pack (Neovim 0.12+)

In init.lua:

vim.pack.add {
  { src = 'https://github.com/code-2026-theme/nvim', name = 'code-2026' },
}

require('code-2026').setup {}
vim.cmd.colorscheme 'code-2026'

name matters here: the repository is code-2026-theme/nvim, and vim.pack names the plugin directory after the repository, so without it the theme would be installed as nvim.

No priority or lazy equivalent is needed — vim.pack.add() installs (on first run) and adds to 'runtimepath' synchronously, so the plugin is usable on the next line.

To follow a branch, tag or commit instead of the default branch:

vim.pack.add {
  {
    src = 'https://github.com/code-2026-theme/nvim',
    name = 'code-2026',
    version = 'main',                     -- branch, tag, or commit hash
    -- version = vim.version.range('1.0'), -- or the greatest matching semver tag
  },
}

Then:

  • :lua vim.pack.update() — fetch updates and open a confirmation buffer; :write to apply, :quit to discard.
  • :lua vim.pack.del({ 'code-2026' }) — uninstall, after removing the spec from init.lua.

See :help vim.pack for the rest.

lazy.nvim
{
  'code-2026-theme/nvim',
  name = 'code-2026',
  lazy = false,
  priority = 1000,
  opts = {},
  config = function(_, opts)
    require('code-2026').setup(opts)
    vim.cmd.colorscheme 'code-2026'
  end,
}
packer.nvim
use {
  'code-2026-theme/nvim',
  as = 'code-2026',
  config = function()
    require('code-2026').setup {}
    vim.cmd.colorscheme 'code-2026'
  end,
}

setup() is optional — :colorscheme code-2026 alone gives you the defaults. Call setup() only when you want to change something, and always before the colorscheme command (calling it afterwards reapplies the theme, which also works).

Configuration

The complete set of options, with defaults:

require('code-2026').setup {
  background = 'dark',      -- 'dark' | 'light' | 'auto' | 'sync'
  transparent = false,      -- clear the editor background
  terminal_colors = true,   -- set vim.g.terminal_color_0..15
  dim_inactive = false,     -- darken unfocused windows (NormalNC)

  styles = {
    comments = { italic = true },
    keywords = {},
    conditionals = {},
    functions = {},
    methods = {},
    variables = {},
    builtins = { italic = true },
    parameters = {},
    properties = {},
    types = {},
    strings = {},
    numbers = {},
    booleans = {},
    constants = {},
    operators = {},
    namespaces = {},
    macros = {},
    attributes = {},
    tags = {},
    headings = { bold = true },

    floats = 'solid',       -- 'solid' | 'transparent' | 'auto'
  },

  palette = {},                                        -- static color overrides
  on_colors = function(colors) end,                    -- programmatic color overrides
  highlights = {},                                     -- static highlight overrides
  on_highlights = function(highlights, colors) end,    -- programmatic highlight overrides
  plugins = {},                                        -- e.g. { telescope = false }
}

Unknown option names and invalid styles.floats values produce a warning and are ignored — a typo will never leave you without a colorscheme.


background

Selects the light or dark variant.

Value Effect
'dark' (default) Always use the dark palette
'light' Always use the light palette
'auto' Detect the OS color mode once at setup() and stay fixed
'sync' Detect at setup() and re-apply whenever the OS color mode changes

'auto' and 'sync' read the OS setting via macOS defaults read -g AppleInterfaceStyle or GNOME gsettings. They fall back to 'dark' when detection is unavailable.

-- Follow the OS appearance, switching in real time:
require('code-2026').setup { background = 'sync' }

When background changes, vim.o.background is updated and the ColorScheme event fires so statuslines and other plugins can pick the new palette.

transparent

Clears the background of Normal, NormalNC, the sign column, line numbers, fold column, statusline, tabline, winbar and diagnostic virtual text, letting your terminal background through.

require('code-2026').setup { transparent = true }

Floating windows are not affected — see styles.floats.

styles.floats

Value Effect
'solid' (default) Floats, popups and completion menus always painted (#202122)
'transparent' Floats never painted
'auto' Follows transparent

Keeping this at 'solid' with transparent = true gives you a see-through editor with readable popups, which is usually what you want:

require('code-2026').setup {
  transparent = true,
  styles = { floats = 'solid' },
}

Affects NormalFloat, FloatBorder, FloatTitle, Pmenu*, and the float-based groups of every plugin integration (telescope, blink.cmp, noice, lazy, mason, …).

terminal_colors

Sets vim.g.terminal_color_0vim.g.terminal_color_15 so :terminal buffers use the theme's ANSI palette. Set to false to leave them alone. See Matching your terminal for the same values in Ghostty/kitty form.

dim_inactive

Paints unfocused windows (NormalNC) with bg_inactive, a darkened bg. Ignored when transparent = true.

styles.<token>

Every entry is an nvim_set_hl() attribute table merged into the highlight specs of that token family. Add an attribute with true, remove one the theme sets with false:

require('code-2026').setup {
  styles = {
    comments = { italic = false },   -- drop the default italic
    keywords = { italic = true },
    functions = { bold = true },
    types = { italic = true },
    parameters = { italic = true },
    headings = { bold = true, underline = true },
  },
}

Usable attributes: bold, italic, underline, undercurl, underdouble, underdotted, underdashed, strikethrough, reverse, nocombine.

Key Default Applies to (plus every group linked to these)
comments { italic = true } Comment, SpecialComment, @comment*, @markup.quote
keywords Keyword, Statement, Label, StorageClass, PreProc, Include, Define, PreCondit, @keyword*
conditionals Conditional, Repeat, Exception, @keyword.return, @keyword.conditional, @keyword.repeat
functions Function, @function, @function.call, @function.builtin
methods @function.method, @function.method.call, @lsp.type.method
variables Identifier, @variable, @variable.builtin
builtins { italic = true } @variable.builtin, @function.builtin, @type.builtin, @module.builtin, @attribute.builtin
parameters @variable.parameter, @lsp.type.parameter
properties @property, @field, @variable.member, @lsp.type.property
types Type, Structure, Typedef, @type*, @constructor, @lsp.type.class/enum/interface/struct
strings String, Character, @string*, @string.escape, @string.regexp
numbers Number, Float, @number, @number.float
booleans Boolean, @boolean
constants Constant, @constant*, @lsp.type.enumMember, @lsp.type.const, readonly variables
operators Operator, @operator, @lsp.type.operator
namespaces @module, @namespace, @lsp.type.namespace
macros Macro, @function.macro, @constant.macro, @lsp.type.macro
attributes @attribute, @tag.attribute, @lsp.type.decorator
tags Tag, @tag, @tag.builtin
headings { bold = true } @markup.heading and @markup.heading.1.6

palette

Static color overrides, applied on top of the base palette before anything is derived:

require('code-2026').setup {
  palette = {
    bg = '#0d0e0f',
    keyword = '#f97583',
    func = '#c9a0ff',
    comment = '#7d8590',
  },
}
All palette keys

Backgrounds

Key Value Used for
bg #121314 editor background
bg_alt #191a1b statusline, tabline, panels
bg_menu #202122 floats, popups, completion
bg_line #242526 cursorline, folds, inlay hints
bg_widget #262728 LSP references, illuminate
bg_select #276782 visual selection
bg_match #1e4252 search matches
border #2a2b2c window separators
border_alt #333536 float borders

Foregrounds

Key Value Used for
fg #bbbebf default text
fg_alt #bfbfbf emphasized text
fg_dim #8c8c8c secondary text
fg_muted #555555 line numbers, whitespace
white #ffffff text on accent backgrounds

Accent

Key Value
accent #3994bc
accent_dim #297aa0
accent_alt #48a0c7

Syntax

Key Value Key Value
comment #8b949e annotation #ffa657
string #a5d6ff param #ffa657
regex #7ee787 member #79c0ff
number #79c0ff tag #7ee787
keyword #ff7b72 attr #79c0ff
func #d2a8ff module #4ec9b0
type #4ec9b0 macro #48a0c7
variable #bbbebf operator #ff7b72
constant #79c0ff preproc #ff7b72

Diagnostics & diff

Key Value Key Value
err #f44747 diff_add #1b3a1b
warn #cd9731 diff_add_fg #7ee787
info #6796e6 diff_del #3a1b1b
hint #3a94bc diff_del_fg #ffa198
ok #7ee787 diff_chg #2a2a4a
debug #b267e6 diff_chg_fg #79c0ff
diff_text #3a3a63

Derived — computed from the above after palette is applied, so they follow your overrides. Set them explicitly in palette to opt out of the derivation.

Key Derivation
bg_normal NONE when transparent, else bg
bg_panel NONE when transparent, else bg_alt
bg_float NONE when floats are transparent, else bg_menu
bg_inactive bg darkened 35% (used by dim_inactive)
err_bg warn_bg info_bg hint_bg diagnostic color blended 12% onto bg
terminal table of the 16 ANSI colors

on_colors(colors)

Runs after palette, with the whole resolved palette — including the derived keys. Mutate it in place:

local util = require 'code-2026.util'

require('code-2026').setup {
  on_colors = function(colors)
    colors.comment = util.lighten(colors.comment, 0.15)  -- brighter comments
    colors.bg_float = colors.bg                          -- floats share the editor bg
    colors.terminal[1] = '#ff5555'                       -- custom ANSI red
  end,
}

util exposes blend(fg, bg, alpha), darken(hex, amount), lighten(hex, amount), hex_to_rgb and rgb_to_hex.

highlights

Static highlight-group overrides, merged last — after the theme and after on_highlights:

require('code-2026').setup {
  highlights = {
    Comment = { fg = '#6f7680' },       -- merged: the theme's italic is kept
    CursorLine = { bg = '#1c1d1e' },
    ['@variable.parameter'] = { fg = '#ffa657', italic = true },
    Visual = { link = 'CursorLine' },   -- a spec with `link` replaces the group outright
  },
}

Merge rules: table entries merge key-by-key, so you can change only fg and keep the rest. Pass italic = false to clear an attribute. A spec containing link replaces the group completely.

on_highlights(highlights, colors)

Same thing, programmatically, with the palette in hand. Receives the fully built highlight table before highlights is merged on top:

require('code-2026').setup {
  on_highlights = function(hl, colors)
    hl.LineNr = { fg = colors.fg_dim }
    hl.WinSeparator = { fg = colors.accent_dim }
    hl.CursorLineNr = { fg = colors.accent, bold = true }
    hl.MyPluginTitle = { fg = colors.accent, bold = true }  -- new groups are fine too
  end,
}

plugins

All plugin integrations are on by default. Disable any of them by key — the theme then leaves those groups untouched, so the plugin's own defaults (or your config) apply:

require('code-2026').setup {
  plugins = { bufferline = false, dap = false },
}
Key Plugin Key Plugin
gitsigns gitsigns.nvim neo_tree neo-tree.nvim
telescope telescope.nvim nvim_tree nvim-tree.lua
fzf_lua fzf-lua oil oil.nvim
snacks snacks.nvim (picker, notifier, dashboard, indent) indent_blankline indent-blankline.nvim
blink blink.cmp mini mini.nvim (statusline, tabline, pick, files, diff, indentscope)
cmp nvim-cmp lazy lazy.nvim
bufferline bufferline.nvim mason mason.nvim
which_key which-key.nvim trouble trouble.nvim
notify nvim-notify flash flash.nvim
noice noice.nvim illuminate vim-illuminate
dashboard dashboard-nvim, alpha-nvim treesitter_context nvim-treesitter-context
yanky yanky.nvim rainbow rainbow-delimiters.nvim
fidget fidget.nvim dap nvim-dap, nvim-dap-ui
markdown render-markdown.nvim navic nvim-navic

lualine

require('lualine').setup { options = { theme = 'code-2026' } }

The theme reads the resolved palette, so it follows your palette / on_colors overrides.

API

local dark = require 'code-2026'

dark.setup(opts)        -- store config; reapplies the theme if it is already active
dark.load(opts)         -- apply the colorscheme; opts override the stored config for this call
dark.colors(opts)       -- resolved palette table
dark.highlights(opts)   -- resolved highlight table + palette, without applying them

dark.colors() is handy for statuslines and other plugins that need to match:

local c = require('code-2026').colors()
vim.api.nvim_set_hl(0, 'MyGroup', { fg = c.accent, bg = c.bg_alt })

Matching your terminal

The ANSI palette used for :terminal and exported via vim.g.terminal_color_*:

Normal Bright
black #202122 bright black #555555
red #ff7b72 bright red #ffa198
green #7ee787 bright green #91eb99
yellow #cd9731 bright yellow #ffa657
blue #79c0ff bright blue #a5d6ff
magenta #d2a8ff bright magenta #b267e6
cyan #4ec9b0 bright cyan #71d4c0
white #bbbebf bright white #ffffff

With background #121314, foreground #bbbebf, cursor #bbbebf, selection #276782 on #ffffff. Ready-made theme files: Ghostty · kitty.

Ghostty
background = #121314
foreground = #bbbebf
cursor-color = #bbbebf
cursor-text = #121314
selection-background = #276782
selection-foreground = #ffffff

palette = 0=#202122
palette = 1=#ff7b72
palette = 2=#7ee787
palette = 3=#cd9731
palette = 4=#79c0ff
palette = 5=#d2a8ff
palette = 6=#4ec9b0
palette = 7=#bbbebf
palette = 8=#555555
palette = 9=#ffa198
palette = 10=#91eb99
palette = 11=#ffa657
palette = 12=#a5d6ff
palette = 13=#b267e6
palette = 14=#71d4c0
palette = 15=#ffffff
kitty
background            #121314
foreground            #bbbebf
cursor                #bbbebf
cursor_text_color     #121314
selection_background  #276782
selection_foreground  #ffffff
url_color             #48a0c7

color0  #202122
color8  #555555
color1  #ff7b72
color9  #ffa198
color2  #7ee787
color10 #91eb99
color3  #cd9731
color11 #ffa657
color4  #79c0ff
color12 #a5d6ff
color5  #d2a8ff
color13 #b267e6
color6  #4ec9b0
color14 #71d4c0
color7  #bbbebf
color15 #ffffff

Light terminal

With background #FFFFFF, foreground #202020, cursor #0069CC, selection #C2DAF5 on #202020.

Ghostty
background = #FFFFFF
foreground = #202020
cursor-color = #0069CC
cursor-text = #FFFFFF
selection-background = #C2DAF5
selection-foreground = #202020

palette = 0=#f0f1f2
palette = 1=#cf222e
palette = 2=#116329
palette = 3=#953800
palette = 4=#0550ae
palette = 5=#8250df
palette = 6=#116329
palette = 7=#202020
palette = 8=#999999
palette = 9=#cf222e
palette = 10=#116329
palette = 11=#953800
palette = 12=#0550ae
palette = 13=#8250df
palette = 14=#116329
palette = 15=#ffffff
kitty
background            #FFFFFF
foreground            #202020
cursor                #0069CC
cursor_text_color     #FFFFFF
selection_background  #C2DAF5
selection_foreground  #202020
url_color             #0069CC

color0  #f0f1f2
color8  #999999
color1  #cf222e
color9  #cf222e
color2  #116329
color10 #116329
color3  #953800
color11 #953800
color4  #0550ae
color12 #0550ae
color5  #8250df
color13 #8250df
color6  #116329
color14 #116329
color7  #202020
color15 #ffffff

Recipes

Transparent editor, solid popups, italic keywords
require('code-2026').setup {
  transparent = true,
  styles = {
    floats = 'solid',
    keywords = { italic = true },
    comments = { italic = true },
  },
}
No italics anywhere
require('code-2026').setup {
  styles = {
    comments = { italic = false },
    builtins = { italic = false },
  },
}
Darker background, flatter UI
require('code-2026').setup {
  palette = { bg = '#0b0c0d', bg_alt = '#0b0c0d', bg_menu = '#141516' },
  on_highlights = function(hl, c)
    hl.WinSeparator = { fg = c.bg_line }
    hl.SignColumn = { bg = c.bg_normal }
  end,
}
Reuse the palette in your own config
local c = require('code-2026').colors()

require('lualine').setup {
  options = { theme = 'code-2026' },
  sections = { lualine_c = { { 'filename', color = { fg = c.accent_alt } } } },
}

Structure

colors/code-2026.lua              :colorscheme entry point
lua/code-2026/init.lua            setup / load / colors / highlights
lua/code-2026/config.lua          defaults and validation
lua/code-2026/palette.lua         base palette and derived colors
lua/code-2026/theme.lua           group assembly and override pipeline
lua/code-2026/util.lua            color math and merge helpers
lua/code-2026/groups/             editor, syntax, treesitter, lsp, plugins
lua/lualine/themes/code-2026.lua  lualine theme
doc/code-2026.txt                 :help code-2026

Override precedence, in order: base palette → palette → derived colors → on_colors → highlight groups → on_highlightshighlights.

Credits

  • D0nw0r/dark2026.nvim by D0nw0r — the original port this is built on. Licensed MIT; its copyright notice is retained in LICENSE.
  • Microsoft's VS Code Dark Modern 2026 theme — the source palette.

License

MIT

About

Modern Lua port of the VS Code Dark 2026 colorscheme for Neovim with deep Treesitter and LSP support.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages