Skip to content
jasonfungsingPublic

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Latest commit

 

History

317 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Dotfiles

Personal development environment configuration and setup automation for macOS 26.3+.

What This Is

This repository contains my dotfiles and an automated setup script to quickly bootstrap a new macOS machine with my preferred development environment, tools, and configurations. It includes shell configurations, editor settings, terminal multiplexer setup, Git configuration, macOS system preferences, and curated development tooling.

Quick Start

git clone https://github.com/jasonfungsing/dotfiles.git ~/.dotfiles
cd ~/.dotfiles
./install.sh
exec zsh

Prerequisites

  • macOS 26.3 or later
  • Command line tools for Xcode (installed automatically by script)
  • Git (installed automatically if needed)
  • Administrator access (required for some macOS settings and Homebrew installation)
  • Internet connection (for downloading packages and tools)
  • Approximately 5-10 GB of free disk space (for all packages)

What Gets Installed

Dotfiles & Configurations

File Purpose
.zshrc Zsh shell configuration with aliases, plugins, and integrations
.alias_prompt.sh Alias reminder — blocks Enter and suggests the alias when one exists for the typed command
.config/nvim/* Neovim configuration (pure Lua, modular — init.lua plus config/keymaps/plugins/theme/utils)
.tmux.conf Terminal multiplexer (tmux) configuration
.gitconfig Git version control configuration
.hushlogin Suppresses macOS login message

Homebrew Packages (100+)

Organized by category:

  • DevOps & Cloud: Docker, Kubernetes (kubectl, helm, minikube, kind, kops, skaffold, stern), Tailscale
  • Development: Go, Node.js, Python, Java, Ruby
  • Build Tools: Maven, Gradle, Make, CMake, Protobuf
  • CLI Utilities: git, tmux, tmuxinator, lazygit, ripgrep, fzf, jq, curl, wget, btop
  • Language Tools: golangci-lint, shellcheck
  • Databases: RocksDB
  • Miscellaneous: Pandoc, Tesseract OCR, Figlet

See the full package list with rationale.

Applications (via Homebrew Cask & Mac App Store)

  • IDEs: Xcode, Visual Studio Code
  • Terminal: iTerm2 (+ Powerline fonts)
  • Browsers: Google Chrome
  • AI assistants: Claude desktop, Claude Code CLI, Gemini
  • Development: Docker Desktop
  • Productivity: Raycast, Slack, Setapp, Logi Options+
  • Security: Little Snitch, Okta Verify
  • Media: AdBlock for Safari, Dark Reader for Safari

VS Code Extensions

Development extensions including Python, Go, Docker, GitHub integration, and Claude Code.

Installation

Automatic Installation (Recommended)

The install.sh script automates the entire setup process:

./install.sh

What it does (in order — apps install before their configs):

  1. Installs Homebrew, then all Brewfile packages, applications, and VS Code extensions
  2. Uninstalls brew packages, casks, taps, and VS Code extensions not declared in the Brewfile (the Brewfile is the source of truth — skip with --no-prune)
  3. Installs Oh-My-Zsh and sets Zsh as the default shell
  4. Creates symlinks for all dotfiles to your home directory
  5. Installs tmux plugins, points iTerm2 at its config folder (app/iterm2/), and symlinks VS Code settings (app/vscode/)
  6. Sets up the Neovim configuration
  7. Applies macOS system preferences and keyboard shortcuts
  8. Validates the finished setup

Failure handling: the installer only aborts up front for system-wide problems (not macOS, running as root, no network, incomplete repo clone, Command Line Tools missing and uninstallable — it tries a headless install and the GUI installer first). After that, a failing step never stops the run — the remaining steps continue, and every failure is listed in a summary at the end (with a non-zero exit code). Fix the causes and re-run; all steps are idempotent.

A full installation takes roughly 25-45 minutes, depending on internet and disk speed.

Command-Line Flags

Install only specific components:

./install.sh --shell-only        # Only shell config
./install.sh --editor-only       # Only editor config
./install.sh --git-only          # Only Git config
./install.sh --terminal-only     # Only terminal config
./install.sh --system-only       # Only macOS settings
./install.sh --no-brew           # Skip Homebrew packages
./install.sh --no-apps           # Skip applications
./install.sh --no-private        # Skip the private dotfiles repo
./install.sh --dry-run           # Show what would be done

Flags can be combined, e.g. ./install.sh --no-brew --no-apps.

Private companion repo

Licenses and machine-private overrides live in a separate private GitHub repo, not here. Near the end of a full run, install.sh asks whether to set it up: answering yes opens a GitHub login in the browser (if gh isn't already authenticated), clones the private repo to ~/Code/private-dotfiles, and runs its own install.sh, which links its files into place. Answering no (or --no-private, or a non-interactive run) skips it — re-run ./install.sh anytime to set it up later.

Manual Installation

If you prefer to install manually:

  1. Clone the repository:

    git clone https://github.com/jasonfungsing/dotfiles.git ~/.dotfiles
    cd ~/.dotfiles
  2. Create symlinks:

    ln -s ~/.dotfiles/terminal/zshrc ~/.zshrc
    ln -s ~/.dotfiles/terminal/alias_prompt.sh ~/.alias_prompt.sh
    ln -s ~/.dotfiles/terminal/tmux.conf ~/.tmux.conf
    ln -s ~/.dotfiles/git/gitconfig ~/.gitconfig
    ln -s ~/.dotfiles/git/gitignore_global ~/.gitignore_global
    ln -s ~/.dotfiles/mac/hushlogin ~/.hushlogin
    # Neovim is modular — link everything, not just init.lua
    mkdir -p ~/.config/nvim
    for item in ~/.dotfiles/neovim/*; do
      [ "$(basename "$item")" = "README.md" ] || ln -s "$item" ~/.config/nvim/
    done
  3. Install Homebrew and add it to your PATH:

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> "$HOME/.zprofile"
    eval "$(/opt/homebrew/bin/brew shellenv)"
  4. Install Oh-My-Zsh:

    sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
  5. Install packages:

    brew bundle --file=./brew/Brewfile
  6. Set Zsh as default shell:

    grep "$(command -v zsh)" /etc/shells || echo "$(command -v zsh)" | sudo tee -a /etc/shells
    chsh -s "$(command -v zsh)"
  7. Apply macOS settings:

    sh ~/.dotfiles/mac/macos.sh
  8. Reload your shell:

    exec zsh

On first launch, Neovim bootstraps lazy.nvim and installs all plugins automatically — no manual steps needed. See the Neovim documentation for details.

Customisation

Modifying Aliases

Edit alias_prompt.sh and zshrc to add or modify aliases. See the terminal documentation for the complete list and explanations.

Private Configuration

Three files hold machine-private settings, all loaded automatically when present and all provided by the private companion repo's installer (never tracked here):

  • ~/.zshrc.private — shell extras (keys, work aliases), sourced near the end of zshrc
  • ~/.gitconfig.local — git overrides (work identity, proxy), included at the bottom of the shared gitconfig so it wins
  • ~/.tmux.private — tmux extras, sourced at the end of tmux.conf

On a machine without the private repo, plain local files at the same paths work identically.

Changing macOS Settings

Edit mac/macos.sh to modify system preferences. See the macOS documentation for detailed explanations of each setting.

Adding Packages

To add new Homebrew packages:

  1. Edit Brewfile and add your package
  2. Run brew bundle install --file=brew/Brewfile to install

See the Homebrew documentation for the complete package list and rationale.

Updating Dependencies

To update all Homebrew packages:

brew update
brew upgrade

Directory Structure

dotfiles/
├── README.md                 # This file
├── install.sh                # Main installation script
│
├── brew/                     # Homebrew configuration
│   └── Brewfile              # Homebrew package definitions
│
├── neovim/                   # Neovim editor configuration
│   ├── init.lua              # Entry point (pure Lua)
│   ├── config/               # Core settings and autocmds
│   ├── keymaps/              # Key mappings
│   ├── plugins/              # Plugin specs
│   ├── theme/                # Colourscheme
│   └── utils/                # Helper utilities
│
├── terminal/                 # Terminal configuration (zsh + tmux)
│   ├── zshrc                 # Zsh shell configuration
│   ├── zshenv                # PATH for non-interactive shells (ssh/mosh remote commands)
│   ├── alias_prompt.sh       # Custom aliases and prompt
│   ├── cobalt2.zsh-theme     # Zsh theme
│   └── tmux.conf             # tmux configuration
│
├── git/                      # Git configuration
│   ├── gitconfig             # Git version control configuration
│   └── gitignore_global      # Global ignore rules (core.excludesfile)
│
├── app/                      # Application configuration
│   ├── iterm2/
│   │   └── com.googlecode.iterm2.plist  # iTerm2 terminal settings
│   ├── vscode/               # VS Code editor configuration
│   │   ├── settings.json     # Editor settings (symlinked by install.sh)
│   │   └── keybindings.json  # Keybindings (Cmd+Enter → Claude CLI submit)
│   ├── claude/               # Claude Code config (settings, keybindings, status line)
│   ├── copilot/
│   │   └── settings.json     # Copilot CLI preferences (symlinked by install.sh)
│   ├── setapp/
│   │   ├── apps.txt          # Tracked Setapp app list (no Setapp CLI — installs stay manual)
│   │   ├── export-apps.sh    # Regenerate apps.txt from /Applications/Setapp
│   │   ├── export-prefs.sh   # Export each Setapp app's settings to prefs/
│   │   └── prefs/            # App settings plists (imported on fresh machines only)
│   ├── sublime-text/
│   │   └── User/             # Whole Packages/User dir (symlinked by install.sh)
│   └── sublime-merge/
│       └── User/             # Whole Packages/User dir (symlinked by install.sh)
│
└── mac/                      # macOS system configuration
    ├── macos.sh              # macOS system preferences script
    ├── export-shortcuts.sh   # Export keyboard shortcuts to JSON
    ├── keyboard-shortcuts.json  # Saved keyboard shortcuts
    └── hushlogin             # Suppress macOS login message

Troubleshooting

Things the installer cannot do for you

Some failures need a human — they'll appear in the end-of-run failure summary, and these are the fixes:

Failure Manual fix
App Store apps fail ("Not signed in") Sign into the App Store app, re-run
App Store app not purchased on this Apple ID Buy/accept it in the App Store once, re-run
Cask adopt fails on an app you installed by hand (version mismatch) Trash the old app copy, re-run (brew installs a fresh one)
"Operation not permitted" modifying an app bundle, even with sudo System Settings → Privacy & Security → App Management → enable your terminal, restart it, re-run
Little Snitch / network filter blocks downloads Approve the connections in the filter, re-run
Corporate proxy breaks TLS downloads Set HTTPS_PROXY/trust the proxy cert per IT instructions
MDM-managed apps (CrowdStrike Falcon, Workspace ONE) Deliberately not brew-managed — leave them to IT
System-extension apps (Little Snitch) installed but inert Approve the extension in System Settings when prompted

Installation script fails

If the script exits with an error:

  1. Ensure you're in the dotfiles directory: cd ~/.dotfiles
  2. Make the script executable: chmod +x ./install.sh
  3. Run with bash explicitly: bash ./install.sh
  4. Check your internet connection and review the error message

Installation fails with permission errors

Do not run the installer with sudo — it refuses to run as root (Homebrew won't, and symlinks would land in root's home). Run it as your normal user; the steps that genuinely need admin rights prompt for your password themselves.

Symlinks already exist

No action needed — the installer is safe to re-run and always converges on this repo's state. Correct symlinks are left alone, wrong or dangling ones are re-pointed, and a pre-existing real file is backed up to <name>.backup.<timestamp> before being replaced, so nothing is lost.

Or remove it outright:

rm ~/.zshrc && ./install.sh

Zsh not recognised as default shell

Verify installation:

echo $SHELL

If not zsh, ensure it is listed in /etc/shells and set it as default:

grep "$(command -v zsh)" /etc/shells || echo "$(command -v zsh)" | sudo tee -a /etc/shells
chsh -s $(which zsh)

Homebrew installation fails

Ensure you have Command Line Tools installed:

xcode-select --install

Also check free disk space (df -h) and run brew doctor.

Package installation fails

Some packages may require additional dependencies. Check individual package documentation or run:

brew doctor

If brew bundle fails on a specific package, verify it exists with brew search <package-name> and try installing it individually with brew install <package-name>.

macOS settings not applied

Re-run the settings script:

./mac/macos.sh

Some settings require a logout/login. To apply immediately:

killall Finder Dock Mail SystemUIServer

Validation

A full ./install.sh run validates the setup automatically at the end. To validate on its own — after a partial install, or any time something feels off:

./install.sh --validate

This checks:

  • Every symlink exists, points at the right file in this repo, and resolves (dangling symlinks fail)
  • Configs actually load: zsh syntax + interactive startup, Neovim headless launch, tmux config parse, git user.name
  • Zsh is the default shell and Oh-My-Zsh is present
  • brew bundle check confirms the machine matches the Brewfile
  • Key tools (git, jq, node, python3, go) are on the PATH
  • iTerm2 loads its preferences from app/iterm2/
  • Repo health: keyboard-shortcuts.json is valid JSON, install.sh parses

It exits 0 only when every check passes.

You can also spot-check individual components manually:

echo $SHELL           # Should show /opt/homebrew/bin/zsh or /usr/bin/zsh
alias | grep "^t="    # Should show tmux alias
git config user.name  # Should show your name
brew --version        # Should show Homebrew version

Updating

To keep your environment up to date:

u  # Update all packages, casks, Oh-My-Zsh, and Neovim plugins

Or use the full command:

update  # brew update + upgrade (incl. casks) + cleanup, omz update, then
        # nvim --headless "+Lazy! sync" +qa to update Neovim plugins

Uninstallation

To remove the dotfiles configuration:

# Remove symlinks
rm ~/.zshrc
rm ~/.tmux.conf
rm ~/.gitconfig
rm ~/.alias_prompt.sh
rm ~/.hushlogin
rm ~/.oh-my-zsh/custom/themes/cobalt2.zsh-theme
find ~/.config/nvim -maxdepth 1 -type l -delete   # all Neovim config symlinks

# Set bash back as default shell
chsh -s /bin/bash

# Remove dotfiles directory (if desired)
rm -rf ~/.dotfiles

Documentation

For detailed information, see:

Technology Stack

This dotfiles configuration supports a modern development stack focused on:

  • Cloud & DevOps: Docker, Kubernetes, Tailscale
  • Backend Development: Go, Python, Node.js, Java, Ruby
  • Development Tools: Git, tmux, Neovim, VS Code
  • Infrastructure: Helm, Kops, Minikube, Skaffold

Contributing

These are personal dotfiles, but feel free to fork and adapt to your needs.

License

Personal use only. Feel free to use as reference for your own dotfiles.

Support

For issues or questions:

  1. Check Troubleshooting section
  2. Review the relevant folder's README (brew, mac, terminal, neovim)
  3. Check macOS and Homebrew documentation (brew help, man zsh, man tmux)

Last Updated: July 14, 2026 macOS Version: 26.3+ Shell: Zsh Package Manager: Homebrew

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages