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 1.4.0

  • Repeated snippet tabstops survive typing in Live Preview — with a body like $1 *a$2* *b$2* $0, Tab placed both cursors correctly, but the first keystroke moved them outside the emphasis and outside the snippet’s own fields, so the session was dropped and a second keystroke produced *az*y *ybz* where *azy* *bzy* was wanted. The guard that covers a tabstop jump now also covers the first edit at a tabstop (snippets)
  • <Esc> now honours your own mappings — :imap <Esc> … and :vmap <Esc> … did nothing at all, because the built-in mode exit ran before the mapping table was ever consulted. Only exact matches win, matching Neovim; <C-[> follows the mapping because it is Escape, while <C-c> stays a dependable escape hatch, and a recursive imap <Esc> <Esc> falls back to the built-in exit (remapping, vimrc)
  • :stopinsert (:stopi) exists — it had been documented in three places without being implemented, so the published recipes for handing insert mode to another plugin silently left the editor in insert mode. It lands the cursor where <Esc> would and is a no-op outside insert mode (ex commands)
  • Two previously unreported table defects are now recorded — a snippet tabstop inside a table in Live Preview, and set tablewidget=raw not accepting typed text inside a table in Live Preview, where a typed character lands at the end of the document instead (known limitations)

See the full changelog for details.