FISH-PROMPT-TUTORIAL(1)

🐟✨ FISH-PROMPT-TUTORIAL ✨🐟

okay bestie, welcome to FISH-PROMPT-TUTORIAL(1) from the fish-shell gang πŸ’… this whole page lives in the fish-shell manual and it's literally a glow-up tutorial for your prompt. buckle up πŸŽ€

⚠️ heads up! this document uses formatting to show what a prompt would look like. if you're reading this in the man page, you probs wanna switch to the html version instead β€” run help custom-prompt to view it in a web browser 🌈

fish ships a number of prompts that you can view with the fish_config command, and many users have shared their prompts online 🫢

but like β€” you can also write your own, or adjust an existing prompt. it's genuinely a great way to get comfy with fish's scripting language ✨

unlike other shells, fish's prompt is built by running a function β€” fish_prompt. or, more specifically, three functions:

  • fish_prompt, which is the main prompt function πŸ‘‘
  • fish_right_prompt, which is shown on the right side of the terminal πŸ¦‹
  • fish_mode_prompt, which is shown if vi mode is used 🧚

these functions are run, and whatever they print is displayed as the prompt (minus one trailing newline).

if the SHELL_PROMPT_PREFIX or SHELL_PROMPT_SUFFIX environment variables are set, they are automatically prepended and appended to the left prompt πŸ”₯

here, we will just be writing a simple fish_prompt. periodt πŸ’…


🌸 OUR FIRST PROMPT 🌸

let's look at a very simple example:

function fish_prompt
    echo $PWD '>'
end

this prints the current working directory (PWD) and a > symbol to show where the prompt ends. the > is quoted because otherwise it would signify a redirection 😭

because we've used echo, it adds spaces between the two so it ends up looking like (assuming _ is your cursor):

/home/tutorial >_

πŸŽ€ FORMATTING πŸŽ€

echo adds spaces between its arguments. if you don't want those, you can use string join like this:

function fish_prompt
    string join '' -- $PWD '>'
end

the -- indicates to string that no options can come after it, in case we extend this with something that can start with a - πŸ’‘

there are other ways to remove the space, including echo -s and printf 🫢


🌈 ADDING COLOR 🌈

this prompt is functional, but a bit boring ngl. we could add some color ✨

fortunately, fish offers the set_color command, so you can do:

echo (set_color red)foo

set_color can also handle RGB colors like set_color 23b455, and other formatting options including bold and italics πŸ‘‘

so, taking our previous prompt and adding some color:

function fish_prompt
    string join '' -- (set_color green) $PWD (set_color --reset) '>'
end

--reset tells the terminal to go back to its default formatting options πŸ’œ

set_color works by producing an escape sequence, which is a special piece of text that terminals interpret as instructions β€” for example, to change color. so set_color red produces the same effect as:

echo \e\[31m

although you can write your own escape sequences by hand, it's much easier to use set_color 🧚


πŸ¦‹ SHORTENING THE WORKING DIRECTORY πŸ¦‹

this is fine, but our PWD can be a bit long, and we are typically only interested in the last few directories. we can shorten this with the prompt_pwd helper that will give us a shortened working directory:

function fish_prompt
    string join '' -- (set_color green) (prompt_pwd) (set_color --reset) '>'
end

prompt_pwd takes options to control how much to shorten. for instance, if we want to display the last two directories, we'd use prompt_pwd --full-length-dirs 2:

function fish_prompt
    string join '' -- (set_color green) (prompt_pwd --full-length-dirs 2) (set_color --reset) '>'
end

with a current directory of "/home/tutorial/Music/Lena Raine/Oneknowing", this would print

~/M/Lena Raine/Oneknowing>_

slay πŸ“


πŸ’… STATUS πŸ’…

one important bit of information that every command returns is the status. this is a whole number from 0 to 255, and usually it is used as an error code β€” 0 if the command returned successfully, or a number from 1 to 255 if not.

it's useful to display this in your prompt, but showing it when it's 0 seems kind of wasteful πŸ™ˆ

first of all, since every command (except for set) changes the status, you need to store it for later use as the first thing in your prompt. use a local variable so it will be confined to your prompt function:

set -l last_status $status

and after that, you can set a string if it is not zero:

# Prompt status only if it's not 0
set -l stat
if test $last_status -ne 0
    set stat (set_color red)"[$last_status]"(set_color --reset)
end

and to print it, we add it to our string join:

string join '' -- (set_color green) (prompt_pwd) (set_color --reset) $stat '>'

if $last_status was 0, $stat is empty, and so it will simply disappear ✨

so our entire prompt is now:

function fish_prompt
    set -l last_status $status
    # Prompt status only if it's not 0
    set -l stat
    if test $last_status -ne 0
        set stat (set_color red)"[$last_status]"(set_color --reset)
    end

    string join '' -- (set_color green) (prompt_pwd) (set_color --reset) $stat '>'
end

and it looks like:

~/M/L/Oneknowing>false
~/M/L/Oneknowing[1]>_

after we run false (which returns 1) 😌


🧚 TRANSIENT PROMPT 🧚

to enable transient prompt functionality, set the fish_transient_prompt variable to 1:

set -g fish_transient_prompt 1

with this set, fish re-runs prompt functions with a --final-rendering argument before running a commandline. so you can use it to declutter your old prompts πŸ’– for example if you want to see only the current directory name when you scroll up:

function fish_prompt
    set -l last_status $status
    set -l stat
    set -l pwd
    # Check if it's a transient or final prompt
    if contains -- --final-rendering $argv
        set pwd (path basename $PWD)
    else
        set pwd (prompt_pwd)
        # Prompt status only if it's not 0
        if test $last_status -ne 0
            set stat (set_color red)"[$last_status]"(set_color --reset)
        end
    end

    string join '' -- (set_color green) $pwd (set_color --reset) $stat '>'
end

now running two commands in the same directory could result in this screen:

Oneknowing>false
~/M/L/Oneknowing[1]>_

lowkey obsessed 😭


πŸ‘‘ SAVE THE PROMPT πŸ‘‘

once you are happy with your prompt, you can save it with funcsave fish_prompt (see funcsave β€” save the definition of a function to the user's autoload directory) or write it to ~/.config/fish/functions/fish_prompt.fish yourself ✍️

if you want to edit it again, open that file or use funced fish_prompt (see funced β€” edit a function interactively) πŸ’…


🌟 WHERE TO GO FROM HERE? 🌟

we have now built a simple but working and usable prompt, but of course more can be done πŸ”₯

  • fish offers more helper functions:
    • prompt_login to describe the user/hostname/container or prompt_hostname to describe just the host
    • fish_is_root_user to help with changing the symbol for root
    • fish_vcs_prompt to show version control information (or fish_git_prompt / fish_hg_prompt / fish_svn_prompt to limit it to specific systems)
  • you can add a right prompt by changing fish_right_prompt or a vi mode prompt by changing fish_mode_prompt πŸ¦‹
  • some prompts have interesting or advanced features:
    • add the time when the prompt was printed
    • show various integrations like python's venv
    • color the parts differently

you can look at fish's sample prompts for inspiration ⭐ open up fish_config, find one you like and pick it. for example:

fish_config prompt show # <- shows all the sample prompts
fish_config prompt choose disco # <- this picks the "disco" prompt for this session
funced fish_prompt # <- opens fish_prompt in your editor, and reloads it once the editor exits

Author ✨

fish-shell developers

fish-shell developers


and that's the whole page bestie 🫢 brought to you by version 4.9, dated Sep 08, 2026 β€” go make your prompt iconic, iykyk πŸ’œ

πŸ“¦ where this page comes from
  • arch rolling: fish 4.9.3-1 Β· GPL-2.0-only AND BSD-3-Clause AND ISC AND MIT AND PSF-2.0
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms