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:

  1. vimrc
  2. .vimrc
  3. init.vim
  4. .init.vim
  5. obsidian.vimrc
  6. obsidian.vim
  7. .obsidian.vimrc
  8. .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

CommandDescription
map / nmap / imap / vmapMode-specific key mappings
noremap / nnoremap / inoremap / vnoremapNon-recursive mappings
unmap / nunmap / iunmap / vunmapRemove mappings
setSet plugin options (see tables below)
let mapleaderSet the leader key
exmapDefine a named command from an Obsidian command
obcommandExecute an Obsidian command by ID (alias of :ob)
sourceSource another vimrc file
gmap / gnoremapGlobal key mapping for non-editor contexts
gunmapRemove a global mapping
whichkeygroupName a which-key group by prefix
whichkeylabelLabel an individual binding in which-key
gwhichkeygroupName a global which-key group by prefix
gwhichkeylabelLabel a global binding in which-key
surroundmapRegister a custom surround pair
surroundunmapRemove 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.

OptionAliasDescriptionDefault
textobjectstoMarkdown-aware text objectson
replacewithregisterrwrReplace-with-register operatoron
navigationnavHeading, list, and link navigationon
hardwraphwgq/gw hard-wrap operatorson
listcontinuationlcSmart list continuation on o/Oon
tablenavtnTable cell navigationon
workspacenavwnPane/tab/sidebar controlon
numbernuShow absolute line numbersoff
relativenumberrnuShow relative line numbersoff
flashFlash-style f/F/t/T labelson
flashmultilinefmlFlash searches beyond current lineon
flashjumpFlash bidirectional jump mode (s)off
flashcleverfClever-f repetitionoff
flashsearchLabels on /? search matcheson
labelmatchfontsizelmfsScale labels to match line font sizeoff
easymotionemEasyMotion/Hop navigationon
easymotiondimmingemdDim non-target text during EasyMotionon
hintmodehmVimium-style hint labelson
statusbarsbVim mode in status baron
chorddisplaycdPending keystrokes in status baron
powerlineplColored powerline status baroff
expandtabetUse spaces instead of tabson
pcreUse JavaScript regexps in search/subston
cursorlineculCursor line highlighton
foldcolumnfdcFold column indicatorsoff
markgutterAlias for signcolumn (compat)on
snippetsEnable snippet expansionon
snippetbundledInclude bundled Obsidian snippetson
vimtextareasvtaVim keybindings in text areasoff
yankringYank-ring paste cyclingon
harpoonHarpoon file pinningon
dialEnhanced increment/decrementoff
jumplistVim-style jump list for <C-o>/<C-i>on
foldawarenavigationAuto-unfold on navigationon
foldpersistencePersist fold state across sessionsoff
undotreeutEnable undo tree trackingon
undofileudfPersist undo tree across sessionsoff
smoothcursorscEnable animated cursoroff
smoothcursorglidescgSmooth cursor movement (glide)on
smoothcursorsmearscmEnable smear trailon
subwordSpider.nvim-style subword motionsoff
pickerTelescope-style pickeron
pickerleadermappingsLeader key picker shortcutson
pickeromnisearchOmnisearch picker integrationoff
pickertasksObsidian Tasks picker integrationoff
pickerdataviewDataview picker integrationoff
ripgrepUse ripgrep binary for grepoff
oilOil file exploreroff
oilhiddenfilesShow hidden files in Oiloff
undotreeautoopenAuto-open undo tree on branchoff
imswitchingInput method auto-switchingoff

Number options

Use set <option>=<value>.

OptionAliasDescriptionDefaultRange
scrolloffsoLines to keep visible above/below cursor50-9999
scanlimitslMax lines to scan for text objects205-200
labelfontsizelfsFont size for EasyMotion/hint labels1410-20
tabstoptsTab display width41-8
shiftwidthswIndent width41-8
textwidthtwLine wrap width for gq/gw800-200
insertmodeescapetimeoutimetTimeout (ms) for insert escape sequence1000100-5000
operatorshadowtimeoutostTimeout (ms) for operator-prefix disambiguation10000-5000
numberwidthnuwMinimum line number column width21-20
jumplistsizeMaximum jump list entries2001-1000
undotreemaxnodesutmnMaximum undo tree nodes per file1000100-5000
yankhighlightdurationYank highlight duration (ms)2000-5000
smoothcursorsmoothnessscsCursor movement smoothness0.50-1
smoothcursorstiffnessscstSmear trail head stiffness0.60.1-1
smoothcursortrailstiffnesssctsSmear trail tail stiffness0.30.1-1
smoothcursordampingscdSmear trail velocity decay0.850.1-0.99
smoothcursormaxlengthscmlMaximum smear trail length (px)40050-800
oilconfirmdeletethresholdOil delete confirmation threshold50-100

String options

Use set <option>=<value>.

OptionAliasDescriptionDefault
clipboardclipSystem clipboard sync (unnamed/unnamedplus)(off)
insertmodeescapeimeTwo-key sequence to exit insert mode(off)
flashjumpkeyKey to trigger flash jump modes
flashminpatternlengthfmplMinimum chars before labels in jump mode1
yankhighlightmodeYank highlight style (off/solid/fade)solid
easymotionlabelsemlCharacters for EasyMotion and flash labelsasdghklqwertyuiopzxcvbnmfj
hintlabelshlCharacters for hint mode labelsasdfghjkl
guicursorPer-mode cursor shapes(block/bar/block/underline/underline)
tablewidgetTable widget mode (native/raw)native
whichkeywkWhich-key hints (off/leader/all)off
whichkeygroupingwkgWhich-key grouping (flat/grouped)grouped
whichkeysortwksWhich-key sort order (which-key/groups-first)which-key
whichkeyiconswkiWhich-key icons (on/off)on
workspacenavviewtypeswnvtView types for workspace nav interception(empty — uses defaults: markdown, graph, pdf, canvas, empty, image, bases)
cursorlineoptculoptCursor line highlight mode (number/line/both)number
signcolumnsclSign column visibility (auto[:N]/yes[:N]/no)auto
linenumbermodelnmLine number display (deprecated — use statuscolumn)hybrid
statuscolumnstcCustom gutter layout format string(empty — plugin-managed)
snippetdirPath to user snippet JSON directory(off)
snippettriggerSnippet trigger mode (completion/tab/both)both
pickermatcherPicker match engine (ufuzzy/obsidian)ufuzzy
ripgreppathPath to ripgrep binary(off)
ripgrepargsAdditional ripgrep arguments(off)
grepmodeGrep backend (ripgrep/grep)ripgrep
oilsortOil default sort (name/mtime/size)name
hinthotkeyKey to trigger hint mode(off)
undotreepositionUndo tree sidebar position (left/right)right
impresetIM preset (custom/macism/im-select/fcitx5-remote/ibus)custom
imbinarypathPath to IM binary(off)
imobtainargsArgs for obtaining current IM(off)
imswitchargsArgs for switching IM{im}
imdefaultnormalDefault IM for normal mode(off)
imrestorebehaviorIM restore behavior (restore/default)restore
imdefaultinsertDefault 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 definition

Group 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 H

The 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 bindings

Global 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 explorer

These 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

SettingReason
configModeCircular dependency — cannot control config file loading from vimrc
leaderBindingsAlready achievable via nmap <leader>x :command in vimrc
pickerKeymapComplex 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.