bash readline vi editing mode default keyboard shortcut cheat sheet

Bash provides two modes for command line editing - emacs and vi. Emacs editing mode is the default and I already wrote an article and created a cheat sheet for this mode.

This time I am going to introduce you to bash's vi editing mode and give out a detailed cheat sheet with the default keyboard mappings for this mode.

The difference between the two modes is what command each key combination (or key) gets bound to. You may inspect your current keyboard mappings with bash's built in bind command:

$ bind -P

abort can be found on "\C-g", "\C-x\C-g", "\M-\C-g".
accept-line can be found on "\C-j", "\C-m".
alias-expand-line is not bound to any keys

To get into the vi editing mode type

$ set -o vi

in your bash shell (to switch back to emacs editing mode, type set -o emacs).

If you are used to a vi text editor you will feel yourself at home.

The editing happens in two modes - command mode and insert mode. In insert mode everything you type gets output to the terminal, but in the command mode the keys are used for various commands.

Here are a few examples with screenshots to illustrate the vi editing mode.

Let '[i]' be the position of cursor in insert mode in all the examples and '[c]' be the position of cursor in command mode.


Once you have changed the readline editing mode to vi (by typing set -o vi), you will be working in insert mode.

The example will be performed on this command:

$ echo arg1 arg2 arg3 arg4[i]

Example 1:

Suppose you have typed a command with a few arguments and want to insert another argument before an argument which is three words backward.

$ echo arg1 (want to insert arg5 here) arg2 arg3 arg4[i]

Hit 'ESC' to switch to command mode and press '3' followed by 'B':

$ echo arg1 [c]arg2 arg3 arg4

Alternatively you could have hit 'B' three times: 'BBB'.

Now, enter insert mode by hitting 'i' and type 'arg5 '

$ echo arg1 arg5 [i]arg2 arg3 arg4

Example 2:

Suppose you wanted to change arg2 to arg5:

$ echo arg1 [c]arg2 arg3 arg4

To do this, you can type 'cw' which means 'change word' and just type out 'arg5':

$ echo arg1 arg5[c] arg3 arg4

Or even quicker, you can type 'f2r5', where 'f2' moves the cursor right to next occurrence of character '2' and 'r5' replaces the character under the cursor with character '5'.

Example 3:

Suppose you typed a longer command and you noticed that you had made several mistakes, and wanted to do the correction in the vi editor itself. You can type 'v' to edit the command in the editor and not on the command line!

Example 4:

Suppose you typed a long command and remembered that you had to execute another one before it. No need to erase the current command! You can switch to command mode by hitting ESC and then type '#' which will send the current command as a comment in the command history. After you type the command you had forgotten, you may go two commands back in history by typing 'kk' (or '2k'), erase the '#' character which was appended as a comment and execute the command, this makes the whole command look like 'ESC 2k0x ENTER'.

These are really basic examples, and it doesn't get much more complex than this. You should check out the cheat sheet for other tips and examples, and try them out!

To create the cheat sheet, I downloaded bash-2.05b source code and scanned through lib/readline/vi_keymap.c source code file and lib/readline/vi_mode.c to find all the default key bindings.

It turned out that the commands documented in vi_keymap.c were all documented in man 3 readline and I didn't find anything new.

After that I checked bashline.c source file function initialize_readline to find how the default keyboard shortcuts were changed. I found that 'CTRL-e' (which switched from vi mode to emacs) got undefined, 'v' got defined which opens the existing command in the editor, and '@' which replaces a macro key (char) with the corresponding string.

The cheat sheet includes:

  • Commands for entering input mode,
  • Basic movement commands,
  • Character finding commands,
  • Character finding commands,
  • Deletion commands,
  • Undo, redo and copy/paste commands,
  • Commands for history manipulation,
  • Completion commands,
  • A few misc. commands, and
  • Tips and examples

Download Vi Editing Mode Cheat Sheet

PDF format (.pdf):
Download link: bash vi editing mode cheat sheet (.pdf)
Downloaded: 184398 times

ASCII .txt format:
Download link: bash vi editing mode cheat sheet (.txt)
Downloaded: 44541 times

LaTeX format (.tex):
Download link: bash vi editing mode cheat sheet (latex .tex)
Downloaded: 18766 times

This cheat sheet is released under GNU Free Document License.


January 08, 2008, 23:40

Thanks! It's finally here after a long wait :)
It works equally well on ksh too.

January 09, 2008, 00:00

Ankush, yeah, it's finally here :) Great to hear that it works well on ksh, as well!

Next cheat sheets are going to be on Linux IPTables packet flow (which I created some 4 years ago), and I'll have another one on bash's history expansion.

Johannes Permalink
January 09, 2008, 02:07

I had no idea this was possible! Thanks a lot!

January 09, 2008, 21:11

Same loyal readers, great articles everytime.
No, u slona vse ravno ...
Thanks, will test tonight

January 11, 2008, 22:54

Hello Peter,

Thanks for visiting and commenting on our blog! We are plesantly surprised that you came upon our blog.

Your video lectures are quite impressive! And we, at the EIC ( Maryland, hope you get into MIT :)

Shaj Mathew

Brian Doyle Permalink
January 18, 2008, 17:40

Is there a way to tell visually if you are in command mode or insert mode from the terminal in a visual way? Like in vim you can setup the INSERT to display when you are in insert mode. Thanks.

January 18, 2008, 17:55

Brian, as far as I know it is not possible to visually tell whether you are in insert mode or command mode.

January 19, 2008, 12:40

In the 1st example you don't need to use capital B, it's enough with just b.

January 20, 2008, 04:57

Martins, yup, I don't need a capital B in this particular example but if argN, where N = 1, 2, ..., was a more complex one like "(foo)", then the the lowercase 'b' would treat ')' and '(' as separate words...

mischa Permalink
January 25, 2008, 12:14

nice cheat sheet Peter :),

i was wondering if it was possible to get visual feedback in what mode you currently are.

do you have any idea's on that?


January 26, 2008, 03:47

Mischa, as far as I know that is not possible. But it's not that confusing. I am mostly working in vi mode, and now have bound the most useful of emacs bindings to vi mode, so I got a mixed vi/emacs mode.

February 01, 2008, 20:13

Really Helpful :-)

Erik Wognsen Permalink
February 23, 2008, 03:00

Thanks for the guide :-)

"... have bound the most useful of emacs bindings to vi mode, so I got a mixed vi/emacs mode."

Can you give some tips on how to do this? Did you edit the readline source? I'd really love to have ^P in insert mode go up just as in normal mode.

Tyler King Permalink
May 05, 2008, 07:20

thanks for the cheats got them in time for a exam and was very helpful in remembering those syntax .... i bow to the great ones thanks a bunch keep 'em coming see ya

soday Permalink
June 11, 2008, 21:16

Just what I needed. Thanks!

June 14, 2008, 00:54

This is killer !!!

I haven't read anywhere about this bash's feature

June 14, 2008, 20:55

I toyed around with bash edit modes years ago and for some reason although I prefer vim wholeheartedly over emacs I have gotten to prefer the emacs edit mode at the commandline. I think it's because, gnu readline is a widely used library, so therefore I can do ctrl-a to get to the front of the line in bash and in firefox text boxes and in etc etc.

The vi edit mode for bash would be nice, but like many people say it's not really great for general computing. Since I log into over 10 different boxes for different things and get csh, bash or whatever depending, I'd rather have something that just works. On the systems I use a lot, I will customize my environment a bit, especially if my home is exported across different machines, but in general I go plain vanilla.

As long as I have a long merging history set, I'll use whatever shell pops up by default.


Just my $0.08 or so... judging by the length.

June 14, 2008, 21:10

Actually, where I said 'vi edit mode for bash would be nice' I meant, it would be nice with the following improvements.
1) easy way to switch between vi and emacs mode with a single keystroke
2) a way to see what mode I was in when in vi mode

I know there I times I would really like to be bouncing around the command line with /'s and n and hjkl and all those goodies, but I meant to say I just never have the time to switch to it and generally don't need it.

July 21, 2014, 15:32

bind a key to emacs-editing-mode

John thomas Permalink
June 14, 2008, 21:15


Ultimate Anonymity

June 14, 2008, 22:14

There is a link to the Emacs mode in the article, too. Both are very cool!

June 15, 2008, 05:00

Instead of using set -o vi you add 'set editing-mode vi' to you $HOME/.inputrc file you have vi-keybinding-loveless in all applications that support readline. You can also set this to system wide by added this to /etc/inputrc.


mike Permalink
June 16, 2008, 21:33

Hey -
Very interesting stuff. Is there any way to get this to support text objects like in vim? For example ciw for "change inner word." This would also be great to edit command args in quotes, i.e. ci" or ci'.

November 17, 2014, 05:43

In recent bash versions it's possible with some inputrc sauce:

June 22, 2008, 06:23

pets head deliver frog tom university

June 22, 2008, 06:24

look green australia me head deliver night we juicy we woman all night girl german

July 13, 2008, 05:46

australia english jhon bag bag red joke steven green

July 16, 2008, 17:18

Looked at vi mode cheat sheet, text version. Is there an error under Basic Movement? Then, "h" s/b left and "l" s/b right. Thanks for well laid out easy to read cheat sheet.

cygwin user Permalink
July 23, 2008, 14:38

it works perfectly in cygwin !

javaroast Permalink
July 28, 2008, 08:29

Thank you for your work on the cheat sheets. I'll definitely be adding your blog to the read list.

Wolf Permalink
August 15, 2008, 21:27

Thank you very much!

Tim Permalink
January 06, 2009, 04:37

thx dude, great article

Sun Yu Permalink
March 26, 2009, 14:14

becauese M-k == ESC k, you can just use M-k to switch into command mode; also M-h M-l M-j M-w ...

Adriano Permalink
April 26, 2009, 06:17

hi Peter, thanks very much for pointing out that ā€˜vā€˜ is defined to open the command itself in an editor (which will be $VISUAL, not $FCEDIT, by the looks of bashline.c).

Since 'v' is used a lot in vim for visual highlighting, it is easy by habit to accidently hit the v-key at the bash commandline while editing in the vi-mode. Plus calling in $VISUAL is probably overkill in most situations...

It seems extremely difficult to remap v for other purposes, unlike the other keys. Maybe it's impossible, but I would appreciate hearing from you first ;-) Thanks very much.

PS- (set keymap vi-insert) is probably the closest to vim among four other vi-choices.

anonymous Permalink
June 06, 2009, 19:29

vi mode where it pops in like an (arg: 3) just sucks.

Very distracting and fucked up. Those asshole kind of solutions looking for problems need to be options, not the default action.

Some jerk doesn't have enough to do so they fuck up perfectly good software.

September 09, 2009, 14:08

You should ban the person above, and delete their comment. How rude!

Although I do agree that having to learn UNIX just so I can edit a file E.G. 'edit file.ext' is a bit anoying! :)

September 10, 2009, 13:20

Hi! I was surfing and found your blog post... nice! I love your blog. :) Cheers! Sandra. R. Permalink
December 12, 2009, 18:37

Chris, actually he's right. Wholeheartedly, I really like Bash with its Vi-mode but this (arg: 1) thing is plain confusing. Is it possible to disable it somehow?

Once again, Peter, you are shedding lots of light in some dark corners of the Unix world. I have subscribed to your feed and look forward to not only updates, but reading your older stuff, which is new to me.

argv Permalink
January 16, 2010, 22:11

one thing that is awkward about vi is having to reach for the esc to switch modes key, which nowadays is usually located in a corner of the keyboard

there's another way to switch. ctrl-[
this might be on the other side of your keyboard so it gives you a way to switch modes from the opposite side

also, hitting v to jump into your editor seems like a "annoyance" until you begin creating user-defined functions in your interactive shell. or maybe you like saving short scripts.

e.g. you are typing up a good one-liner and then you decide to make it a function and save it for later use. you add give it a name() and brackets { ;} and then hit v. :w name :q and you're done. this is the essence of quick and dirty.

you can load these functions on the fly in other one-liners too, using sed. like this:
commands | sed '1i\
. nameoffunction
' | sh
i don't use bash. i use a very basic bourne-like shell that's stripped of "features" but close to being POSIX compliant. but with vi mode, tabcomplete and functions it's more than enough. vi mode is a good thing. and there are alternatives to readline if you look around.

argv Permalink
January 16, 2010, 23:15

i just noticed the ctrl-[ shortcut is mentioned in the post about command line history. well done.

one more thought: someone above mentioned the ubiquity of readline and emacs bindings. and the desirability of one standard set of bindings that works "everywhere". but if we are focusing on unix and the command line (cf, e.g., gui apps), i wonder if /bin/sh is not even more ubiquitous than readline. every system that runs scripts is likely have sh.

so from any shell one could type /bin/sh and then set -o vi. and then one is in familiar territory.

and according to the open standards group, if it's a terminal that supports command line editing, it should have vi mode.

i like both types of bindings, but i wonder which is really more ubiquitous.

January 29, 2010, 00:27

new to the bourne shell...any goo tutorials? anything will b appreciated

Jay Permalink
March 24, 2010, 19:32

on ksh (perhaps on bash, who knows), you might consider also adding one of
set -o vi-esccomplete
set -o vi-tabcomplete
to change the file and command completion behaviour.

Jon Permalink
March 24, 2010, 20:25

This was an excellent post. I saw some things I didn't know about. Btw, you can also search your history with '/' while in edit mode. So, if you know you've ssh'd into a machine but don't remember how long ago you did it, you can do a '/ssh' and find it (use 'n' for next find 'N' for previous).

March 24, 2010, 23:27

Nice post, Peter.

Just a couple of remarks:

In your Examples 1 and 2, for completeness and to be precise, you could mention that the user should hit the Enter key at the end, to actually execute the modified commands.

And likewise, in Example 3, that they should hit and then Enter, to exit the temporary file brought up by vi for the v command, and that the command gets executed immediately (IIRC) when they type that key sequence - you don't get a chance to edit it more, as I recall.

Other than those two minor nits, useful article, and it's cool that you dug through the source to find info for it ...

- Vasudev

March 24, 2010, 23:30

Aargh! due to use of angle brackets to indicate colon, etc., my above comment got garbled. Here is what I really meant:

For this:

"they should hit and then Enter"

substitute this:

"they should hit colon w q and then Enter"

- Vasudev

March 25, 2010, 02:37

Didn't notice the message about using "<" to insert a "less than" sign, before posting.

March 25, 2010, 02:40

Ok, you !%$# blog software: I meant "and lt semicolon" - finally ! :-) I hope ...

Raj Permalink
April 16, 2010, 12:46

Two things that keep me using tcsh are:
  * automatically switches to command mode on history or arrow key
  * uses tab-completion by default
That said I would like to use bash's loop-rollup and function aliasing,
but since I use command mode more than anything the ROI isn't there.

Tweezak Permalink
November 19, 2010, 04:42

I'm an old HPUX user and KSH and default vi mode command line editing are seemingly hard wired into my digits. BASH was really getting tiresome. This find will save my sanity (or what's left of it). Thanks for writing this!

Now if I could only remap the escape key to the spot God intended it to be...where the caps lock is. Anyone who used to use old HP workstations knows exactly what I'm talking about.

ndf Permalink
December 18, 2010, 01:12


Not sure if you'll see this, but if you'll create a file (I call mine .xmodmap-esc) with these lines:

clear Lock
keycode 0x42 = Escape

And then load it with:
xmodmap $FILENAME

December 02, 2010, 01:24

Nice article, great!I like it, thanks for sharing it with us. its worth reading!

foobar Permalink
March 05, 2011, 02:30

this is incredible.. i can't believe i didn't know about this before. thanks!

June 25, 2011, 22:30

Fantastic! Now I just wonder if anyone has written a script to automatically match your bash vi mode key maps to your existing Vim key maps. That would save me a whole lot of grief and appease the DRY gods.

Florian Permalink
July 27, 2011, 19:10

Thanks to your guide, the vi mode has become even more useful!

However, I found one downside which is due to a "feature" introduced in bash 4.2:

This broke my path completion completely and I didn't find a way to get the 4.1 behaviour back. Also the workaround suggested in above mentioned thread seems to be available only in emacs mode (afaics vi mode doesn't support the 'shell-expand-line' command.

Any hint is greatly appreciated!

saurav shrestha Permalink
August 09, 2011, 22:34

Firstly thanks for the wonderful cli-experience-changing tutorial!

I have but one gripe that I'm trying to sort out. Whenever I try to edit the command in 'vi' itself by pressing the 'v' key, it opens up in nano!

If someone would be willing to show how to fix this, it'd be much appreciated.

Angus Warren Permalink
September 08, 2011, 04:43

You need to update your $EDITOR variable to reflect the editor that you prefer.

Add this line to your .bashrc:

export EDITOR=vim

September 14, 2011, 15:47

Oh my god, how the hell did I not know about this? This seriously makes my life so much better, thank you so much! I was sick and tired of having to hold down the arrow keys to get to the beginning of the line!

Agnes Permalink
April 04, 2012, 07:55

You can use CTRL-A and CTRL-E in emacs mode (default) to jump to the beginning and end of a line. Works in any textbox in OSX, actually.

unixrefresher Permalink
June 05, 2012, 00:43

thanks... this works for me. I though the vi functionality in command line won't work in bash. :-)

Wesley Steinbrink Permalink
August 22, 2012, 03:48

Thanks for explaining the vi at the bash line. Didn't know about the "v" editing - nice. Also, at the bash line, Alt-l can be substituted for Esc. It is much easier. Further Alt-l can be used in most vims. Where it can't, I like :imap

Wesley Steinbrink Permalink
August 22, 2012, 03:51

The editor got me. The previous comment was to be Alt - lower case L pressed at the same time. The imap should read :imap < M - l > < E s c > without the spaces

Wesley Steinbrink Permalink
August 22, 2012, 04:27

Also in input mode, Alt-s works as a convenient backspace. Too bad it doesn't work in gvim etc.

Tyler Permalink
September 10, 2012, 22:13

You just changed my life

Kostya Permalink
September 30, 2012, 19:14

Thanks a lot for this :)) I really love vi and always wondered how to use it to edit bash command line... then I was studying `bind` builtin and discovered this wonderful ability to use readline commands. Then googling gave off your blog, and it is excellent!
Didn't even know that in default mode I was using emacs commands. OK I'll see if the "mixed" emacs+vi mode could help.
Thanks again!!!

User Permalink
February 12, 2013, 17:56

Thank you.

Alexandre Martins Permalink
September 26, 2013, 16:37

Hello Peter

Really nice cheatsheet.

I also came here to tell you that you can abtain the same vi mode by editing ~/.inputrc and adding

set editing-mode vi

This will enable the vi mode in bash, zsh, ksh and every other application that uses libreadline.

Leave a new comment

(why do I need your e-mail?)

(Your twitter handle, if you have one.)

Type the word "browser_38": (just to make sure you're a human)

Please preview the comment before submitting to make sure it's OK.