Installing Fish on Windows (WSL) — A Complete step by step for Beginners (or not)
{ Versão em Português }
When you finish this Tutorial, you’ll go from this:
To this:
About
Fish is a command interpreter; one of several translators between User and Operating System known as shell, such as: cmd, PowerShell, bash, zsh, etc..
One of the best things of Fish is that the AutoComplete and AutoSuggestion features are factory-installed, ready to use with no need to install or configure.
Click here to learn more about Fish Shell
Since Fish is a shell for Unix, that means, it doesn’t work on standard Windows, so you will need to install Windows Subsystem for Linux (WSL)
IMPORTANT
Before proceeding with this tutorial, create a System Restore Point (C:/) — ALWAYS do that when installing or changing Windows settings.
WSL 2 Prerequisite
To install the latest and best version of WSL (WSL 2), your machine needs to support Hyper-V. In some cases, Windows 11 may have it enabled by default. To check, open the Task Manager.
If it’s disabled, restart your machine and access the BIOS to enable it. The Hyper-V/Virtualization setting is usually found under Advanced or CPU Configuration.
Note: If you don’t have Hyper-V, you can still install WSL version 1.
Installation
Microsoft Documentation
- Install WSL
- Install WSL (manually)
1) Installing WSL (Windows Subsystem for Linux)
Open Command Prompt (cmd) as Administrator and run the command below.
Note: If
wsl --install
returns the HELP Menu, this means you already have wsl installed — go to the next step
Note: If Ctrl + v doesn’t work in the terminal, press the right mouse button to paste.
wsl --install
will execute the following actions:
- Enables the WSL and Virtual Machine Platform components
- Downloads and install the latest Linux Kernel
- Downloads and installs the Ubuntu Linux distribution
After complete installation, Restart your Computer
Note: If the auto installation fails, install manually
2) Configuring Ubuntu
Now that WSL has been installed, click on the Start Menu and open the «app» Ubuntu
Note: If the app doesn’t appear, click here and search for Ubuntu, select the installed version and click Start
Wait for the installation to finish and register a username and password
3) Installing Fish
Fish Documentation
- Official Website
- Official GitHub
- Installing
Open cmd and run the command bash
or wsl
to access your Linux (Ubuntu) environment
Installing the Fish repository
sudo apt-add-repository ppa:fish-shell/release-3
Note: if
apt-add-repository
is a not found command runsudo apt install software-properties-common
Checking and Installing Updates
sudo apt update && sudo apt upgrade
Installing Fish
Sets Fish as default Shell
That’s it, congratulations, you have installed the Fish Shell on your Windows.
Now just run the command fish
in Ubuntu Terminal (bash or wsl) to access your new shell
Configuring Terminal’s Appearance
Now let’s make your terminal look nicer.
1) Installing Windows Terminal
We will no longer use the old standard terminal. Click here and install Windows Terminal
- To make some modifications to Fish, it is necessary to install the plugin manager Oh My Fish
2) Installing Oh My Fish (omf)
Oh My Fish Documentation
- Official GitHub
Open cmd through Windows Terminal and run wsl
, then fish
to access the Fish Shell.
To continue we need Git
Installing omf
curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | fish
3) Installing the Theme
You can preview and choose another theme by clicking here
However, in this tutorial we’ll install and configure the bobthefish theme
4) Configuring bobthefish Theme
Use the command below to enter the fish folder and open it in Windows
cd ~/.config/fish/ && explorer.exe .
Now open the config.fish
file, paste the codes below and then Save the file
if status is-interactive
# Commands to run in interactive sessions can go here
set -g theme_display_git_default_branch yes
set -g theme_title_display_process yes
set -g theme_title_display_path no
set -g theme_title_use_abbreviated_path no
set -g theme_date_format "+%d/%m/%y %H:%M"
set -g theme_display_user yes
set -g theme_display_hostname yes
set -g fish_prompt_pwd_dir_length 6
set -g theme_display_jobs_verbose yes
end
Click here to learn what each command above does
This will be the result
5) Installing Nerd Font
Nerd Fonts Documentation
- Official GitHub
To replace the «errors» [] with Symbols, we need to install a font from Nerd Fonts.
We’ll install SourceCode Pro (SauceCodePro NF). To see more Fonts click Here
You can install all the styles if you want. I usually install just these three:
Regular,
Semibold and
Bold
After downloading, go to your Downloads folder in Windows and run all the .ttf files to install the font.
6) Configuring Windows Terminal
Now we can change the terminal font to fix the []
Click on the little arrow > Settings
Click Open JSON file in the lower-left corner of the screen
- Inside «profiles»>«default» do the changes below, then Save the file:
- Change the name of the «Ubuntu» you installed to Fish (or any other)
- Add the theme (colorScheme) «Campbell»
- Add the guid of Fish to be the default Windows Terminal Profile
If you want your Terminal to be translucent, add the values below inside «defaults»
Note: Transparency effects must be enabled in Windows for this to work: Start Menu > Settings > Personalization > Colors
"defaults": { "opacity": 50, "useAcrylic": true, "font": { "face": "SauceCodePro Nerd Font" } }, "list": [ { "colorScheme": "Campbell", "icon": "https://avatars.githubusercontent.com/u/11728505?s=48&v=4", "guid": "{51855cb2-8cce-5362-8f54-464b92b32386}", "name": "Fish", "hidden": false, "source": "CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc" } ]
Sets Fish as default Shell on Windows Terminal
7) Configuring Symbols (Font)
You can choose between two symbol styles: PowerLine Fonts or Nerd Fonts
set -g theme_powerline_fonts yes
or
set -g theme_nerd_fonts yes
Note: Use
yes
to enable andno
to disable (sets only one as YES)
THE END
Advertisement
fish Shell is Really a Friendly Interactive Shell Which Be Used on GNU/Linux, OS X or UNIX Systems. fish is a user-friendly and Exotic Shell. Previously we have talked about UNIX Shell, Terminal and Terminal Emulators for providing the basic idea. On OS X, we usually use oh-my-zsh with iTerm2 and Homebrew as package manager. That oh-my-zsh can be replaced with fish Shell or at least can be tested for usability.
fish Shell : Basics
Exotic as the syntax are not from Bourne shell or C shell and certain features are enabled by default. Navigate to fishshell dot com on your browser to check the features of this Shell. It is possible to use fish on Windows with Cygwin. For general purpose, we are describing the basic usage of fish shell with OS X fish shell App, it is portable, no installation is needed. This will install fish on OS X (be careful, its not the portable one) :
brew install fish && echo «/usr/local/bin/fish» | sudo tee —a /etc/shells |
For Debian 8.0, we will install in this way :
wget http://download.opensuse.org/repositories/shells:fish:release:2/Debian_8.0/Release.key apt—key add — < Release.key echo ‘deb http://download.opensuse.org/repositories/shells:/fish:/release:/2/Debian_8.0/ /’ >> /etc/apt/sources.list.d/fish.list apt—get update apt—get install fish |
If you change Debian_8.0
to Debian_7.0
for Deb 7.0.
fish Shell : OS X Basic Usage For Testing
If you have downloaded that App for OS X on Desktop and your username is abhishekghosh
, then if you run :
exec ‘/Users/abhishekghosh/Desktop/fish.app/Contents/Resources/base/bin/fish’ |
on iTerm2, instead of oh-my-zsh, you will be using fish shell portable version. It will give you the information to type help
as command and hit the return key. It will open the webpage on default browser instead of normal command line options. It is optimized for GUI. Now, if you type :
You’ll see that you are getting automatic suggestions or incremental search. If you run ls -al
command, you’ll feel that it is very fast. It is POSIX compliant shell, so normal usage like :
set abhishek abhishek—ghosh echo $abhishek |
You’ll get abhishek-ghosh
as return. fish has good syntax highlighting with error checking feature. Other things are written in the official website. We provided the basic idea.
Tagged With fish shell windows , friendly interactive shell , download fish shell windows , fish shell for windows
This page looks best with JavaScript enabled
I have been a Powershell user since it was released in Windows 10. But, I had been switching between Powershell and Linux Bash — just so I can.
Fish changed the world for me.
It is unbelievable that I did not quite know Fish until late of Y2018. One of the positives of seeing a lot of developer videos is learning how other developers work.
In one of those videos, the shell had some crazy colors and auto-completing like nobody’s business. I attributed that to Mac at that time, but some lazy browsing led me to the Fish shell.
And, what a shell that is.
(I totally understand if you are freaked out by my freaking out on a shell. That is so 90’s).
-
I love the autocomplete / auto-suggestions. This is so helpful and you will be left wondering how you could live without one
-
See above * (infinity)
Setup on Windows
If you are a Windows user like me — you may need to do a few things to get Fish working.
In WSL:
sudo apt install fish
Type ‘fish’ to enter Fish shell and try out. If you like what you find, you can replace the default shell by —
$ chsh -s /usr/bin/fish
If you get a “PAM: Authentication failure” with the above command, verify that the correct path exists in ‘/etc/shells’.
$ which fish ' -- find path of install, typically /usr/bin/fish
$ cat /etc/shells ' -- verify whether usr/bin/fish is listed as shell
Your default WSL shell should now be Fish. If you are working on an emulator (like Commander), you should run wsl.exe instead of bash.exe.
I would have said ‘enjoy fishing’ at this time, but will not do that since I am a vegetarian.
WRITTEN BY
Prashanth Krishnamurthy
Technologist | Creator of Things
From Wikipedia, the free encyclopedia
Fish
Version 4.0.0 of fish |
|
Original author(s) | Axel Liljencrantz |
---|---|
Developer(s) | Fish-shell developers[1] |
Initial release | 13 February 2005; 20 years ago |
Stable release |
4.0.2[2] |
Repository |
|
Written in | Rust[3] |
Operating system | Unix-like |
Type | Unix shell |
License | GPL-2.0-only[4] |
Website | fishshell |
Fish (friendly interactive shell; stylized in lowercase) is a Unix-like shell with a focus on interactivity and usability. Fish is designed to be feature-rich by default, rather than highly configurable,[5] and does not adhere to POSIX shell standards by design.[6]
Fish displays incremental suggestions as the user types, based on command history and the current directory. This functions similarly to Bash’s Ctrl+R history search, but is always on, giving the user continuous feedback while typing commands. Fish also includes feature-rich tab completion, with support for expanding file paths (with wildcards and brace expansion), environment variables, and command-specific completions. Command-specific completions, including options with descriptions, can be to some extent generated from the commands’ man pages, but custom completions can also be included with software or written by users of the shell.[7]
The creator of Fish preferred to add new features as commands rather than syntax. This made features more discoverable, as the built-in features allow searching commands with options and help texts. Functions can also include human readable descriptions. A special help command gives access to all the fish documentation in the user’s web browser.[8]
The syntax resembles a POSIX compatible shell (such as Bash), but deviates in many ways[9]
# Variable assignment # # Set the variable 'foo' to the value 'bar'. # Fish doesn't use the = operator, which is inherently whitespace sensitive. # The 'set' command extends to work with arrays, scoping, etc. > set foo bar > echo $foo bar # Command substitution # # Assign the output of the command 'pwd' into the variable 'wd'. # Fish doesn't use backticks (``), which can't be nested and may be confused with single quotes (' '). > set wd (pwd) > set wd $(pwd) # since version 3.4 > echo $wd ~ # Array variables. 'A' becomes an array with 5 values: > set A 3 5 7 9 12 # Array slicing. 'B' becomes the first two elements of 'A': > set B $A[1 2] > echo $B 3 5 # You can index with other arrays and even command # substitution output: > echo $A[(seq 3)] 3 5 7 # Erase the third and fifth elements of 'A' > set --erase A[$B] > echo $A 3 5 9 # for-loop, convert jpegs to pngs > for i in *.jpg convert $i (basename $i .jpg).png end # fish supports multi-line history and editing. # Semicolons work like newlines: > for i in *.jpg; convert $i (basename $i .jpg).png; end # while-loop, read lines /etc/passwd and output the fifth # colon-separated field from the file. This should be # the user description. > while read line set arr (echo $line|tr : \n) echo $arr[5] end < /etc/passwd # String replacement (replacing all i by I) > string replace -a "i" "I" "Wikipedia" WIkIpedIa
No implicit subshell
[edit]
Some language constructs, like pipelines, functions and loops, have been implemented using so called subshells in other shell languages. Subshells are child programs that run a few commands in order to perform a task, then exit back to the parent shell. This implementation detail typically has the side effect that any state changes made in the subshell, such as variable assignments, do not propagate to the main shell. Fish never creates subshells for language features; all builtins happen within the parent shell.
# This will not work in many other shells, since the 'read' builtin # will run in its own subshell. In Bash, the right side of the pipe # can't have any side effects. In ksh, the below command works, but # the left side can't have any side effects. In fish and zsh, both # sides can have side effects. > cat *.txt | read line
Variable assignment example
[edit]
This Bash example doesn’t do what it seems: because the loop body is a subshell, the update to $found
is not persistent.
found='' cat /etc/fstab | while read dev mnt rest; do if test "$mnt" = "/"; then found="$dev" fi done
Workaround:
found='' while read dev mnt rest; do if test "$mnt" = "/"; then found="$dev" fi done < /etc/fstab
Fish example:
set found '' cat /etc/fstab | while read dev mnt rest if test "$mnt" = "/" set found $dev end end
Universal variables
[edit]
Fish has a feature known as universal variables, which allows a user to permanently assign a value to a variable across all the user’s running fish shells. The variable value is remembered across logouts and reboots, and updates are immediately propagated to all running shells.
# This will make emacs the default text editor. The '--universal' (or '-U') tells fish to # make this a universal variable. > set --universal EDITOR emacs # This command will make the current working directory part of the fish # prompt turn blue on all running fish instances. > set --universal fish_color_cwd blue
- Advanced tab completion (with support for writing custom completions).
- Syntax highlighting with extensive error checking.
- Support for the X clipboard.
- Smart terminal handling based on terminfo.
- Searchable command history.
- Web-based configuration (fish_config).
Bash/fish translation table
[edit]
Feature | Bash syntax | fish syntax | Comment |
---|---|---|---|
variable expansion: with word splitting and glob interpretation |
$var or ${var[@]} or ${var[*]} |
deliberately omitted | Identified as a primary cause of bugs in posix compatible shell languages[10] |
variable expansion: scalar |
"$var" |
deliberately omitted | Every variable is an array |
variable expansion: array |
"${var[@]}" |
$var |
Quoting not necessary to suppress word splitting and glob interpretation. Instead, quoting signifies serialization. |
variable expansion: as a space separated string |
"${var[*]}" |
"$var" |
|
edit line in text editor | Ctrl+X,Ctrl+E | Alt+E | Upon invocation, moves line input to a text editor |
evaluate line input | Ctrl+Alt+E | —[11] | Evaluates expressions in-place on the line editor |
history completion | Ctrl+R | implicit | |
history substitution | !! | deliberately omitted | Not discoverable |
explicit subshell |
(expression) |
fish -c expression |
|
command substitution |
"$(expression)" |
|
|
process substitution |
<(expression) |
(expression | psub) |
Command, not syntax |
logical operators |
!cmd && echo FAIL || echo OK |
not command and echo FAIL or echo OK |
|
variable assignment |
var=value |
set var value
|
|
string processing: replace |
"${HOME/alice/bob}" |
string replace alice bob $HOME |
|
string processing: remove prefix or suffix pattern, non-greedily or greedily |
var=a.b.c "${var#*.}" #b.c "${var##*.}" #c "${var%.*}" #a.b "${var%%.*}" #a |
string replace --regex '.*?\.(.*)' '$1' a.b.c #b.c string replace --regex '.*\.(.*)' '$1' a.b.c #c string replace --regex '(.*)\..*' '$1' a.b.c #a.b string replace --regex '(.*?)\..*' '$1' a.b.c #a |
|
export variable |
export var |
set --export var |
Options discoverable via tab completion |
function-local variable |
local var |
by default | |
scope-local variable | no equivalent |
set --local var |
|
remove variable |
unset var |
set --erase var |
|
check if a variable exists |
test -v var |
set --query var |
|
array initialization |
var=( a b c ) |
set var a b c
|
Every variable is an array |
array iteration |
for i in "${var[@]}"; do echo "$i" done |
for i in $var echo $i end |
|
argument vector: all arguments |
"$@" |
$argv |
|
argument vector: indexing |
"$1" |
$argv[1] |
|
argument vector: length |
$# |
(count $argv) |
|
argument vector: shift |
shift
|
set --erase argv[1] |
|
array representation in environment variables |
PATH="$PATH:$HOME/.local/bin" |
set PATH $PATH $HOME/.local/bin |
fish assumes colon as array delimiter for translating variables to and from the environment. This aligns with many array-like environment variables, like $PATH and $LS_COLORS. |
export and run |
LANG=C.UTF-8 python3 |
env LANG=C.UTF-8 python3 |
env LANG=C.UTF-8 python3 works in any shell, as env is a standalone program.
|
arithmetic |
$((10/3)) |
math '10/3' |
expr 10 / 3 works in any shell, as expr is a standalone program.
|
escape sequence |
$'\e'
|
\e |
printf '\e' works in both shells; their printf builtins are both compatible with the GNU printf standalone program.[12]
|
single quoted string: escape sequences |
'mom'\''s final backslash: \' |
'mom\'s final backslash: \\' |
Bash only requires replacement of the single quote itself in single quoted strings, but the replacement is 4 characters long. The same replacement works in fish, but fish supports a regular escape sequence for this, thus requires escaping backslashes too (except permits single backslashes that don’t precede another backslash or single quote). |
- Comparison of command shells
- Unix
- ^ «fish shell team members». GitHub.com. Retrieved 2021-07-28.
- ^ «Release 4.0.2». 20 April 2025. Retrieved 24 April 2025.
- ^ «fish-shell 4.0b1, now in Rust». fishshell.com. Retrieved 18 December 2024.
- ^ fishshell.com License for fish
- ^ Liljencrantz, Axel (2005-05-17). «Fish — A user-friendly shell». Linux Weekly News. Retrieved 2010-03-24.
- ^ «Fish docs: design». Retrieved 2021-04-09.
- ^ «Writing your own completions». fish shell. Archived from the original on 2024-08-31.
- ^ Linux.com. CLI Magic: Enhancing the shell with fish. Retrieved 2010-03-24.
- ^ Paul, Ryan (19 December 2005). «An in-depth look at fish: the friendly interactive shell». Ars Technica. Retrieved 10 March 2015.
the Posix syntax has several missing or badly implemented features, including variable scoping, arrays, and functions. For this reason, fish strays from the Posix syntax in several important places.
- ^ «Bash Pitfalls». Retrieved 2016-07-10.
This page shows common errors that Bash programmers make. (…) You will save yourself from many of these pitfalls if you simply always use quotes and never use word splitting for any reason! Word splitting is a broken legacy misfeature inherited from the Bourne shell that’s stuck on by default if you don’t quote expansions. The vast majority of pitfalls are in some way related to unquoted expansions, and the ensuing word splitting and globbing that result.
- ^ «RFC: Add binding to expand/evaluate tokens on commandline». GitHub. 2013-05-16. Retrieved 2021-04-09.
- ^ «printf does not support \e». fish issues. 11 Jul 2013. Retrieved 24 March 2016.
- Official website – containing documentation and downloads
- fish on GitHub (active)
- fish on Gitorious (obsolete)
- fish on SourceForge (obsolete)
- Fish-users – general discussion list for fish users
- Shell Translation Dictionary — another Bash/Fish translation table
Let’s talk about why fish. Why not use zsh?
- Smart and user-friendly
-
powerful features such as syntax highlighting, autosuggestions, and tab
completions that simply work out of the box. - No need to learn works without configuration (beginner-friendly).
First, we need to install fish using the command:
# This will install fish and its dependencies.
sudo apt install fish
Now we need to set fish-shell as our default shell.
copy this command at the end of the line.
# This will tell us the path of fish binary
# Copy it in the clipboard
which fish
# Use command sudo chsh -s <paste path of fish shell> <your username>
# Just like:
sudo chsh -s /usr/bin/fish username
Note: Restart your terminal and see if it works.
Now we have fish as our default shell.
I previously stated that configuration is optional. Nonetheless, I will show
you how to configure it so that we have a less-boring shell.
How to inherit the system-wide environment variables on startup, from
bash?
Using the package bass we can solve just that.
First, we need to install a plugin manager in Fish called Fisher from
git.io/fisher.
# This will install fisher plugin manager for us.
curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher
After installing we can now:
# this will update fisher as well as the plugins installed.
fisher update
Next, we will install bass from
https://github.com/edc/bass. To do
this we just use Fisher like this:
fisher install edc/bass
To use bass we can configure fish like so:
🖊️ Copy the command in .config/fish/config.fish
# Inherit system-wide environment variables.
bass source /etc/profile
That completes the configuration.
Other notable plugins we can use:
# Autopair brackets & qoutes.
fisher install jorgebucaran/autopair.fish
# Jump to folder easily.
fisher install jethrokuan/z
How to style fish using the starship cross-shell prompt?
Finally, we have come to the last part of this tutorial.
Have you noticed how attractive my shell is in comparison to yours? That’s
because I’m using a Starship preset. This will be quick, so follow me again.
To install it we use:
# This will install the latest package in your local bin directory.
curl -sS https://starship.rs/install.sh | sh -s -- --bin-dir ~/.local/bin/
Next, we need to initialize it using our shell.
# Add this to your fish config.
starship init fish | source
Setting up the preset from
starship.rs
# Copy this command and we are good to go.
starship preset pastel-powerline > ~/.config/starship.toml
- Additional plugin for fisher
fisher install jorgebucaran/nvm.fish
👏 Excellent job!
Note: Restart your terminal to make sure all changes take effect.
Don’t forget to follow 🌏 my socials and subscribe to my 💌 newsletter.