Image of the glider from the Game of Life by John Conway
Skip to content

My ZSH Prompt

Lately, I've been plagued with getting my zsh prompt exactly the way I want. I've been using the clint theme bundled with zsh, but it's multiline prompt, and poor color choice started getting to me. So, I figured I'd change it and start with something simple, maybe mimicking bash a little, and slowly building out from there. The result, thus far, I'm pleased with. It's a basic bash-like prompt, showing the username, hostname, current working directory and current history number. What isn't showing, but will if needed, is the returned exit code on failure. Here's a demo of the prompt in action:

aaron@kratos:~ 262 % ls -ld tmp 
drwxrwxr-x 2 aaron root 4096 2008-01-30 13:22 tmp
aaron@kratos:~ 263 % rm -rf tmp
aaron@kratos:~ 264 % ls -ld tmp
ls: tmp: No such file or directory
aaron@kratos:~[2] 265 % echo $?
aaron@kratos:~ 266 %

Nice. Only showing the exit code, when there's a failure, otherwise, keep it hidden. What I currently can't figure out, but will, is showing only when I'm behind a screen session. So far, the PS1 variable is as follows:

aaron@kratos:~ 266 % echo $PS1
%n@%m:%~%(?..[%?]) %h %#
%n - username
%m - hostame up to the first dot
%~ - current working directory
%(?..%?) - testing for failure on exit code
%? - the exit code
%h - history number
%# - % if unprivileged, # if privileged

The tricky part for me, was getting the syntax for testing the exit code. The syntax is %(x.true-string.false-string), where 'x' is some arbitrary testing condition, in this case, '?' for exit codes. After the first dot, if the test passes, show true-string, if it fails, show false-string after the second dot. So, in my case, I'm returning an empty string on a returned 0 exit code, and the failed exit code on false (in brackets). Now, to figure that out with screen sessions.

What do you think? If you're a zsh user, I'd be interested in your PS1 variable.

{ 15 } Comments

  1. Thom May | January 31, 2008 at 8:02 am | Permalink

    if [[ -n $SSH_CLIENT || -n $REMOTEHOST ]] then
    PS1=': ${CHROOT}%T %(5~|.../%2c|%~) %# '
    PS1=': ${CHROOT}%T %(5~|.../%2c|%~) %# '

  2. Tuxero | January 31, 2008 at 8:17 am | Permalink

    What is ZSH?
    This is the first time I hear about it.
    Cheers mate!

  3. Smarter | January 31, 2008 at 9:12 am | Permalink

    [smarter@fenny ~/Builds/revu/extremetuxracer]% echo $PS1
    %{$reset_color$bold_color$fg[green]%}[%{$reset_color$reset_color$fg[green]%}%n%{$reset_color$bold_color$fg[green]%}@%{$reset_color$reset_color$fg[green]%}%m%{$reset_color$bold_color$fg[green]%} %{$reset_color$reset_color$fg[cyan]%}%~%{$reset_color$bold_color$fg[green]%}]%{$reset_color$reset_color$fg[green]%}%# %{$reset_color$reset_color%}
    Clean and green (:

  4. eddie | January 31, 2008 at 10:07 am | Permalink

    What is ZSH?

    cool dude. We are heading to a momentum when everybody can handle xorg.conf or grub but doesn't know what bash is.

    computer illiterates ftw!

    PS: copying your $PS1 to my ~/.bashrc at light speed

  5. Scott Robertson | January 31, 2008 at 11:45 am | Permalink


    name@host:(last element of pwd)$
    At far right is the exit code if not 0.
    Colors make it a bit hard to read.

  6. Seth | January 31, 2008 at 12:33 pm | Permalink

    I can respect that you don't like multi-line prompts (sometimes they can really get in the way, or make the terminal look *super* busy (the clint theme is three (!) lines)). In spite of that, here's a quick note about the bad default colors:

    prompt clint blue cyan white yellow white
    prompt -h clint

    Regardless, nice writeup of a simple and elegant prompt.

  7. Glenn | January 31, 2008 at 2:51 pm | Permalink

    My PS1 prompt is pretty basic:
    PS1=%B%m%b >

    but what I really like is the right justified prompt which is where I display the current directory...


  8. Hobbsee | February 1, 2008 at 2:50 am | Permalink

    Thanks thom! I'd been wondering about a different remote prompt! Mine now is:

    if test `whoami` != "root"
    PS1="${fg_light_cyan}%B%n@%m:${fg_light_blue}%~${fg_light_gray}%#%b "
    PS1="${fg_red}%B%n@%m:${fg_red}%~${fg_light_gray}%#%b "

  9. Anonymous bin Ich | April 4, 2008 at 10:02 am | Permalink


    PROMPT=$'%(?..%{\e[41;38m%}%B-%?-%b%{\e[0m%} )%(1j.%{\e[01;33m%}[%j] .)%{\e[01;32m%}%m%{\e[0m%} %{\e[01;36m%}%2~%{\e[0m%} %B%#%b '
    RPROMPT=$'%{\e[00;07m%}%(?..$exitstuff)% %{\e[0m%} %T'

    # Taken and modified from "atom's .zshrc" public release v0.109 -
    precmd () {
    local exitstatus="${?}"
    if [[ ${exitstatus} -ge 128 && $exitstatus -le (127+${#signals}) ]]; then
    # Last process was killed by a signal. Find out what it was from
    # the $signals environment variable.
    unset exitstuff

    The function here tells you the name of the interrupt, which I like 🙂
    Also, RPROMPT tells the time in reverse video, so no problem while testing different themes etc. Although I am planning to switch it to the left so that copy-pasting can become easier 🙂

  10. mjg | May 30, 2008 at 1:51 pm | Permalink

    this is in my .zshrc:

    local smiley="%(?,%{$fg[green]%}:%)%{$reset_color%},%{$fg[red]%}:(%{$reset_color%})"

    looks like this:

    [user@host][:)] % cd sh
    [user@host][:)] % ls foo
    ls: cannot access foo: No such file or directory
    [user@host][:(] %

    It will show a green smiley if the last command finished successfully, or a red frowney if it did not.

  11. Redd Vinylene | December 7, 2008 at 4:13 am | Permalink

    Hello Aaron! What you think of this?


    if [[ `whoami` = root ]] then








    PROMPT+="$a2(%~) %{$reset_color%}"


    Do let me know!

  12. James | January 6, 2009 at 5:42 pm | Permalink

    # Git branch
    function __prompt_git() {
    local git_dir ref br top;
    git_dir=$(git rev-parse --git-dir 2> /dev/null) || return
    ref=$(git symbolic-ref HEAD 2> /dev/null) || return
    top=$(cat $git_dir/patches/$br/current 2>/dev/null) && top="/$top"
    echo "($br$top)"

    # Colour stuff
    autoload colors zsh/terminfo
    if [[ "$terminfo[colors]" -ge 8 ]]; then
    eval PR_$color='%{$terminfo[bold]$fg[${(L)color}]%}'
    eval PR_LIGHT_$color='%{$fg[${(L)color}]%}'
    (( count = $count + 1 ))

    # Environment variables

    Lovely little prompt. Looks kinda like…

    osx:~ james$ (master) 00:38 !61

    …but with lots of pretty colours! 😮

    I'm mainly posting because I want a Mac with Safari on the comment list!

  13. Erus_Iluvatar | January 8, 2010 at 10:37 am | Permalink

    PS1="%(!.#.$) "

    Simple and powerfull.

  14. Brianskywalker | April 13, 2010 at 12:47 am | Permalink

    > cd /usr/share/doc/zsh/

    local pscolor="%B%(?,%F{green},%F{red})"
    PS1="${pscolor}> %f%b"
    PS2="${pscolor}> %f%b"
    RPROMPT="(%!%) %T"

    A very simple ascii art fish, used as a ps1. The eye is actually the pwd, and the fish turns red when the last command returns an error. I also have a right-aligned prompt with the history event number and time.

    This is somewhat novel but very useful.

  15. Aaron | April 13, 2010 at 7:54 am | Permalink

    @Brianskywalker I can't reproduce your prompt. I just get a series of double quotes. On the other hand, I like adding an ASCII fish to the prompt. I need more of a playful prompt.

{ 1 } Trackback

  1. My ZSH Prompt | January 31, 2008 at 9:22 am | Permalink

    [...] unknown wrote an interesting post today onHere’s a quick excerptaaron@kratos:~ 262 % ls -ld tmp drwxrwxr-x 2 aaron root 4096 2008-01-30 13:22 tmp aaron@kratos:~ 263 % rm -rf tmp aaron@kratos:~ 264 % ls -ld tmp ls: tmp: No such file or directory aaron@kratos:~[2] 265 % echo $? 2 aaron@kratos:~ 266 % … [...]

Post a Comment

Your email is never published nor shared.