A Neovim plugin for Solidtime — start, stop, and manage time entries without leaving your editor.
- Start / stop time entries from Neovim
- Single persistent floating window with a tabbed interface — no stacking popups
- Edit the active time entry (project, task, description, billable, tags) inline
- Browse and manage projects, clients, tasks, and time entries in a unified shell
- Tickets — search Freedcamp issues or Planka cards, link them to Solidtime tasks, and start timers directly from ticket results
- Auto-tracking — automatically starts/stops timers when you switch git projects
- Idle detection — warns and optionally stops the timer after configurable periods of inactivity
- IPC — broadcasts stop events to other Neovim instances so only one timer runs at a time
- Configurable keymaps; any mapping can be disabled individually
- Neovim >= 0.9
- A Solidtime account and API key
curlavailable on$PATH
{
"nick22985/solidtime.nvim",
config=function()
require("solidtime").setup()
end,
}Run :SolidTime auth to enter your API key. The key is stored in Neovim's credentials store and loaded automatically on subsequent startups.
If you self-host Solidtime, set api_url in your setup() call (see Configuration).
Open the plugin with <leader>so (or :SolidTime open). This opens the floating shell on the Timer tab.
The shell has seven tabs shown at the top of the floating window:
[Timer] Status Projects Clients Tasks Entries Tickets
| Key | Action |
|---|---|
<Tab> | Cycle to the next tab |
<S-Tab> | Cycle to the previous tab |
<leader>1–<leader>7 | Jump directly to tab 1–7 (Timer → Tickets) |
Note: bare number keys (
1–6) are intentionally not bound inside the shell so they remain available for Vim count motions (e.g.5j,3k).
| Key | Action |
|---|---|
j / k | Move cursor down / up |
<CR> | Confirm / edit highlighted item |
a | Add / create new item |
d | Delete highlighted item |
q / <Esc> | Close or go back |
When a timer is running the tab opens an edit form directly showing elapsed time, description, project, task, tags, and billable status. Press s to stop, or edit any field and press <CR> on Save.
When stopped, press s to start a new entry.
Paginated history of your time entries. Use [ / ] to page through results.
To bulk-delete entries:
- Press
don individual entries (or visual-select a range and pressd) to stage them for deletion. Staged entries are marked visually. - Press
:wto commit the deletion. All staged entries are sent to the API and removed from the list.
The Tickets tab lets you search for tickets from external issue trackers and act on them without leaving Neovim.
| Provider | What is searched |
|---|---|
| Freedcamp | Issues across your projects |
| Planka | Cards across boards/projects |
Configure providers in your setup() call:
require("solidtime").setup({
tickets= {
providers= {
freedcamp= {
api_key="your-freedcamp-api-key",
api_secret="your-freedcamp-api-secret",
},
planka= {
base_url="https://planka.example.com",
username="you@example.com",
password="yourpassword",
},
},
},
})Alternatively, run :SolidTime auth freedcamp or :SolidTime auth planka to enter credentials interactively. They are stored in ~/.solidtime_api_config and never hard-coded in your config.
The first time you open the Tickets tab for a project, press p to pick and link a ticket provider project (or Planka board). The choice is saved to projects.json and remembered for that git repo.
| Key | Action |
|---|---|
/ | Enter search mode — type a query, press <Esc> to run it |
<CR> | Load all tickets (when no results yet), or open action menu |
o | Open the selected ticket in the browser |
j / k | Move between ticket results |
gg / G | Jump to first / last ticket |
<C-d> / <C-u> | Scroll half-page down / up |
p | Pick / change linked project or board |
<leader>g | Toggle global search (search all projects, not just linked) |
<Esc> | Clear search query; second press exits global mode |
q | Close the shell |
| Option | Description |
|---|---|
| Open in browser | Open the ticket URL in your system browser |
| Create Solidtime task | Create a task in the linked Solidtime project |
| Start timer with this title | Start a timer using the ticket title as description |
| Create task and start timer | Both of the above in one step |
Each result row shows the ticket title followed by badge tags:
Fix login crash [MyProject][Dev Board][In Progress]
- Project — shown in global search so you know where the card lives
- Board — the Planka board (or Freedcamp project) the ticket belongs to
- Status — the list/column name (Planka) or status title (Freedcamp)
- Priority — label names if present
- Status — quick summary of the currently running entry
- Projects — create, rename, delete projects; press
ton a project to open its tasks - Clients — create, rename, delete clients
- Tasks — manage tasks across projects; press
<CR>to toggle done,rto rename
All list pickers, confirmations, and text inputs stay inside the floating shell — no external popups.
All options are optional — the defaults work out of the box once authenticated.
require("solidtime").setup({
-- API endpoint. Defaults to the hosted service.api_url="https://app.solidtime.io/api/v1",
-- Enable plugin logging (stored in storage_dir).enable_logging=true,
debug_mode=false,
-- Directory for local state (pending syncs, etc.).storage_dir=vim.fn.expand("~/.local/share/nvim/solidtime"),
-- JSON file that maps git-repo names to Solidtime projects for auto-tracking.projects_config_file=vim.fn.expand("~/.config/solidtime/projects.json"),
-- Idle detection. Set to 0 to disable. stop timeout must be > warn timeout.idle_warn_timeout=5, -- minutes before a warning notificationidle_stop_timeout=10, -- minutes before the timer is auto-stopped (0 = never auto-stop)-- Auto-tracking tweaks.autotrack= {
-- Delay (ms) before showing the startup auto-start notification.-- Increase if your notification plugin (noice, nvim-notify, etc.) loads slowly.startup_notify_delay=100,
},
-- External ticket providers (Freedcamp, Planka, …).tickets= {
providers= {
freedcamp= {
api_key="...",
api_secret="...",
},
planka= {
base_url="https://planka.example.com",
username="...",
password="...",
},
},
},
-- Keymaps. Set any value to false to disable that mapping.keymaps= {
-- Globalopen="<leader>so", -- open SolidTime (Timer tab)start="<leader>ts", -- open Start Time Entry formstop="<leader>te", -- stop running timer immediatelyedit_active="<leader>tx", -- open Timer tab to edit active entryreload="<leader>tr", -- reload plugin-- Inside the shell windownav_down="j",
nav_up="k",
confirm="<CR>", -- confirm / edit highlighted itemclose="q",
close_alt="<Esc>",
add="a", -- create new itemdelete="d", -- delete highlighted itemtasks="t", -- open tasks for highlighted projectnext_page="]", -- next page (entries tab)prev_page="[", -- previous page (entries tab)
},
})| Command | Description |
|---|---|
:SolidTime auth | Enter / update your API key |
:SolidTime open | Open the shell on the Timer tab |
:SolidTime start | Open the Start Time Entry form |
:SolidTime stop | Stop the running timer |
:SolidTime edit | Open the Timer tab to edit the active entry |
:SolidTime projects | Open the shell on the Projects tab |
:SolidTime clients | Open the shell on the Clients tab |
:SolidTime tasks | Open the shell on the Tasks tab |
:SolidTime entries | Open the shell on the Entries tab |
:SolidTime tickets | Open the shell on the Tickets tab |
:SolidTime status | Open the shell on the Status tab |
:SolidTime reload | Hot-reload the plugin |
:SolidTime unproject | Remove the current git project from auto-tracking |
Auto-tracking starts and stops timers automatically based on which git repository you are working in.
- Open the plugin with
<leader>so. - Switch to the Projects tab (
<Tab>or<leader>3) and register the desired project, or edit~/.config/solidtime/projects.jsonmanually:
{
"my-repo": {
"solidtime_project_id": "<uuid>",
"organization_id": "<uuid>",
"member_id": "<uuid>",
"auto_start": true,
"default_description": "Development",
"default_billable": false,
"default_tags": []
}
}- On
VimEnter,BufEnter,DirChanged, andFocusGained, the plugin detects the current project by walking up to the git root (falling back to the CWD basename). - If the project changes and
auto_startistrue, the previous timer is stopped and a new one is started. - If the same Solidtime project entry is already running on the server when Neovim starts, it is adopted instead of creating a duplicate.
When a timer is running, activity events (CursorMoved, InsertEnter, BufWritePost, …) reset an idle clock. After idle_warn_timeout minutes of no activity a warning is shown; after idle_stop_timeout minutes the timer is automatically stopped.