This is fish shell, the shell for the future, the shell to match your modern home terminal’s needs and requirements.
I taught myself to use fish a while ago, and now, I’m going to write a tutorial about it, and here are some of its quirks and features.
Fish is a shell, like bash, but different. Some of the selling points include, but are not limited to:
$ brew install fish
See where your fish is installed:
$ which fish /usr/local/bin/fish
Now append that to your shells file to make it available:
$ echo "/usr/local/bin/fish" >> /etc/shells
Now you can just do:
And you’re using fish. Go back to bash if you like:
Check your fish version:
$ fish --version fish, version 3.1.0
Check if there’s a new version:
$ brew update $ brew outdated
brew update will update the homebrew package registry, and
brew outdated will list out-of-date homebrew packages.
Then just upgrade fish:
$ brew upgrade fish
Reload your terminal window and confirm the version:
$ fish --version fish, version 3.1.2
You probably want to make it the default shell, issue the "change shell" command:
$ chsh -s /usr/local/bin/fish
Now restart or refresh your terminal and it should load to Fish.
But, if you still see your old bash and you’re using iTerm2, you might have defined the shell in the iTerm2 settings (like I had), just change the setting to "Login shell":
$ chsh -s /usr/local/bin/fishagain.
Now iTerm should pick up fish when it restarts.
That will open a web-based GUI where you can select a color theme and configure the look of the shell. When you’re done, come back to the shell and hit enter to exit the config mode.
An important directory for all fish users is
~/.config/fish. All the config lives down there.
~/.config/fish/config.fish is equivalent to to
From there you can export your environmental variables, for example. fish has the
--export flag that you can use:
# config.fish set --export AUTH_TOKEN blahBlah
The bash way of exporting variables seems to work, too:
Fisher makes it easy to install utilities. All you need to do is to add it to your functions directory:
$ curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
Syntax for adding packages with fisher:
┌── GitHub path to the repo ┌─────┴────┐ fisher add jethrokuan/z
That would install
z from github.com/jethrokuan/z.
Listing installed packages:
$ fisher ls
When you install packages, fisher writes them into
~/.config/fish/fishfile. You can then subject this file to version control so you can keep your fish packages in sync between machines.
Fish is not POSIX compatible, so bash doesn’t work out of the box. But you can always do:
That opens a bash shell, then
$ exit to get back.
But if you pass it the
-c option, bash will read from a string and you can stay in the current shell:
$ bash -c someBashCommand
man bash for more.
In fish, you can of course run scripts written in any language you imagine if the shebang is correct (
#!/bin/bash). But some scripts modify the shell environment, and need to be sourced. This is what fish can’t do, but bass was designed to do just that. It’s a simple python wrapper that calls scripts in bash and passes in and out the needed environmental variables.
Install it with fisher:
$ fisher add edc/bass
For example, you can make nvm (Node Version Manager) work in fish:
function nvm bass source (brew --prefix nvm)/nvm.sh ';' nvm $argv end
Add that function to
~/.config/fish/functions and call nvm normally.
This bridges us up to the nvm options in fish.
We all love nvm, but nvm doesn’t work right out the box in fish. But it’s not hard to get it running.
bass, as shown above.
fish-nvm is an nvm written in pure fish, no shenanigans. It has worked great for me. Install it with fisher:
$ fisher add jorgebucaran/fish-nvm
If you just want something easy that works, you can stop reading now.
fast-nvm-fish is a minimal script that aims to make your shell load-up really fast even when you have multiple node version installed. It doesn’t support aliases tho.
Bash has aliases and function. Fish simplifies this by only having functions. They’re stored in
Few simple examples to showcase how the functions work:
# ~/.config/fish/functions/ls.fish function ls command ls --color=auto $argv end
Get the current week number:
# ~/.config/fish/functions/week.fish function week --description "Gets the current week number" date +%V end
Really handy function to nuke all merged git branches:
# ~/.config/fish/functions/git_delete_merged.fish function git_delete_merged --description='Deletes merged branches' git branch --merged | grep -v '\*' | xargs -n 1 git branch -d end
You simply call the function by its name to execute it:
--description flag, it supposed to work so that you can see the description next to the function name when you tab complete. But I just can’t get it working. There used to be a bug rendering it useless, but it’s been fixed in the v3.0 of fish. Nonetheless, it doesn’t work for me.
Fish function to reload shell on Mac:
function reload --description 'Reloads shell (i.e. invoke as a login shell)' exec $SHELL -l end
Here’s some more fish resources:
Comments would go here, but the commenting system isn’t ready yet, sorry. Tweet me @hiljaa if you want to make a correction etc.