Persistent marks and annotations for Neovim that survive code changes, branch switches, and file moves.
- Persistent Marks: Marks that survive across sessions, branch switches, and code changes
- Smart Matching: Intelligent position restoration using git blame, line content, and surrounding context
- Project-Scoped: Storage organized per project in
.git/persistent_marks/ - Dual Support: Works with both Vim marks (a-z, A-Z) and Extmarks for annotations
- Visual Indicators: Sign column shows all marks and notes at a glance
- Automatic: Save/restore marks automatically on buffer events
- Smart match each mark on restoring each buffer
- Match marks after file renamed
- Neovim 0.5+ (for extmarks support)
- Git repository (for smart matching features)
Plug 'solomonxie/nvim-marks'{
"solomonxie/nvim-marks",
config = function()
-- Plugin is configured automatically
-- Optional: add custom keymaps or settings
end,
}use {
"solomonxie/nvim-marks",
config = function()
-- Plugin is configured automatically
end,
}- Clone the repository:
git clone https://github.com/solomonxie/nvim-marks.git ~/.config/nvim/pack/plugins/start/nvim-marks- Restart Neovim
- Open Marks Window: Press
min any buffer - Add Mark: Press any letter
a-zin the marks window - Add Note: Press
+to add an annotation - Delete Mark/Note: Press
-to remove marks/notes - Quit: Press
qto close the marks window
" Open marks management window
m
" In the marks window:
" Press a-z - Add a local mark at current line
" Press A-Z - Add a global mark at current line
" Press + - Add a note/annotation
" Press - - Delete mark/note at current line
" Press * - List all marks in current file
" Press q - Quit marks window- Local Marks (
a-z): File-specific marks - Global Marks (
A-Z): Cross-file marks that work across your project - Notes: Rich annotations with multi-line content
" 'A " Jump to any mark (standard Vim mark navigation)
" ma " Jump to mark 'a'
" mA " Jump to global mark 'A'The plugin works out of the box. Customizations are to be done.
When working on large codebases, it's common to have important annotations, bookmarks, or marks that help navigate and understand the code. However, these marks can be lost when switching branches, pulling updates, or making changes to the code. Persistent marks ensure that these important references are saved and can be restored even after significant changes to the codebase.
If we want to put a mark on a line, we need to first know which line it is. But line numbers change so often, and even the line content may change too. So we need an "anchor" to associate the mark with the line which can survive:
- Line number changes
- Line content changes
- File moves/renames
- Branch switches
- Edits outside of the editor
- And more...
To satisfy all these requirements is really hard, which is why it's so difficult to find a good plugin for this feature.
Nvim-marks uses a combination of strategies to ensure marks are "persistent-ish". It does not pursue 100% accuracy which could make it very slow and complex, but it tries to cover most common scenarios and be smart enough to handle most day-to-day cases.
The plugin collects this information for each mark:
- File path (relative to project root)
- Line number
- Line content
- Surrounding lines content
- Git blame info (commit hash, author, date, etc)
When restoring a mark, nvim-marks tries to match each piece of information with weights and calculates the most confident position to restore the mark. If the overall confidence is low, it will still keep the mark showing in the Mark List but without an associated line number, so that the user can manually link it to a line whenever needed.
Marks are stored in JSON files based on your customization. By default it's under your project's .git/persistent_marks/ directory:
.git/persistent_marks/
├── your-project-name/
│ ├── src__main__lua.json
│ └── vimmarks_global.json
Each file contains:
- Local marks/notes (
vimmarksandnotes) - Global marks (
vimmarks_global): Cross-file marks A-Z
- Fast startup: ~1ms initialization time
- Efficient matching: Uses cached git blame information
- Minimal overhead: No impact on normal editing workflow