| .github | ||
| docs | ||
| src | ||
| test | ||
| test-vault | ||
| .editorconfig | ||
| .gitignore | ||
| .npmrc | ||
| .prettierignore | ||
| ACKNOWLEDGEMENTS.md | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CONTRIBUTING.md | ||
| esbuild.config.mjs | ||
| eslint.config.mts | ||
| flake.lock | ||
| flake.nix | ||
| justfile | ||
| KNOWN_LIMITATIONS.md | ||
| LICENSE | ||
| manifest.json | ||
| NEOVIM_PLUGIN_ECOSYSTEM_ANALYSIS.md | ||
| package-lock.json | ||
| package.json | ||
| quartz.config.yaml | ||
| README.md | ||
| styles.css | ||
| tsconfig.json | ||
| version-bump.mjs | ||
| versions.json | ||
| vitest.config.ts | ||
| wdio.conf.mts | ||
Vim Motions
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, Lua configuration with vim.keymap.set / vim.opt / vim.fn / vim.api / vim.tbl_* / autocommands / timers / highlight groups, and a built-in .obsidian.vimrc loader.
Features
- Markdown text objects — operate on bold, italic, code, math, links, blockquotes, code blocks, callouts, tags, table cells, subwords, numbers, quotes, wikilinks, URLs, arguments, and indentation with
d,c,y,v - Structural navigation — jump between headings, lists, links, and buffers with
]h,]l,]n,]b - Lua configuration —
.obsidian.init.luawith conditional logic, function keymaps,vim.fn.*,vim.api.*(buffer APIs,nvim_set_hl),vim.tbl_*,vim.snippet.*,vim.json,vim.inspect,vim.regex(ECMAScript RegExp),vim.schedule/vim.defer_fn/vim.uvtimers, autocommands (19 events),vim.obsidiannamespace (includingvim.obsidian.imfor input method control), buffer-local keymaps, async file reading (vim.ob.fs.read), multi-file configs viarequire(),collectgarbage()support,__gcuserdata finalization, and Neovim-compatible syntax - Built-in vimrc —
.obsidian.vimrcloader with 75+ configurable settings and which-key support with Lucide icons - Flash motions — enhanced
f/F/t/Twith labels on all visible matches (flash.nvim-inspired). Auto-jumps on single match. Operator-pending (df,cf,yf), visual mode, multi-line search. Incrementalsjump mode (type multiple chars to narrow, labels update live), post-commit//?search labels, clever-f repetition, label conflict skipping,[3/15]search match counter. Dynamically sized match highlights and labels positioned after matched text (flash.nvim parity) - EasyMotion / Hop — jump to any visible position with two keystrokes, with operator-pending support
- Workspace keyboard control — navigate panes, tabs, and sidebar without a mouse (
<C-w>,gt/gT,:sp/:vs) - Surround — add, change, or delete surrounding delimiters (vim-surround with Markdown support, including
dsf/csffor function calls, dot-repeat foryswith text objects) - Hard-wrap formatting — Markdown-aware
gq/gwoperators with prefix preservation - Replace-with-register —
gr{motion}replaces text with register contents without clobbering the register (vim-ReplaceWithRegister parity) - Yank-ring paste cycling — cycle through numbered register history with
<C-p>/<C-n>after pasting. Wraps around registers"1–"9. Cancels on any non-cycling command. - Table editing — cell navigation, text objects, manipulation commands, format-on-exit auto-alignment, cursor-aware table widget, and embedded per-cell editing with vim-enabled cell editors and direct table manipulation (
o,dd,J/K,H/L,=) - Oil explorer — oil.nvim-inspired file manager: edit directories as buffers, create/rename/delete files with vim commands
- Telescope-style picker — fuzzy finder with 14 built-in sources (files, buffers, commands, headings, outline, grep, live grep, marks, registers, tags, backlinks, recent, harpoon, snippets), preview pane, frecency scoring, bundled integrations for Omnisearch, Obsidian Tasks, and Dataview, and a provider API for external plugin integration
- Snippets — VS Code-compatible snippet expansion with tabstop navigation, variables, choice nodes, context filtering. 60+ bundled Obsidian snippets. User-defined snippets via JSON files or LuaSnip-inspired Lua DSL with reactive
f()/d()nodes - 100+ ex commands —
:sp,:vs,:e,:grep,:ob,:Oil,:sidebar, navigation/action aliases, and more - Vimium-style hints — navigate the entire Obsidian UI with keyboard hints (
f,F,yf,df) - Line numbers — configurable line number gutter with absolute, relative, and hybrid modes. Neovim-compatible
statuscolumnAPI for custom gutter layouts (vim.opt.statuscolumn = "%s %l %r %C"). Cursor line highlight (cursorline/cursorlineopt), configurable number width, mobile-responsive gutter, and Obsidian's native line numbers suppressed when active - Marks — dedicated sign column gutter showing mark letters next to marked lines, configurable via
signcolumn(auto/always/off), consistent font size regardless of content, gutter layout matching Neovim (sign column → line numbers → fold column), global mark persistence across files and sessions (A–Z), and a grouped marks picker with cross-file navigation - Harpoon — pin files to numbered slots for instant switching (
<leader>1–<leader>9), cursor position tracking, persistence across sessions, auto-updating on file rename/delete - Fully remappable keybindings — every keybinding can be customized via Lua or vimrc across all contexts (editor, oil explorer, picker, workspace)
- Folding — full Neovim-style fold commands:
zf(create),zd(delete),zE(eliminate all),zm/zr(incremental level), custom fold providers for frontmatter and callouts, descriptive fold placeholder text, fold-aware navigation (auto-unfold on]h), cross-session fold persistence, and optional fold column gutter (set foldcolumn) with click-to-fold - Input method switching — automatic IM switching for CJK users when entering/leaving insert mode. Supports macism, im-select, fcitx5-remote, ibus, and any external binary. Platform presets for one-click setup, per-editor state with session persistence, composition guard,
:IMToggle/:IMStatusex commands, Lua API (vim.obsidian.im). Desktop only. - Vim in text areas — focused
<textarea>elements in modals and plugin UIs are replaced with a vim-enabled editor overlay. Starts in insert mode for transparent typing; press Escape for normal mode, second Escape returns to modal. Experimental, disabled by default. Desktop only. - Cross-note jump list —
<C-o>and<C-i>navigate backward/forward through jump history across notes. Jumps recorded ongd, picker selection, harpoon, oil, EasyMotion, and 100+ other navigation paths. Persists across sessions.:jumpsdisplays the list.set jumplist/set jumplistsizefor configuration - Undo tree — undotree-style branching undo history visualization.
g-/g+navigate chronologically across all branches with buffer content restoration.:earlier/:laterby count, time, or save point.:undolistmodal. Sidebar view (:UndoTreeToggle) with tree rendering, keyboard nav, collapse/expand, diff preview.vim.fn.undotree()Lua API. Optional persistence (set undofile). 5 settings:enableUndoTree,undoTreeMaxNodes,undoTreePosition,undoTreeAutoOpen,undoFile - Animated cursor — canvas-based smooth cursor movement and smear-cursor.nvim-style spring-damper smear trail. Per-mode cursor shapes, configurable stiffness/damping/smoothness,
prefers-reduced-motionsupport. Disabled by default. 8 settings:animatedCursor,smoothCursor,cursorSmoothness,smearTrail,smearStiffness,smearTrailingStiffness,smearDamping,smearMaxLength - Subword motions — spider.nvim-style
w/b/e/geoverride stopping at camelCase, snake_case, and kebab-case boundaries. Opt-in setting. - Enhanced increment/decrement — dial.nvim-style
<C-a>/<C-x>cycling hex colors, booleans, dates, CSS values, and checkboxes - Custom text objects — define delimiter-pair text objects from Lua via
vim.textobject.add()+vim.gen_spec.pair() - External grep — optional ripgrep or GNU grep binary for native-speed vault search in the picker. Desktop only with in-memory fallback.
- Quality of life: Neovim defaults (
Y/Q), yank highlight, smart list continuation, scrolloff, insert escape sequences, chord display, powerline status bar, and settings hot-reload
Installation
From community directory
Search for "Vim Motions" in Settings → Community plugins → Browse.
Manual installation
- Download
main.js,manifest.json, andstyles.cssfrom the latest release. - Create a folder
vim-motionsin<your-vault>/.obsidian/plugins/. - Copy the downloaded files into that folder.
- Restart Obsidian and enable the plugin in Settings → Community plugins.
Recommended setup
Disable Obsidian's built-in Vim mode (Settings → Editor → Vim key bindings → off). Vim Motions provides its own enhanced vim engine — a fork of codemirror-vim — with Neovim-correct behavior, async motion support, correct cursor positioning in Live Preview, and theme-aligned styling.
The plugin also works with built-in vim mode enabled, but the fork provides a more accurate Vim experience. See the recommended setup guide for details.
Documentation
Full documentation: https://saberzero1.github.io/motions
- Getting started
- Features
- Lua configuration
- Settings reference
- Keybinding cheat sheet
- Remapping guide
- Known limitations
- Changelog
Requirements
- Obsidian v1.7.2 or later
- Desktop or mobile (physical keyboard recommended on mobile)
Development
npm install # Install dependencies
npm run dev # Development build (watch mode)
npm run build # Production build
npm run lint # Lint
npm run test:e2e # E2E tests (requires nix develop)
See CONTRIBUTING.md for the full development guide, testing strategy, and contribution guidelines.
License
MIT — Emile Bangma