Vim Motions has built-in vimrc support, compatible with obsidian-vimrc-support syntax. When both plugins are installed, they coexist — Vim Motions registers its own :ob command independently.
Lua configuration available
Vim Motions also supports Lua configuration with Neovim-compatible syntax. Lua config provides conditional logic and function-based keymaps. See lua-config for details.
File location
The plugin searches the vault root for the first matching file in this order:
vimrc.vimrcinit.vim.init.vimobsidian.vimrcobsidian.vim.obsidian.vimrc.obsidian.vim
The first file found is used. Override this with a custom path in Settings → Vim Motions → Vimrc & key bindings → Custom vimrc path. The settings UI shows which file is currently active.
Shared config across vaults (desktop only)
On desktop, the custom path can be an absolute filesystem path — useful for sharing one vimrc across multiple vaults:
~/.config/obsidian/vimrc(Linux)~/Library/Application Support/obsidian/vimrc(macOS)C:\Users\<you>\.config\obsidian\vimrc(Windows)
Any absolute path (starting with /, ~, or a drive letter) is read directly from the filesystem instead of through the vault. This is not available on mobile.
Obsidian Sync
Obsidian Sync skips dotfiles. Use a non-dotfile name like
vimrc(the first candidate in the fallback chain) to ensure your config syncs across devices.
Example vimrc
" Leader key
let mapleader = " "
" Key mappings
nnoremap j gj
nnoremap k gk
" Settings (override Settings UI values)
set scrolloff=5
set textwidth=80
set clipboard=unnamed
set expandtab
set tabstop=4
set shiftwidth=2
set insertmodeescape=jk
set insertmodeescapetimeout=1000
set easymotion
set nopowerline
set easymotionlabels=asdghklqwertyuiopzxcvbnmfj
" Cursor shapes (bundled fork mode only)
set guicursor=n:block,i:bar,v:block,r:underline,o:underline
" Mode prompts
let g:mode_prompt_normal = "N"
let g:mode_prompt_insert = "I"
" Leader key mappings
exmap saveFile obcommand editor:save-file
nmap <leader>w :saveFile<CR>
" Which-key labels
whichkeygroup <leader>t Table
whichkeylabel <leader>w Save file
" Global mappings (non-editor contexts)
gmap <leader>f :obcommand switcher:open
gmap <leader>e :obcommand file-explorer:reveal-active-file
gnoremap <leader>s :sidebar left
gunmap H
" Global which-key labels
gwhichkeygroup <leader> +leader
gwhichkeylabel <leader>f Open file
" Custom surround pairs
surroundmap l [[ ]]
surroundmap m $$ $$Supported commands
| Command | Description |
|---|---|
map / nmap / imap / vmap | Mode-specific key mappings |
noremap / nnoremap / inoremap / vnoremap | Non-recursive mappings |
unmap / nunmap / iunmap / vunmap | Remove mappings |
set | Set plugin options (see tables below) |
let mapleader | Set the leader key |
exmap | Define a named command from an Obsidian command |
obcommand | Execute an Obsidian command by ID (alias of :ob) |
source | Source another vimrc file |
gmap / gnoremap | Global key mapping for non-editor contexts |
gunmap | Remove a global mapping |
whichkeygroup | Name a which-key group by prefix |
whichkeylabel | Label an individual binding in which-key |
gwhichkeygroup | Name a global which-key group by prefix |
gwhichkeylabel | Label a global binding in which-key |
surroundmap | Register a custom surround pair |
surroundunmap | Remove a custom surround pair |
Leader key
let mapleader supports any key: space (let mapleader = " "), comma, semicolon, backslash (default). The leader key’s default Vim binding is automatically unmapped so leader-prefixed sequences work correctly.
Boolean options
Use set <option> to enable, set no<option> to disable.
| Option | Alias | Description | Default |
|---|---|---|---|
textobjects | to | Markdown-aware text objects | on |
replacewithregister | rwr | Replace-with-register operator | on |
navigation | nav | Heading, list, and link navigation | on |
hardwrap | hw | gq/gw hard-wrap operators | on |
listcontinuation | lc | Smart list continuation on o/O | on |
tablenav | tn | Table cell navigation | on |
workspacenav | wn | Pane/tab/sidebar control | on |
number | nu | Show absolute line numbers | off |
relativenumber | rnu | Show relative line numbers | off |
flash | — | Flash-style f/F/t/T labels | on |
flashmultiline | fml | Flash searches beyond current line | on |
flashjump | — | Flash bidirectional jump mode (s) | off |
flashcleverf | — | Clever-f repetition | off |
flashsearch | — | Labels on /? search matches | on |
labelmatchfontsize | lmfs | Scale labels to match line font size | off |
easymotion | em | EasyMotion/Hop navigation | on |
easymotiondimming | emd | Dim non-target text during EasyMotion | on |
hintmode | hm | Vimium-style hint labels | on |
statusbar | sb | Vim mode in status bar | on |
chorddisplay | cd | Pending keystrokes in status bar | on |
powerline | pl | Colored powerline status bar | off |
expandtab | et | Use spaces instead of tabs | on |
pcre | — | Use JavaScript regexps in search/subst | on |
cursorline | cul | Cursor line highlight | on |
foldcolumn | fdc | Fold column indicators | off |
markgutter | — | Alias for signcolumn (compat) | on |
snippets | — | Enable snippet expansion | on |
snippetbundled | — | Include bundled Obsidian snippets | on |
vimtextareas | vta | Vim keybindings in text areas | off |
yankring | — | Yank-ring paste cycling | on |
harpoon | — | Harpoon file pinning | on |
dial | — | Enhanced increment/decrement | off |
jumplist | — | Vim-style jump list for <C-o>/<C-i> | on |
foldawarenavigation | — | Auto-unfold on navigation | on |
foldpersistence | — | Persist fold state across sessions | off |
undotree | ut | Enable undo tree tracking | on |
undofile | udf | Persist undo tree across sessions | off |
smoothcursor | sc | Enable animated cursor | off |
smoothcursorglide | scg | Smooth cursor movement (glide) | on |
smoothcursorsmear | scm | Enable smear trail | on |
subword | — | Spider.nvim-style subword motions | off |
picker | — | Telescope-style picker | on |
pickerleadermappings | — | Leader key picker shortcuts | on |
pickeromnisearch | — | Omnisearch picker integration | off |
pickertasks | — | Obsidian Tasks picker integration | off |
pickerdataview | — | Dataview picker integration | off |
ripgrep | — | Use ripgrep binary for grep | off |
oil | — | Oil file explorer | off |
oilhiddenfiles | — | Show hidden files in Oil | off |
undotreeautoopen | — | Auto-open undo tree on branch | off |
imswitching | — | Input method auto-switching | off |
Number options
Use set <option>=<value>.
| Option | Alias | Description | Default | Range |
|---|---|---|---|---|
scrolloff | so | Lines to keep visible above/below cursor | 5 | 0-9999 |
scanlimit | sl | Max lines to scan for text objects | 20 | 5-200 |
labelfontsize | lfs | Font size for EasyMotion/hint labels | 14 | 10-20 |
tabstop | ts | Tab display width | 4 | 1-8 |
shiftwidth | sw | Indent width | 4 | 1-8 |
textwidth | tw | Line wrap width for gq/gw | 80 | 0-200 |
insertmodeescapetimeout | imet | Timeout (ms) for insert escape sequence | 1000 | 100-5000 |
operatorshadowtimeout | ost | Timeout (ms) for operator-prefix disambiguation | 1000 | 0-5000 |
numberwidth | nuw | Minimum line number column width | 2 | 1-20 |
jumplistsize | — | Maximum jump list entries | 200 | 1-1000 |
undotreemaxnodes | utmn | Maximum undo tree nodes per file | 1000 | 100-5000 |
yankhighlightduration | — | Yank highlight duration (ms) | 200 | 0-5000 |
smoothcursorsmoothness | scs | Cursor movement smoothness | 0.5 | 0-1 |
smoothcursorstiffness | scst | Smear trail head stiffness | 0.6 | 0.1-1 |
smoothcursortrailstiffness | scts | Smear trail tail stiffness | 0.3 | 0.1-1 |
smoothcursordamping | scd | Smear trail velocity decay | 0.85 | 0.1-0.99 |
smoothcursormaxlength | scml | Maximum smear trail length (px) | 400 | 50-800 |
oilconfirmdeletethreshold | — | Oil delete confirmation threshold | 5 | 0-100 |
String options
Use set <option>=<value>.
| Option | Alias | Description | Default |
|---|---|---|---|
clipboard | clip | System clipboard sync (unnamed/unnamedplus) | (off) |
insertmodeescape | ime | Two-key sequence to exit insert mode | (off) |
flashjumpkey | — | Key to trigger flash jump mode | s |
flashminpatternlength | fmpl | Minimum chars before labels in jump mode | 1 |
yankhighlightmode | — | Yank highlight style (off/solid/fade) | solid |
easymotionlabels | eml | Characters for EasyMotion and flash labels | asdghklqwertyuiopzxcvbnmfj |
hintlabels | hl | Characters for hint mode labels | asdfghjkl |
guicursor | — | Per-mode cursor shapes | (block/bar/block/underline/underline) |
tablewidget | — | Table widget mode (native/raw) | native |
whichkey | wk | Which-key hints (off/leader/all) | off |
whichkeygrouping | wkg | Which-key grouping (flat/grouped) | grouped |
whichkeysort | wks | Which-key sort order (which-key/groups-first) | which-key |
whichkeyicons | wki | Which-key icons (on/off) | on |
workspacenavviewtypes | wnvt | View types for workspace nav interception | (empty — uses defaults: markdown, graph, pdf, canvas, empty, image, bases) |
cursorlineopt | culopt | Cursor line highlight mode (number/line/both) | number |
signcolumn | scl | Sign column visibility (auto[:N]/yes[:N]/no) | auto |
linenumbermode | lnm | Line number display (deprecated — use statuscolumn) | hybrid |
statuscolumn | stc | Custom gutter layout format string | (empty — plugin-managed) |
snippetdir | — | Path to user snippet JSON directory | (off) |
snippettrigger | — | Snippet trigger mode (completion/tab/both) | both |
pickermatcher | — | Picker match engine (ufuzzy/obsidian) | ufuzzy |
ripgreppath | — | Path to ripgrep binary | (off) |
ripgrepargs | — | Additional ripgrep arguments | (off) |
grepmode | — | Grep backend (ripgrep/grep) | ripgrep |
oilsort | — | Oil default sort (name/mtime/size) | name |
hinthotkey | — | Key to trigger hint mode | (off) |
undotreeposition | — | Undo tree sidebar position (left/right) | right |
impreset | — | IM preset (custom/macism/im-select/fcitx5-remote/ibus) | custom |
imbinarypath | — | Path to IM binary | (off) |
imobtainargs | — | Args for obtaining current IM | (off) |
imswitchargs | — | Args for switching IM | {im} |
imdefaultnormal | — | Default IM for normal mode | (off) |
imrestorebehavior | — | IM restore behavior (restore/default) | restore |
imdefaultinsert | — | Default IM for insert mode | (off) |
Mode prompt customization
let g:mode_prompt_normal = "N"
let g:mode_prompt_insert = "I"
let g:mode_prompt_visual = "V"
let g:mode_prompt_replace = "R"Which-key labels
" Group labels — collapse bindings under a named prefix
whichkeygroup <leader>t Table
whichkeygroup <leader>g Git
" Command labels — describe individual bindings
whichkeylabel <leader>w Save file
whichkeylabel gd Go to definitionGroup and command labels from vimrc are merged with labels configured in Settings. If the same key appears in both, the vimrc value takes precedence.
Global key mappings
gmap and gnoremap define key bindings for non-editor contexts — graph view, canvas, PDF viewer, reading mode, file explorer, and any other view where no editor is focused. These bindings use the same <leader> key as editor mappings.
" Map <leader>f to open the quick switcher in non-editor views
gmap <leader>f :obcommand switcher:open
" Map <leader>e to reveal the active file in the explorer
gmap <leader>e :obcommand file-explorer:reveal-active-file
" Map a key to an ex command
gnoremap <leader>s :sidebar left
" Remove a default global binding
gunmap HThe right-hand side must be either :obcommand <command-id> (to execute an Obsidian command) or :<ex-command> [args] (to execute a global ex command like :sidebar, :split, :grep, etc.). Key-to-key remapping is not supported in global context.
gnoremap is functionally identical to gmap — both are accepted for familiarity with Vim syntax.
Use gunmap to remove any global binding, including built-in defaults like H (previous tab) or L (next tab). After gunmap, the key is no longer intercepted and propagates to Obsidian’s native handlers.
:gmap and :gunmap also work from the editor’s : command line:
:gmap H :files
:gunmap L
:gmaps " list all active global bindingsGlobal which-key labels
Label your global bindings for the non-editor which-key overlay:
gwhichkeygroup <leader> +leader bindings
gwhichkeylabel <leader>f Open file
gwhichkeylabel <leader>e Reveal in explorerThese labels appear in the which-key overlay when a partial global key sequence is pending (e.g., pressing <leader> in a non-editor view shows all <leader>* global bindings).
Override behavior
When configuration mode includes vimrc (Lua + Vimrc or Vimrc only), vimrc values override the corresponding Settings UI values for the current session. Overrides are persisted in a configOverrides block in data.json so they survive Obsidian restarts. The base settings always reflect UI-set values — configOverrides captures the last-known vimrc/Lua values and merges them on top at startup.
Settings overridden by vimrc appear as disabled controls in the settings tab with a note showing the vimrc directive (e.g., “Set by vimrc: set scrolloff=10”). Changing a setting via the Settings UI clears the override for that key.
Gutter settings require one restart
Settings that control CM6 gutter extensions (
number,relativenumber,signcolumn,foldcolumn,cursorline,statuscolumn) take effect on the next Obsidian restart after the first config file change. This matches the Settings UI behavior — these extensions are created once at startup.
Settings not available via vimrc
| Setting | Reason |
|---|---|
configMode | Circular dependency — cannot control config file loading from vimrc |
leaderBindings | Already achievable via nmap <leader>x :command in vimrc |
pickerKeymap | Complex array-valued keys — not suited for :set syntax |
Unknown set options produce a console.warn on first encounter per vimrc load, helping you identify typos or Neovim-only options. Options recognized by the plugin or CM Vim built-in options (number, relativenumber, wrap, etc.) are not warned about.
Soft-reload
The vimrc file is watched for changes. When you save the file, nmap, set, exmap, and other commands are re-applied without reloading the plugin. Adding, modifying, or removing exmap definitions all take effect on save — the fork’s undefineEx() API cleans up stale handlers automatically.
Known issues
nmap L $and similar mappings may not apply if the vimrc file encounters I/O timing issues — reload the plugin as a workaround
See known-limitations > Vimrc for detailed technical limitations.