FISH-PROMPT-TUTORIAL(1) fish-shell FISH-PROMPT-TUTORIAL(1)

**Warning:**

This document uses formatting to show what a prompt would look like. If you are viewing this in the man page, you probably want to switch to looking at 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 &lt;&gt; command, and many users have shared their prompts online.

However, you can also write your own, or adjust an existing prompt. This is a good way to get used to fish's scripting language &lt;&gt;.

Unlike other shells, fish's prompt is built by running a function - fish\_prompt &lt;&gt;. Or, more specifically, three functions:

- fish\_prompt &lt;&gt;, which is the main prompt function
- fish\_right\_prompt &lt;&gt;, which is shown on the right side of the terminal.
- fish\_mode\_prompt &lt;&gt;, which is shown if vi mode &lt;#vi-mode&gt; is used.

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

If the **SHELL\_PROMPT\_PREFIX** &lt;#envvar-SHELL\_PROMPT\_PREFIX&gt; or **SHELL\_PROMPT\_SUFFIX** &lt;#envvar-SHELL\_PROMPT\_SUFFIX&gt; environment variables are set, they are automatically prepended and appended to the left prompt.

Here, we will just be writing a simple fish\_prompt.

# [OUR FIRST PROMPT](#OUR_FIRST_PROMPT)

Let's look at a very simple example:

```
function fish_prompt


    echo $PWD '>'
end
```

This prints the current working directory (**PWD** &lt;#envvar-PWD&gt;) and a **&gt;** symbol to show where the prompt ends. The **&gt;** is quoted &lt;#quotes&gt; because otherwise it would signify a redirection &lt;#redirects&gt;.

Because we've used echo &lt;&gt;, it adds spaces between the two so it ends up looking like (assuming **\_** is your cursor):

```
/home/tutorial >_
```

# [FORMATTING](#FORMATTING)

**echo** adds spaces between its arguments. If you don't want those, you can use string join &lt;&gt; 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 &lt;&gt;.

# [ADDING COLOR](#ADDING_COLOR)

This prompt is functional, but a bit boring. We could add some color.

Fortunately, fish offers the set\_color &lt;&gt; 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](#SHORTENING_THE_WORKING_DIRECTORY)

This is fine, but our **PWD** &lt;#envvar-PWD&gt; can be a bit long, and we are typically only interested in the last few directories. We can shorten this with the prompt\_pwd &lt;&gt; 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>_
```

# [STATUS](#STATUS)

One important bit of information that every command returns is the status &lt;#variables-status&gt;. 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 &lt;&gt;) changes the status, you need to store it for later use as the first thing in your prompt. Use a local variable &lt;#variables-scope&gt; 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](#TRANSIENT_PROMPT)

To enable transient prompt functionality, set the **fish\_transient\_prompt** &lt;#envvar-fish\_transient\_prompt&gt; 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]>_
```

# [SAVE THE PROMPT](#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 &lt;&gt;) 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 &lt;&gt;).

# [WHERE TO GO FROM HERE?](#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:**](#fish)

- **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)

<!--THE END-->

- You can add a right prompt by changing fish\_right\_prompt &lt;&gt; or a vi mode prompt by changing fish\_mode\_prompt &lt;&gt;.

[**Some prompts have interesting or advanced features**](#Some)

- 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 &lt;&gt;, 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](#Author)

fish-shell developers

# [Copyright](#Copyright)

fish-shell developers

October 26, 2026 4.9

---

Document: fish-prompt-tutorial(1) from fish 4.9.3-r4 (Chainguard OS)
Source: https://github.com/fish-shell/fish-shell
