Vim & Neovim Essentials: The Keybindings You Actually Need
Vim looks like a puzzle box. It's really about eight keys and one config file.
Everyone’s first Vim story is the same: you open it by accident, type something, and now you’re trapped in a terminal that won’t let you leave. It’s a rite of passage. But once you learn the handful of commands that actually matter, that same “impossible” editor becomes the fastest thing on your keyboard.
This guide covers the keybindings you’ll use 95% of the time, plus a minimal init.lua to get Neovim feeling comfortable out of the box.
Modes, in One Paragraph
Vim has modes instead of menus. Normal mode is for moving around and running commands — it’s the default. Insert mode is for typing text, like a normal editor. Visual mode is for selecting text. You’ll spend most of your time bouncing between Normal and Insert.
Opening and Closing
Start Neovim from the terminal:
nvim filename.txtFrom Normal mode, these are the exits:
| Command | What it does |
|---|---|
:w |
Save |
:q |
Quit |
:wq or ZZ |
Save and quit |
:q! |
Quit without saving |
💡 Quick Check: After
:wq, you should land back at your shell prompt with no error message. If you instead seeE37: No write since last change, you tried to quit with unsaved edits — add the!or save first.
Insert Mode
From Normal mode, any of these drop you into Insert mode:
| Command | What it does |
|---|---|
i |
Insert before the cursor |
a |
Insert after the cursor |
I |
Insert at start of line |
A |
Insert at end of line |
o |
Open a new line below and insert |
O |
Open a new line above and insert |
Press Esc to leave Insert mode and go back to Normal mode. That single keystroke is the one habit that makes everything else click.
⚠️ Important Exception:
oandOalways insert a new line — they don’t just move your cursor. If you only want to move to the line above or below, usej/kin Normal mode instead.
Visual Mode: Selecting Text
| Command | What it does |
|---|---|
v |
Character-wise visual select |
V |
Line-wise visual select |
Ctrl-v |
Block (column) visual select |
Move the cursor with h j k l (or arrow keys) to extend the selection, then act on it — delete, yank, indent, whatever you need.
Copy, Cut, and Paste
Vim calls copy/cut “yank” and “delete,” and paste is “put.”
| Command | What it does |
|---|---|
yy |
Yank (copy) the current line |
dd |
Delete (cut) the current line |
y (in visual mode) |
Yank the selection |
d (in visual mode) |
Delete the selection |
p |
Paste after the cursor / below the line |
P |
Paste before the cursor / above the line |
💡 Why This Matters: Every delete in Vim also copies to the same register
dduses, soddthenpis a quick way to move a line down. It looks like a coincidence the first time you notice it — it isn’t.
A Minimal init.lua
Neovim’s config lives at ~/.config/nvim/init.lua. This is enough to make it feel like a real editor without pulling in a plugin manager:
-- ~/.config/nvim/init.lua
-- Leader key (used as a prefix for custom shortcuts)
vim.g.mapleader = " "
-- Line numbers
vim.opt.number = true
vim.opt.relativenumber = true
-- Indentation
vim.opt.tabstop = 2
vim.opt.shiftwidth = 2
vim.opt.expandtab = true
vim.opt.smartindent = true
-- Search
vim.opt.ignorecase = true
vim.opt.smartcase = true
vim.opt.incsearch = true
-- Quality of life
vim.opt.wrap = false
vim.opt.scrolloff = 8
vim.opt.termguicolors = true
-- Keymaps
vim.keymap.set("n", "<leader>w", ":w<CR>", { desc = "Save file" })
vim.keymap.set("n", "<leader>q", ":q<CR>", { desc = "Quit" })
vim.keymap.set("v", "<", "<gv", { desc = "Indent left, keep selection" })
vim.keymap.set("v", ">", ">gv", { desc = "Indent right, keep selection" })Drop that in place and restart Neovim — no plugins required.
💡 Why This Works:
relativenumberpairs with the movement keys from earlier — once line numbers show distance instead of absolute position, a command like5dd(delete 5 lines) becomes something you can read off the screen instead of guessing.
Or: Install My Config From GitHub
If you’d rather skip typing out a config by hand, I keep a ready-to-use Neovim setup in my
dotfiles repo
. It’s built on
lazy.nvim
(a plugin manager) and is split into a few small files instead of one giant init.lua:
.config/nvim/
├── init.lua -- bootstraps lazy.nvim, loads everything else
└── lua/
├── options.lua -- the vim.opt settings
├── keymaps.lua -- leader key + keymaps
├── autocmds.lua -- autocommands
└── plugins/ -- one file per plugin (colorschemes, lualine, etc.)The repo also holds my shell and Hyprland configs, so you only want the nvim folder out of it — not the whole thing.
1. Back up your current config, if you have one:
mv ~/.config/nvim ~/.config/nvim.bak2. Clone just the nvim folder using a sparse checkout:
git clone --filter=blob:none --sparse https://github.com/darkrift-opt/dotfiles.git ~/dotfiles-tmp
cd ~/dotfiles-tmp
git sparse-checkout set .config/nvim
cp -r .config/nvim ~/.config/nvim
cd ~ && rm -rf ~/dotfiles-tmp--filter=blob:none skips downloading file contents you don’t need, and sparse-checkout set .config/nvim checks out only that folder — so you’re not pulling the Hyprland or shell configs at all. (If your git version is older than 2.25, skip the sparse steps and just clone normally, then cp -r the nvim folder out — a bit more data, same result.)
💡 Why This Matters: A full clone would still work fine —
cp -r ~/dotfiles-tmp/.config/nvim ~/.config/nvimgets the same result either way. Sparse checkout just avoids downloading configs for tools you may not even be using.
3. Launch Neovim:
nvimThe first launch will look busy — init.lua detects that lazy.nvim isn’t installed yet, clones it automatically, and then lazy.nvim installs every plugin listed under lua/plugins/. Just let it finish.
💡 Quick Check: Once the plugin install window closes, you should see a themed statusline at the bottom and no red error banners at the top. If you see
module 'options' not foundor similar, thelua/folder didn’t come along withinit.lua— recheck step 2.
A few things worth knowing about this config specifically:
- Leader key is
Space, same as the minimal config above. - Save/quit live under
<leader>fs(save),<leader>qq(quit), and<leader>qs(save and quit) — not the plain<leader>w/<leader>qfrom the DIY version earlier. - Colorscheme is picked at the top of
init.luaviavim.g.active_colorscheme. It ships with several themes already configured inlua/plugins/(Tokyonight, Catppuccin, Oxocarbon, Carbonfox, Black Metal) — change that one line and restart to switch.
⚠️ Important Exception: This config expects the plugin folder structure to stay intact. If you only copy
init.luaand skip thelua/directory, Neovim will start but immediately error out looking foroptions,keymaps, andautocmds.
Cheat Sheet
Print this part.
| Category | Key | Action |
|---|---|---|
| Modes | Esc |
Back to Normal mode |
i / a |
Insert before / after cursor | |
I / A |
Insert at start / end of line | |
o / O |
New line below / above | |
| Movement | h j k l |
Left, down, up, right |
w / b |
Next / previous word | |
0 / $ |
Start / end of line | |
gg / G |
Top / bottom of file | |
| Editing | x |
Delete character |
dd |
Delete line | |
yy |
Yank (copy) line | |
p / P |
Paste after / before | |
u |
Undo | |
Ctrl-r |
Redo | |
| Visual | v |
Visual (character) |
V |
Visual (line) | |
Ctrl-v |
Visual (block) | |
| File | :w |
Save |
:q |
Quit | |
:wq |
Save and quit | |
:q! |
Quit without saving |
That’s the whole toolbox. Everything else — plugins, LSPs, fuzzy finders — is optional polish on top of these fundamentals.