132 comments

[ 3.2 ms ] story [ 174 ms ] thread
Don't have anything to add to this except to say thanks to the team for an amazing product. Been using fish shell for 5+ years now and I love it. "Finally, a command line shell for the 90s"!
I'd like to echo that, I _love_ fish. This looks like a huge release from the changelog.
Many of us use it, I personally in my daily basis development Fish shell is pretty neat and increases productivity in terminal. However I still use Bash in the server side where I need for example, explicit error aborting like `set -e` that Fish doesn't have yet. https://github.com/fish-shell/fish-shell/issues/510
set -e is not great and is not recommended. http://mywiki.wooledge.org/BashFAQ/105
Agree with the "false positives" however in combination with error handling I don't see why not use it.
-e is in the class of things that can be fine to use, but the people least-likely to be prepared to know when it can be are the most likely to expect it to behave better than it does.

Sort of a combination finger-trap/cigar cutter for newbies.

Yeah.. but still useful despite the "false positives" that the link states which are addressable with proper error handling.
`-eu -o pipefail` catches most of what newcomers expect anyway.
I read this as "bash has unintuitive footguns" rather than "set -e has unintuitive footguns with its usage".
Bash doesn't have unintuitive footguns, bash <<is>> a unintuitive footgun :-)
I agree with the second to last recommendation:

> rking's personal recommendation is to go ahead and use set -e, but beware of possible gotchas. It has useful semantics, so to exclude it from the toolbox is to give into FUD.

Manual error handling would be ideal but it's too easy for me to mess up and miss something. Plus, if you really wanted to catch everything with proper error handling you would need to wrap every command in your script.

if you use a bash shebang in your scripts, does it not matter (honest question, I never have used fish)?
I'm surprised that Fish isn't used more for education. I don't know of any distros aimed at new users which have fish as the default. I don't think I've seen any tutorials that use fish to teach shell concepts.

It seems like such a missed opportunity, especially at a time when Linux Gaming is on the rise. There's a whole audience that would have the activation energy of getting into shell scripting lowered by being slightly more friendly and approachable than bash.

I feel like fish is the python of shells, and python has more than proved that a language being 'easy' and approachable makes it much more appealing to a wider audience.

Off topic: I came back to Python after a few years and WOW the LSP is fast and helpful. Maybe that's always been the case but after Typescript forced me to turn my vim into an IDE, Python really outshines it on the tooling.

Edit: the point is that I should try fish too. Great user friendly tooling isn't just for beginners.

(comment deleted)
This is probably due to the fact that fish isn't 100% POSIX compliant. A lot of commands new users see on the web won't work properly in fish shell.

For example, you couldn't set environment variables for one command in fish like you could in other shells until the last minor version (3.1).

I'm glad fish is becoming more like other more standard shells while maintaining its user-friendliness.

I think the lack of being able to reliably copy in commands from tutorials is the biggest issue there. Needing to translate any bash command that uses command substitution is a pain, and is very newbie-unfriendly if they run into it.
As someone with a teeny tiny commit in this release and a maintained personal fork, I feel compelled to say that the biggest benefit of fish over bash/zsh for me is not just the OOTB completions UX etc., but also how much more approachable it is to hacking. I would never even bother reading the source code of bash again, let alone try to patch it, because I have 0 confidence that something completely unrelated is not gonna break.
Fish is my favourite shell because among other things, it has the best support for vi key bindings. I have been using the master version of it without any issues for more than half a year now for the undo / redo support and I'm glad the team has finally released it to stable. Thanks to everyone who worked on this! If anyone is reading this and is using vi mode with bash or zsh, give fish a try, it's so much better!
> If anyone is reading this and is using vi mode with bash or zsh, give fish a try, it's so much better!

Great to hear that. I am using vi key bindings wherever it's possible, for example, text editing, Firefox(vimium) and file manager(ranger). But I have never been able to figure out how to use vi mode effectively in the shell prompt. The last time since I tried vi mode in shell was at least 5 years ago. I could roughly remember that vi mode bindings conflicted with certain oh-my-fish plugins I had installed. Even worse factor was that, I didn't know how to do certain things in vi mode, for example "M-." key to yank last argument from previous command. So I gave it up in the end.

Would you mind sharing what plugins do you use? And how do you work efficiently with vi mode? Thanks ahead.

I’m a die-hard vim user and a fish developer but (gasp!) I don’t use vi mode in fish or any other shell. Alt-V will open $EDITOR with the command line contents preloaded into the buffer and update the prompt on exit, I find that to be good enough without the frustration of trying to convert the prompt into a text editor when it’s not.
This alone might convince me to start using fish again. Thanks for the tip!
That's odd. bash and zsh had leagues better vi bindings the last time I tried. fish had tons of weird errors, most notably that things like `d2w` simply don't work. I actually had to stop using fish and go back to zsh because I couldn't get past the lack of vi support.

Apparently, https://github.com/fish-shell/fish-shell/issues/4019 still has not been fixed. There's no similar issue in bash/zsh.

> it has the best support for vi key bindings

Yeah, maybe not the best. Once could say they're improving though.

> Vi mode bindings now support dh, dl, c0, cf, ct, cF, cT, ch, cl, y0, ci, ca, yi, ya, di, da, d;, d,, o, O and Control+left/right keys to navigate by word

Fish is my shell of choice for a couple years now. Not because it's the perfect shell, but because it's a lot better than any other for interactive shells.

For scripting I still stick to bash because it's more portable and I already know how to cope with its warts. And sometimes when I can't remember the fish syntax by heart, I just launch a bash from inside fish to run my command and then Ctrl-D :-)

I switched to fish a very long time ago (2009 maybe?) because it started up so much faster than zsh w/ all the plugins that it took to get the fancy features fish had out of the box. Since then, fish has only become a lot faster as we have focused on performance and optimizations considerably.
I tried zsh after fish and my impression was somewhat like this: Okay, so I got to do a lot of customizing to get this to work nearly as well as fish does out of the box - can't be bothered!
My impression of ZSH after fish is "ok this made for a really annoying couple of hours to set things up, but now I'll never have an incompatibility hassle again!"

When I was in school and working on my own stuff I liked using fringe shells like xonsh and fish, but working in teams I feel like I need a pretty significant productivity increase to justify using a different tool than everybody else.

Unless you source a lot of shared scripts why would it matter what shell you use interactively? You can install fish and bash side by side and use one in your terminal and one for scripting.
There are even things like bass and replay.fish to deal with sourcing bash scripts
I share a lot of snippets and commands with members of the team, write a lot of bash (which I like to debug in interactive mode), and often follow or produce documented procedures in interactive shell (not quite repetitive enough or frequent enough to bother scripting).
I felt that way until setting up a new computer, then I don't bother and install Fish and move on.
Omz plugins are the worst thing to happen to zsh, only surpassed by nvm.

Omz has so much compatibility code that you end up with way more than you need and a lot of what it ads can be shimmed to lazy load.

Nvm is just fucking trash. I had to rewrite large parts of it to not be total garbage. It still is. Go look at how it's installed and how it loads itself its fuckin insane.

Same here. Fish makes certain things easier (working with variables, for example) but sometimes I still drop a bash shell.
I'd just like to add that if you're considering the switch but are worried about compatibility with bash, things have gotten better. I wouldn't call it outright compatible, but the most problematic differences in syntax (e.g. the absence of &&) went away a few years ago.

If it didn't quite stick the first time, I think it's worth trying again.

The parsing and setting of environment variables was always my #1 hassle with fish. I feel like I see a lot of BASH snippets that get copy pasted around that I always had to re-write or throw in a sub shell. Particularly annoying when you're trying to do something while screen sharing and somebody gives you a snippet which you have to re-write before using it- "Oh yeah it's a hassle but I've got sweet auto-complete" gets old
IMO, copy-and-pasting bash commands is an organizational smell to begin with, but I don't think this particular use case is a reason not to use one shell over another. If you do have a snippet of bash to run, it's easy enough to toss it in a file (with a shebang) and run it as a shell script. And as a bonus, it's reusable and you can add comments/notes for when you have to run it again.
I think the bigger issue is with programs (e.g. nvm) that are either implemented as collections of shell scripts, or function by dynamically generating shell commands.
> IMO, copy-and-pasting bash commands is an organizational smell to begin with

The people who develop the automation have to start somewhere :). If you're standing up a test environment or a PoC, writing down commands get's you 80% of the way to reproducing your results

Fish now supports setting environment variables for a command easier. Previously you had to do

    env MIX_ENV=prod mix compile
Now you can just do

    MIX_ENV=prod mix compile
But I also generally don't use fish for any scripting, I just use bash for that. But at least some copy-paste commands aren't as difficult to translate now.
Fish is my shell of choice, like many in this thread. To me it just works, without configuring anything (ok, maybe a couple of aliases), with great defaults.

As an example, type anything(for instance, '.conf') + up arrow, and there you see all the completions (for instance, 'less /etc/postgresql/10/main/pg_hba.conf' shows for me) based on the shell history. You can then cycle through them with up/down arrows. It is the same as ctrl+R in bash, but so discoverable and plain. I found tons of similar details in fish.

Edit: typos

For this specific use-case, ctrl+R + fzf works nicely.
We’ve added some improvements in this release that should make that a better experience by improving the performance of `history` when piped to fzf (or anything else). The output was previously buffered and GNU wide character comparison/conversion is insanely slow so that had to be hacked around.
It really is my pet peeve with fish, but the last command that started with what you typed cannot be completed that way. For that, you need to use right-arrow.

I kept a fork of fish for that purpose for some time, but that was really too much hassle and I went back to zsh.

Which is pretty sad, because otherwise fish is amazing.

ctrl + e or end will complete commands in that case
IIUC, right-arrow also does, and option-right-arrow will complete individual arguments from the last command one by one (macOS).
>without configuring anything

and if you want to configure stuff it actually also has a neat ui built in with fish_config

> As an example, type anything(for instance, '.conf') + up arrow, and there you see all the completions (for instance, 'less /etc/postgresql/10/main/pg_hba.conf' shows for me) based on the shell history. You can then cycle through them with up/down arrows. It is the same as ctrl+R in bash, but so discoverable and plain. I found tons of similar details in fish.

Fun anecdote: my school's crappy homebrew distribution had a bash plugin that did exactly that (it was the distro's one redeeming feature, honestly).

After I moved to other distros, I missed that feature for years (I hate Ctrl+R).

Looking for plugins that implemented it was how I found fish, and I never looked back.

I always see these posts, get tempted to use fish instead of bash but then I ask the ubiquity question and end up saying "Not today..."
The ubiquity question?
bash is installed by default on pretty much everything but for fish I need to un-learn bash shenanigans like `esac` which I fear would hurt more than help in general.

Either that, or maybe I'm just lazy and missing out on a nice tool...

Fish made me write better bash scripts because it gave me a proper understanding of IFS, test, and other shell “basics” since it removes a layer of automagic by simplifying the syntax. Eg fish discourages the use of `if [` and it makes you realize that the bracket isn’t a grammatical construct but rather a terribly named command.
I switched entirely for interactive use a couple of years ago and have only had positive things to say. I still use Bash for scripts but that’s exclusively scripts which I edit in a real editor with version control, 100% shellcheck, etc. and even then I’ve been rewriting most non-trivial scripts into Python for the last decade so it gets sane error handling and data structures, not to mention usually ending up being shorter due to the richer library.
If you mean for script portability: you can still easily call scripts with bash directly. For scripts that modify the environment, use bass.

If you mean that you still have to use bash on other machines: yeah, I feel you there.

At least for me, I'm fortunate that if I end up using a machine frequently, I can just install fish and add my config/dot files.

I used to have Vim with dozens of plugins installed, nowadays I consciously use Vim without relying on any plugin and try learning to do the same with only the basic movement commands, so I can be productive no matter what machine I'm using/logged into today - otherwise they'll be forgotten (hackers used to survive in the original vi without visual mode or multiple undo, I think surviving a pluginless Vim shouldn't be difficult). Some for the shell.
It deserves a try! However don't get tempted to think that Fish is Bash drop-in replacement, personally I can not be more disagree with that idea.

Bash is a pretty useful and powerful scripting too, especially in server side (among other big list of stuff as you know).

This hasn't happened to me. I guess I've never used my prompt as a programming environment, so switching from zsh to fish hasn't impacted by ability to write posix shell script anymore than it as impacted my ability to write ruby or javascript.

I use fish strictly as a command line and it is fantastic.

Thank you Zanchey, Ridiculousfish, Fabian, and everyone else!
I think Fish is an excellent interactive shell. I've still got Bash as my default shell for non-interactive sessions, but I configured Konsole to start Fish by default for interactive use (Settings->Command, set to the path to the fish executable). That way scripts that need Bash still work, but I get a sane environment for interaction. For "portable" scripts I write POSIX shell, C, or Python, depending on what I need to be portable to.

fish_add_path will solve one of the few annoying things about Fish.

I've been looking at trying Oil as a Bash replacement though, I think Oil for scripting + Fish for interaction might be a best-of-both-worlds setup.

Fwiw fish_add_path doesn’t fundamentally change anything, users do get confused between global and universal variables and how they interact with exported variables like PATH, so this just makes it friendlier.
It also helps prevent duplicate path entries. I'd written an "add_to_path_if_not_present" function, but "fish_add_path" should do the same thing. It's just convenience, but Fish is largely about convenience.
Thanks for sharing. I have a debian box that I try keep as standard as possible, and I think this setup would fit my environment well.
Shebangs direct scripts to the right interpreter. Setting a default interactive shell won’t override it.
True, but there do exist (crappy) scrips with incorrect shebangs. EG specifying `#!/bin/sh` when they should use `#!/usr/bin/env bash`, since `/bin/sh` isn't necessarily bash. Could be dash. Could be fish. Could be oil. Etc.)
I think /bin/sh is required to be a POSIX shell, at least when invoked with that name, and fish wouldn’t qualify.
I see a lot of enthusiasm for fish. Can someone point me to some resources that I can check?

Not the best comparison but: vim has vimtutor, a couple of good vim games and so on. Is there anything for fish?

Honestly, fish is really simple. Just fire it up! You definitely don't need a vimtutor equivalent, you probably won't customize anything beyond the prompt, and the syntax weirdness is pretty intuitive, but you can always use `help function` or whatever to get docs.

Here's the docs if you do want to read about it first: https://fishshell.com/docs/current/

>A new "fish_add_path" helper function to add paths to $PATH

Yes! Modifying PATH has always been cumbersome compared to bash-like shells. This is a welcome addition.

(comment deleted)
I'd like to use fish regularly, but I feel really attacked by the over-the-top usage of color and unrequested auto-completion. Even a "monochrome" theme I tried was shoveling many different shades of gray into my terminal. It does not seem to honor the NO_COLOR variable either. Is there any way to obtain a default configuration with everything disabled?
It's a good point, but how many of the features are useful without any colors at all? At least the auto-completion would just look like any typed text.

Perhaps fish is not for you?

I think it’s a fair ask - imagine using fish on a monochrome screen, for example. I could imagine using underlines or inverse text frontage autocomplete in such a theme/mode. Let’s see if someone here already knows such a theme, or gets inspired to make one. ;-)
> Perhaps fish is not for you?

It nearly is! I love fish powerful completion, just find it annoying that it is triggered automatically. Also fish syntax seems saner than bourne's, and I love it (but miss process substitution from time to time). Unfortunately, I cannot stand the flashiness. With some work, I have managed to disable all colors by setting a lot of fish_color variables in my configuration file. But the auto-completion drains me after a few minutes of use. As if you are speaking to somebody and they complete all your sentences! Even if the completion is correct, isn't that extremely annoying?

I think what you are talking about are the fish "suggestions". By default, that text is greyed out and if you like the suggestion, you can cursor-right (or ctrl-f) to accept it. But if you don't like the suggestion, you just keep typing.

If my hunch (that you are talking about the suggestions) is correct, then perhaps it works to set it to white on white or black on black, or whatever matches your color scheme. It will still be there, but you won't see it :-). (But you would get it after cursor-right or end or ctrl-f or ctrl-e...)

hahha, cool hack! I'm still a bit irked that the text is there (but invisible), but this is the desired "normal" effect.
It would be nice if it was possible to turn autosuggestions off, I agree.
You can use `psub` for process substitution, e.g. to compare two sorted files:

    diff -u (sort a |psub) (sort b |psub)
Why would you want to disable colors.
I find them distracting and annoying. Somehow colored text overwhelms me and I have trouble reading.
what's the difference between this and zsh? both seem to have the same set of features. also zsh is the default shell for macOS (as of Catalina)
Fish has many more features out of box. To match fish with zsh you need to install many zsh plugins. Because the features are native to fish they are much faster in fish than zsh.

Fish has a great help system and error messages.

Fish is also a much cleaner programming language because it doesn't need to carry the historical quirks of bash, zsh, and posix. That said I wouldn't recommend using it as a programming language.

Folks make a big deal about everything Fish gives you out of the box, but for someone who already has Zsh well–configured (eg. syntax highlighting, autosuggestions, fzf), can someone sell me on things I might be missing out on from Fish?
Assuming zsh is already doing everything you want the biggest thing you're missing is speed.
"Speed" seems a vague claim. What are you referring to? Startup time, interactive use, scripting?
WTF are you doing where shell "speed" is the bottleneck? How does it happen that your shell starts "slow". This post has lots of speed comments. I don't get it. Are bash pipes slower than others? Do folk have a shell that takes longer than 250ms to start?
I tried out many of the popular shells (bash, zsh, fish, etc) many years ago when my daily driver was an older thinkpad, and some of the startup times were painfully slow for me. It definitely drove me toward the more minimal shells like ksh and rc. On newer hardware it hasn't been noticeable, but it's real.
Not OP but fish's fuzzy autocomplete is snappy, especially on low-end hardware even when I mistype a lot, where zsh will often just freeze completely, for me at least.
Not having to fight against POSIX. Arrays are first-class, strings don't split when you don't want them to, things that could be builtins generally are builtins instead of inscrutable syntax.

Command output is split on newlines, which turns out to work really well with most Unix tools and only breaks on the most pathological of filenames. The newbie-ism `for f in (ls)` isn't actually harmful in fish.

Autocomplete definitions are very straightforward and declarative, so writing your own is easy. See https://fishshell.com/docs/current/cmds/complete.html#exampl.... zsh's system is more intimidating. (I even contributed completions for a few commands to this release of fish.)

I put off switching from bash for years but quit cold turkey for fish a couple of years ago, and find myself appreciating that almost daily.

One of the underappreciated values is that while you can configure it you get great functionality out of the box. Switching was chsh, picking a theme in the interactive config, and going back to work. The only I’ve really felt the need to do was to add the Terraform workspace to my prompt, which was quite easy.

I made myself use Fish for a week as an experiment. Day one was a little rough. Day two was easier. On day three I decided to customize my prompt, and after seeing how trivially easy that was (you write a fish function called "fish_prompt" that uses shell commands to build your prompt) compared to Zsh or Bash, I was... hooked.
I definitely built up the switching costs in my head based on past experience with zsh. Good defaults are easy to undervalue.
I used to really use fish pervasively in my computer, but after a while I realized that I forgot literally all of bash (like I forgot how for-loops look like, how word split works…) and I just switched back to macOS default zsh.

I’m still wanting a fish-alike interative shell that improves on the Bourne shell language (and bash extensions). I’m having hopes on Oil shell [0], but it’s still in an early stage so I guess I’ll have to wait for a far future…

[0]: https://oilshell.org

> Significant performance improvements to completion of the available commands (#7153), especially on macOS Big Sur where there was a significant regression (#7365, #7511).

This is buried down in the Completion section but this is a big deal if you’ve upgraded to MacOS Big Sur: completing a command could hang the shell for 10-15 seconds making it nearly unusable. Thanks for fixing this!

I used fish for a couple years but switched back to zsh. I found the incompatibilities with bash/zsh to be annoying at times and finally just decided to do the "When in Rome do as the Romans" do thing and adopt zsh.
Same here. If you miss fish's smart auto-completion I can recommend this zsh plugin though:

https://github.com/zsh-users/zsh-autosuggestions

Sadly, this plugin is a pale copy of fish's power - it isn't folder-aware (fish will offer different suggestions for different folders) and it isn't context aware (fish will try to autocomplete the current line based on the context of the current folder, zsh-autosuggestion will just blindly offer history line that starts with what's typed)
I just use tab complete if I want a file from my working directory, which I actually prefer.

If anybody else is using zsh-autosuggestions, it's really worth looking into configuring it rather than using it out of the box. It exposes some pretty cool options. It was sub-par out of box in comparison to fish, but after some tweaking I like it better. You can do things like ignore history based completions on certain commands (like git, I don't need my last commit message popping up)

zsh-autosuggestion definitely has per-folder suggestions, in normal day-to-day work I haven't seen a difference to fish so far (fish may have added features in the last two years that I'm not aware of, but the basic context-senstive suggestions are definitely supported).
(comment deleted)
I had the same experience (but only used fish for a few months). I am quite happy with zsh after settling on zim [1] for plugins and starship for the prompt (starship supports many different shells) [2]. My main takeaway from fish is was that we deserve great autocompletion. The zim autocompletion module is almost as good as fish.

[1] https://github.com/zimfw/zimfw

[2] https://starship.rs

Fish has saved me from so many hours of zsh yak shaving. It is the best.
Love fish, but I always add the Bob the Fish theme which adds a really nice Powerline command line theme which effectively shows me current git status with just enough info to be useful much of the time.
>undo is bound to Control+Z, and redo to Alt+/

Unfortunate choice of keys for redo IMO

Control+Y is already taken, and Control+Shift+Z is indistinguishable from Control+Z because of terminal limitations. So I can't think of anything better.
It's not totally arbitrary, at least. In Emacs, Alt+/ is bound to Undo/Redo by default.
When in college my prof dared me to switch from bash to fish (because he thought it would be a funny failure) and I'm still using it today. It's a fantastic shell!