Personal zsh and tmux setup for macOS and Ubuntu.
Clone the repo, then run the installer:
git clone git@github.com:<your-user>/dotfiles.git ~/projects/dotfiles
cd ~/projects/dotfiles
./scripts/install.sh --profile autoOn a fresh Ubuntu machine, install system packages too:
./scripts/install.sh --profile ubuntu --install-packagesOn macOS:
./scripts/install.sh --profile macos --install-packagesPreview all file operations first:
./scripts/install.sh --profile auto --dry-run- Detects or accepts a profile:
macos,ubuntu, orgeneric - Installs shell dependencies unless
--no-depsis passed:oh-my-zsh,zsh-autosuggestions,zsh-syntax-highlighting, andpowerlevel10k - Optionally installs system packages with
--install-packages - Writes
~/.config/dotfiles/env.zsh - Copies zsh, Powerlevel10k, and tmux files into
$HOME - Backs up existing target files as
*.backup.YYYYMMDDHHMMSS - If an old
.zshrcis backed up, extracts non-style local settings into~/.zshrc.localor~/.zshrc.local.candidate
The installer does not overwrite an existing .zshrc in place.
If ~/.zshrc already exists, it is renamed first:
~/.zshrc.backup.YYYYMMDDHHMMSS
Then this repo copies its managed zsh entrypoint into place:
~/projects/dotfiles/home/.zshrc -> ~/.zshrc
After that, the installer extracts local settings from the backup:
- kept in
~/.zshrc.local: environment variables, PATH additions, aliases, and functions - commented for review: prompt, theme, completion style, framework init, conda, inline passwords, and token-looking variables
The intent is:
- repo
.zshrcowns display and shell UX: prompt, Powerlevel10k, oh-my-zsh, completion init, completion style, history defaults, keybinding defaults ~/.zshrc.localowns machine-local behavior: private environment variables, aliases, PATH additions, work-specific SSH shortcuts, host-specific functions
If ~/.zshrc.local already exists, the installer will not overwrite it. It writes:
~/.zshrc.local.candidate
Review that file and copy only the lines you want.
home/: files copied into$HOMEprofiles/: platform-specific shell snippets copied through~/.config/dotfiles/env.zshscripts/install.sh: installer and backup managerdocs/: notes
Install without downloading shell dependencies:
./scripts/install.sh --profile ubuntu --no-depsRe-run after pulling updates:
git pull
./scripts/install.sh --profile auto --no-depsUse symlinks instead of copies for development:
./scripts/install.sh --profile auto --linkMerge useful lines from an existing .zshrc:
./scripts/merge-zshrc.sh ~/.zshrc.backup.YYYYMMDDHHMMSS
vim ~/.zshrc.localChange the default shell after installing zsh:
chsh -s "$(command -v zsh)"The installer writes the selected profile to:
~/.config/dotfiles/env.zshhome/.zshrc loads that file and then sources:
profiles/macos.zshprofiles/ubuntu.zshprofiles/generic.zshif you add one later
Put machine-specific aliases, private tokens, and SSH shortcuts in:
~/.zshrc.localUse home/.zshrc.local.example as a template. This file is not installed or tracked.
If a machine already has a .zshrc, the installer backs it up before copying this repo config.
It then extracts the old file into ~/.zshrc.local when that file does not exist.
If ~/.zshrc.local already exists, it writes ~/.zshrc.local.candidate instead.
The merge rule is:
- repo
.zshrc: prompt, completion init, theme, key UI, tmux/p10k integration - local
.zshrc.local: environment variables, PATH additions, aliases, functions, machine-specific SSH shortcuts - commented for review: inline passwords, token-looking variables, conda, and style/framework settings that conflict with the repo
- Conda is intentionally not configured.
- GitHub CLI, Git config, and Ghostty are intentionally out of scope.
- tmux clipboard uses
wl-copy,xclip, orxselon Linux when available. ~/.zshrc.localis intentionally not installed or tracked.