A Neovim plugin for managing line bookmarks with Telescope integration and SQLite storage. Mark, organize, and quickly navigate between important locations in your codebase.
bookmarks.nvim
vs. Native Vim MarksWhile Vim's native marks (ma
, 'a
) are useful for temporary navigation, bookmarks.nvim
provides a more robust, feature-rich, and persistent bookmarking system.
Feature | Native Vim Marks | bookmarks.nvim |
---|---|---|
Storage | Plain text (.viminfo /shada ) |
SQLite Database for structured, queryable, and persistent storage |
Scope | Local (per-file) or Global (cross-file) | Project-aware: Bookmarks are tied to a project root |
Branch-specific | No | Yes: Bookmarks can be isolated per Git branch and toggled at runtime |
Data | File path, line, and column only | Rich metadata: line content, timestamp, project info |
UI | Command-based (:marks ) |
Interactive UI: Telescope integration for fuzzy search, browsing, and live previews |
Persistence | Only global marks (A-Z ) persist across sessions |
All bookmarks are persistent by default |
Management | Manual, must remember mark letters | Centralized API: Add, remove, list, and navigate bookmarks |
Dependencies | None (core feature) | Requires sqlite.lua and telescope.nvim |
Using lazy.nvim
:
{
"heilgar/bookmarks.nvim",
dependencies = {
"kkharji/sqlite.lua",
"nvim-telescope/telescope.nvim",
"nvim-lua/plenary.nvim",
},
config = function()
require("bookmarks").setup({
-- your configuration comes here
-- or leave empty to use defaults
default_mappings = true,
db_path = vim.fn.stdpath('data') .. '/bookmarks.db'
})
require("telescope").load_extension("bookmarks")
end,
cmd = {
"BookmarkAdd",
"BookmarkRemove",
"Bookmarks"
},
keys = {
{ "<leader>ba", "<cmd>BookmarkAdd<cr>", desc = "Add Bookmark" },
{ "<leader>br", "<cmd>BookmarkRemove<cr>", desc = "Remove Bookmark" },
{ "<leader>bj", desc = "Jump to Next Bookmark" },
{ "<leader>bk", desc = "Jump to Previous Bookmark" },
{ "<leader>bl", "<cmd>Bookmarks<cr>", desc = "List Bookmarks" },
},
}
require("bookmarks").setup({
-- Storage configuration
db_path = vim.fn.stdpath('data') .. '/bookmarks.db', -- Path to SQLite database
-- Branch configuration
use_branch_specific = false, -- Enable/disable branch-specific bookmarks (can be toggled at runtime)
-- Keymaps configuration
default_mappings = true, -- Set to false to disable default keymaps
-- Custom mappings example (if default_mappings = false):
mappings = {
add = "ma", -- Add bookmark at current line
delete = "md", -- Delete bookmark at current line
list = "ml", -- List all bookmarks
}
})
:BookmarkAdd
- Add bookmark at current line:BookmarkRemove
- Remove bookmark at current line:Bookmarks
- Open Telescope to browse bookmarks:BookmarksToggleBranchScope
- Toggle branch-specific bookmarks on/off<leader>ba
- Add bookmark<leader>br
- Remove bookmark<leader>bj
- Jump to next bookmark in file<leader>bk
- Jump to previous bookmark in file<leader>bl
- List bookmarks (opens Telescope)<leader>bt
- Toggle branch-specific bookmarks on/offInside Telescope bookmarks view:
<CR>
- Jump to selected bookmark<Del>
- Delete selected bookmarkTo disable default keymaps, set default_mappings = false
in setup and define your own:
vim.keymap.set('n', '<your-keymap>', require('bookmarks.commands').add_bookmark)
vim.keymap.set('n', '<your-keymap>', require('bookmarks.commands').remove_bookmark)
vim.keymap.set('n', '<your-keymap>', require('bookmarks.navigation').jump_to_next)
vim.keymap.set('n', '<your-keymap>', require('bookmarks.navigation').jump_to_prev)
vim.keymap.set('n', '<your-keymap>', require('telescope').extensions.bookmarks.list)
The plugin defines these highlight groups that you can customize:
BookmarkHighlight
- Highlight for bookmarked linesBookmarkSignHighlight
- Highlight for the bookmark sign column indicatorExample of customizing highlights:
vim.api.nvim_set_hl(0, "BookmarkHighlight", {
bg = "#3a3a3a",
underline = true
})
vim.api.nvim_set_hl(0, "BookmarkSignHighlight", {
fg = "#458588",
})
local bookmarks = require("bookmarks")
-- Add bookmark at current line
bookmarks.add_bookmark()
-- Remove bookmark at current line
bookmarks.remove_bookmark()
-- Navigate bookmarks in current file
bookmarks.jump_to_next()
bookmarks.jump_to_prev()
-- Jump to a specific bookmark
bookmarks.jump_to_bookmark(filename, line_number)
-- Get all bookmarks
local storage = require("bookmarks.storage")
local all_bookmarks = storage.get_bookmarks()
-- Get bookmarks for specific file
local file_bookmarks = storage.get_file_bookmarks(filename)
Contributions are welcome! Please feel free to submit a Pull Request.
Thanks to:
Search for bookmarks by filename, content, or line number directly from the search prompt. The UI is designed for maximum readability with clear visual separation between entries.
The bookmarks viewer features a vertical layout with:
When use_branch_specific
is enabled, bookmarks are stored and shown per Git branch. This means:
:BookmarksToggleBranchScope
or <leader>bt
.This is useful for workflows where you want to keep bookmarks isolated to specific features or tasks per branch.
You can show the current bookmarks scope (global or branch) in your statusline using the built-in helper:
Add this to your init.lua
:
vim.o.statusline = "%f %h%m%r %=%{v:lua.require('bookmarks').status()}"
If you use lualine.nvim:
require('lualine').setup {
sections = {
lualine_c = {
'filename',
{ function() return require('bookmarks').status() end }
},
-- ... other sections ...
}
}
This will show Bookmarks: branch=my-feature
or Bookmarks: global
in your statusline, depending on the current mode.