ZSH on OS X
These are the steps I followed for installing and customizing ZSH on 10.7 Lion.
Installation Instructions
Install a new version of zsh through MacPorts
OS X Lion comes with a newer version of zsh (4.3.11) in /bin, but if you want to maintain a current version, you can install it from MacPorts (or Fink or Homebrew depending on which package manager you prefer). The syntax is similar. For MacPorts,
sudo port install zsh-devel +mp_completion +examples +dec +pcre
MacPorts will install zsh in /opt/local/bin/zsh. Unfortunately, OS X will not recognize zsh as a login shell until /etc/shells is edited to include /opt/local/bin/zsh. My /etc/shells reads
# List of acceptable shells for chpass(1). # Ftpd will not allow users to connect who are not using # one of these shells. /bin/bash /bin/csh /bin/ksh /bin/sh /bin/tcsh /bin/zsh /opt/local/bin/zsh
/etc/shells is a protected file and can only be edited with admin or root privaleges.
sudo gvim /etc/shells
Alternatively,
sudo sh -c "echo '/opt/local/bin/zsh' >> /etc/shells
Change the default shell to zsh
Option 1 (preferred): In Terminal.app, execute
chsh -s /opt/local/bin/zsh
Option 2: You should also be able to make the change through System Preferences -> Users & Groups. Unlock the pane (lower left corner). Right click on your account and select “Advanced Options…” (note: if the pane is not unlocked, the contextual menu will not appear).
Your default shell can be changed from the opened dialog
These are the steps I followed for installing and customizing ZSH on 10.7 Lion.
Install ZSH Templates
There are two main template packages that can be added to zsh. These packages extend the default functionality of ZSH. Please see their documentation for further information. The packages:
- Oh My Zsh: “A community supported framework for managing your ZSH installation.” Oh-my-zsh provides a growing collection of plugins and addons that enhance your zshell.
- zsh-templates-osx: “A collection of files that help the user to customize the zsh shell for the Mac OS X operating system”
I originally tried using zsh-templates-osx. The instructions are simple: a custom /private/etc/zshrc and /private/etc/zshenv are downloaded and written with appropriate root permissions. These files are sourced with new login shells (see this article).
cd /private sudo svn co http://zsh-templates-osx.googlecode.com/svn/trunk/etc
The template files are added to /Library/init/zsh.
cd /Library sudo svn co http://zsh-templates-osx.googlecode.com/svn/trunk/Library/init
I had a few problem with the install, including problems with the order of my bin directories in $PATH (zsh-templates-osx sets variables through path_helper), environment variables, and the sourcing of etc/zshrc and etc/zshenv. I’m assuming that the error lies on my end. If you have an idea, please leave me a comment.
I settled on oh-my-zsh. Installation was also simple. Directly from their website:
Step 1: Clone the repository. Templates files are copied to a hidden directory ~/.oh-my-zsh in your $HOME directory.
git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh
Step 2: Backup your ~/.zshrc
cp .zshrc .zshrc_backup
Step 3: Copy their .zshrc to your $HOME.
cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
Step 4: Add back any customizations from your original .zshrc (now .zshrc_backup) file back to their .zshrc.
Oh-my-zsh actives the wonderful tab-completion, history, and directory navigation features of ZSH by default. Any further changes to your user experience is straight forward: themes and additional plugins can be loaded through ~/.zshrc and further modifications can be added to .zsh files in ~/.oh-my-zsh/lib. To change your theme and add additional plugins, edit
ZSH_THEME="robbyrussell"
to change your theme. A list of current themes is maintained here. Additional plugins can be added. Edit plugins=(list of plugins) in ~/.zshrc.
plugins=(git osx macports)
A full list of plugins is maintained here.
Additional aliases and settings are placed into ~/.oh-my-zsh/lib as a group of files with .zsh suffixes. Any file with this suffix will be sourced. These files (for example aliases.zsh) can be freely edited.
Further additions to zshrc
Fortunately, oh-my-zsh turns on most of features a common user will need. Most of my additions were $PATH additions for ROOT, MacPorts and X11, required environment variables, and my dircolor settings (see below).
The only noteworthy additions are the automatic ls after a cd as suggested by a post on StackOverflow, and the ordering of my PATH variables.
# Path additions
# List items in the reverse order you want them to appear in $PATH (i.e. last
# items appear first ).
PATH=/usr/X11/bin:$PATH # X11 Stuff
PATH=$ROOTSYS/bin:$PATH # ROOT Data Analysis Framework
PATH=/opt/local/bin:$PATH # MacPorts
PATH=/opt/local/sbin:$PATH # MacPorts
PATH=/usr/local/bin:$PATH # User binaries
PATH=$HOME/bin:$PATH # Personal binaries
export PATH
# List directory contents after a 'cd'
function chpwd() {
emulate -LR zsh
ls
}
Add greater color customization through dircolors
Although oh-my-zsh provides a default color scheme, I prefer the greater customization provided by dircolors. dircolors is not included in the base 10.7 distribution. An integrated dircolors and ls must be installed. This combination is included an integrated component of of the GNU core utilities package (coreutils), a suite of basic file, shell, and text manipulation utilities (see GNU Operating System coreutils). coreutils can be installed through MacPorts.
Here's an overview of the procedure we will follow:
- Install coreutils through macports
- Create a custom .dir_colors file in your $HOME enumerating your color choices
- Ensure your $TERM type is included in .dir_colors
- Edit ~/.zshrc to evaluate dircolors when ls is called
- Alias your ls to include the --color flag.
- Adjust oh-my-zsh
First, install coreutils
sudo port install coreutils
Please install without the +with_default_names option. +with_default_names uses the regular names for new standard unix programs rather than prefacing them with a 'g', e.g. ls instead of gls. This is a problem if MacPorts is ever updated. Please see my post here.
After the installation of coreutils, create a ~/.dir_colors file.
touch ~/.dir_colors
I have included mine below, adapted and designed for text on a black terminal. Please make sure that your TERM is included in the .dir_colors header. To see your version of TERM:
echo $TERM
For my computer the result was xterm-256color. Your Terminal type can be changed in Terminal Preferences.
My ~/.dir_colors file
# DIRCOLOR file for the mac. # Designed for a text on black terminal. # Below, there should be one TERM entry for each terminal # type that can be colored. TERM linux TERM linux-c TERM mach-color TERM console TERM con132x25 TERM con132x30 TERM con132x43 TERM con132x60 TERM con80x25 TERM con80x28 TERM con80x30 TERM con80x43 TERM con80x50 TERM con80x60 TERM dtterm TERM xterm TERM xterm-color TERM xterm-256color # Default for OS X 10.7 TERM xterm-debian TERM rxvt TERM screen TERM screen-bce TERM putty TERM screen-w TERM vt100 TERM Eterm COLOR yes # Below are the color init strings for the basic file types. # A color init string consists of one or more of the following # numeric codes: # # Attribute codes: # 00=none 01=bold 04=underscore 05=blink 07=reverse # 08=concealed # Text color codes: # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta # 36=cyan 37=white # Background color codes: # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta # 46=cyan 47=white NORMAL 00 # Global default FILE 00 # Normal file DIR 04;40;33 # Directory (DEFAULT: 01;34 - CHANGED S.M.) LINK 01;36 # Symbolic link. FIFO 40;33 # Pipe SOCK 01;35 # Socket DOOR 01;35 # Door BLK 40;33;01 # Block device driver CHR 40;33;01 # Character device driver ORPHAN 40;31;01 # Symlink to nonexistent file # This is for files with execute permission: EXEC 01;32 # List any file extensions like '.gz' or '.tar' that you would # like ls to colorize below. Put the extension, a space, and # the color init string (and any comments you want to add after # a '#'). # USER DEFINED # Archive files .tar 01;31 # archives or compressed (bright red) .tgz 01;31 .tar.gz 01;31 .arj 01;31 .taz 01;31 .lzh 01;31 .zip 01;31 .z 01;31 .Z 01;31 .gz 01;31 .bz2 01;31 .deb 01;31 .rpm 01;31 .jar 01;31 # Images and video .fig 01;35 .jpg 01;35 .jpeg 01;35 .gif 01;35 .bmp 01;35 .pbm 01;35 .pgm 01;35 .ppm 01;35 .tga 01;35 .xbm 01;35 .xpm 01;35 .tif 01;35 .tiff 01;35 .png 01;35 .mov 01;35 .mpg 01;35 .mpeg 01;35 .avi 01;35 .fli 01;35 .gl 01;35 .dl 01;35 .xcf 01;35 .xwd 01;35 # Audio .ogg 01;35 .mp3 01;35 .wav 01;35 .aac 01;35 # Programming *Makefile 01;33 .C 01;33 .cpp 01;33 .cc 01;33 .c 01;33 .for 01;33 .h 01;33 .tcl 01;33 .py 01;33 .sh 01;33 .o 33 .so 33 # Documents *README 01;37;41 *Readme 01;37;41 *readme 01;37;41 .tex 01;37;40 .dvi 01;37;40 .ppt 01;37;40 .pptx 01;37;40 .doc 01;37;40 .docx 01;37;40 .xls 01;37;40 .xlsx 01;37;40 .ps 01;37;40 .eps 01;37;40 .pdf 01;37;40 .txt 01;37;40 .htm 01;37;40 .xml 01;37;40 .pot 01;37;40 .nb 01;37;40 # Spectra (physics stuff) .spe 32 .spn 32 .sec 32 .asc 32 .mat 32 .spc 32 .Spc 32 .root 32 .gf2 32 .gf3 32 # Data .dat 01;04;35 .evt 01;04;35 .bin 01;04;35 # Temporary files *~ 36 .bak 36 .tmp 36 *# 36
Add the following lines to your ~/.zshrc to ensure that dircolors runs when ls or any ls variant is called.
# Color listing
eval $(dircolors ~/.dir_colors)
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
ls must be called with the --color flag. Modify the ls aliases in ~/.oh-my-zsh/lib/aliases.zsh.
# List direcory contents export LS_OPTIONS='--color' alias l='ls $LS_OPTIONS' alias ll='ls $LS_OPTIONS -lh' alias lll='ls $LS_OPTIONS -alh' alias sl='ls $LS_OPTIONS' # often screw this up
Lastly, ~/.oh-my-zsh/lib/theme-and-appearance.zsh needs modified so ls is not called with the -G flag. Change alias ls='ls -G' to alias ls='ls --color, i.e.
# Enable ls colors # Edited - S.M. Changed ls -G -> ls --color. Requires dircolor to be valid. if [ "$DISABLE_LS_COLORS" != "true" ] then # Find the option for using colors in ls, depending on the version: Linux or BSD ls --color -d . &>/dev/null 2>&1 && alias ls='ls --color=tty' || alias ls='ls --color' fi
Conclusions
That should be all! Questions and comments can be addressed below.

