Fish Shell Syntax Highlighting Guide

How Fish Shell's built-in syntax highlighting works, how to customize colors for commands, errors, paths, and strings, plus theme management.

Fish Shell Syntax Highlighting Guide

One of the reasons I switched from Zsh to Fish was syntax highlighting. In Zsh, you need the zsh-syntax-highlighting plugin and some configuration to get commands colored as you type. In Fish, it’s built in and works from the first time you open the shell.

Fish highlights your command line in real time. Valid commands appear in one color, invalid commands in red, strings get their own color, file paths that exist are underlined. You catch typos before hitting Enter. No plugins, no setup.

This guide covers how it works and how to customize the colors.

What Fish highlights

Fish colors different parts of the command line based on their meaning:

ElementWhat it looks like (default)Variable
Valid commandsBluefish_color_command
Invalid commandsRedfish_color_error
Parameters/argumentsCyanfish_color_param
Options (flags starting with -)Cyanfish_color_option
Quoted stringsYellowfish_color_quote
Redirections (>, >>, |)Cyanfish_color_redirection
Valid file pathsUnderlinedfish_color_valid_path
Comments (# …)Greyfish_color_comment
Escape sequences (\n, \t)Cyanfish_color_escape
AutosuggestionsGreyfish_color_autosuggestion
Selection (vi visual mode)White on bluefish_color_selection
Search matchesYellow backgroundfish_color_search_match

The most useful part: command validation happens as you type. Type gti instead of git and it immediately turns red. You don’t need to run the command to know something’s wrong.

Customizing colors

Using the web interface

The quickest way:

fish_config

This opens a browser-based tool where you can click on colors and see a live preview. Under the “Colors” tab, you can modify each syntax element individually. When you’re happy, click “Set Theme” and the changes apply immediately.

Using set_color variables

For command-line configuration:

# Make commands green instead of blue
set -U fish_color_command green

# Make errors bold red
set -U fish_color_error red --bold

# Make strings orange
set -U fish_color_quote bryellow

# Make autosuggestions dimmer
set -U fish_color_autosuggestion 555 --dim

# Underline valid paths with a specific color
set -U fish_color_valid_path --underline cyan

Using set -U (universal) saves the setting permanently across all Fish sessions. Using set -g (global) only lasts for the current session.

Available colors

Fish supports named colors and hex codes:

Named colors: black, red, green, yellow, blue, magenta, cyan, white, and their bright versions (brred, brgreen, etc.)

Hex colors: Three or six digit hex codes like f60 or ff6600

Modifiers: --bold, --dim, --italics, --underline, --reverse, --strikethrough

Background: --background=color sets the background color

Examples:

set -U fish_color_command 5fd700           # bright green (hex)
set -U fish_color_error ff0000 --bold      # bold red
set -U fish_color_quote ff8700 --italics   # italic orange
set -U fish_color_comment 6c7086 --dim     # dim grey

Built-in themes

Fish ships with several color themes. List them:

fish_config theme show

Apply one:

fish_config theme choose dracula

Popular built-in themes:

  • default — the standard Fish colors
  • dracula — dark theme with purple/pink tones
  • catppuccin-mocha — pastel dark theme
  • catppuccin-latte — pastel light theme
  • nord — cool blue tones
  • solarized-dark and solarized-light
  • tomorrow and tomorrow-night
  • base16-** — several Base16 variants

Since Fish 4.4, Catppuccin themes are also included.

To save the theme permanently:

fish_config theme choose dracula
fish_config theme save

Applying themes across all sessions

If you have multiple Fish sessions running and want them all to update:

# Add this to config.fish first:
function apply-my-theme --on-variable=my_theme
    fish_config theme choose $my_theme
end

# Then set the universal variable from any session:
set -U my_theme dracula

All running sessions pick up the change automatically.

Custom theme from scratch

If you want full control, set every variable explicitly. Here’s an example minimal dark theme:

# ~/.config/fish/conf.d/my-theme.fish
set -U fish_color_normal normal
set -U fish_color_command 5fd700          # green
set -U fish_color_keyword 5fd700
set -U fish_color_quote ff8700            # orange
set -U fish_color_redirection 87d7ff      # light blue
set -U fish_color_end 87d7ff
set -U fish_color_error ff5f5f --bold     # bold red
set -U fish_color_param 87d7ff
set -U fish_color_option 87d7ff
set -U fish_color_comment 6c7086          # grey
set -U fish_color_selection --background=3a3a5c
set -U fish_color_operator ff87d7         # pink
set -U fish_color_escape ff87d7
set -U fish_color_autosuggestion 555555
set -U fish_color_valid_path --underline
set -U fish_color_cwd 5fd7ff
set -U fish_color_cwd_root red
set -U fish_color_user 87d7ff
set -U fish_color_host normal
set -U fish_color_host_remote ff8700
set -U fish_color_status red
set -U fish_color_cancel -r
set -U fish_color_search_match --background=555555

Pager (completion menu) colors

The tab completion pager has its own set of colors:

set -U fish_pager_color_completion normal           # completion text
set -U fish_pager_color_description grey             # description text
set -U fish_pager_color_prefix cyan --underline      # matched prefix
set -U fish_pager_color_progress white --background=cyan  # progress bar
set -U fish_pager_color_selected_background --background=3a3a5c

These are separate from the command-line syntax colors. The pager colors control what you see when you press Tab and browse completions.

How syntax highlighting differs from Zsh and Bash

Bash has no syntax highlighting at all. What you type is plain text until you run it.

Zsh needs the zsh-syntax-highlighting plugin. It works well once installed, but it’s an external dependency you have to manage. Zsh-syntax-highlighting supports custom highlighter patterns, which Fish doesn’t need because its built-in system covers more ground.

Fish does it natively. The highlighting is part of the shell itself, runs on every keystroke, and validates commands against your PATH in real time. There’s nothing to install and nothing that can fall out of date.

This is one of the core arguments for Fish over Zsh — features like this work out of the box.

Troubleshooting

Colors look wrong — your terminal may not support 256 colors or true color. Check with:

set_color ff8700; echo "This should be orange"; set_color normal

If it’s not orange, your terminal needs a different color mode setting. Most modern terminals (Ghostty, iTerm2, WezTerm, Alacritty) support true color by default.

Colors reset after restart — you’re probably using set -g instead of set -U. Global variables don’t persist. Use universal (-U) for permanent color settings.

Theme not applying to all sessionsfish_config theme save only saves to new sessions. Use the --on-variable pattern described above to update running sessions.