A Pomodoro timer plugin for Neovim with a nui.nvim popup UI, statusline integration, configurable presets, and a full Lua API.
- Neovim 0.9+
- nui.nvim
{
"stinobe/nvim-pomodoro",
dependencies = { "MunifTanjim/nui.nvim" },
config = function()
require("pomodoro").setup({
-- optional overrides
})
end,
}| Key | Action |
|---|---|
<leader>ps |
Open start popup |
<leader>pc |
Open config / preset picker |
<leader>px |
Stop timer |
<leader>pn |
Skip to next phase |
require("pomodoro").setup({
presets = {
-- Built-in presets are always included; user presets are merged/added.
{ name = "Classic", work = 25, short_break = 5, long_break = 15, rounds = 4 },
{ name = "Deep", work = 50, short_break = 10, long_break = 30, rounds = 3 },
},
active_preset = "Classic", -- default preset for <leader>ps
-- Icon shown in the statusline/HUD. Requires a Nerd Font.
-- Use a plain string like "P" or an emoji like "🍅" if you don't have one.
icon = "",
-- Controls what is shown in the HUD / statusline:
-- "full" -> [icon] Work 24:59 (default)
-- "compact" -> [icon] 24:59
-- "time" -> 24:59
-- "icon" -> [icon]
format = "full",
notify = true, -- vim.notify on session transitions
colors = {
-- nil = borrow fg from colorscheme (WarningMsg / DiagnosticOk / DiagnosticInfo)
-- override with hex strings to pin specific colors:
-- work = { fg = "#ff6b6b", bg = "#1e1e2e" }
work = { fg = nil, bg = nil },
short_break = { fg = nil, bg = nil },
long_break = { fg = nil, bg = nil },
},
keymaps = {
start = "<leader>ps",
config = "<leader>pc",
stop = "<leader>px",
skip = "<leader>pn",
},
-- keymaps = false -- disable all default keymaps
})A small floating window that appears in the corner when a session starts.
require("pomodoro").setup({
hud = {
enabled = false, -- true to use floating HUD instead of statusline injection
position = "bottom-right", -- "top-right" | "top-left" | "bottom-right" | "bottom-left"
},
})When hud.enabled = false (the default), the timer is automatically injected into
vim.o.statusline when a session starts and removed when it stops. This works with
a plain Neovim statusline. If you use lualine or heirline, add
require("pomodoro").get_status as a component manually:
-- lualine
sections = {
lualine_x = {
{ require("pomodoro").get_status },
},
}get_status() returns "" when idle so the component takes no space between sessions.
local p = require("pomodoro")
p.setup(opts) -- initialize / reconfigure
p.start("Classic") -- start with named preset (omit to use active_preset)
p.stop() -- reset to idle
p.pause() -- freeze countdown
p.resume() -- continue countdown
p.skip() -- jump to next phase immediately
p.get_status() -- statusline string, e.g. " Work 12:34 " (with highlight)
p.get_status_plain() -- same without highlight escape sequences
p.get_state() -- { phase, remaining, round, total_rounds, paused, preset }
p.open_start() -- open the start / preset picker popup
p.open_config() -- open the config popupListen to timer events via User autocmds:
vim.api.nvim_create_autocmd("User", {
pattern = "PomodoroTick", -- fires every second
callback = function() ... end,
})
-- Other patterns:
-- PomodoroStarted, PomodoroStopped
-- PomodoroPaused, PomodoroResumed
-- PomodoroPhaseChangedBy default the timer borrows its foreground color from built-in Neovim highlight groups so it fits any colorscheme:
| Phase | Source group | Typical color |
|---|---|---|
| Work | WarningMsg |
Yellow / orange |
| Short break | DiagnosticOk |
Green |
| Long break | DiagnosticInfo |
Blue / cyan |
Override any phase in setup({ colors = { work = { fg = "#hex" } } }).