Custom zsh Prompts
zsh uses two variables for the prompt - PROMPT and RPROMPT. We can set these ourselves and do some clever stuff. PROMPT is the normal prompt while RPROMPT means 'right prompt' and displays on the right of the command line.
For the examples I give here I use a ~/.prompt file and source it from ~/.zshrc so you will need to add the line:
source $HOME/.prompt
to your .zshrc
DEFINE SOME COLOURS
If we want to colour our prompt then it's useful to define some colour variables. We can set these in ~/.prompt. Note: '^[' is an escape sequence and needs to escaped in your editor. In vim this is usually achieved by Ctrl-v [Esc].
# normal
black="%{^[[0;30m%}"
red="%{^[[0;31m%}"
green="%{^[[0;32m%}"
yellow="%{^[[0;33m%}"
blue="%{^[[0;34m%}"
magenta="%{^[[0;35m%}"
cyan="%{^[[0;36m%}"
white="%{^[[0;37m%}"
# bold (grey is actually bold black)
grey="%{^[[01;30m%}"
bred="%{^[[01;31m%}"
bgreen="%{^[[01;32m%}"
byellow="%{^[[01;33m%}"
bblue="%{^[[01;34m%}"
bmagenta="%{^[[01;35m%}"
bcyan="%{^[[01;36m%}"
bwhite="%{^[[01;37m%}"
# underscore
ublack="%{^[[04;30m%}"
ugrey="%{^[[01;04;30m%}"
ured="%{^[[04;31m%}"
ugreen="%{^[[04;32m%}"
uyellow="%{^[[04;33m%}"
ublue="%{^[[04;34m%}"
umagenta="%{^[[04;35m%}"
ucyan="%{^[[04;36m%}"
uwhite="%{^[[04;37m%}"
# blinking
kgrey="%{^[[01;05;30m%}
kred="%{^[[05;31m%}"
kgreen="%{^[[05;32m%}"
kyellow="%{^[[05;33m%}"
kblue="%{^[[05;34m%}"
kmagenta="%{^[[05;35m%}"
kcyan="%{^[[05;36m%}"
kwhite="%{^[[05;37m%}"
normal="%{^[[0m%}"
# example of background colour
# foreground white = 37
# background red = 41
fgwhitebgred="%{^[[0;37;41m%}"
PROMPT EXPANSION VARIABLES
There are a number of special variables that we can use in our prompt that will expand to username, hostname, date, time etc. Here are a few (there are more and zsh docs will list those):
| %% | A `%'. |
| %) | A `)'. |
| %d %/ | Present working directory ($PWD). If an integer follows the `%', it specifies a number of trailing components of $PWD to show; zero means the whole path. |
| %~ | As %d and %/, but if $PWD has a named directory as its prefix, that part is replaced by a `~' followed by the name of the directory. If it starts with $HOME, that part is replaced by a `~'. |
| %h %! | Current history event number. |
| %L | The current value of $SHLVL. |
| %M | The full machine hostname. |
| %m | The hostname up to the first `.'. An integer may follow the `%' to specify how many components of the hostname are desired. |
| %t %@ | Current time of day, in 12-hour, am/pm format. |
| %T | Current time of day, in 24-hour format. |
| %* | Current time of day in 24-hour format, with seconds. |
| %n | $USERNAME. |
| %N | The name of the script, sourced file, or shell function that zsh is currently executing, whichever was started most recently. If there is none, this is equivalent to the parameter $0. An integer may follow the `%' to specify a number of trailing path components to show; zero means the full path. |
| %i | The line number currently being executed in the script, sourced file, or shell function given by %N. This is most useful for debugging as part of $PS4. |
| %w | The date in day-dd format. |
| %W | The date in mm/dd/yy format. |
| %D | The date in yy-mm-dd format. |
| %D{string} | string is formatted using the strftime function. See man page strftime(3) for more details. Three additional codes are available: %f prints the day of the month, like %e but without any preceding space if the day is a single digit, and %K/%L correspond to %k/%l for the hour of the day (24/12 hour clock) in the same way. |
| %l | The line (tty) the user is logged in on. |
| %? | The return code of the last command executed just before the prompt. |
| %_ | The status of the parser, i.e. the shell constructs (like `if' and `for') that have been started on the command line. If given an integer number that many strings will be printed; zero or no integer means print as many as there are. This is most useful in prompts PS2 for continuation lines and PS4 for debugging with the XTRACE option; in the latter case it will also work non-interactively. |
| %E | Clears to end of line. |
| %# | A `#' if the shell is running with privileges, a `%' if not. Equivalent to `%(!.#.%%)'. The definition of `privileged', for these purposes, is that either the effective user ID is zero, or, if POSIX.1e capabilities are supported, that at least one capability is raised in either the Effective or Inheritable capability vectors. |
So with a few of these we can do some interesting things.
An Example
Here is my current prompt: (shrunken)
![]()
This is achieved by creating a function in ~/.prompt and then calling it from ~/.zshrc:
white_time_left_prompt() {
C1=$white
C2=$bwhite
C3=$grey
PROMPT="${C1}[$C3%D{%H:%M:%S}$C1] $C1($C2%n$C1@$C2%m$C1)%#$normal "
RPROMPT="$C1($C2%~$C1)$normal"
}
(I use C1 etc. so that it is easier to copy the function and change the colours, but you could just as well put the colour strings directly in there.)
In ~/.zshrc I have:
source $HOME/.prompt
white_time_left_prompt
Conclusion
Well this is a short intro to zsh prompting and it only needs a little experimenting to find a nice one. Here is my ~/.prompt file with colours and some prompt functions set. Because of the escape codes you will need to save this file and rename it. Copy-pasting will not work:


