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 compliance standards. Light themes allow contrast ratio to be customized.
β¨ What's New / π¨ Breaking Changes
π¨ 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 around January 1st of 2026.
π¨ v3.0: Themed Syntax
Each style now uses its signature color for statements and keywords.Prefer the classic yellow syntax? See how to opt-out under API Commands β
Click any card below to view the full preview and syntax sample. β Or click here to view all full previews
![]() Night Night Sky |
![]() Midnight Off Black |
![]() Abyss Black |
![]() Starlight Black Vivid |
![]() Desert Grey |
![]() Sol Red |
![]() Canyon Orange |
![]() Dune Yellow |
![]() Cactus Green |
![]() Mirage Teal |
![]() Lagoon (Default) Blue |
![]() Twilight Purple |
![]() Rose Pink |
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 |
![]() Canyon |
![]() Dune |
![]() Cactus |
![]() Mirage |
![]() Lagoon |
![]() Twilight |
![]() Rose |
- 13 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
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 |
| Slack | extras/slack |
| Termux | extras/termux |
| Thunderbird | extras/thunderbird |
| TMUX | tmux-oasis |
| 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-canyon
colorscheme oasis-dune
colorscheme oasis-cactus
colorscheme oasis-mirage
colorscheme oasis-lagoon
colorscheme oasis-twilight
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, default used when colorscheme is set to "oasis"
dark_style = "auto", -- Applies to your primary style only: "auto" uses `style`. Or override with another dark theme (e.g., "abyss")
light_style = "auto", -- Applies to your primary style only: "auto" uses `style`. Or override with another light 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
-- 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
})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.

























































