These are my configuration files for shells and other common software on UNIX-like operating systems. To see what software this repository currently configures, please see the
This configuration is compatible only with GNU Bash 4 and up and Zsh 5 and up. Backwards compatibility is typically not an issue because I compile my own software when it is not available on a given machine.
I don't recommend just cloning this repository and using it. Rather, I would recommend picking out pieces that you like and inserting them into your own configurations.
Build and install
Note: This Waf configuration requires Python 3, and is typically tested and run with the latest version of Python.
First, configure the dotfiles. This will detect the software present on the current system and configure the dotfiles to adapt to them. The dotfiles are configured to install to your home directory by default.
To install to a directory other than your home directory:
./waf configure --prefix=/my/different/prefix
Next, build the dotfiles. Some of the dotfiles are used verbatim, and some are generated by the build system. The generated files will be placed in the
To install the dotfiles to your home directory:
Mac OS X Notes
Mac OS X suffers from two issues which pertain directly to the dotfiles.
First, the Mac OS X-provided global Zsh startup files are organized incorrectly. Mac OS X uses a small utility called
path_helper which loads a default
PATH for various shells. With Bash, it is configured to append to the
PATH only when Bash is started as a login shell (using
/etc/profile). However, with Zsh, this code is placed in
/etc/zshenv which is read on login and non-login shell startups. The workaround is:
sudo mv /etc/zshenv /etc/zprofile
My Bash and Zsh configurations are set up such that both use a common set of aliases and functions. In this way, I can use Bash and Zsh comfortably while maintaining one base for my common files. My main shell is Zsh.
Two difficult topics to understand with the shell are environment variables and shell startup files. These are some links that help explain these topics:
My dotfiles are somewhat unique in that they are not simply files that are copied or symlinked into place. I have checked out some dotfile managers, but they don't offer the level of customization I desire. Instead, my dotfiles are generated by a real build system and installed just like compiled software. This repository uses the Waf build system to generate dotfiles.
Using Waf is a large advantage. While most dotfile managers don't support Windows, Waf requires only Python and therefore operates without problems. Although this repository doesn't currently contain configuration files for Windows, it may contain them in the future. Since Waf is a real build system, it allows incremental rebuilds of the dotfiles just like any normal build system. Installation of the files is also well-managed.
For 90% of people who use shells, generating dotfiles would be overkill. However, for people like me who require many external tools and would like their dotfiles to work on different systems, generation offers some key benefits:
- Shell scripts have no module system that they can use to require certain features, so they typically depend on external executables. For example, if I wanted to download a file in Python, I could make my Python module depend on Requests. However, a shell script would typically use
curl. Well-behaved scripts typically do checks for these executables and warn the script user that they are missing. However, these checks can be tedious and are frequently omitted, leaving the presence of these executables to pure assumption.
- Because shell scripting languages are interpreted, they are only able to do checks like this at runtime. For blocks of code that run frequently (like the rc file or the prompt), these checks can start to take up precious time.
By treating the shell configuration files as just another piece of compiled software, optimized configuration files based on the utilities found on the system at compile-time can be generated.
Setting up devpi
devpi is a caching PyPi server that I use to speed up the install of Python packages. It does a bunch of over things, too, but I haven't found a need for them yet. The Waf build system automatically detects the presence of devpi and installs proper dotfiles for it.
Setting it up isn't always simple, but I've documented the steps here for posterity. Normally, you would want to install devpi to your user site in your system Python like so:
pyenv shell system pip install devpi-server
However, devpi depends on a recent version of Setuptools, and the user site's package will not override the system version. Platforms like Mac OS 10.9, for instance, might have an ancient Setuptools installed in the system Python that won't work with devpi. In that case, I've been doing the following:
pyenv install 3.4.1 # or latest devpi-compatible Python, if not installed already pyenv virtualenv 3.4.1 devpi341 pyenv shell devpi341 pip install devpi-server # Make devpi-server available on the global PATH ln -s "$(pyenv which devpi-server)" ~/bin/devpi-server
This solves the issue of the old Setuptools by installing devpi-server to a virtualenv. I believe that this requires the pyenv-which-ext plugin to be installed.
These are some command-line utilities that I use often. They are usually installed using Homebrew (Mac OS X), yum (Fedora, CentOS), or aptitude (Debian, Ubuntu), or compiled from source and installed to my home directory.
- ack - file tree search, grep replacement
- aria2 - download utility and accelerator, similar to
- autojump - easily navigate directories
- htop, htop-osx - top replacement
- pyenv - Python environment manager
- rbenv - Ruby environment manager
- tig - text-interface mode for git (git log viewer, mostly replaced by magit)
- tmux-MacOSX-pasteboard - workaround for
pbcopyunder Mac OS X
- tmux - terminal multiplexer, GNU screen replacement
- tmuxifier - manage complex tmux sessions easily
- xclip - command line interface to the X11 clipboard