Last updated: July 2026
You’re SSH’d into a server, typed vi config.php, and now nothing responds the way you expect. That’s because vi is modal — understand two modes and everything clicks.
The two modes
- Normal mode (default): keys are commands. Press
Escany time to get back here. - Insert mode: keys type text. Enter it with
i(insert here),a(after cursor),o(new line below).
Everything below is typed in Normal mode.
Save and quit — the ones everyone googles
| Command | Action |
|---|---|
:w | Save |
:wq or ZZ | Save and quit |
:q | Quit (fails if unsaved changes) |
:q! | Quit and discard changes |
:w newname | Save as a new file |
Stuck with “E45: ‘readonly’ option is set”? You opened a root-owned file without sudo. Save anyway with:
:w !sudo tee %
Moving around
| Command | Action |
|---|---|
h j k l | left / down / up / right (arrows work too) |
0 / $ | start / end of line |
gg / G | first / last line |
:42 or 42G | jump to line 42 |
Ctrl-f / Ctrl-b | page down / up |
Editing
| Command | Action |
|---|---|
x | delete character |
dd | delete (cut) line — 5dd cuts 5 lines |
yy | copy line — 5yy copies 5 |
p / P | paste below / above |
u | undo |
Ctrl-r | redo |
. | repeat last change |
Search and replace
/error " search forward for 'error'; n = next, N = previous
?error " search backward
:%s/old/new/g " replace every 'old' with 'new' in the file
:%s/old/new/gc " same, but confirm each one
:noh " clear search highlighting
Three habits that make vi pleasant
set number(or in~/.vimrc) shows line numbers — invaluable when an error says “line 87”.- Learn
ci"— change inside quotes. Cursor anywhere in"some value", typeci", and you’re editing a fresh empty string. Works with(,{,'too. vimtutorin your terminal is a 25-minute interactive lesson; it pays for itself the same day.
On modern distros vi is usually Vim (or its slim build); every command above works in both. For scheduling the scripts you just edited, see the crontab guide.
