As developers, we spend a lot of time in our shells: making them fast and responsive improves our productivity. I play around with a lot of development tools (as I mentioned in a previous post) trying to find the best combination of intelligence, responsiveness, and fun. Recently I was investigating alternatives to oh-my-zsh, which is a wonderful set of Zsh packages but suffers from weird slowdowns and, unfortunately, requires a lot of configuration. I stumbled upon prezto and I love it – originally an optimized fork of oh-my-zsh, it’s now its own project, and it is fast, beautiful, and leverages the full power of Zsh. It looks like this:

You should get it. And when you do, use these configuration settings to make your experience even better.

Customize your .zpreztorc

You’ll want to enable a bunch of modules in your .zpreztorc , which is the configuration file for everything prezto. Here’s my modules:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # Set the Prezto modules to load (browse modules). # The order matters. zstyle ':prezto:load' pmodule \ 'environment' \ 'terminal' \ 'editor' \ 'history' \ 'directory' \ 'spectrum' \ 'utility' \ 'ssh' \ 'completion' \ 'homebrew' \ 'osx' \ 'ruby' \ 'rails' \ 'git' \ 'syntax-highlighting' \ 'history-substring-search' \ 'prompt'

They’re not kidding when they say the order matters: prompt must come last, history-substring-search must come before it, and syntax-highlighting must come before that. The result of messing this up will likely be a ton of Zsh errors output to your shell after every command.

Some highlights from this list:

history and history-substring-search work together to bring you one of the most awesome features of zprezto: when you type in a command and press up and down, you’ll only get history results of you typing that command. Super helpful for typing in ssh, then going back in time to see your previous ssh servers.

syntax-highlighting gives you some fish-style highlights. Executable commands will turn blue, incomplete or unrecognized commands will turn red, folders get underlined… it provides immediate and visceral visual feedback to what you’re entering.

directory gives you some awesome shortcuts for the directory stack: d to see all the directories you’ve entered, then the numbers 1 to 9 to jump to a previous directory you’ve visited.

And that’s just a start. Visit the prezto modules list and view each individual module’s README to learn more about them.

After modules are done, get your identities into the SSH agent! There’s a configuration block for that later:

1 2 # Set the SSH identities to load into the agent. zstyle ':prezto:module:ssh:load' identities 'id_rsa' 'id_rsa.github' 'id_rsa.client1' 'id_rsa.client2' # all the rest of your identities

I also set up a custom theme for myself, the source of which I’ll include below. If you want to enable that theme (or a different one), you’ll also need to specify it in your .zpreztorc :

1 2 3 4 # Set the prompt theme to load. # Setting it to 'random' loads a random theme. # Auto set to 'off' on dumb terminals. zstyle ':prezto:module:prompt' theme 'josh'

You can find the full text of my .zpreztorc as a gist.

Customize your .zshrc

.zshrc is loaded in every interactive shell: use it to set up your Ruby switcher, important aliases, and anything else you need for maximum awesomeness. Mine is fairly self-explanatory:

# # Executes commands at the start of an interactive session. # # Authors: # Sorin Ionescu <sorin.ionescu@gmail.com> # # Source Prezto. if [[ -s "${ZDOTDIR:-$HOME}/.zprezto/init.zsh" ]]; then source "${ZDOTDIR:-$HOME}/.zprezto/init.zsh" fi # Customize to your needs... # Start rbenv export PATH="$HOME/.rbenv/bin:$PATH" eval "$(rbenv init -)" # Add homebrew to the completion path fpath=("/usr/local/bin/" $fpath) # why would you type 'cd dir' if you could just type 'dir'? setopt AUTO_CD # Now we can pipe to multiple outputs! setopt MULTIOS # This makes cd=pushd setopt AUTO_PUSHD # This will use named dirs when possible setopt AUTO_NAME_DIRS # If we have a glob this will expand it setopt GLOB_COMPLETE setopt PUSHD_MINUS # No more annoying pushd messages... # setopt PUSHD_SILENT # blank pushd goes to home setopt PUSHD_TO_HOME # this will ignore multiple directories for the stack. Useful? I dunno. setopt PUSHD_IGNORE_DUPS # 10 second wait if you do something that will delete everything. I wish I'd had this before... setopt RM_STAR_WAIT # use magic (this is default, but it can't hurt!) setopt ZLE setopt NO_HUP # only fools wouldn't do this ;-) export EDITOR="subl -n -w" setopt IGNORE_EOF # If I could disable Ctrl-s completely I would! setopt NO_FLOW_CONTROL # Keep echo "station" > station from clobbering station setopt NO_CLOBBER # Case insensitive globbing setopt NO_CASE_GLOB # Be Reasonable! setopt NUMERIC_GLOB_SORT # I don't know why I never set this before. setopt EXTENDED_GLOB # hows about arrays be awesome? (that is, frew${cool}frew has frew surrounding all the variables, not just first and last setopt RC_EXPAND_PARAM # Who doesn't want home and end to work? bindkey '\e[1~' beginning-of-line bindkey '\e[4~' end-of-line # Incremental search is elite! bindkey -M vicmd "/" history-incremental-search-backward bindkey -M vicmd "?" history-incremental-search-forward # Search based on what you typed in already bindkey -M vicmd "//" history-beginning-search-backward bindkey -M vicmd "??" history-beginning-search-forward bindkey "\eOP" run-help # oh wow! This is killer... try it! bindkey -M vicmd "q" push-line # it's like, space AND completion. Gnarlbot. bindkey -M viins ' ' magic-space

Select your theme

There are a lot of cool themes out there. But I was pretty used to my old Zsh theme, which was simple, clean, and had an obvious indicator when your last command failed. For an example of what it looks like, see the screenshot at the start of this post.

The arrow on the left shows green when your last exit code was 0, and red when it was 1. It includes the branch you’re on, with an indicator of whether you have uncommitted files on the right-hand side. It does a ton more as well, and here’s the source for your use:

# # A stripped-down sorin theme. # # Authors: # Sorin Ionescu <sorin.ionescu@gmail.com> # Josh Symonds <josh@joshsymonds.com> # # Screenshots: # http://i.imgur.com/nBEEZ.png # # Load dependencies. pmodload 'helper' function prompt_josh_pwd { local pwd="${PWD/#$HOME/~}" if [[ "$pwd" == (#m)[/~] ]]; then _prompt_josh_pwd="$MATCH" unset MATCH else _prompt_josh_pwd="${${${(@j:/:M)${(@s:/:)pwd}##.#?}:h}%/}/${pwd:t}" fi } function prompt_josh_precmd { setopt LOCAL_OPTIONS unsetopt XTRACE KSH_ARRAYS # Format PWD. prompt_josh_pwd # Get Git repository information. if (( $+functions[git-info] )); then git-info fi # Get ruby information if (( $+functions[ruby-info] )); then ruby-info fi } function prompt_josh_setup { setopt LOCAL_OPTIONS unsetopt XTRACE KSH_ARRAYS prompt_opts=(cr percent subst) # Load required functions. autoload -Uz add-zsh-hook # Add hook for calling git-info before each command. add-zsh-hook precmd prompt_josh_precmd # Set editor-info parameters. zstyle ':prezto:module:editor:info:completing' format '%B%F{red}...%f%b' zstyle ':prezto:module:editor:info:keymap:primary' format '%B%(?;%{%F{green}%} ;%{%F{red}%} )❯%f%b' zstyle ':prezto:module:editor:info:keymap:primary:overwrite' format ' %F{red}♺%f' zstyle ':prezto:module:editor:info:keymap:alternate' format ' %B%F{green}❮%F{yellow}❮%F{red}❮%f%b' # Set git-info parameters. zstyle ':prezto:module:git:info' verbose 'yes' zstyle ':prezto:module:git:info:action' format ':%%B%F{yellow}%s%f%%b' zstyle ':prezto:module:git:info:added' format ' %%B%F{green}✚%f%%b' zstyle ':prezto:module:git:info:ahead' format ' %%B%F{yellow}⬆%f%%b' zstyle ':prezto:module:git:info:behind' format ' %%B%F{yellow}⬇%f%%b' zstyle ':prezto:module:git:info:branch' format '%F{green}%b%f' zstyle ':prezto:module:git:info:commit' format ':%F{green}%.7c%f' zstyle ':prezto:module:git:info:deleted' format ' %%B%F{red}✖%f%%b' zstyle ':prezto:module:git:info:modified' format ' %%B%F{blue}✱%f%%b' zstyle ':prezto:module:git:info:position' format ':%F{red}%p%f' zstyle ':prezto:module:git:info:renamed' format ' %%B%F{magenta}➜%f%%b' zstyle ':prezto:module:git:info:stashed' format ' %%B%F{cyan}✭%f%%b' zstyle ':prezto:module:git:info:unmerged' format ' %%B%F{yellow}═%f%%b' zstyle ':prezto:module:git:info:untracked' format ' %%B%F{white}◼%f%%b' zstyle ':prezto:module:git:info:keys' format \ 'prompt' ' $(coalesce "%b" "%p" "%c")%s' \ 'rprompt' '%A%B%S%a%d%m%r%U%u' # Define prompts. PROMPT='%F{cyan}${_prompt_josh_pwd}%f${git_info:+${(e)git_info[prompt]}}%(!. %B%F{red}#%f%b.)${editor_info[keymap]} ' RPROMPT='${editor_info[overwrite]}${VIM:+" %B%F{green}V%f%b"}${git_info[rprompt]}' SPROMPT='zsh: correct %F{red}%R%f to %F{green}%r%f [nyae]? ' } prompt_josh_setup "$@"

Place this in ~/.zprezto/modules/prompt/functions/prompt_josh_setup and then select it in your .zpretorc for best results.

prezto is easy to configure and presents a lot of powerful options: you’ll want to spend some time getting used to it. But it’s also really enjoyable. Once you start learning the power behind your shell and how easy it becomes to access, I guarantee that you’ll never look back.