Skip to content

Coming from NvChad

mnml was built by an NvChad refugee, for NvChad refugees. The vim input handler is first-class — not a “vim emulation layer” bolted onto a modeless editor — and the leader system is a built-in which-key trie under <space> with the chord vocabulary you already have in your fingers. If you came in from nvim --clean plus NvChad, almost everything you reach for already works.

This page is the migration map. It assumes you know vim. The job here is to point at the handful of places where mnml’s chord differs from NvChad’s, surface the new chords mnml added (Harpoon, integrations, AI panes), and tell you which Neovim feature isn’t here so you can stop reaching for it.

standard is the default input style — flip it once and forget:

~/.config/mnml/config.toml
[editor]
input_style = "vim"

Or per-workspace at <workspace>/.mnml/config.toml if you want vim everywhere except one team’s onboarding repo. Switch at runtime any time:

:set input=vim
:set input=standard

The runtime swap is non-destructive — your buffers, cursor, undo history, and macros survive the handler change. Toggle from the palette as editor: toggle keymap, the chord <leader>tk, or the bufferline mode chip. The architecture is documented in Editing — the short version is that both handlers translate keys into the same closed EditOp set, so the editor and every pane around it never branch on which mode is active.

If you launched mnml without setting the config, force it for one run:

Terminal window
mnml --input vim ~/some/project

These are the chords NvChad ships with mnml’s equivalents alongside. Categories follow how you’d actually learn them.

These are pure-vim behavior, nothing to translate. mnml’s vim handler covers them as you’d expect:

  • Modes: Esc / i / a / o / O / s / c… / v / V / Ctrl-V / R
  • Motions: hjkl, wbge, 0$^, f/t/F/T plus ; , repeat, %, gg/G, H/M/L, Ctrl-D/Ctrl-U/Ctrl-F/Ctrl-B, { / } for paragraph nav, ( ) for sentence nav
  • Operators: d / c / y / > / < / = / gU / gu / gq / gJ (no-space join) / ~ (toggle case)
  • Text objects: iw/aw, i(/a(, i"/a", ip/ap, is/as, plus tree-sitter if/af (function), ic/ac (class), ia/aa (argument), ii/ai (indent)
  • Visual-block (Ctrl-V) + I / A to insert/append on every line — the real multi-cursor for the column case

The statusline mode chip differentiates VISUAL (char), V-LINE (V), and V-BLOCK (Ctrl-V) — same purple background, different label and tooltip — so NvChad’s “which kind of visual am I in?” muscle memory transfers without squinting.

The . dot-repeat, jumplist (Ctrl-O / Ctrl-I), and changelist (g; / g,) all work. Macros (qa…q@a) and named/numbered registers ("ay, "+y, "0p) are persisted across restarts. Counts thread through macros — 5@a replays macro a five times, like vim.

A couple of edge-case motions that match vim exactly (and didn’t always):

  • $ lands on the line’s last printable char, not one cell past it. Paste after $ lands immediately after the last visible character.
  • G (bare) lands on the start of the last line, not the phantom row past a trailing newline.
  • * and # advance past the current match — the star jumps to the next occurrence of the word under the cursor (instead of finding the cursor’s current word).
  • V doesn’t snap the cursor down a row — the anchor moves to line_start, the cursor stays put, and '< / '> after a yank reflect the correct row range.
  • :%s/.../.../g is one undo step — a 12-match substitute reverts on one u, not twelve.

cc, guu, gUU, g~~ all operate on the full line and leave the cursor at the start of the next line, so g~~g~~g~~ walks down toggling case line by line.

See Editing for the full operator + text-object inventory; this page won’t repeat it.

What you do in NvChadWhat it is in mnml
:e <file>:e <file> — opens new buffer (creates if missing)
:bn / :bp / :bd:bn / :bp / :bd (also :b <name> fuzzy match)
<leader>fb (buffer picker)<leader>fb
:tabnew / gt / gT / :tabcloseAll present
:vsp / :sp:vsplit / :split, plus the <leader>sv / <leader>ss chords
Ctrl-w h/j/k/lCtrl-w h/j/k/l (also <leader>sh/sj/sk/sl)
Ctrl-w w cycleCtrl-w w (also <leader>sw)
Ctrl-w c closeCtrl-w c or Ctrl-w q (also <leader>sc)
Ctrl-w = equalizeCtrl-w =
Ctrl-w o close-othersCtrl-w o (also <leader>so)
Ctrl-w > < + - resizeCtrl-w > < + -
Ctrl-w T move to new tabCtrl-w T
Ctrl-w f split-open file under cursorCtrl-w f
Ctrl-w d split + goto definitionCtrl-w d
Ctrl-w n new scratch splitCtrl-w n

Ctrl-w H/J/K/L (move split to the far edge of the parent) and Ctrl-w x / Ctrl-w r (swap / rotate) work too. Maximize the active split with Ctrl-w _ (height) or Ctrl-w | (width).

NvChadmnml
/pattern ?pattern n N * #All present
:noh / :nohlsearch:noh / :nohlsearch
:%s/old/new/g (and /gc confirm)Yes — including ranges, :'<,'>s/…, :s//repl/g repeat-search
:g/pattern/d / :v/pattern/dPresent
gf open file under cursorgf (mnml maps to editor.open_at_cursor)
gx open URL under cursorgx (opens in OS browser)
gd / gD LSP goto def / declarationgd / gD
Ctrl-] jump to tag (= goto def)Ctrl-] (mapped to lsp.goto_definition)
Ctrl-T jump backCtrl-T (mapped to nav.back)
K hover docsK (LSP hover popup)

gi (jump to last-insert + insert), gI (insert at column 0), gv (restore last visual), g; / g, (changelist) are present.

All present with vim’s exact semantics:

  • ma set local mark, mA global mark
  • 'a jump to line, `a jump to exact column
  • "ay / "ap, "+y / "+p (system clipboard), "*y / "*p (X11/Wayland primary)
  • "0p last yank, "1p"9p delete ring
  • qaq record, @a replay, 5@a replay 5×, @@ repeat last

Marks + macros persist across mnml restarts via per-workspace <workspace>/.mnml/ storage. The delete ring resets at startup (vim parity).

  • Ctrl-R <reg> paste register inline (vim canonical)
  • Ctrl-V <key> insert next keystroke verbatim (use for literal Tab, etc.)
  • Ctrl-O <cmd> one-shot Normal — fire one normal command then back to Insert
  • Ctrl-N / Ctrl-P walk the completion popup
  • Ctrl-Space request LSP completion explicitly

za toggle, zc close, zo open, zR open-all, zM close-all, zf create fold (visual or with motion). LSP-supplied fold ranges + indent-fallback folds both work; za toggles whichever applies at the cursor.

<space> is the leader in vim mode (it’s Ctrl-K in standard mode — same trie, different entry chord). After <space> a which-key popup paints the available continuations. Press the next char to descend; press Esc to back out. Press ? at the root for a full cheatsheet pane.

What follows is every chord the built-in trie ships with. Source of truth: src/whichkey.rs. Categories match the trie groups.

ChordCommandNotes
<leader>ffpicker.filesFuzzy file picker (NvChad parity)
<leader>fbpicker.buffersOpen-buffer picker
<leader>fgfind.grepWorkspace live-grep (NvChad parity — added 2026-06-08)

:Rg <pattern> / :vimgrep and Ctrl-Shift-F also work for the workspace-grep pane.

ChordCommand
<leader>bnbuffer.next
<leader>bpbuffer.prev
<leader>bdbuffer.close
<leader>brbuffer.reopen (reopen the last-closed)

NvChad’s “close all but this” doesn’t have a chord today — palette: buffer: close others.

ChordCommand
<leader>teview.toggle_tree (file explorer)
<leader>tkeditor.toggle_keymap (vim ⇄ standard)
<leader>tttheme.pick (theme picker)
<leader>thview.toggle_hidden (hidden files in focused tree node)
<leader>tHview.toggle_hidden_all (hidden files everywhere)

A deeper surface than NvChad ships. The full git story is on Git.

ChordCommand
<leader>gddiff file
<leader>gDdiff worktree
<leader>gAdiff all vs HEAD (multi-file)
<leader>gppeek change at cursor
<leader>gbblame toggle
<leader>gccommit
<leader>glcommit graph
<leader>gsstatus / staging pane
<leader>gmAI (Claude) commit message
<leader>gMAI rewrite of HEAD’s message
<leader>gxCodex commit message
<leader>gocheckout branch
<leader>gnnew branch
<leader>gwworktrees → shell
<leader>gSstash (prompts for message)
<leader>gPstash pop
ChordCommand
<leader>lacode actions
<leader>lccomplete at cursor
<leader>lssymbols in this file
<leader>lSworkspace symbols
<leader>looutline pane
<leader>ldgoto definition
<leader>lhhover docs
<leader>lrfind references
<leader>lRrename symbol
<leader>lediagnostics list
<leader>lnnext diagnostic
<leader>lpprev diagnostic

Mirror of Ctrl-w but via leader — handy when you set up a layout from scratch.

ChordCommand
<leader>svsplit right
<leader>sssplit down
<leader>sh/j/k/lfocus left/down/up/right
<leader>swfocus next split
<leader>scclose split
<leader>soclose others

mnml ships an in-editor HTTP client (.http / .curl / .rest files). See HTTP client.

ChordCommand
<leader>hssend request
<leader>hycopy as curl
<leader>hdask Claude (debug)
ChordCommand
<leader>Tarun all
<leader>Tfrun this file
<leader>Ttrun test at cursor
<leader>Tlre-run last-failed
<leader>Thheal failing test (Claude)
<leader>Twflaky/wobbly dashboard
ChordCommand
<leader>Ppcross-host PR picker
<leader>Prrefresh cross-host cache (background)

See Cross-host PR workflow.

The integration siblings (forge / cloud / observability viewers) launch from here. Each chord opens a separate sibling binary as a pane — the sibling has to be installed for the chord to do anything visible.

ChordCommandSibling
<leader>ibBitbucket viewermnml-forge-bitbucket
<leader>igGitHub viewermnml-forge-github
<leader>ilGitLab viewermnml-forge-gitlab
<leader>izAzure DevOps viewermnml-forge-azdevops
<leader>ijJira viewermnml-tickets-jira
<leader>icAWS CodeBuildmnml-aws-codebuild
<leader>iwCloudWatch Logsmnml-aws-cloudwatch-logs
<leader>iaAWS Amplifymnml-aws-amplify
<leader>iLAWS Lambdamnml-aws-lambda
<leader>ieAWS EventBridgemnml-aws-eventbridge
<leader>idDynamoDBmnml-db-dynamodb
<leader>isS3 browsermnml-fs-s3
<leader>iAAzure Blobmnml-fs-azure-blob
<leader>iRRDSmnml-aws-rds
<leader>iCECSmnml-aws-ecs
<leader>iEECRmnml-aws-ecr
<leader>ioCognitomnml-aws-cognito
<leader>iqSQSmnml-aws-sqs
<leader>iNSNSmnml-aws-sns
<leader>iDDatadogmnml-datadog
<leader>iKDockermnml-docker
<leader>iFCloudflaremnml-cloudflare
<leader>iGGmailmnml-gmail
<leader>iSSlackmnml-slack
<leader>iTTeamsmnml-teams
<leader>iMMandrillmnml-mandrill
<leader>iBButtondownmnml-buttondown
<leader>ihhtopsystem binary (mnml offers brew install / apt install if missing)
<leader>iIiftopsystem binary (mnml offers brew install / apt install if missing)
<leader>irbtopsystem binary (mnml offers brew install / apt install if missing)
ChordCommand
<leader>aaask Claude
<leader>aeexplain selection
<leader>affix bugs
<leader>arrefactor
<leader>awwrite tests
<leader>ammirror Claude session
<leader>acopen Claude Code
<leader>aCClaude chat (with context)
<leader>axopen Codex
<leader>atshell pane
<leader>aMmixr DJ panel

Note the capital — lowercase i is taken by integrations. NvChad’s <leader>i for “insert” needed to move; capital I keeps the muscle memory close.

ChordCommand
<leader>Issnippet picker
<leader>Ixexpand snippet at cursor

The ThePrimeagen Harpoon idiom — pin a small set of “I keep coming back to these” files, jump to them by index. mnml ships it as a built-in.

ChordCommand
<leader>Hapin active file
<leader>Hmmenu / picker
<leader>1<leader>9jump to harpoon slot 1–9
ChordCommand
<leader>wsave (write)
<leader>qclose buffer
<leader>etoggle file tree
<leader>pcommand palette
<leader>orun task (palette-style task runner)
<leader>mmarkdown preview
<leader>Bopen browser (Chrome via CDP)
<leader>rrestart mnml
<leader>?cheatsheet pane (every chord → command)

Honest list of places where NvChad muscle memory doesn’t translate cleanly.

NvChad puts “insert” group under <leader>i. mnml has 28 integration siblings (one of them named mnml-tickets-jira<leader>ij), so <leader>i is the integrations group. Snippets live under capital <leader>I instead. The trie test integrations_group_is_reachable enforces this — there was a regression in May 2026 where the two groups collided and silently nuked integrations.

<leader>w closes a buffer? No — it saves

Section titled “<leader>w closes a buffer? No — it saves”

<leader>w is file.save (write). For “close buffer” use <leader>q (or :bd, or <leader>bd). The single-letter <leader>w matches more of the vim-ism of :w than NvChad’s “window-close” interpretation.

Ctrl-D / Ctrl-U half-page scroll vs multi-cursor

Section titled “Ctrl-D / Ctrl-U half-page scroll vs multi-cursor”

NvChad keeps Ctrl-D as vim’s half-page-down. In mnml’s vim mode it’s the same — Ctrl-D scrolls a half page. (mnml’s standard-mode Ctrl-D is the VS-Code-style “add next occurrence” multi-cursor chord, but that’s a different mode entirely.)

There’s no :Telescope ex command. The two pickers you’d want:

  • Ctrl-P opens the file picker (also <leader>ff / picker.files)
  • Ctrl-Shift-P opens the command palette (also F1)

Fuzzy-search is built-in across both — Ctrl-N / Ctrl-P walk results, Enter picks.

:Telescope find_files etc. — palette instead

Section titled “:Telescope find_files etc. — palette instead”

The command palette (Ctrl-Shift-P / <leader>p) is the catch-all. Every command — every chord, every ex command, every plugin action — is reachable from it by name. If you forget a chord, search the palette for what you want to do.

mnml’s “plugins” model is two parts: registered commands (Rust-side, in src/command.rs) and out-of-process sibling binaries launched as Pty panes via :term <binary>. There’s no Lua, no Packer/Lazy, no per-buffer autocmds. If you need a thing, either it’s already there as a command + chord, or you write a sibling.

Treesitter is on by default — no :TSInstall

Section titled “Treesitter is on by default — no :TSInstall”

Tree-sitter highlighting + text objects (if/af, ic/ac, ia/aa, ii/ai) are baked in. Languages are bundled, no per-install step. If a language isn’t highlighting, file an issue — that’s a missing grammar, not a config problem.

No which-key.nvim plugin to configure — the trie IS the config

Section titled “No which-key.nvim plugin to configure — the trie IS the config”

The leader trie is the source of truth at src/whichkey.rs. A [keys.leader] config overlay for user-extensions is a planned refinement (today the trie is built-in); the popup itself is always on.

A 60-second path from “fresh install” to “I can work like I did in NvChad.”

  1. Set vim mode in ~/.config/mnml/config.toml:

    [editor]
    input_style = "vim"
  2. Launch in your workspace:

    Terminal window
    mnml ~/some/project
  3. Check the mode chip in the bottom-left of the statusline. It should read NORMAL (block cursor). If it doesn’t, :set input=vim and try again.

  4. Try a leader chord — press <space>, wait a beat, the which-key popup should paint. Press f to descend into find, then f to open the file picker.

  5. Press <leader>? to open the cheatsheet pane — every chord, every command, searchable.

You’re in. The rest is muscle memory you already have.

  • Editing — the architectural framing, ex commands, vim-surround, multi-cursor specifics
  • Settings & configuration — TOML schema, the settings overlay, every config knob
  • LSP — language servers, completion, code actions, refactors
  • Git — the deeper git workflow under <leader>g
  • Cross-host PR workflow<leader>Pp + the multi-host PR cache
  • Coming from VS Code — the other half of the migration story, for teammates