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.
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.