Skip to content


Subversion checkout URL

You can clone with
Download ZIP


vi mode missing #65

arael opened this Issue · 85 comments

Maybe I overlooked in the documentation but it seems to me that the vi mode is missing. I think that fish shell is awesome but without the vi mode I cannot use it as my everyday shell. Is there any way to enable the vi mode in fish right now?

Maybe it is possible to achieve this through the configuration somehow although I have doubts. It is more likely that this is a missing feature.

Thank you very much for all your work.


I think this is on the list of planned features somewhere…


what is vi mode suppose to do?


Emacs is a powerful text editing program. Usually the default for all shells is the emacs mode. This means that the command line editing can be performed by using emacs shortcuts. So Ctrl-a puts the cursor on the beginning of the line and Ctrl-e on the end of the line. Alt-f advances the cursor forward word by word while Alt-b works in reverse. Alt-d cuts a word and Ctrl-y pastes it etc. If you know emacs you can use most of its keyboard shortcuts to edit your command line.

Vi/Vim is also a text editor program. The vi mode has its own set of shortcuts and it is modal. There is the normal or command mode and the insert mode. The command mode is used to browse the history and perform command line editing just like in vi. The insert mode is meant to insert text. So in the normal mode pressing 0 puts the cursor on the beginning of the line while $ puts it at the end. You can advance between words by pressing w or e and cut words by pressing cw (change word). Pressing p pastes the word back etc. The vi mode is very useful for people using vi/vim as their default editor. It is quite efficient if you know vi.

If you are interested I suggest you to search on web more info about the subject. Knowing how to move efficiently on your command line is useful and interesting and most importantly more productive.




okey, been using emacs all my life and i never thought of the vi/m isers around the world ;)


If you plan to make vi mode, please make it display current mode (command/insert/visual). As much as I like vim I find vi mode in shell extremly annoying and unusable since I never know which mode I am in.


@SebastianThorn We are out there brother. ;)

@silenc3r That is an excellent suggestion. I highly second that.
In bash I have the same problem. Pressing i first has become an habit of mine. This would be very useful to have in fish.


I second that.
The missing vi-mode was the one thing keeping me from using the original fish shell.
"Complete vi-mode key bindings" was in the manual section of "Missing features" forever.


There's an interesting implementation of this being developed on the mailing list:


It is not complete yet but it is functional actually.


@kalikiana Thank you for that link. I got it working and it looks nice. However, it's not on-par with the zsh vi-mode yet.

It also seems pretty slow. Actions like jump back one word have a lag of a few hundred milliseconds.

This script surely seems like a good start, but with the slowness I guess it can become somewhat annoying if you use it on a daily basis.


zomg +1




How's the status on this?


Well, there is nothing in the release notes yet so I guess the vi-mode is still missing. You can check here:


I'm not aware of any work being done on this, though obviously it's highly desired.

I'd like to do it but I'm not a vi user, so it'll take me a while to ramp up. On the other hand it makes an excellent excuse to learn.


There is a partial implementation of vi-mode here. It's not updated currently.

@ridiculousfish, I think one of the main obstacles which makes it difficult to introduce a vi-mode is the lack of bind modes: the ability to quickly switch a current set of bound keys to another one is highly desirable. Introducing it will greatly simplify extension of vi-mode bindings by the ordinary users.
I mean something like this:

bind -m vi-normal i 'some action' # for the key 'i' to work only in vi-normal mode
bind -m vi-normal # to switch to the vi-normal mode, where only 'i' key is defined

There was a message by Ian Munsie (the author of the vi-mode) on a fish shell mailing list with a feature request he needed for his implementation of the vim mode. They might be still relevant:

For the suggestion of an option to catch the next symbol, I think that bind '' func would be enough if func can determine which key was pressed. Passing the key in as a parameter would make sense, but would likely break existing code, so perhaps a special variable could be introduced for this purpose? If there is already a way to do this that I've missed let me know, but as far as I can tell self-insert is the only function that can do this.

There is still also the caveat that if '' is not bound to self-insert then commandline -f repaint doesn't repaint the prompt, which would need to be fixed before I could make use of it.

Another feature I'd like is a way to temporarily suppress the auto-suggestion feature. It's a bit out of place in vi normal mode, and can obscure the results of the change-case commands if a suggestion is already being displayed. I see there is already a suppress_autosuggestion variable which is set when pressing backspace - it would be great if I could set that with something like commandline -f suppress_autosuggestion when leaving insert mode. I personally don't mind whether I have to explicitly re-enable it or just wait until it is implicitly re-enabled next time a character is



I'm waiting for this too.



I've just discovered fish and it seems great. But using bash in vi-mode for years make it a deal breaker for me.

Nobody mentioned it, but vi-mode is not a bash or zsh feature (provided they did not rewrote it totally), it's a readline feature :

I see a few readline references in codebase, but mostly about a "inject readline function" option, so I'm not sure if fish use readline. If it does, I suppose we could have a basic support by switching its mode to vi on fish init. I'm afraid it's not the case, though, as setting set editing-mode vi in ~/.inputrc does not affect fish.


good find @oelmekki, all new to me


I'm not convinced vi-style really works well for a command line, even though you could consider me a hardcore Vim user. It's really shitty in readline, and actually even in Vim I use vim-rsi to get the default readline bindings in Insert and Command mode, because they're just better for single-line input with minor editing, which is what you tend to do in a shell. However, fish actually makes multi-line commands more useful, so things might be different in fish. If we do this in fish, I think it's important that we avoid the limitations of vi-mode in readline, which for me means making it clear which mode you're in (such as by putting it in the prompt and repainting it on mode changes, and/or in the terminal title) and that it supports Vim's features for multi-line editing and the operator-pending mode. That means things like ciw and da( should work and that jk moves between lines, etc. None of those work or do the right thing in readline's vi-mode. Proper support for repeat (with .) is also rather telling about the quality of a vim imitation.

However I'm not sure if having two completely different key bindings supported is in line with fish's design philosophy. Might be fine to extend bind with the necessary features to make this possible in a third-party script though.


@dag Well, your proposition is surely interesting, and I would be glad if this happens. But just to be clear, I would love to have an implementation as "shitty" as readline's one instead of nothing, if your view of correct implementation happens to be too difficult to realize.


same here. I really like the suggestions dag made and it would be great to have that implemented but I would settle with the readline support gladly.


I sympathize but I think that way lies zsh: there's a feature or configuration option for everything, but nothing feels quite complete or thought out. fish on the other hand tries hard to not make anything an option (but of course it's unavoidable) and to prefer quality features over quantity. But at the same time I think that fish tries to be highly customizable, which isn't the same thing as configurable. What I mean is that it provides the tools to let you easily script any feature you want. Take for instance my recent comment over in #128. That's what I'm after with extending bind without adding a vi mode option in fish core.


@dag i'd greatly prefer vi-mode, could the behavior be added as a compile-time "hack" for right now until there's a definitive solution?


@trevor No clue, I'm not on the developer team or anything like that!



dpc commented


dag commented

I'm curious if anyone in favor of this maps : to q: in Vim? :wink:

The command-line window in Vim is really awesome in certain situations, but most of the time the command-line mode is preferable.


@dag what are you proposing for fish?


I use q: in vim whenever I have to line edit a previous command at all. That isn't very often, so it doesn't make any sense to map : to it. However, I find myself doing quite a bit of line editing in zsh, and even the meager vi keys there suit me far better for that than the emacs-like keys. I use t and f motions from time to time, for instance, and I prefer the vi word motions to meta key chords.

I'm not particularly worried about the outcome of this feature request, or how exactly any resolution is implemented (option vs. plugin). Not having vi keys would mean my never using fish, though. Other people finding the alternate key bindings acceptable doesn't do me any good at all.




+1 I can't live without vi mode anymore


Me too, please +1!




Hi everyone,

This is clearly a feature which is desired by a number of people - no need to add more '+1's!

fish does not use readline, and it would be a reasonably large amount of work to graft on to fish.

I can't speak for all the committers, but I am very nervous about committing 'hacks' that do not integrate well with the fish philosophy, as those have a nasty way of finding their way into releases and thus becoming supported behaviour. The same goes for compile-time options.

For now:

  • how well does the script suggested above work? Is it suitable for inclusion in the main codebase?
  • are there any missing features (as described above) which are still missing and which need to be implemented in the fish codebase?

I'm not sure about including this inside fish. It's perfectly possible to implement this in shell script itself - see The only problem with it is performance (Python has rather slow parser), but I believe vi mode written in awk or C wouldn't be too slow.

Also, please remember fish doesn't use readline, as it's not powerful enough compared to current solution used by fish shell. For example, I don't think syntax highlighting would be possible with readline (and please don't give zsh as example, zsh doesn't use readline, but zle).

zle could be a possibility, however, I don't think moving fish to use it would be worth it, as already lots of code was written for interactive editing, and syntax highlighting in zle is really weak.


One of the problems with is that is excessively redefines keyboard bindings. Since fish doesn't give a way to switch between sets of bindings, script has to delete all the bindings and setup again when switching between vi-modes. It's ok, but it looks like a dirty hack, so I do not think it worth including it to the fish in this form.


I have switched to zsh/prezto like three weeks ago and I'm really glad I did it. I strongly suggest every vi-mode user to switch to zsh/prezto. It is so far the best experience of the vi-mode I had.

The is not a complete solution. There probably are some other commands missing but the two I use a lot are cc and dd. The first one cuts the command line and enters the inserting mode. The other cuts the command line and stays in the command mode.

Another feature that is missing is the current mode feedback. One does not know in which mode is the shell until a or i is pressed. If the letters are printed on the command line then the current mode is insert mode. This is not good and it is one of the reasons I switched from bash to zsh.


@zanchey David, the existing hack has exactly one downside: it depends on python, python script is embedded in shell script and is incredibly slow, which all is solvable by rewriting a major part of it with shell script. I would of course prefer fish to have native readline support, but f it's a significantly more effort or doesn't that can definitely wait.
I'm spending most of my time on zsh/oh-my-zsh, but fish has all that i use out of the box, and look much more consistent and elegant and would completely switch in case if fish had better vi mode support.


A vi mode is obviously highly desired. The biggest obstacle to my authoring a native vi mode is the simple fact that I am a vi neophyte, and so liable to screw it up.

IEEE Std 1003.1 (tm!!!), which is closest thing to a Unix standard that exists, defines the behavior of a vi-like mode for /bin/sh. You can see it here. If I were to attempt to implement a vi mode, I would base it upon that standard, unless there was a better one.

Can someone with more vi experience comment on the suitability of the OpenGroup spec for vi mode? What's wrong, or missing?


@ridiculousfish Should be pretty much sufficient as default.
By the way, pulling back my opinion on readline. Seems that zsh doesn't use readline, but also uses a custom bind (bindkey for zsh) to run commands.

These are the defaults for vim-mode in zsh: insert mode, command mode. This may be an example how people extend this.

So bind needs:

  • optional -M option;
  • way to determine and set current mode;

People with no C knowledge can then take this over.


Well zsh has more than that, as I pointed out before there is some vim compatibility such as cc, dd and s. Maybe some other that I don't recall right now. But event the standard mode would be great. @ridiculousfish you should join the vim elite :D we have biscuits and sunny days all year round.




I agree with @arael . Zsh probably does add some extra vim-like commands but having the "standard" implemented as a first step would be great. cc and dd would be covered by the spec linked in any case.

The spec seems to cover all of the basics that I use on a daily basics @ridiculousfish, and would be an excellent place to start IMO


If I follow fish concepts correctly it doesn't make sense to introduce modes to keybindings, since the only application for it is that vi style editing mode. I have an alternative idea.

Functions should be responsible for setting modes to env. C code is left intact in this case. The plugin mentioned above is based on that principle, we should just rewrite what it does in fish script. Esc switches to normal mode, while i, a, s etc switch to insert mode. In normal mode the switch should pass through all keypresses.

Question is - is there a way for a function to determine which key binding was pressed when it was run (for the sake of being able to pass through)?
@zanchey @ridiculousfish Please let me know what you think.


Started a bounty on BountySource for that issue. Dead or alive!


+1 just registering my interest on the issue.




+1. Oh, right. Obviously, there is lots of interest about this issue, but that doesn't mean developers have to be flooded with plus ones. The biggest problem now is about implementation, and I don't think it would be good to integrate a hack that doesn't work well with everything else. If you want to put a comment, please make it constructive - I fail to see how +1 is constructive.


I think +1s are important if GitHub doesn't support the number of "likes", "hearts" or "stars" per issue. Otherwise, how would Repo developers get any feedback on feature request popularity.

Some thoughts on the actual feature:

What annoys me a lot in bash: there is no way to determine what is the current mode you are using. The cursor is the same, the color is the same, there are no indicators at all. Even though there are only two mode available (insert and normal), it is still important. I have heard VIM users who don't like bash set -o vi mode because of that.


re: What annoys me a lot in bash: there is no way to determine what is the current mode you are using.

They could switch to vim zsh. :neckbeard:



Hi, can you tell me more on what you mean here?

My use-case:

  1. I switch back to some tab or screen tab or just different terminal window
  2. I don't remember (and I can't) what was the last state of the command line (normal or insert)
  3. To switch to vim (edit current line in vim) I need to press 'v' from the normal mode
  4. Since I don't know what is the current mode, I would tap ESC and then press 'v' but it is not better than just switching to normal mode every time (exactly the thing that annoys me).

Any changes on that question? Would love to use vi mode in fish!


Bottom line:
Issue reopened.
There are couple different ways on how to implement this.
Milestone is fish-future which means:

These are bugs that are not targeted for an upcoming release. If you can provide a fix for a bug in this milestone, we'll generally accept it for the next release even if the bug is not in the release.

+1's do not work.
Please help if you're a good C coder and can submit a patch.


@pirj: I'm going to confirm this. Make a good patch, submit it, and it will be accepted for next fish shell release. fish-future is intentional - it isn't high priority (because it's relatively complex), but that doesn't mean developers don't want this feature. The patch implementing bind modes, or something like that would be preferred.


For those who cannot wait the official vi-mode for fish I submitted a vi-mode plugin into the oh-my-fish repo: bpinto/oh-my-fish#107
The vi key bindings support is basic but I plan to improve it a bit. See the README for more info.


You might be interested in this: #1218.

@keith keith referenced this issue from a commit in keith/dotfiles
@keith keith Some fish settings.
Probably won't ever use fish, there are still some massive features
missing fish-shell/fish-shell#165

Fixed by applying #1218. This is not an April Fools' joke. Now the +1 flood can stop. If you want to test new vi mode, download the newest master, and run fish_vi_key_bindings. You can also use fish_vi_prompt to see the current status (or use $fish_bind_mode directly). There are still some issues, like #1387, but the basic support for vi bindings now exists.

@furunkel: Feel free to apply for $200 at You probably are aware of this bounty, if you read this topic, but I mention this just in case. I believe your patch wasn't easy to make anyway, so you definitely deserve this bounty from the community.

@xfix xfix closed this

Thank you very much!


Awesome, thanks !

Now the +1 flood can stop.

By the way, if this annoys you, make sure to report it to github. A +1
feature on issues is long overdue, and all popular open source
repositories are annoyed by this.


Thank you, @furunkel!


OMG this is soooooo cool! And just in time, too!

@ibmibmibm ibmibmibm referenced this issue in powerline/powerline

Add fish shell's vi-mode support #878

@zanchey zanchey modified the milestone: next-minor, fish-future

The $200 bounty that was posted on this issue waiting to be claimed, @furunkel :)


Is there any information on when this feature will be included in release? I don't see it in 2.1.1.


It will be in the next minor release (2.2.0).


Ugh, I just updated fish nightly on my machine to the version fish, version 2.1.2-1247-gfbe28fd and now after command execution vim mode always jumps in to insert mode. I have hard times understanding what has changed. Any tips? Thank you.


Most probably this has changed.


Ok, it's related to the #1933 issue. I actually don't like this change, feels weird. Not sure that blindly mimicking vim mode from zsh is a good idea on it's own. I will erase this binding in my configuration, not a problem.

Thanks for pointing this out, @vially


How do other vi-mode users feel about switching to insert mode after command execution? I merged that because it's what bash and zsh do, so I assumed it would feel natural, but maybe I was mistaken.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.