Vim Motions includes several convenience features that improve the day-to-day Vim experience in Obsidian.
Keybindings
Quality of life
Enhanced Vim behavior and Obsidian-specific improvements.
Link to original
Keybinding Description o/OSmart list continuation (bullets, numbers, checkboxes, blockquotes) YYank to end of line ( y$)QReplay last recorded macro ( @@)@:Repeat last ex command &Repeat last :ssubstitution on current lineg&Repeat last :ssubstitution on all linesgMGo to middle character of text line KKeyword lookup (hover preview on links, char info) ]<Space>Add N blank lines below cursor [<Space>Add N blank lines above cursor ZZWrite current file and close tab ( :wq)ZQClose tab without saving ( :q)g;Older change g,Newer change g-Older undo state g+Newer undo state <C-p>Cycle paste previous register (or kif not cycling)<C-n>Cycle paste next register (or jif not cycling)
Smart list continuation
Pressing o or O on a list line automatically continues the list marker on the new line. Supports:
- Unordered lists (
-,*,+) - Ordered lists (
1.,2.) - Task lists (
- [ ],- [x]), including custom checkbox states ([!],[?],[/]) - Indented and nested lists
- Blockquote lists (
> -), including lists indented inside a quote (> -) - Blockquotes and callouts with no list marker (
>,> >), matching what Obsidian’s own Enter does on the same line
Works correctly on the first line after YAML frontmatter. Lines inside a fenced code block are left alone, including fences written inside a blockquote. Disable for plain Neovim behavior via Settings → Vim Motions → Smart list continuation on o/O, vim.opt.listcontinuation = false in Lua, or set nolistcontinuation in vimrc.
Neovim backend
With the Neovim backend connected, continuation is Neovim’s own
comments/formatoptionsmachinery rather than this implementation, and the two do not agree on every line. Neovim continues>on a blockquote, but drops the list marker on> - item(giving>), drops the checkbox on- [ ] todo(giving-), does not continue ordered lists at all, and has no fenced-code-block exclusion. Indentation style is preserved either way — the mirrored buffer follows your Settings → Editor → Indent using tabs and Tab indent size.
Pressing o on a parent item that has more-indented children inserts the new item at the parent’s level, not the child’s. This matches Obsidian’s own Enter key and Neovim; outliner-style child-level insertion is available from Lua if you prefer it.
Yank highlight
Yanked text is briefly highlighted to provide visual feedback on what was yanked. Three modes are available in Settings → Vim Motions → Vim features → Yank highlight:
- Solid (default) — highlight appears instantly and disappears after the configured duration, matching Neovim’s
vim.highlight.on_yank()behavior - Fade — highlight gradually fades out over the configured duration
- Off — no highlight
Duration is configurable via the Yank highlight duration slider (50–3000ms, default 200ms), or in your config:
vim.opt.yankhighlightmode = "solid"/vim.opt.yankhighlightduration = 200in Luaset yankhighlightmode=solid/set yankhighlightduration=200in vimrc
Blocks that Live Preview renders — callouts, embedded notes, images, and tables — are highlighted as a whole when the yank reaches any of their lines. A rendered block is opaque, so it is either highlighted or not; there is no partial highlight within one.
Tip
Override the highlight color with a CSS snippet: set
--vim-motions-yank-bgon.theme-darkor.theme-light(e.g.,--vim-motions-yank-bg: rgba(255, 200, 0, 0.4);).
Info
Yank highlight requires the bundled fork engine or the Neovim backend (built-in vim mode OFF). The built-in vim does not emit the
vim-yankevent used for detection; under the Neovim backend aTextYankPostnotification drives the same renderer, so bothsolidandfadework. Works with remapped yank keys — detection is based on the actual yank operation, not keypress sniffing.
Yank-ring paste cycling
After p, P, gp, or gP, press <C-p> to replace the pasted text with the previous numbered register ("1–"9). <C-n> cycles in the opposite direction. Cycling wraps around the register list. Any non-cycling command cancels the cycling state, after which <C-p>/<C-n> revert to their default k/j behavior.
Visual-mode paste cycling also works: select text with viw or V, press p to paste, then <C-p>/<C-n> to cycle through registers. Visual block paste (<C-v>) is excluded.
Dot-repeat (.) after cycling pastes the final cycled text, not the original. When cycling exits, the paste register is updated with the final content so the fork’s repeatLastEdit replays the correct text. This matches yanky.nvim’s update_register_on_cycle behavior. System clipboard registers ("+/"*) are excluded from the register update.
Toggle via Settings → Vim Motions → Vim features → Yank-ring paste cycling, vim.opt.yankring = false in Lua, or set noyankring in vimrc.
Change list navigation
g; and g, jump to older and newer change positions respectively, letting you quickly revisit locations where you made edits. The :changes ex command displays the full change list in a modal.
Undo tree navigation
| Key | Action |
|---|---|
g- | Navigate to chronologically older undo state (across branches) |
g+ | Navigate to chronologically newer undo state (across branches) |
Undo tree
Use g- and g+ to move to older/newer undo states (branch-aware). Open the sidebar with :UndoTreeToggle (or :UndoTreeShow / :UndoTreeHide) to visualize branches, see relative timestamps, and preview the change summary for the selected node. Branch points include a toggle to collapse alternate histories.
Saved states can be navigated by count with :earlier Nf / :later Nf (where N is the number of saved states to move).
Neovim defaults
Yyanks to end of line (y$) instead of the entire lineQreplays the last recorded macro (@@) instead of entering Ex mode&repeats last:ssubstitution on current line;g&repeats on all linesgMgoes to middle character of text line (distinct fromgm— middle of screen line)Ktriggers keyword lookup — hover page preview on wikilinks, opens external URLs, char info on plain text. The preview opens whether or not the Page preview core plugin is set to require Ctrl/Cmd for that source, since pressingKis itself the explicit request, and stays open until you click or move the mouse off the editor]<Space>/[<Space>adds blank lines below/above cursor (supports count)v_*/v_#searches for selected text from visual modeg<C-A>/g<C-X>increments/decrements numbers sequentially in visual selectiong<Tab>goes to last accessed tab page<C-U>in insert mode deletes to insert-start position (not line start)
Vim mode status bar
Shows the current mode (NORMAL / INSERT / VISUAL / REPLACE) in Obsidian’s status bar. Customizable per-mode text (including emoji) via Settings → Vim Motions → Vim mode display prompt, vim.g.mode_prompt_normal = "N" in Lua, or let g:mode_prompt_normal = "N" in vimrc.
Vim chord display
Shows pending keystrokes (e.g., 2d, gq) in the status bar as you type a multi-key command. Toggle via Settings → Vim Motions → Vim chord display, vim.opt.chorddisplay = false in Lua, or set nochorddisplay in vimrc.
Powerline-style status bar
Optional colored mode indicator with per-mode background colors and a triangular separator. No special fonts required.
Override colors via CSS custom properties (--vim-pl-normal-bg, --vim-pl-insert-bg, --vim-pl-visual-bg, --vim-pl-replace-bg) or via the Style Settings plugin with separate light/dark mode defaults.
Toggle via Settings → Vim Motions → Powerline-style status bar, vim.opt.powerline = true in Lua, or set powerline / set nopowerline in vimrc.
Which-key hints
Shows available key continuations in a popup after a short delay. Three modes:
- Off — no popup (default)
- Leader key only — popup appears after pressing the leader key
- All partial keys — popup appears after any partial key sequence (
dshows motions/text objects,gshows g-prefixed commands, etc.)
Leader bindings can be grouped by prefix — pressing <leader> shows t → Table (+11) instead of listing all table commands. Drill into a group by pressing its key.
Configure via Settings → Vim Motions → Which-key hints, vim.opt.whichkey = "leader" in Lua, or set whichkey=leader in vimrc. See which-key for detailed setup.
Scrolloff
Configurable number of lines to keep visible above and below the cursor when scrolling (0–9999, default: 5).
Centered cursor
Set
vim.opt.scrolloff = 999in your Lua config orset scrolloff=999in your vimrc to keep the cursor vertically centered while scrolling — the standard Vim pattern for centered scrolling.
Adapts to your font size automatically via EditorView.defaultLineHeight. Configure via Settings → Vim Motions → Advanced → Scrolloff lines, vim.opt.scrolloff = 5 in Lua, or set scrolloff=5 in vimrc.
Configurable insert escape
Set a two-key sequence to exit insert mode (e.g., jk, jj):
vim.opt.insertmodeescape = "jk"in Luaset insertmodeescape=jkin vimrc- Settings → Vim Motions → Vim engine → Insert mode escape
Timeout is configurable via vim.opt.insertmodeescapetimeout = 1000 in Lua or set insertmodeescapetimeout=1000 in vimrc (default: 1000ms, matching Neovim’s timeoutlen).
Macro recording indicator
Shows RECORDING @{register} in the status bar when recording a macro.
Ex command completion
Tab-complete ex commands as you type in the : command line.
Configuration hot-reload
Configuration files (init.lua and .obsidian.vimrc) are watched for changes. When you save a config file, it is automatically re-applied without reloading the plugin.
You can also manually trigger a reload of all configuration files using the Vim Motions: Reload configuration command from the Obsidian command palette.
Settings hot-reload
All feature toggles and vim engine settings take effect immediately when changed — no Obsidian restart required. This includes clipboard, tabstop, shiftwidth, expandtab, pcre, insertmodeescape, insertmodeescapetimeout, operatorshadowtimeout, and textwidth. All nine settings also persist across restarts — the plugin syncs saved values to the vim engine on every plugin load.
See known-limitations > UI & display for known display-related limitations and known-limitations > Vimrc for vimrc timing issues.