I still remember the panic the first time I accidentally opened vi on a remote server, typed a few letters expecting them to appear on screen, and instead watched my terminal do something completely unexpected — beeping, moving the cursor, doing anything but inserting text. If you’ve had that exact moment, welcome, you’re in good company. Almost everyone who’s used Linux for more than a week has a “how do I even quit this thing” story about vi. This guide is the one I wish someone had handed me back then — from the absolute basics up through the editing tricks I actually use daily now.
What Is vi, and Why Does It Behave So Differently?
vi (short for “visual,” contrasted with the line-based ed editor that preceded it) is a modal text editor that ships on essentially every Unix and Linux system by default. That word “modal” is the whole story of why vi feels alien at first: unlike editors like Nano or a GUI text editor, vi has distinct modes, and what your keystrokes do depends entirely on which mode you’re in.
On most modern Linux distributions, the vi command is actually a symlink or alias to vim (“Vi IMproved”), a much more capable superset that adds syntax highlighting, undo trees, plugins, and more, while remaining fully backward compatible with classic vi commands. Everything in this guide applies to both.
The Three Core Modes
- Normal mode (also called command mode) — this is where
vistarts by default. Keystrokes here are commands, not text. Pressingddoesn’t type a “d,” it starts a delete operation. - Insert mode — this is the mode where typing actually inserts text into the document, like a normal editor.
- Command-line mode (or “ex mode”) — entered by typing
:from normal mode, used for saving, quitting, search-and-replace, and other line commands.
Understanding this three-mode model is 90% of learning vi. Every confusing moment new users have (“why isn’t it typing what I press?”) comes down to being in the wrong mode.
Opening and Closing Files
To open a file:
vi filename.txt
If the file doesn’t exist, vi will create it in memory and write it to disk the first time you save.
To open a file at a specific line number:
vi +42 filename.txt
To open and jump straight to the first match of a search pattern:
vi +/searchterm filename.txt
Quitting — The Command Everyone Googles First
You are in normal mode, so type : first to enter command-line mode, then:
| Command | Effect |
|---|---|
:q | Quit (only works if there are no unsaved changes) |
:q! | Quit and discard all unsaved changes |
:w | Write (save) the file without quitting |
:w filename | Save a copy under a new filename |
:wq or :x | Save and quit |
ZZ (from normal mode, no colon) | Save and quit — shortcut equivalent to :wq |
ZQ | Quit without saving — shortcut equivalent to :q! |
If you remember nothing else from this guide, remember :wq to save-and-exit and :q! to bail out without saving.
Switching Between Modes
From normal mode, these keys enter insert mode at different positions:
| Key | Effect |
|---|---|
i | Insert before the cursor |
a | Insert (append) after the cursor |
I | Insert at the beginning of the current line |
A | Insert (append) at the end of the current line |
o | Open a new line below the current one and enter insert mode |
O | Open a new line above the current one and enter insert mode |
To leave insert mode and return to normal mode: press Esc. This is the single most-used key in vi, and the one habit worth building first.
Cursor Movement (Normal Mode)
vi was designed for keyboards without dedicated arrow keys, so movement is done with letter keys — and even on modern keyboards, this remains faster once it’s muscle memory because your hands never leave the home row.
| Key | Moves |
|---|---|
h | Left |
l | Right |
j | Down |
k | Up |
w | Forward one word |
b | Backward one word |
e | To the end of the current/next word |
0 | To the beginning of the line |
^ | To the first non-blank character of the line |
$ | To the end of the line |
gg | To the first line of the file |
G | To the last line of the file |
:42 or 42G | Jump to line 42 |
Ctrl+f | Page forward |
Ctrl+b | Page backward |
Editing Commands
This is where vi genuinely earns its reputation for speed once you know it. Commands compose: a number (count), an operator, and a motion combine into a single action.
| Command | Effect |
|---|---|
x | Delete the character under the cursor |
dd | Delete (cut) the current line |
3dd | Delete 3 lines |
dw | Delete from cursor to end of word |
d$ | Delete from cursor to end of line |
yy | Yank (copy) the current line |
3yy | Yank 3 lines |
p | Paste after the cursor/line |
P | Paste before the cursor/line |
u | Undo |
Ctrl+r | Redo |
. | Repeat the last change — extremely powerful for repetitive edits |
r<char> | Replace a single character under the cursor |
cw | Change (delete + enter insert mode) the current word |
cc | Change the entire current line |
~ | Toggle case of character under cursor |
The count-operator-motion pattern is worth internalizing: d (delete) + 3w (3 words) = d3w deletes the next three words. 2dd and d2d both delete two lines — vi is flexible about count placement. This composability is why experienced vi users can make complex edits in a handful of keystrokes.
Search and Replace
Search (from normal mode):
/searchterm
Press Enter, then n to jump to the next match, N for the previous match.
?searchterm
Same as / but searches backward.
Find and replace (ex/command-line mode):
:%s/old/new/g
Breaking this down: % means “every line in the file,” s is substitute, old is the search pattern, new is the replacement, and g means “every occurrence on the line,” not just the first. This is genuinely one of the most useful things in vi — I use it constantly for quick config file edits over SSH where opening a GUI editor isn’t practical.
Variants:
:s/old/new/ " replace first match on current line only
:s/old/new/g " replace all matches on current line
:5,10s/old/new/g " replace on lines 5 through 10 only
:%s/old/new/gc " replace all, with confirmation prompt for each
Working with Multiple Files and Windows
vi file1.txt file2.txt
Then use :n to move to the next file, :prev to go back.
Split windows:
:split filename " horizontal split
:vsplit filename " vertical split
Move between splits with Ctrl+w followed by an arrow key or w to cycle through.
Configuration: .vimrc
vi/vim behavior can be customized through a config file at ~/.vimrc (for the current user) or /etc/vim/vimrc (system-wide, distro-dependent path). A few genuinely useful settings I keep in mine:
set number " show line numbers
set expandtab " convert tabs to spaces
set tabstop=4 " tab width
set shiftwidth=4 " indent width
syntax on " enable syntax highlighting
set hlsearch " highlight search matches
set ignorecase " case-insensitive search
Practical Sysadmin Use Cases
- Quick server-side config edits over SSH:
vi /etc/nginx/nginx.conf, make the edit,:wq, reload the service — no need to copy files back and forth to a local machine. - Bulk find-and-replace across a config file:
:%s/old_ip/new_ip/gafter a server migration. - Editing crontabs safely:
crontab -etypically opensvi(or your$EDITOR) by default, and knowing:wqvs:q!matters here since a bad save can break scheduled jobs. - Recovering from a crashed session:
vi(andvim) leaves a.filename.swpswap file if a session ends abnormally. Reopening the file will prompt you to recover, with:recoveror choosing “Recover” at the prompt. - Diffing two files interactively:
vimdiff file1 file2(orvim -d) opens a side-by-side diff view — genuinely useful for comparing config versions.
Troubleshooting Common vi Problems
- “I’m stuck and can’t type anything” — you’re probably in normal mode; press
ito enter insert mode. - Random letters are triggering weird behavior — you’re in normal mode and those letters are being interpreted as commands; press
Escfirst, always, when in doubt. E325: ATTENTIONswap file warning on open — means a previousvi/vimsession on this file didn’t exit cleanly (crash, killed SSH session, etc.). You can choose to recover changes, open read-only, or delete the stale.swpfile.- Can’t save, “permission denied” — you don’t have write access to the file; either use
sudo vifrom the start, or in newervim, try:w !sudo tee %to force a privileged write without restarting the whole session. - Colors look wrong over SSH — usually a terminal
$TERMmismatch; settingexport TERM=xterm-256coloron the client side often fixes it.
vi vs vim vs Other Editors
| Editor | Strengths | Weaknesses |
|---|---|---|
vi | Available on literally every Unix/Linux system, even minimal recovery environments | No syntax highlighting, no undo tree, more limited features |
vim | Everything vi has plus syntax highlighting, plugins, better undo, visual mode | Slightly heavier; not always installed by default on minimal images |
nano | Much easier for beginners, on-screen shortcut hints | Far less powerful for heavy editing, slower for experienced users |
emacs | Extremely extensible, full computing environment | Steep learning curve, different (non-modal) philosophy |
The honest reason to learn vi specifically, even if you prefer another editor day-to-day: it’s the one editor guaranteed to be present on essentially any Linux or Unix system you’ll ever SSH into, including minimal recovery shells and embedded systems. Knowing at least i, Esc, :wq, and :q! is close to a baseline requirement for serious Linux system administration.
Security Implications
Be mindful when editing files with elevated privileges — sudo vi /etc/shadow or similar should be done deliberately and briefly, since a stray swap file left behind (.filename.swp) can sometimes retain sensitive content in a world-readable location depending on umask settings. It’s good practice to confirm swap file cleanup (:x normally removes it) and to avoid running vi as root for routine, non-privileged edits — edit as a regular user and use sudo only for the specific privileged file.
Compatibility Across Distributions
Every mainstream Linux distribution ships either vi or vim (often as vi symlinked to vim) by default — Debian, Ubuntu, RHEL, CentOS, Fedora, Arch, Alpine, and even minimal container base images like busybox typically include at least a lightweight vi implementation. This universality is precisely why it remains essential to know: unlike nano or GUI editors, you cannot always assume it’s missing, and you also cannot always assume something fancier is available.
Summary
vi‘s modal design feels backwards for the first ten minutes and genuinely fast for every minute after that once the muscle memory sets in. The core loop to remember is: Esc to get to normal mode, i/a/o to get into insert mode, and :wq or :q! to leave. Everything else — movement, deletion, search-and-replace — builds on that same normal-mode command vocabulary, and it’s worth learning well precisely because it’s the one editor you can count on being available anywhere you work on Linux.
References
man 1 vi/man 1 vim- Official Vim documentation: https://www.vim.org/docs.php
vimtutor— an interactive tutorial shipped with vim, run it directly from your terminal- POSIX specification for
vi: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/vi.html