Color Your Shell Prompt Red If the Last Command Threw an Error
We'll cover examples that work with both bash and zsh. We'll go with red for errors and your default color for non-errors.
Quick Jump: Configuring your Prompt | Demo Video
Before we jump into the solution, here’s a brief primer on exit codes because it will be important to know about this when looking at the solution.
A standard Unix pattern is to have commands return a non-zero exit code when they fail or throw an error. For example using exit 1
is very common for errors but you’ll often see other numbers too for specific types of errors. When a command is successful it’ll exit 0
.
Your shell allows you to reference $?
which stores the exit code of the last run command. You can run echo $?
to check it out.
Here’s a few examples:
# The whoami command returns the name of the user who ran the command.
$ whoami
nick
$ echo "$?"
0
# On my machine abc123 isn't a valid command.
$ abc123
zsh: command not found: abc123
$ echo "$?"
127
In this case it’s pretty clear the abc123
command threw an error because zsh reported the command wasn’t found but other tools don’t always provide error messages.
For example echo hello | grep hi
provides no output but grep failed because no match was found. In this case echo $?
will return 1.
Now with grep it’s pretty clear something went wrong because you have no results but with other commands it’s not always clear, especially if you don’t know how the tool works ahead of time.
Wouldn’t it be nice to visually see that without needing to manually check the exit code?
Yes it would be and we can do that by coloring up your prompt to be red if the last command failed and then use your default color when it’s successful. Typically you’d color up the $
character or whatever character you’ve chosen to break up your prompt’s information with the command you’re running but you can do whatever you want.
Configuring your Prompt
We’ll go over examples for both zsh
and bash
and in both cases it will work out of the box without any additional plugins or extra functions.
In both cases you can experiment by copy / pasting these prompts into your current shell to tweak things to your liking and then when you’re happy you can place them into your .zshrc
or .bashrc
file so they persist.
zsh
setopt PROMPT_SUBST
PROMPT='%B%{$fg[green]%}%n@%{$fg[green]%}%M %{$fg[blue]%}%~%{$fg[yellow]%}%{$reset_color%} %(?.$.%{$fg[red]%}$)%b '
The important part for this post is %(?.$.%{$fg[red]%}$)
which is near the end of the line. There’s a lot going on in this short amount of code.
%(?.YAY.NAY)
is the general pattern for the above where YAY
will run if the last run command was successful and NAY
will run if it failed.
With that said, $
is the YAY
case in our prompt which will output $
using whatever color you set previously (your default color). Then %{$fg[red]%}$
is the NAY
case which does the same thing except uses a red $
.
If you wanted to see the exit code on error you could use %(?.$.%{$fg[red]%}[%?]$)
. It’s doing the same thing as before except now it also includes [%?]
where %?
shows the exit code too. Now on error your prompt will show nick@kitt ~/src/github/dotfiles [127] $
.
bash
We’ll focus only on coloring up the $
. Everything else about the prompt has been replaced with ...
to show your user and path, etc..
PS1="... \$([ \$? == 0 ] && echo '$' || echo '\e[01;31m$') \e[00m"
The overall strategy is the same as zsh except we’re using a shell if condition that fits nicely on one line.
In this case we’re looking at $?
to see if it’s 0. If so then we can output a default color $
, otherwise we make a red $
. We’re using ANSI colors for this since Bash doesn’t have human named color variables out of the box. 01;31m
sets the foreground bright red and 00m
ensures any custom colors get reset back to their default color.
We also need to escape $
in a few spots so that everything in the $()
gets evaluated whenever PS1
is used instead of immediately when your bashrc file is loaded. I saw this trick referenced here https://stackoverflow.com/a/44214096.
The video below goes into a bit more details about everything.
Demo Video
Timestamps
- 1:11 – A quick primer on checking the exit code of the last run command
- 2:12 – Taking a look at the solutions
- 3:40 – zsh solution
- 5:27 – Optionally include the error code number in your prompt
- 7:05 – bash solution
Have you configured your prompt to do this? Let me know below.