Install fish

# Debian / Ubuntu
sudo apt install fish

# Arch
sudo pacman -S fish

# Fedora
sudo dnf install fish

# macOS
brew install fish

# Make it the default shell for your user
chsh -s "$(which fish)"

# (Log out and back in)

Install starship

# Universal installer
curl -sS https://starship.rs/install.sh | sh

# Or via mise / cargo / package manager
mise use -g starship@latest
brew install starship
sudo pacman -S starship
sudo apt install starship   # Debian 13+ has it in main

Add to fish:

# In fish: ~/.config/fish/config.fish
starship init fish | source

Open a new fish session — the new prompt appears.

What fish gives you out of the box

  • Auto-suggestions — while typing, fish shows the rest of the most-recent matching command in gray. Right-arrow accepts it.
  • Syntax highlighting — valid commands are green, invalid are red, paths that exist are underlined.
  • Tab completions — built from parsed man pages plus per-program completion files. git checkout <tab> shows branches; kubectl logs <tab> shows pods.
  • Abbreviations — like aliases, but expand inline when you press space, so you see what's actually running:
    abbr -a g 'git'
    abbr -a gst 'git status'
    abbr -a k 'kubectl'
    Type g then space; the prompt shows git. Type gst then space; the prompt shows git status. No more "wait, what does gpush alias to?"
  • Per-directory historyhistory can be searched by directory: history --contains foo.

What fish doesn't have

fish is intentionally not POSIX. foo && bar is foo; and bar in fish; export FOO=bar is set -x FOO bar. Most everyday scripts unchanged from bash won't run in fish without translation. Two ways to handle this:

  1. Run bash scripts as bash. Anything with a #!/bin/bash shebang executes in bash regardless of your interactive shell. Same goes for bash script.sh — fish is only your interactive shell.
  2. For deployment / CI / cron scripts, write them in POSIX sh or bash; never in fish syntax. Treat fish as your interactive shell, not your scripting language.

starship config

~/.config/starship.toml — defaults are sensible. Common tweaks:

# Don't show every cwd component — only the last two
[directory]
truncation_length = 2
truncate_to_repo = false

# Per-line layout
format = """
$username\
$hostname\
$directory\
$git_branch$git_status\
$kubernetes\
$aws\
$nodejs$python$rust$golang\
$cmd_duration\
$line_break\
$character"""

# Kubernetes context indicator (off by default for safety)
[kubernetes]
disabled = false
format = '[\($cluster:$namespace\)](bold cyan) '

# Show command duration only for commands >500ms
[cmd_duration]
min_time = 500

# Better Git branch indicator
[git_branch]
symbol = " "
format = '[$symbol$branch]($style) '

# Custom user@host only when on SSH
[username]
show_always = false
format = '[$user]($style)@'
[hostname]
ssh_only = true

The full reference: starship.rs/config. The defaults are good enough; tweaking is optional.

fish abbreviations worth setting

# ~/.config/fish/conf.d/abbreviations.fish

# Git
abbr -a g    git
abbr -a gst  'git status'
abbr -a gco  'git checkout'
abbr -a gcb  'git checkout -b'
abbr -a gp   'git push'
abbr -a gpf  'git push --force-with-lease'
abbr -a gl   'git log --oneline --graph --decorate'

# Kubernetes
abbr -a k     kubectl
abbr -a kg    'kubectl get'
abbr -a kgp   'kubectl get pods'
abbr -a kgs   'kubectl get services'
abbr -a kgd   'kubectl get deployments'
abbr -a kdp   'kubectl describe pod'
abbr -a kl    'kubectl logs'
abbr -a klf   'kubectl logs -f'

# Modern unix
abbr -a ls    eza
abbr -a ll    'eza -lah --git'
abbr -a cat   'bat -p'

Integrate with zoxide + fzf

If you've installed zoxide and fzf (from the modern Unix CLI tutorial):

# ~/.config/fish/config.fish
zoxide init fish | source

# fzf key-bindings (Ctrl-R history, Ctrl-T file picker, Alt-C cd picker)
fzf --fish | source

Now z proj jumps to your most-frecent matching directory; Ctrl-R opens fzf-powered history search.

If you're staying with zsh / bash

starship works identically there:

# bash: ~/.bashrc
eval "$(starship init bash)"

# zsh: ~/.zshrc
eval "$(starship init zsh)"

For zsh, the canonical companion config is oh-my-zsh or prezto; pick one for plugin management and theme defaults, then add starship as the prompt. zsh's auto-suggestions plugin (zsh-autosuggestions) gives the fish-style ghost text in zsh.

Why not zsh + Oh My Zsh + Powerlevel10k?

Powerlevel10k is fast and beautiful but a sizable framework with its own DSL. fish + starship gets you the same visible benefits with less moving config and a shell whose interactive ergonomics are noticeably better. For someone whose muscle memory is deeply zsh-shaped, the switch isn't necessary; for someone starting fresh, fish + starship is the smaller, faster path.

What requires a Nerd Font

The shell-prompt icons (Git branch, language symbols, lock for SSH, etc.) come from a Nerd Font — a regular font patched with developer-friendly glyphs. Install one (nerdfonts.com); set the terminal emulator's font to it. Without a Nerd Font, you see ? boxes where icons should be.

Recommended choices: JetBrains Mono Nerd Font, Hack Nerd Font, Fira Code Nerd Font (with ligatures), Berkeley Mono Nerd Font.