Skip to content

Repository files navigation

中文 | English

Introduction

After reading webpro's article, I discovered many useful dotfiles. I think they are great, but I don't want to copy them directly (I believe everyone's computer setup is unique). I want a configuration that fits me, just like mathiasbynens.

Quick start

Clone the repository, then run the installer(Mac/Linux):

git clone https://github.com/genwilliam/dotfiles.git ~/dotfiles
cd ~/dotfiles
./install.sh

If you want the installer to also delete any README* files under your home directory (e.g. from previous sync attempts), run:

./install.sh --remove-readmes

For Windows users, use one of these installers instead:

# PowerShell (recommended on Windows)
./install-for-windows.ps1
# Git Bash shell script
./install-for-windows.sh

Important

On Windows, creating symbolic links usually requires either Administrator privileges or Developer Mode. If you run into link creation errors, run your terminal as Administrator, or enable Developer Mode: Settings → Privacy & security → For developers → Developer Mode.

If you only want to validate the dotfiles links and warm up zsh startup caching, run:

./bootstrap.sh

As Joshua Clayton said in a recent episode of The Changelog, if you're unhappy with your dotfiles, you're doing it wrong™. Pick and choose what you like from other people's dotfiles. Learn from everyone, follow no one. Build your own lightsaber. Rebuild it from scratch with confidence. Original: https://wynnnetherland.com/journal/dotfiles-discovery

If you don't know what dotfiles are, this article is helpful.
If you don't want to read it, here's a short explanation:

Dotfiles are configuration files in Unix-like systems (such as macOS and Linux) whose names start with .. They are usually used to store user-level application settings.

They are called dotfiles because each filename starts with a dot.

Important

Before you start, I need to mention that my shell setup is based on zsh. If you use another shell (such as bash, fish, or others), I cannot guarantee this setup will work. This repository may help you.

If you want to change your default shell (set zsh as default), searching on Google should help.

I like this principle (we all do, right?). So in my dotfiles, different tools do different jobs, even if a file only has one line, for example:

  • tmux handles terminal multiplexing
  • zsh handles the shell
  • neovim handles text editing
  • git handles version control

...

zsh

Before you begin, please read zsh/bash loading order.

Moral:   For bash, put stuff in ~/.bashrc, and make ~/.bash_profile source it.   For zsh, put stuff in ~/.zshrc, which is always executed.

Briefly talk about my understanding:

File Load Order When It Is Loaded Shell Type Runs Every Shell Start? Typical Use
.zshenv 1 Loaded for every Zsh invocation login / interactive / non-interactive / scripts ✅ Yes Basic environment variables (PATH, LANG, EDITOR)
.zprofile 2 Loaded when a login shell starts login shell ❌ No (login only) Login initialization, brew shellenv, PATH setup
.zshrc 3 Loaded for interactive shells interactive shell ❌ No (interactive only) aliases, prompt, plugins, completion
.zlogin 4 Loaded after .zshrc in a login shell login shell ❌ No (login only) Post-login tasks, startup messages

I do not use the Oh My Zsh runtime framework anymore. Zsh plugins are loaded directly from Homebrew paths in zsh/zshrc.d/plugins.zsh (source-based, framework-free). The ohmyzsh/ directory in this repo is kept only as a historical plugin-list archive.

Completion cache stability (compinit / compdump)

In large plugin setups, repeated source ~/.zshrc can become unexpectedly slow when compinit keeps rebuilding completion metadata (compdump).

  • Re-sourcing ~/.zshrc in the same shell can cause completion metadata drift if path arrays are not deduplicated.
  • Once metadata differs, compinit may regenerate completion cache, which can make reload time jump from milliseconds to hundreds of milliseconds.

Current fix in this repo

  • Enable fpath/path uniqueness (typeset -gU fpath path) to prevent duplication during repeated sourcing.
  • Pin cache locations with ZSH_CACHE_DIR and ZSH_COMPDUMP under ~/.cache for deterministic cache behavior.
  • Use compinit -C -d "$ZSH_COMPDUMP" in completion.zsh to prefer cache reuse.
  • Keep completion policy explicit: Tab uses menu selection, while fzf-tab is available via keybinding.

I've used two themes: powerlevel10k and starship.

Caution

I don't know whether you prefer p10k or starship, so I include both. However, I currently use starship, so you will see a p10k folder in this repo. If you don't need p10k, you can delete it. Likewise, if you need p10k, you can delete the starship config, then move and replace the files from ./p10k into ./zsh.

A Zsh prompt configuration based on Powerlevel10k, using a Rainbow + Powerline style, and requiring Nerd Font.

  • Left side shows: current directory and Git status
  • Right side shows: command exit code, execution time, language versions (Node/Python/Ruby, etc.), K8s/cloud context, and current time
  • Enables instant prompt (near-zero startup delay) and transient prompt (simplified previous prompt lines)
  • Uses modular config in zshrc.d/ for easier maintenance

68991B896A7E070B52E1C9364463BD49

If you don't like my style, run p10k configure in your terminal to reconfigure it. If fonts are missing, the configuration wizard may display incorrectly.

If you are a Windows user, this article explains it in detail.

starship

CleanShot 2026-03-12 at 10.43.32@2x

A Zsh prompt configuration based on Starship, with integration for multiple languages and tools. If the current directory is a Git repository, the prompt shows branch and status. If the current directory contains a Node.js project, it shows the Node.js version. If it contains a Python project, it shows the Python version. Note that for Python version display, you need to activate a Python environment.

CleanShot 2026-03-12 at 10.46.26@2x

starship.toml

This file needs to be placed in ~/.config.

ln -s ~/dotfiles/starship/starship.toml ~/.config/starship.toml

This is the Starship configuration file. You can modify it based on your needs. The format is TOML. You can find more details here.

git

gitconfig
  • gitconfig contains global Git settings, such as username and email.

  • If you want to know what each option means and how it works, see this article.

  • The content here should not be used directly; you need to customize it.

One important note: if your email is written directly in config, it may expose your address. But GitHub can hide your email address. See this article. You can enable Keep my email addresses private in GitHub to get a noreply email address. CLI Git will not use it automatically, but you can put that address in gitconfig to avoid exposing your real email.

If you prefer to use your real email locally, you can split your config and create a file such as .gitconfig.local to store personal info.

gitignore_global

gitignore_global contains global Git ignore rules (such as node_modules). You can modify it as needed. Its path must match the setting in gitconfig; otherwise Git won't load these rules.

If you don't like this approach, you can remove it and add a .gitignore file in each project instead, which gives more flexible per-project control.

tmux

My tmux configuration is based on oh-my-tmux Automatically install this configuration as follows:

curl -fsSL "https://github.com/gpakosz/.tmux/raw/refs/heads/master/install.sh#$(date +%s)" | bash

After syncing this repo, tmux mainly reads customizations from tmux/tmux.conf.local.

Enabled plugins

  • tmux-plugins/tmux-copycat: quick regex-based search in scrollback/copy-mode.
  • tmux-plugins/tmux-resurrect: save and restore tmux sessions/windows/panes.
  • 27medkamal/tmux-session-wizard: project/session switcher popup (fzf + zoxide).
  • tmux-plugins/tmux-sensible: safer defaults and compatibility tweaks.
  • tmux-plugins/tmux-yank: copy selected text into system clipboard.
  • tmux-plugins/tmux-open: open highlighted path/URL with system handler.

Optional but currently disabled:

  • tmux-plugins/tmux-cpu
  • tmux-plugins/tmux-continuum

TPM lifecycle keys:

  • Prefix + I: install plugins
  • Prefix + u: update plugins
  • Prefix + Alt + u: uninstall removed plugins

Enabled and custom features

  • Based on Oh My Tmux theme model and status segments.
  • Mouse mode enabled by default (set -g mouse on).
  • Larger scrollback history (set -g history-limit 10000).
  • Copy to OS clipboard enabled (tmux_conf_copy_to_os_clipboard=true).
  • Added split shortcut: Prefix + = for left/right split (split-window -h).
  • Kept split shortcut: Prefix + - for top/bottom split.
  • Added dd delete flow in session tree (Prefix + s):
    • first d enters delete key table
    • second d kills selected session/window/pane
    • Esc exits delete key table

Note: Prefix + s is tmux built-in choose-tree, while tmux-session-wizard default key is Prefix + T unless customized.

Common tmux shortcuts

Assume default prefix is Ctrl+b.

Session and tree

  • Prefix + s: open session tree (choose-tree)
  • j / k: move down/up in list
  • dd: delete selected item (custom behavior in this repo)
  • Prefix + T: open session wizard popup (plugin default)

Windows and panes

  • Prefix + c: create new window
  • Prefix + w: open window tree/list
  • Prefix + -: split top/bottom
  • Prefix + =: split left/right (custom)
  • Prefix + x: kill current pane
  • Prefix + z: zoom/unzoom pane
  • Prefix + q: show pane numbers

Navigation and maintenance

  • Prefix + h/j/k/l: move between panes
  • Prefix + H/J/K/L: resize pane
  • Prefix + r: reload tmux config
  • Prefix + m: toggle mouse mode (custom toggle)

Copy mode and clipboard

  • Prefix + [: enter copy mode
  • In copy-mode-vi: v start selection, y copy and exit
  • Copied content is piped to system clipboard on macOS/Linux when backend tool is available

nvim

Based on nvchad nvim configuration, If you don't have nvim installed, you can use the following command to install it (macOS):

brew install nvim

Or download it from the official website.

Brewfile

It contains Homebrew packages installed via brew. Please inspect this file with a text editor first and adjust it to your needs. It uses Brewfile format. You can find more details here.

Then install with:

brew bundle --file=./Brewfile

About the appdir parameter

appdir is an option in Homebrew Brewfile. It specifies where cask apps are installed. By default, Homebrew installs apps into /Applications. If you want another directory, you can set this parameter, for example:

brew install --cask devtoys --appdir="~/Applications"

Why do I use appdir?

On macOS, the first user account is always an administrator account. Administrator accounts belong to the admin group and have sudo privileges. This means they can effectively control the system, including privileged operations, which increases risk.

Tools like sudo can have weaknesses that may be exploited by concurrently running programs.

Apple recommends this best practice: use a separate standard account for daily work, and use an administrator account only for installation and system configuration.

You don't have to log in through the macOS login screen as the admin account all the time. When terminal commands require admin privileges, the system prompts for authentication, then the terminal continues with those privileges. For this, Apple provides guidance on hiding the admin account and its home directory here. It's an elegant approach to avoid having a visible “ghost” account.

Quoted from https://github.com/drduh/macOS-Security-and-Privacy-Guide

Chinese translation

If you don't want to pass this parameter every time you install a cask app, you can search online for alternatives.

bin

The bin folder contains custom commands/scripts. You can modify them as needed. This folder should be added to your PATH environment variable so you can run commands directly in terminal.

macos

The macos folder contains macOS configuration scripts (for example, system preference settings). You can modify them as needed. Scripts in this folder should be made executable with chmod +x, then run directly in terminal.

The macos scripts can use the defaults command to modify system preferences. You can read more about defaults here.

install.sh

This one-shot script does the following:

  • macOS: installs Homebrew (with confirmation), then installs apps/packages from Brewfile
  • Linux: skips Homebrew/Brewfile and uses your detected package manager for required packages
  • Installs oh-my-zsh
  • Installs p10k or starship (starship by default)
  • Installs zsh plugins
  • Prints Meslo Nerd Font guidance at the end

For Meslo Nerd Font:

About

my dotfiles for macos

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages