Markdown text objects

Operate on Markdown structures with standard Vim operators (d, c, y, v).

The Neovim RPC backend supports the tree-backed objects below in operator-pending and visual modes. i= / a= remains fork-only because Neovim’s bundled Markdown grammar has no highlight node.

KeybindingDescription
i* / a*Inside/around bold (**...**) or italic (*...*)
i_ / a_Inside/around italic (_..._)
i` / a`Inside/around inline code
i$ / a$Inside/around math ($...$ or $$...$$), with smart disambiguation
i~ / a~Inside/around strikethrough (~~...~~)
i= / a=Inside/around highlight (==...==)
il / alInside/around links ([[wikilink]] or [text](url))
iC / aCInside/around fenced code blocks
iB / aBInside/around blockquotes (>)
io / aoInside/around callouts (> [!type])
it / atInside/around HTML/XML tags
ir / arInside/around table row (raw markdown only)
i| / a|Inside/around table cell (between | pipes)
iS / aSSubword
in / anNumber
iq / aqAny quote
iD / aDDouble brackets
gLURL
i, / a,Argument
ii / aiIndentation

Structural navigation

Jump between document structures. Works with counts (e.g., 3]h jumps 3 headings) and operators (e.g., d]h deletes to the next heading).

KeybindingDescription
]h / [hNext/previous heading (any level)
]1–]6 / [1–[6Next/previous heading of specific level
]l / [lNext/previous list item (same indent level)
]n / [nNext/previous link
]b / [bNext/previous open buffer (tab)

Subword motions

KeyActionNotes
wNext subword startRequires enableSubwordMotions setting. Stops at camelCase/snake_case/kebab-case boundaries. Unicode-aware (Arabic, CJK, accented Latin)
bPrevious subword startSame
eEnd of current/next subwordSame
geEnd of previous subwordSame

Table navigation

Navigate Markdown table cells without leaving Vim mode.

KeybindingDescription
]| or ]cMove to the next table cell
[| or [cMove to the previous table cell
]rMove to same column in next row
[rMove to same column in previous row

Table text objects

Operate on table cells with standard Vim operators.

KeybindingDescription
i|Inside table cell (content between pipes)
a|Around table cell (content plus trailing pipe)

Table manipulation

Manage table structure using the <leader>t prefix.

KeybindingDescription
<leader>tmInsert table
<leader>toAdd row below
<leader>tOAdd row above
<leader>tJMove row down
<leader>tKMove row up
<leader>tddDelete row
<leader>tiLAdd column to the right
<leader>tiHAdd column to the left
<leader>tLMove column right
<leader>tHMove column left
<leader>tdcDelete column
<leader>trRealign table columns

Embedded table navigation

Available when the table widget is set to “Embedded” and the cursor enters a table. These keybindings are active in the table navigation layer (before entering a cell).

KeybindingDescription
h / lMove cell highlight left / right
j / kMove cell highlight down / up
i / a / c / s / EnterEnter cell editing
EscapeExit table
o / OAdd row below / above
ddDelete row
dcDelete column
J / KMove row down / up
H / LMove column left / right
I / AAdd column left / right
=Realign table
Tab / Shift-TabNext / previous cell (wraps across rows)

Owned table surface

Available when set tablewidget=owned and the cursor is inside a table in Live Preview. The plugin renders the table itself and a nested editor hosts the caret, while the parent editor’s vim owns every command — one vim state, one undo history, one document.

KeybindingDescription
Any normal-mode commandRouted to the parent’s vim (dd, D, u, ., zz, counts)
h / lMove by one character within the table
j / kMove one table row; at the first or last row, leaves the table
v / VCharwise / linewise visual mode, rendered inside the table
i / a / o and friendsEnter insert mode; typed text goes into the document
EscapeLeave insert or visual mode

Desktop, Live Preview and the bundled engine only. See tables > Owned table surface for what is not supported yet.

Picker shortcuts

Open picker sources with the <leader>f prefix.

KeybindingDescription
<leader>ffFind files
<leader>fgLive grep (vault search)
<leader>fbSwitch buffers
<leader>fhSearch headings
<leader>foDocument outline
<leader>fkBacklinks
<leader>ftSearch tags
<leader>frRecent files
<leader>fmJump to mark
<leader>fRRegisters
<leader>fpResume last picker

Harpoon

Pin files to numbered slots for instant switching. See harpoon for details.

KeybindingDescription
<leader>haPin current file
<leader>hrRemove current file
<leader>htToggle pin
<leader>hpOpen harpoon picker
<leader>1–<leader>9Jump to slot 1–9
<leader>hnNext pin
<leader>hNPrevious pin

Keyboard shortcuts inside picker

KeyAction
<C-n> / <C-p>Navigate down/up
<C-j> / <C-k>Navigate down/up
<Up> / <Down>Navigate down/up
<Enter>Select item
<Escape> / <C-c>Close picker
<C-x>Open in horizontal split
<C-v>Open in vertical split
<C-t>Open in new tab
<C-d> / <C-u>Scroll preview down/up

Hard-wrap operators

Reformat paragraphs with Markdown-aware line wrapping.

KeybindingDescription
gqq / gwqReformat current line at textwidth (default 80)
gqj / gwjReformat current and next line
gqip / gwipReformat paragraph
Visual gq / gwReformat selected lines

Undo tree navigation

KeyAction
g-Navigate to chronologically older undo state
g+Navigate to chronologically newer undo state
:earlier NGo back N changes
:later NGo forward N changes
:earlier Ns/Nm/Nh/NdGo back by time
:earlier NfGo to Nth previous save point
:undolistShow undo tree modal
:UndoTreeToggleToggle undo tree sidebar
:UndoTreeShowOpen undo tree sidebar
:UndoTreeHideClose undo tree sidebar

Custom operators

KeybindingDescription
g@{motion}Call the function stored in operatorfunc over the range of {motion}.

Replace-with-register operator

Replace text covered by a motion with the contents of a register, discarding
the replaced text (not written back to any register). The register supplying the
replacement is preserved, so you can paste the same text repeatedly without
re-yanking.

Blockwise visual selections (<C-V>) are supported.

KeybindingDescription
gr{motion}Replace {motion} text with unnamed register (")
grrReplace current line with unnamed register (linewise)
"a gr{motion}Replace {motion} text with register a
Visual grReplace selection with unnamed register

Example usage:

yiw        " yank inner word
griw       " replace next inner word (register preserved — repeat!)
grr        " replace current line
grap       " replace a paragraph
"agr$      " replace to end of line using register a

Info

gr{motion} is not a Neovim built-in — it originates from the
vim-ReplaceWithRegister plugin. In Neovim 0.10+, the gr prefix is used
for LSP actions (grn rename, grr references, gra code action). Since
Obsidian has no LSP, this plugin repurposes gr for replace-with-register
and exposes the former grn/grr/gra workspace actions as leader
bindings (<leader>rn, <leader>rb, <leader>ra) and ex commands
(:renamenote, :showbacklinks, :contextactions).

Flash motions

Enhanced character search — when multiple matches are visible, labels appear for direct jumping.

KeybindingDescription
f{char}Find {char} forward — autojump on single match, labels on 2+
F{char}Find {char} backward
t{char}Till before {char} forward
T{char}Till after {char} backward

Flash works with operators (df, cf, yf) and visual mode (vf). Repeat with ; and ,.

Flash jump mode

Bidirectional character search (disabled by default, enable with set flashjump).

KeybindingDescription
s{char}Search {char} bidirectionally — labels on all matches

The trigger key is configurable via set flashjumpkey=<key>.

Flash search labels

After committing a / or ? search, labels appear on all visible matches for direct jumping.

EasyMotion find motions

Jump to specific characters forward, backward, or in both directions.

KeybindingDescription
<leader><leader>f{char}Find {char} forward
<leader><leader>F{char}Find {char} backward
<leader><leader>s{char}Find {char} in both directions
<leader><leader>t{char}Till before {char} forward
<leader><leader>T{char}Till after {char} backward

EasyMotion word motions

Jump to word starts or ends across the visible editor.

KeybindingDescription
<leader><leader>wWord start forward
<leader><leader>bWord start backward
<leader><leader>eEnd of word forward
<leader><leader>geEnd of word backward
<leader><leader>WWORD start forward
<leader><leader>BWORD start backward
<leader><leader>EEnd of WORD forward
<leader><leader>gEEnd of WORD backward

EasyMotion line motions

Jump directly to lines above or below the cursor.

KeybindingDescription
<leader><leader>jLine down
<leader><leader>kLine up

EasyMotion search motions

Jump to search matches forward or backward.

KeybindingDescription
<leader><leader>nNext search match forward
<leader><leader>NNext search match backward

EasyMotion repeat

KeybindingDescription
<leader><leader>.Repeat last EasyMotion motion

Repeats the most recent EasyMotion motion with a fresh label overlay. Works in operator-pending mode (d<leader><leader>. deletes to the repeated target) and inherits motionArgs from the original motion (linewise, inclusive, forward flags are preserved).

Surround

Add, change, or delete surrounding delimiters like brackets, quotes, and tags.

KeybindingDescription
ds{target}Delete surrounding (ds" on "hello" → hello)
dstDelete surrounding tag
cs{target}{replacement}Change surrounding (cs"' → 'hello')
cst{replacement}Change surrounding tag
ys{motion}{replacement}Add surround (ysiw) on hello → (hello))
ys{motion}<tag>Surround with HTML tag (ysiw<em> → <em>hello</em>)
ysiwf + name + EnterSurround with function call (print(hello))
ysiwF + name + EnterSurround with spaced function call (print( hello ))
dsfDelete surrounding function call (print(hello) → hello)
csf + name + EnterChange surrounding function name (foo(bar) → baz(bar))
yss{replacement}Surround entire line (yss" → "line content")
cS / yS / ySSNewline surround variants (delimiters on separate lines)
S{replacement}Surround visual selection (visual mode)
S<tag>Surround selection with tag (visual mode)
gSNewline surround selection (visual mode)
2ds), 2cs)Count: delete/change 2nd-level surrounding bracket
2ysiw*Count: repeat delimiter (**hello** for Markdown bold)
2ds*Count: delete repeated delimiter (unbold **hello**)
<C-G>s{char}Insert mode: inserts both delimiters, type inside them

Workspace navigation

Navigate Obsidian panes, tabs, and history following Neovim conventions.

KeybindingDescriptionGlobal
h / j / k / lNative File Explorer: parent/next/previous/child; counts workYes
<C-w>h/j/k/lFocus pane left/down/up/rightYes
<C-w>vSplit verticalYes
<C-w>sSplit horizontalYes
<C-w>nNew horizontal split (alias for <C-w>s)Yes
<C-w>c / <C-w>qClose current tabYes
<C-w>oClose all other tabsYes
gt / gTNext/previous tabYes
NgtGo to Nth tab (e.g., 3gt goes to tab 3)Yes
g<C-t>Go to tab by number (e.g., 3g<C-t> goes to tab 3)—
H / LPrevious/next tab (non-editor views only)Yes
<C-w>wCycle to next paneYes
<C-w>WCycle to previous paneYes
<C-w>pFocus previously accessed paneYes
<C-w>TMove current pane to a new tab—
<C-w>^Split + open alternate file—
g<Tab>Go to last accessed tab (alias for <C-w>p)—
Ctrl-o / Ctrl-iJump backward / forward through jump history (supports count)Yes
<C-^> / <C-6>Switch to alternate (previously edited) fileYes
<C-]>Follow link under cursor (alias for gd)—
<C-t>Pop from link follow (jump list backward)—
gdGo to definition — open the link under the cursor—
gDOpen link under cursor in a new tab—
<C-w>gdOpen link under cursor in a horizontal split—
<C-w>gDOpen link under cursor in a vertical split—
gxOpen URL under cursor in browser—
KKeyword lookup — hover preview on links, char info on text—
gfOpen file switcher (quick open)—
]f / [fAlias for gf (go to file)—
gOOpen document outline (searchable heading list)—
g<C-g>Show document statistics (words, lines, characters)—
gp / gPPaste and move cursor past pasted text—
gaShow character info under cursor (codepoint, hex)—
gmGo to middle of screen line—
goGo to character offset (byte N in buffer, with count)—
g8Show UTF-8 byte sequence for character under cursor—
gFGo to file with optional line number (file.md:42)—
<C-g>Show file info (name, lines, position, percentage)—
<leader>rnRename current note—
<leader>rbShow backlinks to current note—
<leader>raShow context actions for current note—

Fold commands

KeybindingDescription
zoOpen fold at cursor
zOOpen fold at cursor recursively
zcClose fold at cursor
zCClose fold at cursor recursively
zaToggle fold at cursor
zAToggle fold at cursor recursively
zdDelete fold at cursor
zDDelete fold at cursor recursively
zf{motion}Create fold for {motion} text
zFCreate fold for [count] lines
zEEliminate all folds
zmFold more (increment fold level)
zMClose all folds
zrFold less (decrement fold level)
zROpen all folds
znFold none — disable folding, open all folds
zNFold normal — re-enable folding
ziToggle fold enable
zvOpen enough folds to view cursor line
zxReapply fold level and reveal cursor
zXReapply fold level
zjMove to start of next fold
zkMove to end of previous fold
[zMove to start of current fold
]zMove to end of current fold

Vertical scroll

KeybindingDescription
zzCentre the cursor line in the viewport
z.Centre the cursor line, cursor to first non-blank
ztScroll the cursor line to the top of the viewport
z<CR>Cursor line to the top, cursor to first non-blank
zbScroll the cursor line to the bottom of the viewport
z-Cursor line to the bottom, cursor to first non-blank

Info

On a wrapped line these commands position the whole logical line, not
the cursor’s display row — Vim’s scroll_cursor_halfway works in whole-line
heights, so zz with the cursor at the start, middle, or end of one wrapped
line produces the same scroll position. When the line is taller than the
viewport, Vim scrolls inside the line (skipcol) by just enough to keep the
cursor visible, which puts a cursor at the end of the line on the last
visible row. Both behaviours match Neovim.

Tip

zt and zb leave scrolloff rows of margin above and below
the cursor line, and stop at the centred position once that margin no longer
fits — so with set scrolloff=999, zt, zb and zz all centre the line.
zz itself is unaffected by scrolloff on a line that fits the viewport.
Inside a line taller than the viewport the margin applies to the cursor’s own
display row instead, and is unreachable at the line’s first and last rows.

Horizontal scroll

KeybindingDescription
zsScroll text so cursor column is at the left edge
zeScroll text so cursor column is at the right edge
zHScroll half a screen width to the left
zLScroll half a screen width to the right

Select mode

KeybindingDescription
ghEnter select mode (charwise)
gHEnter select mode (linewise)
g<C-h>Enter select mode (blockwise)
<C-g>Toggle between visual and select mode (in visual/select)
gVPrevent select mode reselection after mapping

Virtual replace mode

KeybindingDescription
gREnter virtual replace mode (replace by screen column)

Non-editor view bindings

Navigate and interact with non-editor views like PDFs, graphs, and canvases.

KeybindingDescription
fShow hint labels, activate target (click/focus/navigate)
FShow hint labels, open target in new pane
yfShow hint labels, yank target URL or text to clipboard
dfShow hint labels, close target tab or pane
gfShow hint labels, open context menu on target
NfActivate N targets sequentially (e.g., 3f activates 3)
j / kScroll down/up one line
Nj / NkScroll N lines (e.g., 5j scrolls 5 lines down)
ggScroll to top
GScroll to bottom
Ctrl-d / Ctrl-uScroll half page down/up
Ctrl-f / Ctrl-bScroll full page down/up

All non-editor bindings can be customized via gmap, gnoremap, and gunmap in your .obsidian.vimrc. Use :gmap to list all active global bindings. See vimrc > Global key mappings for syntax.

Ex commands

Execute commands via the : command line, grouped by function.

File and buffer

CommandDescription
:w / :writeSave current file
:update / :upSave current file (alias for :w)
:q / :quitClose current tab
:wqSave and close
:x / :xitWrite if modified and close
:xa / :xallWrite if modified all and close all
:e {file} / :edit {file}Open file by name in vault
:e! / :edit!Revert current file to saved version
:enewCreate new untitled note
:saveas {file}Save current buffer as new file
:find {file} / :finFind and open file by partial name match
:read {file} / :rInsert file contents at cursor position
:bn / :bpNext / previous tab
:b {name} / :buffer {name}Switch to tab matching name
:bf / :bfirstGo to first tab
:bl / :blastGo to last tab
:bd / :bcClose current tab
:bw / :bwipeoutClose current tab
:onlyClose all other tabs
:qaClose all tabs
:wa / :wallSave all open files

Editing

CommandDescription
:[range]m {addr} / :moveMove lines in range to target address
:[range]t {addr} / :copy / :coCopy lines in range to target address
:[range]norm {keys} / :normalExecute normal-mode keys from ex line
:[range]normal! {keys}Execute normal-mode keys without remaps
:[range]ce [width] / :centerCenter-align lines (default width: 80)
:[range]le / :leftLeft-align lines (trim leading spaces)
:[range]ri [width] / :rightRight-align lines (default width: 80)
:retab [tabstop] / :retReplace tabs with spaces
:startinsert[!] / :startEnter insert mode (! appends)
:stopinsert / :stopiLeave insert mode (no-op outside it)

Window and tab

CommandDescription
:sp / :splitHorizontal split
:vs / :vsplitVertical split
:newHorizontal split with new note
:vnewVertical split with new note
:tabnew / :tabeditOpen new tab (optionally with file)
:tabclose / :tabcClose current tab
:tabonly / :taboClose all other tabs
:tabfirst / :tabrewindGo to first tab
:tablast / :tablGo to last tab
:tabmoveNo-op (Obsidian has no tab reorder)

Table

CommandDescription
:tableinsertInsert table
:tablerowafter / :tablerowbeforeAdd row below / above
:tablerowup / :tablerowdownMove row up / down
:tablerowdeleteDelete row
:tablecolafter / :tablecolbeforeAdd column right / left
:tablecolleft / :tablecolrightMove column left / right
:tablecoldeleteDelete column
:tablealignleft / :tablealigncenter / :tablealignrightSet column alignment
:tablerealignRealign table columns to uniform widths
CommandShortDescription
:explorerReveal active file in file explorer
:filesFind files by name
:buffers:bufSwitch between open buffers
:lsAlias for :buffers
:headingsSearch all headings across vault
:outlineJump to heading in current file
:backlinks:backlShow files linking to current file
:tagsBrowse vault tags (opens sub-picker)
:quickfixNeovim quickfix list (RPC backend)
:recentRecently opened files
:marksJump to vim marks (grouped by buffer/global)
:grep {query}:greSearch vault content (pre-computed results)
:livegrep:livegReal-time vault content search
:resume:resReopen last picker with same query
:jumpsDisplay the jump list
:Picker:PickOpen meta-picker listing all sources
:snippetsSearch and insert snippets
:snippet name:snipInsert a snippet by name
:Picker {src}Open a named picker source directly
:backNavigate back in history
:forwardNavigate forward in history
:changesShow change list in modal

Harpoon

CommandShortDescription
:HarpoonAdd:HarpoonAPin current file to next slot
:HarpoonRemove:HarpoonRRemove current file (or :HarpoonRemove N for slot N)
:HarpoonOpen harpoon picker
:HarpoonSelect N:HarpoonSJump to pin slot N
:HarpoonNext:HarpoonNNext pin
:HarpoonPrev:HarpoonPPrevious pin

Input method

CommandShortDescription
:IMToggle:IMTToggle input method switching on/off
:IMStatus:IMSShow current input method identifier

Utility

CommandDescription
:ob {command-id}Execute any Obsidian command by ID
:obList all available command IDs
:commandsSearch and execute Obsidian commands
:sidebar left / :sidebar rightToggle left/right sidebar
:reg / :registersBrowse vim registers (paste on select)
:delmarks {marks}Delete specified marks
:version / :veShow plugin version
:violations / :violShow runtime invariant violations
:violations! / :viol!Clear invariant violation log
:gmapList all active global bindings

Obsidian commands

The following commands are available in the Obsidian command palette (Ctrl+P or Cmd+P).

CommandDescription
Vim Motions: Toggle Vim modeToggle the plugin’s vim mode on/off
Vim Motions: Enable Vim modeEnable the plugin’s vim mode
Vim Motions: Disable Vim modeDisable the plugin’s vim mode
Vim Motions: Toggle mobileToggle plugin activation on mobile
Vim Motions: Check conflictsOpen the hotkey conflict resolution modal
Vim Motions: Reload configurationReload both vimrc and Lua config files
Vim Motions: Open configuration in default editorOpen config files in external editor (desktop only)
Vim Motions: Open configuration directory in system explorerReveal the folder holding your config files (desktop only)

Snippets

Snippet keybindings are active during snippet expansion (after a snippet has been triggered).

KeybindingDescription
TabMove to next tabstop / expand snippet at prefix
Shift+TabMove to previous tabstop
EscapeExit snippet mode
Ctrl+NCycle to next choice (on choice fields)
Ctrl+PCycle to previous choice (on choice fields)

Oil explorer

Oil keybindings are only active when an oil buffer is focused. All keybindings are user-remappable via Lua or vimrc — see oil-explorer > Remapping keybindings for details. Oil ex commands (:oilopen, :oilparent, etc.) are always registered — invoking them outside an Oil buffer shows a notice instead of an error.

KeybindingEx commandDescription
<CR>:oilopenOpen file under cursor / navigate into directory
<C-t>:oilopentabOpen file under cursor in new tab
<C-s>:oilopensvOpen file under cursor in vertical split
<C-h>:oilopenshOpen file under cursor in horizontal split
-:oilparentNavigate to parent directory
~:oilrootNavigate to vault root
q:oilcloseClose oil buffer
<C-c>:oilcloseClose oil buffer
<C-l>:oilrefreshRefresh directory listing
g.:oiltogglehiddenToggle hidden files (dotfiles)
gs:oilcyclesortCycle sort order (name → modified time → size)
y.:oilyankpathYank vault-relative file path to clipboard
gf:oilrevealReveal file under cursor in Obsidian file explorer
gx:oilopenexternalOpen file under cursor in default system app
g?:oilhelpShow keybinding help modal
<C-p>:oilpreviewToggle preview split (shows file under cursor, auto-updates on cursor move)
ddStage file deletion (commit with :w)
oStage file creation — type filename, commit with :w
cwStage file rename — edit filename, commit with :w
:wCommit all staged changes (create/rename/delete)
:OilOpen oil explorer (no arg: current dir, .//: vault root, path: specific dir)

Quality of life

Enhanced Vim behavior and Obsidian-specific improvements.

KeybindingDescription
o / OSmart list continuation (bullets, numbers, checkboxes, blockquotes)
YYank to end of line (y$)
QReplay last recorded macro (@@)
@:Repeat last ex command
&Repeat last :s substitution on current line
g&Repeat last :s substitution on all lines
gMGo to middle character of text line
KKeyword lookup (hover preview on links, char info)
]<Space>Add N blank lines below cursor
[<Space>Add N blank lines above cursor
ZZWrite current file and close tab (:wq)
ZQClose tab without saving (:q)
g;Older change
g,Newer change
g-Older undo state
g+Newer undo state
<C-p>Cycle paste previous register (or k if not cycling)
<C-n>Cycle paste next register (or j if not cycling)

Insert mode

KeybindingDescription
<C-u>Delete back to insert-start position (or line start)
<C-a>Re-insert previously inserted text
<C-e>Copy character from line below (same column)
<C-y>Copy character from line above (same column)
<C-G>sInsert-mode surround (inserts both delimiters, type inside)
<C-G>uInsert undo break
<C-G>USuppress undo break on next cursor movement
<C-G>j / kNavigate lines while preserving insert-start column
0<C-D>Delete all indentation on current line
^<C-D>Delete all indentation on current line

Increment/Decrement

KeyActionNotes
<C-a>IncrementEnhanced: cycles hex colors, booleans, dates, CSS values, checkboxes. Requires enableDial setting
<C-x>DecrementSame
g<C-a>Sequential incrementVisual mode: increments numbers across selection (+1, +2, +3…). E.g., 0\n0\n0 → 1\n2\n3
g<C-x>Sequential decrementVisual mode: decrements numbers across selection (-1, -2, -3…)

Remapping

All keybindings above are user-remappable. See remapping for instructions and examples covering editor, oil explorer, picker, and global workspace navigation contexts.