This repository contains all of my configuration for MacOS and Linux, with a focus on terminal, editor, shell, programming environments etc. This repository can easily be forked to allow you to create and customise your own machine setup.
This repository also contains some handy Shell Scripts and Aliases that others might find helpful.
Some key features are:
- Support for setting up a clean machine with developer focused tooling
- The ability to choose what features you do or don't install
- Idempotent setup, which allows you to run the setup whenever you want to add or upgrade features
- Small, simple scripts to setup 'features', such as Ruby and
rbenv, Python, Vim and so on - Small, simple scripts which are sourced into your shell profile, providing things like auto-completion
- Management of dotfiles such as
~/.vimrcand~/.gitconfig - Optional management of private file, such as SSH keys, as long as you have access to an AWS S3 bucket
yes to make changes). The goal is that you can run the setup scripts without changing anything unless you explicitly choose a feature. However, I cannot guarantee I haven't made an mistakes, so please exercise caution.
Screenshot on MacOSX
Screenshot on Ubuntu
- Introduction
- Detailed Documentation
- Quick Start
- SSH Keys, GPG Keys and Private Files
- MacOS - Manual Steps
- Features
- Developer Guide
- Ubuntu Terminal Configuration
- Shell Prompt Theme
- Shell Scripts and Aliases
- Cheat Sheet - TMux
- Cheat Sheet - Vim
- Effective Tmux
- Effective Vim
- Cheat Sheet - Shell
- Tooling Choices
- Contributors
- TODO
The goal of this project is to provide a single command which will setup key features of the system. Each feature should be orthogonal and not depend on other features.
Additional detailed guides and configuration are available:
- Claude Code - Claude Code CLI configuration, plugins, and MCP servers
- Transcription - Voice-to-text transcription setup and tools
- Terminal - Terminal themes and configuration
- Desktop - Desktop environment setup
Run the commands below to quickly setup or update a machine. Note that the default behaviour in all cases is to not make any changes unless the user explicitly confirms them.
# MacOSX only - install command-line tools (so that we have git).
xcode-select --install
# Create a working environment, in my standard format.
mkdir -p ~/repos/github/dwmkerr
cd ~/repos/github/dwmkerr
# Clone the dotfiles - note that a new machine will not have my SSH key
# so this is over https. Once the private files such as SSH keys are copied the
# remote will be updated to use SSH.
git clone https://github.com/dwmkerr/dotfiles.git
cd dotfiles
# Setup the machine - the script will run interactively.
make setupSSH Keys, GPG Keys and Private Files (such as cloud configuration files, which contain sensitive information) can be backed up and restored to a folder on AWS.
This means that to transfer sensitive information from one machine to another, you can simple run backup-private-files on the source machine, and restore-private-files on the target machine.
As long as your AWS profile is configured, this is a one-liner:
make private-files-backupYou will be asked for confirmation before backing up any files.
Assuming you have the AWS CLI, GPG, and pinentry-mac installed (all of which are installed with make setup), run the following commands to create a profile (you will need credentials, which should be in the password manager):
# Restore private files:
make private-files-restoreYou will be asked for confirmation before restoring any files.
The following variables can be used to configure the backup and restore process. The values shown are the defaults, so these only need to be changed if you are using a different S3 bucket or AWS profile name.
# Define the name of the AWS profile used to access the S3 bucket.
# Default is "dwmkerr".
DOTFILES_PRIVATE_PROFILE="dwmkerr" # Use whatever name makes sense for you!
# Define the name of the AWS S3 bucket that stores private files.
# Default is "dwmkerr-dotfiles-private".
DOTFILES_PRIVATE_S3_BUCKET="dwmkerr-dotfiles-private"
# Run AWS configure to create the named profile - you will be asked to provide
# an access key and secret. If this is not setup the backup/restore scripts will
# prompt you to configure.
aws configure --profile
# Backup private files:
make private-files-backupThe following steps have not yet been automated:
- Sign into Chrome and setup sync
- Install and into Bitwarden
- Open Joplin and enable S3 synchronisation (AWS credentials are in Bitwarden)
- For
Terminal, install the profiles under./terminalto give the One Dark / One Light themes
Profiles are in terminal/iTerm2/ and loaded as dynamic profiles:
| Profile | Purpose |
|---|---|
dwmkerr |
Default terminal |
dwmkerr-recording |
No transparency, for screen recordings |
dwmkerr-agent |
Agent identity, dark purple background, isolated tmux |
Install profiles:
make iterm-profilesSee identities/README.md for identity setup details.
Global preferences:
- General: Selection - (Enabled) Applications in terminal may access clipboard
- General: Window (Disabled) Native full screen windows
- Keys: HotKey - (Enabled) Show/hide all windows with a system-wide hotkey (Alt+Space)
These steps are work in progress.
- Restore Parallels virtual machines from backup.
- Restore the
~/.private/folder from a secure backup, to bring back project specific secrets.
Each of the 'features' listed below typically has a ./setup.d/x-<feature-name>.sh script to install or upgrade the feature. Some also have a ./.shell.d/x-<feature-name>.sh file which is sourced by interactive shells if commands need to be run on shell startup (such as enabled pyenv and similar features. The numbers are used to ensure that if there are dependencies on features, we try and install in the right order.
Private Files
Private files, such as GPG and SSH keys can be backed up or restored with the commands below:
make private-files-backup
make private-files-restore
Shell configuration which is private can be kept in ~/.shell.private.d/ - this folder will be loaded by ~/.shell.sh but not checked in.
Package Manager
- Installs or upgrades Homebrew on OSX.
- Updates
apton Ubuntu. - Installs and updates
snapon Ubuntu.
OSX Configuration
Various preferences for OSX, such as showing the path bar on the Finder windows, smaller icons, etc.
Git
Sets up gnupg and the git user settings.
Node
Sets up nvm (Node Version Manager) and the current LTS version of node.
Python
Sets up pyenv (Python Environment Manager) and python3.
Ruby
Sets up rvm (Ruby Version Manager) and ruby.
Golang
Sets up golang and $GOPATH.
Vim
Sets up vim and vim config file. Plugins are installed with PlugInstall.
TMux
This installs tmux and the Tmux Plugin Manager.
Shell
This installs bash, zsh and sets zsh as the default shell for the user. Sets the command prompt and sources the .shell.sh file.
Installs On My Zsh, which I use for themes and some conveniences, and copies over the zsh themes.
To enable features to be used in shells, the shell configuration file will source our special shell.sh file. This file then goes and sources the appropriate files from ~/.shell.d.
OSX Applications
Many applications I used, such as WhatsApp, Visual Studio Code, T-Mux.
This also installs common CLI applications, such as tree, as well as GNU tools (coretools, gsed etc).
Commandline Tools
ag is setup and will use a global ignore file at ~/.ignore. vim-ack also uses this file.
Claude Code
Configuration and setup for Claude Code CLI. See claude/README.md for full details including plugins and MCP servers.
There's not much to say really, just follow the principles below:
- Try to keep features orthogonal, so that they don't rely on each other
- Try to remember to support
bashas well aszsh - Try to remember to support Linux as well as MacOSX
Set the OneDark Theme with:
bash -c "$(curl -fsSL https://raw.githubusercontent.com/denysdovhan/gnome-terminal-one/master/one-dark.sh)"The set_ps1.sh can be used to set PS1 styles:
$ set_ps1 debian
The PS1 is converted to Z-Shell format if the current shell is zsh. My current 'default' theme is named dwmkerr.
The following features are loaded as part of my configuration. Check the link to the source if you'd like to copy over an individual feature for your own use.
The following shell commands are setup:
| Command | Usage |
|---|---|
| Quick Aliases | shell.d/aliases.sh |
serve |
Serve the current folder over HTTP on port 3000. |
vinilla |
Open vi without loading the vimrc (i.e. vanilla configuration). |
| Basic Functions | |
eachdir |
Run a command in each child directory. |
D |
Get the date in ISO86091 format (e.g. 2021-04-24). |
mkd |
Make a directory, using -p and cd into it. |
restart_shell |
Restart the current shell process, useful when profile changes. |
revcut |
Cut, but in reverse (i.e. from the last to the first delimiter). |
toggle_bak |
Toggle *.bak off or on a file (useful to disable config etc). |
| Git Functions | |
ghclone |
Clone from GitHub, e.g: ghclone dwmkerr/effective-shell. |
| Script | Usage |
|---|---|
./scripts/test-shell.d.sh |
Source each ./shell.d file in turn, time result. Good for checking for errors. |
| Command | Usage |
|---|---|
| Sessions | |
tmux detach -E 'bash --noprofile --norc |
Detach the current session and open a vanilla shell. |
| ------------------------------------------- | ------------------------------------------------------------------ |
<leader> R |
Reload Tmux configuration (i.e. source the ~/.tmux.conf file). |
man tmux |
Get help on commands. |
<leader> ? |
Get help on commands. |
Ctrl + h/j/k/l |
Navigate splits (vim aware) |
Meta + h/l |
Move through tabs. |
Ctrl + Meta + h/j/k/l |
Move through tabs. |
move-window -r |
Re-order the tab numbers (useful if there are gaps). |
<leader> / S |
Show Sessions with window preview, hit x to delete. |
<leader> / $ |
Rename session. |
new -s <name> |
New session with name. |
<leader> / Ctrl+S |
Save Tmux Session |
<leader> / Ctrl+R |
Restore Tmux Session |
<leader> / |
Last split |
<leader> { |
Swap pane left |
<leader> } |
Swap pane right |
<leader>. <session-name>:<pane number> |
Move a pane to a session. |
Here's a quick reference. My <Leader> is \, so I've written shortcuts as \x rather than <Leader>x for brevity. I still need to port the above to the structure below.
| Command | Usage |
|---|---|
| Custom Commands | |
<leader>t |
Open current file in NERDTree. |
<leader>w |
Write buffer. |
<leader>\\ |
Open buffer in new tab. |
<leader>d |
Open diffview (git diff viewer). |
<leader>D |
Open file history for all files. |
<leader>dh |
Open file history for current file. |
<leader>dc |
Close diffview. |
<leader>t |
Show current buffer in NERDTree. |
<leader>F |
Toggle focus mode. |
| Other Commands | |
\[<Space> |
blank line above |
]<Space> |
blank line below |
sj |
Splitjoin down (i.e. split a line downwards). |
sk |
Splitjoin up (i.e. join a line upwards). |
:Tabularize /= |
Line up selection, using '=' |
| Navigation | |
gd |
Where possible, will go to a local definition. Supercharged by vim-coc. |
gd |
https://vi.stackexchange.com/questions/42414/for-vim-and-specifically-coc-vim-is-it-idomatic-to-use-gd-to-open-a-link/42415#42415 |
gf |
Open file under cursor. |
gx |
Open link or address under cursor. |
| Spelling | |
]s and [s |
Next/Previous spelling error. |
z= and zg |
Check dictionary / add to dictionary. |
| Markdown | Provided by vim-markdown |
]] and [[ |
Next and previous headers. |
gx |
Open link in standard editor. |
| Focus | From vim-goyo and vim-limelight |
:Goyo |
Enter focus mode. |
:Limelight 0.8 and :Limelight! |
Go into limelight, 80% ultra focus, and toggle limelight. |
let g:limelight_paragraph_span = 1 |
Span more paragraphs in limelight. |
| Markdown Tables | |
\tm |
Enter/Exit 'table mode', which will dynamically format markdown tables. |
ci| |
Example of the | motion for cells - i.e. 'change-in-cell'. |
Note: including the vertical pipe | in the table above would cause rendering issues. So instead, the unicode character | is used to illustrate the commands. Do not use the unicode character, use the normal ASCII 0x7C character.
Other useful stuff:
- By default vim doesn't treat
-as part of a word (for motions, search, autocomplete, etc). Useset iskeyword+=-to change this. This is the changed in myvimrcbut a useful one to remember.
Most essential commands:
- Option - h/l - move left/right between tabs
Here's some of the stuff I find most useful.
If you repeat yourself or do dumb formatting crap, find the idiomatically correct way to do something or use a plugin. Always look up native ways first.
If you have a monorepo with folders like backend and frontend, you need Vim to understand that each is a 'workspace'. This is handled with config like:
autocmd FileType python let b:coc_root_patterns = ['.git', '.env', 'pyproject.toml', 'setup.cfg']Check with:
:CocList foldersSee: https://github.com/neoclide/coc.nvim/wiki/Using-workspaceFolders
Grep all lines with secret and put on clipboard:
:!cat % | grep secret | pbcopyThis example could be used to grab all references to GitHub secrets from a buffer.
C-nto toggle/focus the treeRin the tree to refresh<leader>tto 'tree' the current file, i.e. show the current buffer in NerdTree.
<leader>spacebuffers<leader>ffiles<leader>gripgrep (works amazingly)
I've barely scratched the surface and will force myself to learn more.
<leader>rnrenamegdgo to definition,grgo to references<leader>Ashow code actions, e.g. import missing reference<leader>qfapply default code action, e.g. import missing reference
I use vim-polyglot and vim-coc with vim-tsserver - this seems to cover most of my needs without any additional plugins.
Potential Improvements
- I'm looking into
coc-prettieretc to make sure that auto formatting will happen if/when needed when typing, rather than blindly on save - Eliminate unneeded plugins and conf
I'm currently using fzf-lua after spending a few years on fzf.vim. It seems lightening fast but a little harder to decipher some of the documentation. The main customisations andre:
I find the sj and sk commands invaluable, until something like this becomes native it's a super useful plugin.
COC is used - it's basically setup like VS Code - tab selects the first option. Then <C-n> and <C-p> to cycle (or up/down).
These are just some common commands I often forget:
| Command | Usage |
|---|---|
tput cvvis |
Show the cursor. Useful if it disappears when a command hides it and fails to restore it. |
Why Vim Plug over Vundle?
I was impressed enough with the comments on this post to make the switch, particularly as coc doesn't support Vundle, meaning I had to give Plug a try.
Thanks goes to these wonderful people (emoji key):
|
Dave Kerr 💻 📖 🤔 |
LoKolbasz 🤔 |
This project follows the all-contributors specification. Contributions of any kind welcome!
- fix: correct slow terminal startup
- feat: iTerm OpenAI
- fix: check iTerm restore window size
- fix: Bash Tab Completion: https://stackoverflow.com/questions/7179642/how-can-i-make-bash-tab-completion-behave-like-vim-tab-completion-and-cycle-thro
- feat: install patched nerdfont https://github.com/ryanoasis/nerd-fonts/releases
- Autocomplete for docker/k8s is still not properly setup.
- osx - mas (mac app store CLI: brew)
- osx - set icon
- iterm - set colour scheme
- terminal - raise bug on broken colours
- node is not sourcing properly
- fix: long urls in tmux work if they span lines - unless they are in
vim - vi: decide on vi/nvim
- Note; javascript projects can get CoC support by adding a jsconfig.json file as per https://code.visualstudio.com/docs/languages/jsconfig then :CocInstall coc-tsserver
- Note; golang projects can get CoC support by adding :CocInstall coc-go
- update all to neovim
- todo: document shell shortcuts (repos/dwmkerr)

