I adore fish and can't imagine ever switching back to zsh or bash. First, it's nice and usable out of the box with a huge set of pre-configured completions. Second, it's incredibly easy to customize when I do want to tweak it.
For instance, writing my own prompt was what forever won me over from zsh. Basically, you edit a file named `~/.config/fish/functions/fish_prompt.fish`. That's where autoload functions live. If you type `foo` at the command line and it doesn't already exist, fish will look for a file named `foo.fish` in that directory, load it, and run the `foo` function defined there.
So in your editor, follow that pattern to write a function named `fish_prompt`. Put the commands in there that write your prompt to stdout. Make it as simple or complex as you want.
There. Done. That's all you have to do. Compare these:
Anyway, that was emblematic of my whole experience with fish. It took a lot of un-learning special magic to settle in. It just feels so much more cohesive and consistent than any other shell I've tried. And because of that, I'm way quicker to add little scripts or completions to it that make it even more pleasant for me. I'd say the activation energy for that is far lower than with other shells I've used.
For context, I maintained the FreeBSD "bash-completion" port from 2003 to 2008 or so. It's not that I love fish because I don't know the alternatives. I love it because I do.
No configuration is key for me. After more than 10 years with zsh I realized that configuration is technical debt. If I can have a reasonably modern shell without needing to configure it, that is worth a lot more to me than having things precisely the way I want them.
Absolutely, I've been using fish for at least ten years and have very little config, which was not at all the case before I switched.
The only material thing in my fish config is adding `echo -n (date "+%H:%M:%S ")` to the fish_prompt, which I've come to love having over the years. Consistently really nice to have a sense of when a command started and finished. And `cowsay (fortune -s)` in the fish_greeting ;-).
I added the date to fish_right_prompt in a darker grey. It's there but it's very subtle. Fish is also smart enough to delete the fish_right_prompt text when your cursor gets to it so it doesn't get in the way of long lines. Here's what I use:
function fish_right_prompt --description 'Write out the right prompt'
set_color 666666
date +'%Y-%m-%d %H:%M:%S'
set_color normal
end
That’s such a great idea, I’m annoyed it never occurred to me. Many times I just slip in a ‘date; <cmd>; date;’ and then get annoyed when something is taking too long, but I forgot to timestamp it.
It predates Linux by a lot. It's software flow control for ancient terminals and modems that couldn't keep up, so they'd use in-band ^S and ^Q characters to manage the input and output.
rms also hated it, to the extent that he intentionally used Ctrl-S for the most basic search function of Emacs so that people would have to turn off the ^S/^Q crap throughout the path from the program to their terminal, or they wouldn't be able to use emacs. (Or at least so I've heard; I tried searching for confirmation but failed to find it.)
This sounds like something rms would do, but also seems like a great way to turn people off to your text editor. If you haven't learned Emacs before, are you really going to put up with broken-by-design behavior?
It seems its probably more of a shell thing, than a linux thing. I've never run into this as an issue before, but I would wager it's the "Save" muscle memory which unexpectedly causes this issue for some people.
Oh yeah the save muscle memory is burned into me too, despite having save-on-blur enabled for the last decade. More wondering under what context ctrl-s is having an effect on shell, and what that effect actually is. Is it bg/fg shenanigans?
> My absolute favourite thing about fish is that I type, it’ll automatically suggest (in light grey) a matching command that I ran recently. I can press the right arrow key to accept the completion, or keep typing to ignore it.
You can also accept the suggestion with ctrl+f (or just a part of the suggestion with alt+f).
The best feature of fish is fish_update_completions which will parse all the man pages to provide automatic flag completion, so every binary doesn't have to ship a "--generate-completions-bash" function that you have to source. I can't live without zsh's "*(c-1)" though.
fish is a fine baseline but I want better shell scripting (murex, xonsh) and manipulation abilities (nushell). For the software world, shells are evolving unusually slowly.
Back in ye old days, TAB autocompletion was a big deal when it was new. It was then a big deal when it got a bit fancier in zsh. And it's stagnated since.
Now, with fzf in combination with other tools, I often ask myself: Why isn't this the default in most shells? When I now use bash, it seems very archaic.
Yes, there are a lot of improvements one can do with shells. I should start making a wishlist.
I cannot agree more! Fish shell is the absolute best! I think I may have switched over to it in 2017 _because_ of Julia's blog. And it has been a boon for my productivity.
I set up a whole dotfiles tracking system and periodically keep making backups of the config. Fish has been sole system that has travelled with me to different machines, different companies, running on Macs, running on Linux, running on personal laptops, iMacs, and so so many different versions/instances of workstations on the server in docker, in aws etc etc.
I worked at Amazon in 2017 and we had a whole "developer environment" system built off of Apollo and my Fish config fit right in with the company-defaults for various build systems, log systems, metrics yada yada. I wrote myself a ton of nice aliases, new functions, new scripts.
I moved to Apple in 2019 and brought my Fish config over (sans any Amazon-specific things of course) and all my customizations have ported over nicely. They play well with all the Apple-y unique configs this company now gives its engineers.
Fish has been snappy & delightful.
I guess one could argue zsh could work just as well and has the benefit of being compatible with native bash syntax. But I found zsh and its ilk (oh my zsh) too slow tbh. They're nothing --and I mean zilch, nada-- compared to the speed of Fish. Fish w/ Bass (love the puns in the fish community, btw) accomplishes much of the backward compatibility needs with bash or bash-like syntax; while still performing at the snappy speeds of Fish.
Love Fish! Love Julia's notes! Ahh life is just perfect sometimes!
While we're fanboying over Julia, here's a picture of the time I made myself a t-shirt from Julia's zines of Recurse Center's values: https://x.com/b0rk/status/876571293491109889
If you like this sort of thing, I strongly recommend also checking out the xonsh shell.
It's bash-like, but Python based. Works on both Windows and Linux. Has several of the benefits mentioned in this article. It's really nice that I don't need to learn another language for shell scripting - its language is Python, with some extensions to make it less tedious (e.g. easily executing commands without using os.system or subprocess).
I was just reading the first blog after installing and configuring fish. I wanted to see if she or anyone in my blogroll has any tricks I don’t know about.
Starting up with fish is very easy. You can install it on any new machine and just get on right way. The defaults are very well thought out.
Paste multiple lines in zsh they won’t be executed either (nor in modern bash if I’m not mistaken). I’m not sold by the rest; most of what I read is easily achieved with zsh (or even bash!).
While most of it is _possible_ with zsh and bash, actually achieving it all with either of those tends to require a ton of custom scripts, config, and plugins which then all need maintenance. As someone else in the comments here mentioned, all that extra config and customisation is technical debt. Fish gives you all of that for free and you never need to touch it. Outside of env vars and aliases, my entire config.fish is about 30 lines.
Until you have a default you don’t like and have to dig to find how to change it. Maybe fish’s defaults are saner than zsh’s (and even more than bash’s), but honestly I don’t think it changes much in the end.
For instance, writing my own prompt was what forever won me over from zsh. Basically, you edit a file named `~/.config/fish/functions/fish_prompt.fish`. That's where autoload functions live. If you type `foo` at the command line and it doesn't already exist, fish will look for a file named `foo.fish` in that directory, load it, and run the `foo` function defined there.
So in your editor, follow that pattern to write a function named `fish_prompt`. Put the commands in there that write your prompt to stdout. Make it as simple or complex as you want.
There. Done. That's all you have to do. Compare these:
Official fish docs: https://fishshell.com/docs/current/prompt.html
Official zsh docs: https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.htm
Anyway, that was emblematic of my whole experience with fish. It took a lot of un-learning special magic to settle in. It just feels so much more cohesive and consistent than any other shell I've tried. And because of that, I'm way quicker to add little scripts or completions to it that make it even more pleasant for me. I'd say the activation energy for that is far lower than with other shells I've used.
For context, I maintained the FreeBSD "bash-completion" port from 2003 to 2008 or so. It's not that I love fish because I don't know the alternatives. I love it because I do.