A tiny Neovim plugin for automatic terminal theme synchronization via OSC 11.
When your terminal theme changes, Neovim detects it, asks the terminal for its new background color via OSC 11, and updates its internal background option based on whether that color is light or dark.
OSC11.nvim hooks into that same OSC 11 response and uses the same light/dark detection logic as Neovim.
The difference is that instead of only updating background, it lets you run any Lua function when the terminal switches between light and dark modes.
Note
This project is feature complete for its intended small scope. While actively maintained (don't be scared if there are no commits for a long time), new features will be limited to improvements of existing functionality and simple additions within this scope. Pull requests are welcome as long as they align with these goals.
Warning
It’s recommended to set a colorscheme on startup outside of this plugin. That way, Neovim still has a valid colorscheme if your terminal does not send the required escape codes, if Neovim fails to retrieve them, or if you sometimes use a terminal that does not support this behavior.
- Automatic detection of terminal light/dark theme changes via OSC 11.
- Configurable callbacks for light and dark theme switches.
- Neovim 0.11.0 or higher.
- A terminal that supports OSC 11 responses (e.g., Ghostty).
- If using tmux, you might need
allow-passthroughset toonintmux.conf.
set -g allow-passthrough onSetup with lazy.nvim
{
"afonsofrancof/OSC11.nvim",
opts = {
-- Function to call when switching to dark theme
on_dark = function()
vim.opt.background = "dark"
vim.cmd('colorscheme gruvbox-material')
end,
-- Function to call when switching to light theme
on_light = function()
vim.cmd("colorscheme tokyonight-day")
end,
}
}| Option | Description | Default |
|---|---|---|
on_dark |
Function to call when switching to dark theme | nil |
on_light |
Function to call when switching to light theme | nil |
After setting up the plugin, OSC11.nvim will automatically listen for TermResponse events. When a terminal theme change is detected via an OSC 11 sequence, the corresponding on_dark or on_light callback will be executed.
To demonstrate, if you have a terminal that changes its theme based on the system's light/dark mode, and you've configured OSC11.nvim as shown in the installation section, your Neovim colorscheme will automatically switch between gruvbox-material and tokyonight-day when your terminal theme changes.
- OSC 11 Listener: The plugin sets up an
Autocmdon theTermResponseevent. This event is triggered when the terminal sends a response to a query, which includes OSC 11 responses. - Parse OSC 11 Response: When a
TermResponseis received, the plugin checks if it's an OSC 11 sequence. An OSC 11 sequence (e.g.,^[]11;rgb:RRRR/GGGG/BBBB^[\) contains the current background color of the terminal. - Calculate Luminance: The RGB values from the OSC 11 response are converted to decimal, and a luminance value is calculated. This luminance calculation is the same as Neovim's internal method for determining if a background is light or dark.
- Determine Theme: If the calculated luminance is less than 0.5, the theme is considered "dark"; otherwise, it's "light."
- Execute Callbacks: Based on the determined theme ("dark" or "light"), the corresponding
on_darkoron_lightfunction provided in the configuration is executed. Finally,vim.cmd("redraw!")is called to ensure the Neovim UI is updated.
MIT