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.

KeybindingDescription
o / OSmart list continuation (bullets, numbers, checkboxes, blockquotes)
YYank to end of line (y$)
QReplay last recorded macro (@@)
@:Repeat last ex command
&Repeat last :s substitution on current line
g&Repeat last :s substitution on all lines
gMGo 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 k if not cycling)
<C-n>Cycle paste next register (or j if not cycling)
Link to original

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/formatoptions machinery 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 = 200 in Lua
  • set yankhighlightmode=solid / set yankhighlightduration=200 in 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-bg on .theme-dark or .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-yank event used for detection; under the Neovim backend a TextYankPost notification drives the same renderer, so both solid and fade work. 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

KeyAction
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

  • Y yanks to end of line (y$) instead of the entire line
  • Q replays the last recorded macro (@@) instead of entering Ex mode
  • & repeats last :s substitution on current line; g& repeats on all lines
  • gM goes to middle character of text line (distinct from gm — middle of screen line)
  • K triggers 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 pressing K is 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 mode
  • g<C-A> / g<C-X> increments/decrements numbers sequentially in visual selection
  • g<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 (d shows motions/text objects, g shows 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 = 999 in your Lua config or set scrolloff=999 in 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 Lua
  • set insertmodeescape=jk in 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.