A polished, Neovim-native experience inside Obsidian. Vim Motions adds what’s missing from Obsidian’s built-in Vim mode: Markdown-aware text objects, structural navigation, hard-wrap formatting, workspace keyboard control, EasyMotion, a telescope-style fuzzy picker, Lua configuration with vim.keymap.set / vim.opt / vim.fn / vim.api / vim.ob / vim.tbl_* / autocommands / timers / highlight groups / global keymaps / which-key labels, and a built-in .obsidian.vimrc loader.

Feature highlights

  • Markdown text objects — operate on bold, italic, code, math, links, blockquotes, code blocks, tables, and more with standard Vim operators
  • Structural navigation — jump between headings, lists, links, and buffers with ]h, ]l, ]n, ]b
  • Lua configuration.obsidian.init.lua with vim.keymap.set, vim.opt (including guicursor), vim.fn (including undotree()), vim.api (buffer APIs, nvim_set_hl), vim.ob (68 Obsidian-specific functions: metadata, filesystem, UI, cursor, surround, leader), vim.tbl_*, vim.json, vim.inspect, vim.regex (ECMAScript RegExp), vim.schedule/vim.uv timers, 19 autocommand events, buffer-local keymaps, vim.obsidian.keymap (global keymaps), vim.obsidian.whichkey (which-key labels), async file reading (vim.ob.fs.read), multi-file configs via require(), fuzzy picker API, and hot-reload on save
  • Built-in vimrc.obsidian.vimrc loader with 75+ configurable settings and hot-reload on save
  • Flash motions — enhanced f/F/t/T with jump labels, incremental s search, post-commit //? labels, clever-f
  • EasyMotion / Hop — jump to any visible position with two keystrokes
  • Workspace keyboard control — navigate panes, tabs, and sidebar without a mouse
  • Surround — add, change, or delete surrounding delimiters (nvim-surround parity, custom pairs)
  • Hard-wrap formatting — Markdown-aware gq/gw operators
  • 100+ ex commands:sp, :vs, :e, :grep, :ob, fuzzy picker commands, and more
  • Vimium-style hints — navigate the entire Obsidian UI with keyboard hints
  • Undo tree — branching undo history visualization with g-/g+ chronological navigation, :earlier/:later time travel, sidebar tree view, and optional persistence

Get started

New to Vim Motions?

Start with installation to install the plugin, then follow recommended-setup to configure Obsidian for the best experience.

What’s new in 0.149.0

  • Non-Markdown picker previews are configurablepickerNonMarkdownPreview (set pickerpreview, vim.opt.pickerpreview) chooses rendered (default), hidden, or raw. rendered embeds images, svg and canvas natively and shows a name/type/size card for PDFs, video and audio. Markdown is always previewed, and the setting applies live without a reload (settings reference, #172)
  • The picker no longer reads binary files to preview them — scrolling past a multi-megabyte PDF used to decode the whole binary as UTF-8, and Obsidian cached that string, so memory grew with every binary encountered. Size is now checked from file metadata before any read, in every mode
  • Preview rendering is debounced — holding j issued a fresh read and render per keystroke (roughly 30 previews a second). A 100 ms leading-plus-trailing debounce keeps isolated keypresses instant while collapsing a burst to two
  • The preview pane no longer leaks Component instances — raw-string, empty, loading and error transitions all replaced pane content while leaving embeds, images and transclusions registered. A single teardown path now runs on every transition, including close
  • Sturdier preview error handling — a synchronous throw from a picker source’s preview() is caught as the provider API documents, and superseded in-flight previews are rejected by generation instead of item id, so re-selecting the same item can no longer render a stale result

See the full changelog for details.