DEV Community

Cover image for Customizing my Zsh Prompt
Cassidy Williams
Cassidy Williams

Posted on

Customizing my Zsh Prompt

I have a little .zshrc file to customize my terminal, and I've always wanted a fun prompt besides the default, but haven't really done much to learn it.

So, after some research, I figured out the basics of how to make my little prompt useful without being too overwhelming or distracting!

Here's what it looks like:

Cassidy's ZSH prompt with the time, directory, and git branch

You might notice that I don't have the typical things like my username or machine name or anything, because... I don't need that personally. But, after reading this, you'll be able to add that yourself!

What to type

If you don't know how to open your configuration file, go ahead and open it with vim ~/.zshrc or code ~/.zshrc (or whatever editor your prefer).

First, add these two lines to your .zshrc:

autoload -Uz vcs_info
precmd() { vcs_info }
Enter fullscreen mode Exit fullscreen mode

This loads the Version Control System into your prompt (here's the documentation for it).

Next, you want to add the next line that sets up the Git branch details into your prompt.

zstyle ':vcs_info:git:*' formats '%b '
Enter fullscreen mode Exit fullscreen mode

That %b is the branch name variable. I added a space after it for formatting reasons. You can add other variables in the string there (here's a good blog of options), for example information about stashes, the name of the root directory of the repo, staged changes, etc.

Now, you'll add these final two lines to put your prompt together!

setopt PROMPT_SUBST
PROMPT='%F{green}%*%f %F{blue}%~%f %F{red}${vcs_info_msg_0_}%f$ '
Enter fullscreen mode Exit fullscreen mode

This is hairy-looking, so let me break it down.

Colors!

When you surround things in %F and %f, that changes the foreground color of anything in between them. The color in the {curly braces} is the color that's edited. In this case, you can see green, blue, and red. There's similar things like this with %U and %u to underline, %K and %k for background colors, and more (with documentation here, scroll to "13.2.5 Visual effects"). ZSH understands the colors black, red, green, yellow, blue, magenta, cyan and white by default!

Dates and times!

The %* that you see is the time (in 24-hour format, with seconds). There's more options for this, like %W for the date, for example. The docs for this is here, scroll to "13.2.4 Date and time".

The directory!

The %~ shows the current working directory, and its path. Look at "13.2.3 Shell state" in the docs if you want to replace it with something else.

The variable!

Now the next part is loading in your variable, the ${vcs_info_msg_0_}. This plops your branch variable that we made before in that red text wrapper, there.

The final $ at the end is just to lead the user input. You can replace it with > or ; or WOW or more variables, or whatever you'd like.

The end!

Here is the whole prompt that you can paste in and customize:

autoload -Uz vcs_info
precmd() { vcs_info }

zstyle ':vcs_info:git:*' formats '%b '

setopt PROMPT_SUBST
PROMPT='%F{green}%*%f %F{blue}%~%f %F{red}${vcs_info_msg_0_}%f$ '
Enter fullscreen mode Exit fullscreen mode

Once you've saved this, run source ~/.zshrc to load it in the terminal (or just restart your terminal/open a new tab). Because I like opening and editing quickly, I added these aliases to make the opening + loading faster:

alias bp='vim ~/.zshrc'
alias sa='source ~/.zshrc;echo "ZSH aliases sourced."'
Enter fullscreen mode Exit fullscreen mode

And now the world's ya oystah. I hope this was helpful for you!

Discussion (29)

Collapse
nikfp profile image
Nik F P

This is a really nice trick! In trying to figure this out I ended up giving up and going with a prompt styler - the script syntax was too dense for me at the time.

If you are interested, you should check out Oh-my-posh, it's been awesome to use. Here's a pic of the prompt I've been using:

A prompt picture

This is my custom prompt that has the current username, which shell I'm using, current directory, Node version in use, and the end with the heart is the exit code status of the last command. (turns red if the exit code is non-zero) The second line is git status and only appears if I'm in a repo.

Setting these up can be tricky though, and the nice thing about what you built is it's easier to sync between machines since it's just a script. Nothing needs to be installed. I think I'll try to do something similar to what you have for shell I use on a few places and see if it comes easier to me this time.

Collapse
nssimeonov profile image
Templar++

It's really awesome. I love this. Except I use a theme based on the paradox theme, but I added a few more sections. Being a front-end dev lately and using different node versions for different projects it's a must to see the current npm version as well... especially if direnv somehow messes up loading the the right version for some reason every now and then)

Collapse
narenandu profile image
Narendra Kumar Vadapalli

I use this one and its pretty great out of the box

Collapse
mrxinu profile image
Steve Klassen (He/Him)

I love that you went through the bare bones configuration. I just assumed 'starship' or something like that when you mentioned it in the newsletter. This was much more cool!

Collapse
cassidoo profile image
Cassidy Williams Author

Thanks!

Collapse
lucassperez profile image
Lucas Perez • Edited on

Really nice!

I remember having a very confusing bash code to get the last exit code on my prompt and a somewhat messy code to get the git branch name and status to color it accordingly. When I decided to try zsh I was delighted to learn that it has some very usefull builtins, like vcs_info_msg_0_ and the %? that gets the last exit code. My prompt is not as minimalistic as yours, but I guess I'm going to go more minimal for a few days and see if I like it.

Worth saying that %0(?..%?) will show the last exit code but only if it was not 0. You can even style it like %0(?.. %F{green} exit code: <%?> %f) and so on.

I don't know how to upload images here, please help 😅

dev-to-uploads.s3.amazonaws.com/up...

  • Branch in red: nothing changed
  • Branch in yellow: something changed
  • Branch in light blue: something in staging area (can commit)
  • The error code appears in purple and inside brackets

There are also some experimental things, like highlighting, underlining and putting the letter D before the branch when the local branch is ahead, behind or have diverged, but they don't seem to work all that well.

Here is the code I used to get this prompt.

I actually like a lot the different colors for different states of the repo.

gist.github.com/lucassperez/bc04af...

Collapse
cassidoo profile image
Cassidy Williams Author

Oh whoa that is so cool!! Thank you for sharing!

Collapse
zsh profile image
❮ ZI ❯ • Edited on

🧙‍ Nice post! Would like to propose the advanced level experience of Zsh for Zsh lovers 🧙‍‍♀️
A Swiss Army Knife for Zsh - Unix Shell ⚡
z.digitalclouds.dev ⚡

Collapse
w3ndo profile image
Patrick Wendo

Definitely going to try this now. This is something I really want to try and work out

Collapse
chrisgreening profile image
Chris Greening

I've got a similar prompt w/ branch name and I never realize how much I rely on it until I'm in a place without it and have to git branch every 3 seconds to remember where I am 😅

Great post - thanks Cassidy!

Collapse
cassidoo profile image
Cassidy Williams Author

My git st to figure out the branch is CONSTANT if I don't have it in the prompt hahaha! Thank you!

Collapse
dakdad profile image
Asanka

While a vanilla solution is always nice, my go-to is Prezto!

github.com/sorin-ionescu/prezto

Lot of options and themes with minimal effort :)

Collapse
faisal_foyez profile image
Faisal Islam

I have just tried it and Oh gosh! my prompt looks so clean now. Thank you Cassidy.

Collapse
cassidoo profile image
Cassidy Williams Author

I'm so glad it's helpful for you!

Collapse
richsoule profile image
Rich Soule

I've always added an extra line ( \n ) right before the $ at the end so that all my commands start right at the left edge of the screen. This way if I navigate down a bunch of folders, the long path names don't get in the way.

Collapse
wrench1815 profile image
Hardeep Kumar

Nice post, i also did something similar for my root shell.

BTW those who wanting that jazzy snazzy cool looking terminal with all the goodness and those juicy icons, this is what y'all need github.com/romkatv/powerlevel10k

Collapse
swsch profile image
Stefan Schmiedl

re "quick editing":

alias va='vi ~/.zshrc && . ~/.zshrc'
Enter fullscreen mode Exit fullscreen mode
Collapse
bluemont profile image
Bluemont

But wait, isn't the CLI supposed to be cryptic and colorless? LOL

Collapse
wrench1815 profile image
Hardeep Kumar

Yes and must have that curve of crts and scan lines and stuff like it's from 1980s

Collapse
jnunderwood profile image
John N Underwood

I've tried some of the other prompts mentioned here, but I have settled on Starship (starship.rs/). Highly recommended!

Collapse
cassidoo profile image
Cassidy Williams Author

This looks cool thanks for sharing!

Collapse
dumboprogrammer profile image
Tawhid

Man powerlevel10k is lit with kitty/alcattra

Collapse
cassidoo profile image
Cassidy Williams Author

I truly thought this was a spam comment until I realized these are all technical terms 😆

Collapse
dumboprogrammer profile image
Tawhid

haha 😆 but does my profile look like spam .-.

Collapse
nssimeonov profile image
Templar++

Nice article, but why reinvent the wheel? How about using ohmyposh.dev/ ?

Collapse
basicpixel profile image
O. AlQudah

An easier way to me would be using powerlevel10K zsh theme, it has a more user-friendly configuration process.

Collapse
cassidoo profile image
Cassidy Williams Author

A few folks have mentioned that now, I should check it out!

Collapse
mgutz profile image
Mario Gutierrez

Stopped wasting time with custom prompts when there are faster, more portable solutions, namely starship. Works with zsh, powershell, bash ... on linux, mac and windows.