🌊 Kanagawa Paper
Remixed light and dark Kanagawa color scheme with muted colors.
💡 Motivation
I love the original kanagawa.nvim color scheme, but I found some of the colors a bit too bright and distracting. What I wanted was a more muted theme overall, using less saturated colors inspired by the original theme. You can see a visual preview of the color palette here.
Ink is the dark variant for late nights. Canvas is the light variant for sunny days. Both have Neovim, VS Code, and Zed builds, with matching colors for terminals and other applications.
Ink

Canvas

Unified editor themes
Neovim, VS Code, and Zed share one palette and presentation policy. Bold marks structure and execution landmarks; italics mark comments, documentation, type annotations, and other supporting information where each editor supports them.
For existing Neovim installations, follow the migration instructions before updating. The installable runtime is published on the neovim branch; main contains the shared development source.
VS Code
Installation
- Install Kanagawa Paper from the Visual Studio Marketplace. The extension identity is
SimonHo.kanagawa-paper.
- Open the Command Palette and run Preferences: Color Theme.
- Choose Kanagawa Paper Ink for a dark theme or Kanagawa Paper Canvas for a light theme.
Customization
Use VS Code's workbench.colorCustomizations setting for interface colors and editor.tokenColorCustomizations for syntax colors. See the VS Code theme customization guide for examples and theme-specific overrides.
Zed
Installation
- Open Zed's Extensions view and search for Kanagawa Paper.
- Install the extension.
- Open the theme selector and choose Kanagawa Paper Ink for a dark theme or Kanagawa Paper Canvas for a light theme.
Neovim
Requirements
- Neovim >= 0.8.0
- truecolor terminal support
- undercurl terminal support (optional)
Installation
Install the theme with your preferred package manager, such as lazy.nvim:
{
"thesimonho/kanagawa-paper",
branch = "neovim",
lazy = false,
priority = 1000,
opts = {},
}
The neovim branch contains the installable runtime. The main branch contains development source. To pin a release, replace branch with tag = "neovim-X.Y.Z" using a published Neovim version. Historical v* tags remain available; they do not receive a separate update track.
Migrating an existing installation
Change your plugin specification to the repository and neovim branch shown above, then update the plugin. Existing setup() options and colorscheme names remain available. Install from the distribution branch or a neovim-X.Y.Z tag; the development source requires a build before Neovim can load it.
If your configuration directly requires an internal kanagawa-paper.groups module, update that path to kanagawa-paper.highlights. Semantic-token mappings now live in kanagawa-paper.highlights.semantic; LSP interface highlights live in kanagawa-paper.highlights.lsp. The old module paths have no compatibility aliases. Configurations that only use setup(), color overrides, or highlight overrides do not need these internal path changes.
The default text styles now use bold for declarations, calls, and control flow, and italic for comments, documentation, and type annotations where the editor can identify them. Use the named styles roles described below to customize these choices. Restart Neovim after updating so its parser queries reload. The included Python and TypeScript queries extend installed Tree-sitter queries; they do not install parsers or language servers.
Usage
Kanagawa Paper comes in a few variants:
kanagawa-paper-ink for late nights
kanagawa-paper-canvas for sunny days
kanagawa-paper for automatic theme switching based on vim.o.background
Themes can be changed in a couple of ways:
- Using the background option:
Any change to the value of
vim.o.background will select the corresponding light or dark theme. If this is unset, the theme will default to the dark theme ink.
- Loading the color scheme directly with:
Vim:
colorscheme kanagawa-paper
colorscheme kanagawa-paper-ink
colorscheme kanagawa-paper-canvas
Neovim:
vim.cmd.colorscheme("kanagawa-paper")
vim.cmd.colorscheme("kanagawa-paper-ink")
vim.cmd.colorscheme("kanagawa-paper-canvas")
A full plugin spec example using lazy.nvim:
return {
"thesimonho/kanagawa-paper",
branch = "neovim",
lazy = false,
priority = 1000,
opts = {}, -- your configuration
config = function(_, opts)
require("kanagawa-paper").setup(opts)
vim.cmd.colorscheme("kanagawa-paper-ink")
end,
}
Configuration
[!IMPORTANT]
Set the configuration BEFORE loading the color scheme to ensure the settings are applied, otherwise defaults will be used.
Default configuration
require("kanagawa-paper").setup({
-- enable undercurls for underlined text
undercurl = true,
-- transparent background
transparent = false,
-- highlight background for the left gutter
gutter = false,
-- background for diagnostic virtual text
diag_background = true,
-- dim inactive windows. Disabled when transparent
dim_inactive = false,
-- set colors for terminal buffers
terminal_colors = true,
-- cache highlights and colors for faster startup.
-- see Cache section for more details.
cache = false,
styles = {
-- style for comments
comment = { italic = true },
-- style for functions
functions = { italic = false, bold = true },
functionDeclaration = { bold = true },
functionCall = { bold = true },
typeDeclaration = { bold = true },
controlFlow = { bold = true },
-- style for keywords
keyword = { italic = false, bold = false },
-- style for statements
statement = { italic = false, bold = false },
-- style for types
type = {},
-- style for string escapes
escape = { bold = false },
},
-- override default palette and theme colors
colors = {
palette = {},
theme = {
ink = {},
canvas = {},
},
},
-- adjust overall color balance for each theme [-1, 1]
color_balance = {
ink = { brightness = 0, saturation = 0 },
canvas = { brightness = 0, saturation = 0 },
},
-- override highlight groups
overrides = function(colors)
return {}
end,
-- uses lazy.nvim, if installed, to automatically enable needed plugins
auto_plugins = true,
-- enable highlights for all plugins (disabled if using lazy.nvim)
all_plugins = package.loaded.lazy == nil,
-- manually enable/disable individual plugins.
-- check the `highlights/plugins` directory for the exact names
plugins = {
-- examples:
-- rainbow_delimiters = true
-- which_key = false
},
})
The styles option also accepts named roles for specific text and UI treatments. For example, boolean = { bold = false }, openedFile = { italic = false }, and activeLineNumber = { bold = false } disable those attributes without changing colors. Roles are defined in shared/styles.ts and generated into the Neovim distribution; existing comment, function, keyword, statement, type, and escape overrides keep their names. Diagnostic undercurls remain controlled by undercurl.
Cache
The color scheme comes with a cache option that can be used to speed up startup time.
When you set cache = true in your config, the theme colors and all of your edits/adjustments will be saved to a cache file. This is loaded at startup so colors don't need to be recomputed every time.
Any changes you make to your config (e.g. overriding colors or highlight groups) should automatically invalidate the cache and build a new one.
In rare cases where this doesn't happen and you notice your changes aren't being applied, you can manually rebuild the cache by running :KanagawaPaperCache.
Integrations
Terminals
Matching colorschemes for a number of terminals are provided (e.g. WezTerm, ghostty, etc; see Extras).
The automatic variant of kanagawa-paper switches between light and dark mode based on the value of vim.o.background. This value will generally follow the color mode of your terminal, i.e. if your terminal is set to dark mode via your OS, neovim will pick that up and the theme will automatically be changed to kanagawa-paper-ink.
Tip: if this auto switching is not working for you, the first thing to check is whether the value of vim.o.background is what you expect it to be.
This color scheme comes with matching Lualine themes for both ink and canvas variants.
This will set the theme at startup:
local kanagawa_paper = require("lualine.themes.kanagawa-paper-ink")
-- local kanagawa_paper = require("lualine.themes.kanagawa-paper-canvas")
require("lualine").setup({
options = {
theme = kanagawa_paper,
-- ... your lualine config
},
})
For a more advanced use case you can make use of the background color to set the Lualine theme dynamically. This switches Lualine between light and dark themes based on background color:
require("lualine").setup({
options = {
theme = function()
-- pcall and fallback theme is to handle the case of theme switching/previewing
local ok, t = pcall(
require,
"lualine.themes." .. (vim.o.background == "light" and "kanagawa-paper-canvas" or "kanagawa-paper-ink")
)
if ok then
theme = t
else
theme = require("some other fallback theme")
end
return theme
end,
-- ... your lualine config
},
})
Examples of situations where this might be useful:
- You want to change the theme mid-session
- You want to change background color mid-session (either by manually setting
vim.o.background or with something like dark background toggle in LazyVim)
- You use a plugin for live previews of color schemes
Other applications
Releases
Applications have independent versions and changelogs. Tags such as neovim-4.2.0 identify installable distributions; neovim-source-4.2.0 identifies their development source. There is no moving latest tag. Use the repository’s Deployments → View deployment links for each application’s latest successful publication, or the release list and VS Code Marketplace directly. GitHub’s repository-wide Latest label can refer to any application.
🔥 Contributing
Pull requests are welcome for theme fixes, new features, and new extras.
Using the Conventional Commits format for commit messages is recommended. PRs will then automatically be added to the next Release Notes and application changelogs (Neovim, VS Code).
For the extras, we use a simple template system that can be used to generate styles for the different themes.
How to add a new extra template:
- Create a new TypeScript adapter in packages/extras/adapters.
- Register the adapter, name, and output file extension in the
extras registry in packages/extras/registry.ts.
- Open a PR. CI checks that the extras, palette, and Neovim help generators run successfully. For an optional local preview, run
mise run generate.
[!IMPORTANT]
Post-merge automation on main generates and commits the extras, palette preview, and Neovim help. You do not need to generate or commit these outputs locally, including when contributing from a fork.
Development
Maintainer automation uses GitHub App authentication for Git pushes and trusted publishing for the VS Code Marketplace. See CI automation for the required repository configuration.
Install mise, then run mise install and mise exec -- npm ci --ignore-scripts at the repository root. mise provides Node 22 and npm. Run mise tasks to list the available tasks. Run mise run build to assemble Neovim, VS Code, Zed, and extras under dist/, or mise run watch neovim to rebuild the Neovim target after source edits.
Run mise exec -- npm test for shared logic and target contracts, mise run test for Neovim runtime tests, and mise run test-targets for release tooling tests. The complete gate is mise run check. It also needs Neovim, Python 3, and the pinned Python and Node release dependencies described in the release README.
Build once, then open Neovim from the repository root with your existing lazy.nvim setup. The local .lazy.lua selects dist/neovim, activates Canvas, and reloads the theme after a successful build. Keep mise run watch neovim running while editing source. The preview reads generated swatches and does not write source colors. After .lazy.lua changes, review the file, run :trust from its buffer, then restart Neovim so Lazy can apply the updated plugin path.
| Directory |
Purpose |
shared/ |
Shared palette, semantic roles, and color calculations |
packages/ |
Neovim, VS Code, Zed, and extras build targets |
extras/ |
Copyable generated application configurations |
scripts/ |
Tests, package assembly, and release coordination |
tests/ |
Runtime and package checks |
👏 Acknowledgements