Born from the classic desert.vim, transformed and modernized into something new entirely.
Oasis follows a warm/cool color split philosophy (warm = action/flow, cool = structure/data).
All themes meet AAA WCAG high contrast compliance standards. Light themes allow contrast ratio to be customized.
β¨ What's New / π¨ Breaking Changes
π¨ v5.0: Major Visual Overhaul, Redesign, and New Themes
This release is a major redesign of the palette system and theme pack.
Many themes have been substantially reworked, including background ramps, semantic color relationships, and overall visual identity.
If you prefer the previous appearance, pin to the last v4.2 release like so:
{
'uhs-robert/oasis.nvim',
version = '4.2.0',
config = function()
require('oasis').setup({})
vim.cmd.colorscheme('oasis')
end,
}π¨ v4.1: Legacy Light Themes Removed
The standalone light themes Dawn, Dawnlight, Day, Dusk, and Dust have been removed in v4.1 (deprecated in v4.0).- Use the dual-mode system with
light_style+light_intensityinstead. - Closest matches:
nightwithlight_intensity = 1..5(1=brightest, 5=darkest).
- Configurable plugin integration system.
- Expanded highlight coverage (additional Treesitter + LSP groups + mini ecosystem).
- Palette/highlight override system and LuaLS type definitions.
- New theme generators/formats: CSS, JSON, and Lua themes.
- New/expanded extras: bat themes, Warp, WezTerm/kitty updates, Yazi enhancements, tmux visual selection.
π¨ v4.0: Dual Style Themes / Deprecated Themes
Each style now has 5 light theme variants.- Check out the new light theme screenshots.
- Config options have been updated with new
contrastandlight_intensitysettings andlight/dark_styleupdates. - New API command :OasisIntensity under usage to cycle intensity. Also available via lua for keymap.
| Dawn | Replaced with light_intensity = 1 |
| Dawnlight | Replaced with light_intensity = 2 |
| Day | Replaced with light_intensity = 3 |
| Dusk | Replaced with light_intensity = 4 |
| Dust | Replaced with light_intensity = 5 |
night which also resolves accessibility issues.
Deprecated themes will be completely removed on January 15th of 2026.
Click any card below to view the full preview and syntax sample. β Or click here to view all full previews
Light styles use a saturation intensity scale from 1-5: set from config or via :OasisIntensity.
![]() 1 |
![]() 2 |
![]() 3 |
![]() 4 |
![]() 5 |
Use :OasisIntensity to step through intensity levels 1 β 5 in light mode.
Note
The Night style uses the darkest light backgrounds (lightness 78-84%) compared to the rest.
This provides a middle ground between traditional light and dark modes.
The examples below use the default intensity of level 3.
![]() Night |
![]() Midnight |
![]() Abyss |
![]() Starlight |
![]() Desert |
![]() Sol |
![]() Scorpion Scorched |
![]() Canyon |
![]() Dune |
![]() Cactus |
![]() Mirage |
![]() Lagoon |
![]() Twilight |
![]() Luna Indigo |
![]() Rose |
- 15 theme styles with dual modes: Each theme offers both dark and light variants with 5 adjustable intensity levels.
- Dark/Light Modes: Automatic switching based on your system theme or
vim.o.background. - Comprehensive highlighting - LSP, Tree-sitter, and plugin support
- Fast loading - Direct highlight application for optimal performance based on the plugins in your config
- Zero dependencies - Works out of the box without external plugins
- Modular architecture - Easy to customize and extend
πͺ Supported Plugins
| Plugin |
|---|
| fzf-lua |
| gitsigns.nvim |
| mini.nvim |
| lazy.nvim |
| render-markdown.nvim |
| snacks.nvim |
| which-key.nvim |
Note
Oasis goes beyond Neovim with themes for web browsers, terminals, development tools, and more. Don't miss the Extras!
π Extras
All extra configs for other applications.
To use the extras, refer to their respective documentation.
| Tool | Extra |
|---|---|
| Alacritty | extras/alacritty |
| Bat | extras/bat |
| Btop | extras/btop |
| Dark Reader | extras/dark-reader |
| Firefox | extras/firefox |
| Foot | extras/foot |
| FZF | extras/fzf |
| Gemini CLI | extras/gemini-cli |
| Ghostty | extras/ghostty |
| iTerm | extras/iterm |
| JSON-theme | extras/json-theme |
| Kitty | extras/kitty |
| Konsole | extras/konsole |
| LazyGit | extras/lazygit |
| Lua-theme | extras/lua-theme |
| Qutebrowser | extras/qutebrowser |
| Slack | extras/slack |
| Starship | extras/starship |
| Termux | extras/termux |
| Thunderbird | extras/thunderbird |
| Tridactyl | extras/tridactyl |
| TMUX | tmux-oasis |
| Vimium | extras/vimium |
| Vimium C | extras/vimium-c |
| Warp | extras/warp |
| WezTerm | extras/wezterm |
| Yazi | extras/yazi |
| Zed | extras/zed |
If you'd like an extra config added, raise a feature request and I'll put it together.
Install the theme with your preferred package manager, such as folke/lazy.nvim:
{
"uhs-robert/oasis.nvim",
lazy = false,
priority = 1000,
config = function()
require("oasis").setup() -- (see Configuration below for all customization options)
vim.cmd.colorscheme("oasis") -- After setup, apply theme (or any style like "oasis-night")
end
}After calling setup(), use :colorscheme to apply or swap styles:
vim.cmd.colorscheme("oasis") -- Use your config settings
vim.cmd.colorscheme("oasis-desert") -- Or load any specific styleποΈ All colorscheme commands
" Uses your config settings
colorscheme oasis
" Or load a specific style - must be prefixed with `oasis-`
colorscheme oasis-night
colorscheme oasis-midnight
colorscheme oasis-abyss
colorscheme oasis-starlight
colorscheme oasis-desert
colorscheme oasis-sol
colorscheme oasis-scorpion
colorscheme oasis-canyon
colorscheme oasis-dune
colorscheme oasis-cactus
colorscheme oasis-mirage
colorscheme oasis-lagoon
colorscheme oasis-twilight
colorscheme oasis-luna
colorscheme oasis-roseπ΅οΈββοΈ Different Themes for Different Environments
Don't just pick a favorite. Assign themes based on variables like sudo to easily differentiate between your NeoVim environments. For example:
- Use
solwhen root and/or doing a sudoedit - Use
miragewhen remote - And/or use any theme for any combination above, the only limit is your imagination
local uid = (vim.uv or vim.loop).getuid()
local is_root = uid == 0
local is_remote = vim.env.SSH_CONNECTION ~= nil or vim.env.SSH_TTY ~= nil
local is_sudoedit = (not is_root) and vim.env.SUDOEDIT == "1" -- This requires your shell's config to export a flag like: SUDO_EDITOR="env SUDOEDIT=1 /usr/bin/nvim"
local function pick_colorscheme()
local is_elevated = is_root or is_sudoedit
if is_remote then
return is_elevated and "oasis-abyss" or "oasis-mirage"
else
return is_elevated and "oasis-sol" or "oasis"
end
end
return {
{
"uhs-robert/oasis.nvim",
lazy = false,
priority = 1000,
config = function()
require("oasis").setup()
vim.cmd.colorscheme(pick_colorscheme())
end
}
}π΅ Some plugins may need extra configuration to work
To override the tokyonight default and start fresh in the oasis:
-- No need to apply vim.cmd.colorscheme(), just use this instead! Also works with the different themes for different environments example above.
{
"LazyVim/LazyVim",
opts = {
colorscheme = "oasis",
},
},To include automatic Lualine theme integration:
require("lualine").setup {
options = {
theme = "oasis" -- Automatically matches your current Oasis style
}
}To include tab bar theme integration:
require("tabby").setup({
theme = "oasis" -- Automatically matches your current Oasis style
})β‘ API Commands
Toggle transparency on-the-fly without restarting:
:OasisTransparency-- Or use the Lua API
require("oasis").toggle_transparency()
-- Example: bind to a keymap
vim.keymap.set("n", "<leader>tt", require("oasis").toggle_transparency, { desc = "Toggle transparency" })Toggle the themed_syntax option on-the-fly to switch between themed and classic syntax highlighting (dark themes only):
:OasisThemedSyntax-- Or use the Lua API
require("oasis").toggle_themed_syntax()
-- Example: bind to a keymap
vim.keymap.set("n", "<leader>ts", require("oasis").toggle_themed_syntax, { desc = "Toggle themed syntax" })
β οΈ v3.0 Breaking Change: Themed syntax is now enabled by default. To restore classic syntax highlighting, disable it:require("oasis").setup({ themed_syntax = false, -- Use traditional yellow/khaki for all styles })
This option controls how statement/keyword colors are rendered:
- Enabled (default): Statements and keywords use the theme's primary color (e.g., blue in lagoon, teal in mirage, orange in canyon)
- Disabled: Statements and keywords use traditional yellow/khaki tones across all styles
Cycle the light background intensity (1β5) without reloading to test the waters:
:OasisIntensity-- Or use the Lua API
require("oasis").cycle_intensity()
-- Example: bind to a keymap
vim.keymap.set("n", "<leader>uB", function()
require("oasis").cycle_intensity() -- nil|true shows ui picker, false will cycle
end, { desc = "Select light mode intensity" })- Applies to light palettes only (dark palettes ignore intensity).
- Default intensity is configurable via
light_intensityinsetup().
Check WCAG 2.1 contrast compliance for palettes:
" Check all palettes
:OasisWCAG
" Check specific palette
:OasisWCAG oasis_lagoon-- Lua API
local wcag = require("oasis.tools.wcag_checker")
-- Analyze all palettes
local all_results = wcag.analyze_all()
wcag.print_comparison_table(all_results)
-- Analyze specific palette
local results = wcag.analyze_palette("oasis_lagoon")
wcag.print_palette_results(results)
-- Calculate contrast ratio between two colors
local ratio = wcag.get_contrast_ratio("#e0def4", "#191724") -- Returns: 12.44
-- Get compliance level
local level = wcag.get_compliance_level(ratio, false) -- Returns: "AAA"WCAG Standards:
- AAA (7.0:1): Enhanced contrast for normal text
- AA (4.5:1): Minimum contrast for normal text
- AA Large (3.0:1): Minimum for large text (18pt+ or 14pt+ bold)
Reference: WCAG 2.1 Guidelines
[!NOTE] Light themes can appear muddy and make syntax hard to distinguish when everything is AAA.
If you need AAA compliance then set
force_aaa = trueotherwise tune themin_ratioto meet your needs.
Oasis offers many different styles to choose from. Have fun customizing with setup()!
π¦ Default Options
-- Oasis.nvim
-- Styles: "night", "midnight", "abyss", "starlight", "desert", "sol", "canyon", "dune", "cactus", "mirage", "lagoon", "twilight", "rose"
require("oasis").setup({
style = "lagoon", -- Primary style, the default used when colorscheme is set to "oasis"
dark_style = nil, -- Applies to primary style only: Overrides dark mode with another theme (e.g., "abyss")
light_style = nil, -- Applies to primary style only: Overrides light mode with another theme (e.g., "dune")
light_intensity = 3, -- Light background intensity (1-5): 1=subtle, 5=saturated
use_legacy_comments = false, -- For "desert" style only, uses the loud skyblue comment color from desert.vim for a more retro experience
themed_syntax = true, -- Uses the theme's primary color for statements/keywords. Set to false for the classic yellow syntax from desert.vim for a more retro experience
-- Text styling - toggle individual styles
styles = {
bold = true, -- Enable bold text (keywords, functions, etc.)
italic = true, -- Enable italics (comments, certain keywords)
underline = true, -- Enable underlined text (matching words)
undercurl = true, -- Enable undercurl for diagnostics/spelling
strikethrough = true, -- Enable strikethrough text (deprecations)
},
-- Display options
transparent = false, -- Set to true for transparent backgrounds (bye-bye theme backgrounds)
terminal_colors = true, -- Apply Oasis colors to Neovim's built-in terminal
match_paren_bg = true, -- Enable/disable background on MatchParen highlight
-- Contrast controls (WCAG: AA = 4.5, AAA = 7.0)
contrast = {
-- Note: Light themes obey the targets below. All dark themes target 7.0 by default with only a couple of exceptions that dip to 6.5.
min_ratio = 5.8, -- Clamp 4.5β7.0; target contrast for syntax/terminal colors. Increase for more contrast, decrease for more pop.
force_aaa = false, -- When true, forces AAA (7.0) wherever possible; as a result some colors will appear muddy (bye bye non-primary colors).
},
palette_overrides = {}, -- Override colors in specific palettes
highlight_overrides = {}, -- Override specific highlight groups
-- Plugin integrations
integrations = {
default_enabled = true, -- Default behavior: true = enable all, false = disable all
-- For each plugin: nil = use default_enabled, true = enable, false = disable
plugins = {
fzf_lua = nil,
gitsigns = nil,
lazy = nil,
mini = nil,
render_markdown = nil,
snacks = nil,
which_key = nil,
},
},
})Thirsty for total control? You can override whatever you like.
Whoever drinketh of the water that I shall give him, shall never thirst...
π¨ Changing Palette Colors for Each Style
palette_overrides - Customize colors in palettes. Supports two methods for updating:
require("oasis").setup({
palette_overrides = {
-- Global light overrides (applies to ALL themes)
light = {
bg = { core = "#FFF8F0" }
},
-- Global light intensity 3 (applies to ALL themes)
light_3 = {
bg = { core = "#FFEFE0" }
},
-- Per-theme overrides (use shorthand names: desert, lagoon, etc.)
lagoon = {
syntax = { string = "#FFA0A0", punctuation = "#F89D82", comment = "#665D55" },
ui = { border = "#FFA247" },
-- Light mode for this theme
light = {
syntax = { comment = "#404040" }
},
-- Specific intensity for this theme
light_5 = {
bg = { core = "#FFE8D0" }
}
}
}
})require("oasis").setup({
palette_overrides = function(c, colors)
---@type OasisPaletteOverrides
return {
-- c = current palette
-- colors = base palette from palette.lua (Tailwind-style colors and access to all palettes)
-- Global light overrides (applies to ALL themes)
light = {
syntax = {
comment = c.fg.dim, -- Reference current palette
string = colors.rose[500] -- Reference global colors
}
},
-- Global light intensity 3 (applies to ALL themes)
light_3 = {
bg = { core = "#FFEFE0" }
},
-- Global palette overrides
syntax = {
comment = c.fg.dim,
statement = colors.khaki[500],
},
-- Per-theme overrides (use shorthand names: desert, lagoon, etc.)
lagoon = {
syntax = {
string = colors.rose[500],
punctuation = colors.peach[500],
comment = c.fg.dim
},
-- Light mode for this theme
light = {
syntax = { string = colors.red[800] }
},
-- Specific intensity for this theme
light = {
syntax = { string = colors.red[800] }
}
}
}
end
})Precedence: Global β Global light β Global light_N β Theme β Theme light β Theme light_N
See Color Palettes for each theme's palette structure and Palette for all base colors.
π Changing Colors for Highlight Groups
highlight_overrides - Override or add highlight groups. Supports two methods for updating:
require("oasis").setup({
highlight_overrides = {
-- Global (applies to all themes, all modes)
Comment = { fg = "#808080", italic = true },
Function = { fg = "#E06C75", bold = true },
Identifier = "Function", -- Link to another group
-- Global light mode (all themes, all intensities)
light = {
Comment = { fg = "#606060" },
Normal = { bg = "#000000" },
},
-- Global light intensity 3 (all themes)
light_3 = {
Normal = { bg = "#FFF8F0" }
},
-- Per-theme overrides (use shorthand names: desert, lagoon, etc.)
desert = {
String = { fg = "#FFA0A0" },
-- Desert light mode
light = {
String = { fg = "#6BA5C8" }
},
-- Desert light intensity 3
light_3 = {
Normal = { bg = "#FFF0E0" }
}
}
}
})require("oasis").setup({
highlight_overrides = function(c, colors)
---@type OasisHighlightOverrides
return {
-- c = current palette
-- colors = base palette from palette.lua (Tailwind-style colors)
Comment = { fg = c.fg.dim, italic = true },
String = { fg = colors.red[500] },
Function = { fg = c.theme.primary },
-- Global light overrides
light = {
Comment = { fg = c.fg.muted }
},
-- Per-theme with palette access
desert = {
String = { fg = colors.sky[500] },
light = {
String = { fg = colors.sky[700] }
}
}
}
end
})Precedence: Global β Global light β Global light_N β Theme β Theme light β Theme light_N
See Theme Generator for all highlight groups.
See Color Palettes for each theme's palette structure and Palette for all base colors.

































































