Kshitij (Tjay) Dhyani

Command Palette

Search for a command to run...

macOS on Steroids

The ultimate macOS setup guide for developers who want peak productivity.

This is my almanac for setting up a new macOS machine to my workflows.

Setting up with a coding agent? Run the sections top to bottom. The Brewfile is safe to re-run, and the steps that need a password, a license, or a click in System Settings say so.

Initial System Setup

Step 1: Basic macOS Configuration

Before installing any applications, let's configure macOS for optimal productivity:

1Enable tap to click:

System Settings → Trackpad → Point & Click → Tap to click

2Speed up key repeat rate:

defaults write -g InitialKeyRepeat -int 15defaults write -g KeyRepeat -int 2

3Show hidden files in Finder:

defaults write com.apple.finder AppleShowAllFiles YESkillall Finder

4Disable press-and-hold for accented characters:

defaults write -g ApplePressAndHoldEnabled -bool false

5Show path bar in Finder:

defaults write com.apple.finder ShowPathbar -bool true

6Show status bar with available space in Finder:

defaults write com.apple.finder ShowStatusBar -bool true

7Enable Quit option for Finder:

defaults write com.apple.Finder QuitMenuItem 1killall Finder

What this does: The path bar shows your current folder location at the bottom of Finder windows, while the status bar displays available disk space and item counts. Enabling the Quit menu item allows you to fully quit Finder (useful when Pumba's Panel is your primary file browser)!

8Dock: right edge, small, instant auto-hide, a Quick Note hot corner (bottom-right), and nothing in it but Zen, not even recent apps. The Hyper keys below launch everything else, so the Dock barely needs to exist:

# Position, size, auto-hide
defaults write com.apple.dock orientation -string right
defaults write com.apple.dock tilesize -int 32
defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock autohide-delay -float 0
defaults write com.apple.dock autohide-time-modifier -float 0.4

# No "suggested and recent apps" section
defaults write com.apple.dock show-recents -bool false

# Bottom-right hot corner → Quick Note
defaults write com.apple.dock wvous-br-corner -int 14
defaults write com.apple.dock wvous-br-modifier -int 0

# Dock contents: wipe Apple's defaults, pin only Zen
# (run this part after the Brewfile below has installed dockutil and Zen)
dockutil --remove all --no-restart
dockutil --add /Applications/Zen.app --no-restart

killall Dock

9Turn off macOS's built-in window tiling so it doesn't fight Rectangle:

defaults write com.apple.WindowManager EnableTilingByEdgeDrag -bool false
defaults write com.apple.WindowManager EnableTopTilingByEdgeDrag -bool false
defaults write com.apple.WindowManager EnableTilingOptionAccelerator -bool false
defaults write com.apple.WindowManager EnableTiledWindowMargins -bool false

10Dark mode and natural scrolling off (log out to apply). Menu bar icon spacing is left to Bartender, which resets the spacing keys anyway:

defaults write -g AppleInterfaceStyle -string Dark
defaults write -g com.apple.swipescrolldirection -bool false

11Free up system shortcuts: Raycast takes ⌘Space, CleanShot takes ⌘⇧3/4/5, and ⌃Space, ⌃←/⌃→ and ⌃1 stop switching input sources and Spaces. Put Raycast on ⌘Space and start it first, so you're never left without a launcher:

defaults write com.raycast.macos raycastGlobalHotkey -string "Command-49"   # 49 = Space
open -a Raycast

Then take the shortcuts away from macOS:

# id:char,keycode,modifiers. Screenshots 28-31 + 184, input source 60-61,
# Spotlight 64-65, move a Space left/right 79 + 81, Desktop 1 118
for s in 28:51,20,1179648 29:51,20,1441792 30:52,21,1179648 31:52,21,1441792 \
         184:53,23,1179648 60:32,49,262144 61:32,49,786432 64:32,49,1048576 \
         65:32,49,1572864 79:65535,123,8650752 81:65535,124,8650752 118:65535,18,262144; do
  id=${s%%:*}; IFS=, read -r a b c <<< "${s#*:}"
  defaults write com.apple.symbolichotkeys AppleSymbolicHotKeys -dict-add "$id" \
    "<dict><key>enabled</key><false/><key>value</key><dict><key>parameters</key><array><integer>$a</integer><integer>$b</integer><integer>$c</integer></array><key>type</key><string>standard</string></dict></dict>"
done
/System/Library/PrivateFrameworks/SystemAdministration.framework/Resources/activateSettings -u

Then, in CleanShot's settings, set ⌘⇧3 / ⌘⇧4 / ⌘⇧5 as its fullscreen, area, and all-in-one shortcuts

12App preferences. Quit each app first, or it writes its old settings back on exit. Rectangle keeps only almost-maximize on ⌃⌥↩ plus the half-screen defaults, Trimmy trims on its own with its hotkeys off, and CleanShot saves to Downloads:

R=com.knollsoft.Rectangle
defaults write $R alternateDefaultShortcuts -bool true
defaults write $R allowAnyShortcut -bool true
defaults write $R hideMenubarIcon -bool true
defaults write $R launchOnLogin -bool true
defaults write $R almostMaximize -dict keyCode -int 36 modifierFlags -int 786432
for a in topHalf bottomHalf topLeft topRight bottomLeft bottomRight center \
         firstThird centerThird lastThird firstTwoThirds centerTwoThirds lastTwoThirds \
         maximize maximizeHeight larger smaller restore; do
  defaults write $R $a -dict
done

T=com.steipete.trimmy
defaults write $T generalAggressiveness -string high
defaults write $T terminalAggressiveness -string high
defaults write $T KeyboardShortcuts_trimClipboard -bool false
defaults write $T KeyboardShortcuts_pasteOriginal -bool false

defaults write pl.maketheweb.cleanshotx exportPath -string "$HOME/Downloads"

13Keep the screen on. The display and the Mac never sleep on idle (closing the lid still sleeps it), and there's no screen saver:

sudo pmset -a displaysleep 0 sleep 0
defaults -currentHost write com.apple.screensaver idleTime -int 0

14No widgets. A new Mac puts Calendar, Weather, and Photos widgets on the desktop; hide the widget layer (log out to apply), and stop Photos from opening whenever an iPhone is plugged in:

# System Settings → Desktop & Dock → Show Widgets: off (desktop and Stage Manager)
defaults write com.apple.WindowManager StandardHideWidgets -int 1
defaults write com.apple.WindowManager StageManagerHideWidgets -int 1

# Don't open Photos when an iPhone or camera is connected
defaults -currentHost write com.apple.ImageCapture disableHotPlug -bool YES

15Remove the stock apps I don't use. Only the App Store bundles can go: GarageBand, iMovie, Keynote, Numbers, and Pages, about 8.5 GB with GarageBand's sound library (skip the Logic folder if you use Logic Pro). They go to the Trash, so this is undoable:

for app in GarageBand iMovie Keynote Numbers Pages \
           "Keynote Creator Studio" "Numbers Creator Studio" "Pages Creator Studio"; do
  [ -d "/Applications/$app.app" ] && sudo mv "/Applications/$app.app" ~/.Trash/
done
sudo mv "/Library/Application Support/GarageBand" "/Library/Application Support/Logic" \
        "/Library/Audio/Apple Loops" ~/.Trash/

Safari and everything in /System/Applications (Mail, Music, TV, Maps, News…) live on the sealed system volume and can't be deleted without turning off SIP, which isn't worth it. They stay out of the way anyway: the Dock holds only Zen, and the defaults further down send every file type to my own apps.

Wallpapers & Visual Setup

Desktop Wallpapers

My collection of desktop wallpapers:

SpaceX Starship lifting off through orange-lit smoke beneath a blue skyDracula Mac WallpaperMain WallpaperGojo Suguru Wallpaper

Twitter Banners

For your Twitter account banners and social media:

Twitter BannerSocial Media BannerAlternative BannerBanner OptionDark Anime Banner

Profile Pictures

For consistency across all your accounts:

Original Profile PictureLight Theme Profile PictureDark Theme Profile PictureSilver Surfer Profile PictureMatrix Agent Smith Pixel Art Profile Picture

Installing Homebrew & Core Applications

Step 1: Install Homebrew

Homebrew is the essential package manager for macOS. It simplifies installing and managing applications.

Run this command in Terminal:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

After installation, add Homebrew to your PATH:

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofileeval "$(/opt/homebrew/bin/brew shellenv)"

Step 2: Install Essential Applications

Now let's install all the applications you'll need. I've organized them by category with detailed explanations:

One-Command Installation

Install everything at once with a Brewfile. brew bundle installs each entry on its own, so one renamed or broken cask doesn't sink the rest, and re-running it only installs what's missing:

Priority: Little Snitch goes in first. It needs admin rights, and you approve its system extension and network filter in System Settings → Privacy & Security, so it's watching before the rest of the install starts phoning home.

brew bundle --file=- <<'EOF'
# Priority: the outbound firewall goes in first
cask "little-snitch"

# Third-party taps (Homebrew only loads taps you trust)
tap "steipete/tap"

# CLI tools
brew "node@24", link: true
brew "fnm"
brew "python"
brew "git"
brew "git-lfs"
brew "gh"
brew "uv"
brew "bun"
brew "zoxide"
brew "atuin"
brew "fzf"
brew "yt-dlp"
brew "gallery-dl"
brew "ffmpeg"
brew "exiftool"
brew "pandoc"
brew "poppler"
brew "ghostscript"
brew "watch"
brew "duti"
brew "dockutil"
brew "mas"
brew "rclone"
brew "apify-cli"
cask "gcloud-cli"

# Browsers
cask "zen"
cask "arc"
cask "google-chrome"

# AI and dev tools
cask "claude"
cask "chatgpt"
cask "claude-code@latest"
cask "codex"
cask "ghostty"
cask "zed"
cask "orbstack"
cask "ngrok"
cask "steipete/tap/codexbar", trusted: true

# Productivity and system
cask "obsidian"
cask "raycast"
cask "bettertouchtool"
cask "rectangle"
cask "bartender"   # Bartender 7 = macOS 27 only; on macOS 26 install Bartender 6 (see below)
cask "flux-app"
cask "steipete/tap/trimmy", trusted: true
cask "cotypist"
cask "alcove"
cask "iloader"
cask "mole-app"

# Office and reading (mail, calendar, dictation and files live in Pumba)
cask "libreoffice"
cask "calibre"

# Communication
cask "discord"
cask "slack"
cask "telegram"
cask "zoom"

# Creative and media
cask "cleanshot"
cask "pixelsnap"
cask "screen-studio"
cask "figma"
cask "iina"

# Audio, privacy, fonts
cask "finetune"
cask "soundsource"
cask "protonvpn"
cask "font-jetbrains-mono-nerd-font"
EOF

Then the few things Homebrew can't install:

# Mac App Store: sign in to the App Store app first (mas needs sudo)
sudo mas install 937984704 6446206067 6469021132 310633997   # Amphetamine, Klack, PDFgear, WhatsApp

# pnpm through corepack (respects each repo's packageManager pin)
npm install -g corepack && corepack enable pnpm

# Grok CLI
curl -fsSL https://x.ai/cli/install.sh | bash

Not in the Brewfile on purpose: DaVinci Resolve (no cask), Pear Desktop (pinned version), and Pumba (built from source), all below.

Core Command Line Tools
brew install node@24 && brew link --force node@24

Node.js - JavaScript runtime, pinned to the 24 LTS line. node@24 is keg-only, so link it to put node/npm on your PATH. apify-cli pulls in the latest node as a dependency, and its npm files block the link; brew link --overwrite --force node@24 fixes it (apify-cli keeps its own Node)

brew install fnm && fnm default system

fnm - Per-project Node versions: cd into a repo and fnm switches to the version in its .nvmrc (installing one is fnm install <version>). fnm default system keeps Homebrew's node@24 everywhere else. Shell hook in the .zshrc additions below

brew install python

Python - Essential programming language for scripting and development

brew install git git-lfs && git lfs install

Git - Version control system (brew version is more up-to-date than macOS default), plus Git LFS for repos with large binary files

brew install uv

uv - Extremely fast Python package and project manager, written in Rust

brew install zoxide

zoxide - Smarter cd command that remembers your most used directories

brew install atuin

Atuin - Magical shell history with sync across machines

brew install yt-dlp

yt-dlp - Download videos/images from YouTube and 1000+ other sites

brew install gallery-dl

gallery-dl - Download image galleries and collections from Instagram, Twitter/X, Reddit, Pinterest, and hundreds of other sites

brew install fzf

fzf - Command-line fuzzy finder for files, history, and processes

brew install gh

GitHub CLI - PRs, issues, releases, and auth from the terminal. Coding agents lean on it heavily

brew install ffmpeg exiftool pandoc poppler ghostscript

Media & document toolbelt:

  • ffmpeg - convert, trim, and transcode any audio/video
  • exiftool - read, write, and strip photo/video metadata
  • pandoc - convert between Markdown, DOCX, HTML, PDF, and friends
  • poppler / ghostscript - PDF text extraction, rendering, and compression
brew install --cask gcloud-cli && brew install rclone

Cloud CLIs: Google Cloud (gcloud, bq) and rclone, which syncs files to and from any cloud storage

brew install watch

watch - rerun a command every N seconds

brew install apify-cli

Apify CLI - Run and deploy Apify scrapers (Actors) from the terminal

curl -fsSL https://x.ai/cli/install.sh | bash

Grok CLI - xAI's terminal coding agent. Installs to ~/.grok/bin and adds itself to your PATH

npm install -g corepack && corepack enable pnpm

pnpm through corepack, so each repo gets the pnpm version its packageManager field pins

Browsers
brew install --cask zen

Zen Browser - Privacy-focused browser with excellent customization. My default browser

brew install --cask arc

Arc - Chromium browser with spaces and a vertical sidebar. My second browser, on Hyper + Q

brew install --cask google-chrome

Chrome - Primary browser with excellent DevTools

Development Tools
brew install --cask claude

Claude - Anthropic's desktop app: chat, plus a Code tab that runs Claude Code sessions with a GUI. My main agent surface (Hyper + E)

brew install --cask claude-code@latest

Claude Code - Anthropic's terminal coding agent. The @latest cask tracks the fast release channel; plain claude-code is the stable channel. Skills, plugins, and config are covered further down

brew install --cask codex

Codex CLI - OpenAI's terminal coding agent. The desktop Codex experience lives inside the ChatGPT app (below)

brew install --cask zed

Zed - Free, open-source editor written in Rust, and my default app for every text and code file (setup below). It opens fast, the gutter marks lines changed against git, Project Diff shows every uncommitted change, and the Git Panel stages hunks and commits, so it doubles as my git client. zed . opens a folder

brew install --cask orbstack

OrbStack - Drop-in Docker Desktop replacement plus lightweight Linux VMs. Faster, lighter on battery, and the docker CLI just works

brew install --cask ngrok

ngrok - Expose a localhost port on a public URL for webhooks and demos

brew install --cask ghostty

Ghostty - Fast, feature-rich terminal emulator, and my default terminal (setup below)

brew install --cask steipete/tap/codexbar

CodexBar - Free, open-source menu bar app that keeps every AI coding usage window, credit balance, and reset timer in view across 40+ providers (Codex, Claude Code, Cursor, and more). No login required

Productivity & System Tools
gh repo clone wimpywarlord/pumba ~/Documents/pumba

Pumba - My own app (Hyper + A): a fully local meeting notetaker. It lives in the menu bar, notices when a meeting starts, records your mic and only the meeting app's audio, and writes notes where every point links back to the moment it was said. Transcription and summaries run on the Mac. It also took over from four apps I used to install: Mail (Gmail) replaces Meru, Calendar replaces Notion Calendar, Dictation replaces VoiceInk, and Panel, a keyboard-first file browser, replaces ForkLift. Build and install it with scripts/install.sh; the README lists what that needs (Xcode 26.6 with the Metal Toolchain, a local signing identity, and the model download)

brew install --cask obsidian

Obsidian - Local-first Markdown knowledge base. Plain files on disk, so agents can read and write my notes too (Hyper + D)

brew install --cask raycast

Raycast - Launcher with clipboard history, snippets, window commands, and extensions. On ⌘Space (Step 11 takes that shortcut away from Spotlight)

brew install --cask bettertouchtool

BetterTouchTool - Customize trackpad gestures, keyboard shortcuts, and Touch Bar

brew install --cask flux-app

f.lux - Adjust screen color temperature based on time of day

brew install --cask rectangle

Rectangle - Window management made simple with keyboard shortcuts (my trimmed-down config is in Step 12)

brew install --cask bartender

Bartender - My go-to menu bar manager. Hide, reorder, and reveal menu bar items, with triggers, hotkeys, and per-item show/hide rules. Paid, the most polished option. Heads-up: the cask now installs Bartender 7, which only runs on macOS 27 (on macOS 26 it quits with "macOS 26 compatibility isn't ready yet"). On macOS 26, install the last Bartender 6 instead, checked against the hash Homebrew recorded for it:

curl -fsSL -o /tmp/Bartender6.zip "https://downloads.macbartender.com/B2/updates/6-6-2/Bartender%206.zip"
echo "e178616bc09956e39f0ab0ff9112b8fe89f744b406f8e417fb7b2aaf3524e064  /tmp/Bartender6.zip" | shasum -a 256 -c
ditto -x -k /tmp/Bartender6.zip /Applications/
sudo mas install 937984704

Amphetamine - Keep your Mac awake. Free from the Mac App Store with advanced triggers and session control

sudo mas install 6446206067

Klack - Satisfying mechanical keyboard sounds for every keystroke. Available on the Mac App Store

brew install --cask steipete/tap/trimmy

Trimmy - Watches your clipboard and folds multi-line shell snippets (pipes, redirects, line continuations) into a single pasteable line. I run it on auto-trim with its hotkeys off (Step 12). No dock icon, no network, no daemon

brew install --cask cotypist

Cotypist - On-device AI that predicts your next words in every Mac app. Press Tab to accept. Open source — make your own version

brew install --cask alcove

Alcove - Turns the notch into a Dynamic Island — music controls, notifications, and widgets in the dead space. Lightweight, one-time purchase

brew install --cask iloader

iloader - iOS sideloading companion for getting apps onto your iPhone from the Mac

Office & Documents
brew install --cask libreoffice

LibreOffice - Free and powerful office suite

sudo mas install 6469021132

PDF Gear - Excellent free PDF editor with annotation tools, from the Mac App Store. My default PDF app

brew install --cask calibre

calibre - Ebook library manager and converter. How books get onto my Kobo

Communication
brew install --cask discord

Discord - Community and team communication

sudo mas install 310633997

WhatsApp - Popular messaging platform. I use the Mac App Store build (Hyper + R)

brew install --cask slack

Slack - Work and team communication

brew install --cask telegram

Telegram - Fast messaging with a native macOS client

brew install --cask zoom

Zoom - Video calls

Creative & Media Tools
brew install --cask cleanshot

CleanShot X - Advanced screenshot and screen recording tool

brew install --cask pixelsnap

PixelSnap 2 - Pixel-perfect on-screen measurement tool with edge detection. Measure distances, sizes, and grab colors anywhere on screen. Integrates with CleanShot for design and dev work (Hyper + P)

brew install --cask screen-studio

Screen Studio - Professional screen recording with beautiful animations

DaVinci Resolve - Professional video editing and color grading. The Homebrew cask is gone, so download the installer from Blackmagic directly

brew install --cask figma

Figma - Collaborative design tool for UI/UX

Media Players
brew install --cask iina

IINA - Modern media player designed specifically for macOS. My default for all audio and video (setup below)

brew install --cask pear-devs/pear/pear-desktop

Pear Desktop - Unofficial YouTube Music desktop app (formerly th-ch/youtube-music) with ad-block, plugins, and a proper native window. Installs as YouTube Music.app

I'm pinned to 3.11.0. 3.12.0 was a regression for my setup, so the brew cask (which tracks latest) is not the way to restore it. Pull the exact DMG from GitHub releases instead:

cd ~/Downloads
curl -LO https://github.com/pear-devs/pear-desktop/releases/download/v3.11.0/YouTube-Music-3.11.0-arm64.dmg
MOUNT=$(hdiutil attach -nobrowse YouTube-Music-3.11.0-arm64.dmg | grep -o '/Volumes/.*')
rm -rf "/Applications/YouTube Music.app"
cp -R "$MOUNT/YouTube Music.app" /Applications/
hdiutil detach "$MOUNT"
defaults read "/Applications/YouTube Music.app/Contents/Info.plist" CFBundleShortVersionString   # → 3.11.0

Settings and plugins live in ~/Library/Application Support/YouTube Music and survive a swap of the .app. Back that folder up if you care about your config.

Keeping it pinned: plain brew upgrade skips this cask (auto_updates), so the daily routine is safe. Never run brew upgrade --greedy or brew reinstall --cask pear-desktop — both drag in latest. Inside the app, keep auto-update off (Options menu, or set "autoUpdates": false under options in config.json) and decline the update prompt if it ever shows.

Audio Utilities
brew install --cask finetune

FineTune - My pick. Free, open-source per-app volume control and audio routing in the menu bar

brew install --cask soundsource

SoundSource - My backup, since I own a license. Advanced per-app volume control, audio routing, and system-wide EQ

Security & Privacy
brew install --cask little-snitch

Little Snitch - Outbound firewall. See and block every connection every app tries to make. Priority install: it's first in the Brewfile, and it needs admin rights plus a manual approval of its system extension. The Network Monitor window is only the traffic viewer: quit it (⌘Q) to keep it out of the Dock and ⌘Tab, and the firewall keeps running

brew install --cask protonvpn

ProtonVPN - Secure VPN service with strong privacy focus

brew install --cask chatgpt

ChatGPT - Official OpenAI desktop app. As of July 2026, the standalone Codex app has merged into ChatGPT: one app with Chat, Work, and Codex modes. No separate Codex desktop install — update ChatGPT (or your old Codex app) and switch to the Codex view for repos, diffs, PRs, and agent coding. You can set Codex as the default view / app icon if you live in the coding agent

Terminal Setup with Oh My Zsh

Step 1: Install Oh My Zsh

Oh My Zsh is a framework for managing your Zsh configuration with tons of helpful features.

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

The installer replaces ~/.zshrc (the old one is saved as ~/.zshrc.pre-oh-my-zsh), so run it before anything else appends to that file, or re-run the Grok installer afterwards

Step 2: Install Powerlevel10k Theme

The most powerful and customizable Zsh theme:

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

Then edit your ~/.zshrc:

nano ~/.zshrc

Change the theme line to:

ZSH_THEME="powerlevel10k/powerlevel10k"

Powerlevel10k's icons need a Nerd Font:

brew install --cask font-jetbrains-mono-nerd-font

Then pick JetBrainsMono Nerd Font as the terminal font.

Step 3: Install Essential Zsh Plugins

zsh-autosuggestions

Suggests commands as you type based on your history:

git clone https://github.com/zsh-users/zsh-autosuggestions.git $ZSH_CUSTOM/plugins/zsh-autosuggestions
zsh-syntax-highlighting

Provides syntax highlighting for your shell commands:

git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM/plugins/zsh-syntax-highlighting
zsh-fast-syntax-highlighting

Faster and more feature-rich syntax highlighting:

git clone https://github.com/zdharma-continuum/fast-syntax-highlighting.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/fast-syntax-highlighting
zsh-autocomplete

Real-time auto-completion as you type:

git clone --depth 1 -- https://github.com/marlonrichert/zsh-autocomplete.git $ZSH_CUSTOM/plugins/zsh-autocomplete
Enabling the Plugins

Edit your ~/.zshrc file and update the plugins line:

nano ~/.zshrc

Find the line that says plugins=(git) and replace it with:

plugins=(git zsh-autosuggestions zsh-syntax-highlighting fast-syntax-highlighting zsh-autocomplete)

Apply the changes:

source ~/.zshrc

Configuration Wizard: After restarting your terminal, Powerlevel10k will run a configuration wizard. Choose options that match your aesthetic preferences! Run it in Ghostty, which has the Nerd Font icons built in; elsewhere it falls back to a plain ASCII prompt. Moving from another Mac? Copy the old ~/.p10k.zsh over instead and skip the wizard.

Step 4: Advanced Terminal Tools Setup

Initialize Shell History with Atuin

Set up magical shell history sync:

echo 'eval "$(atuin init zsh)"' >> ~/.zshrcatuin import auto

The init line is what actually binds Ctrl+R and the up arrow to Atuin; without it Atuin is installed but does nothing. fzf (below) also claims Ctrl+R, and whichever loads last in ~/.zshrc wins, so keep this line after the fzf one. The import pulls in your existing shell history (on a fresh Mac there's none yet, so it errors harmlessly)

Moving from another Mac? Copy ~/.local/share/atuin/history.db and ~/.config/atuin/config.toml across, but on the old Mac flush the write-ahead log first, or the copy comes out malformed:

sqlite3 ~/.local/share/atuin/history.db 'pragma wal_checkpoint(TRUNCATE)'
Configure Zoxide for Smart Navigation

Initialize zoxide in your shell:

echo 'eval "$(zoxide init zsh)"' >> ~/.zshrc

Now use z instead of cd - it remembers your most used directories

Setup FZF Integration

Add fuzzy finding to your shell:

$(brew --prefix)/opt/fzf/install

Enables Ctrl+R for history search and Ctrl+T for file search

Step 5: Handy ~/.zshrc Additions

Auto-Activate Python Virtual Environments

Activates the nearest .venv whenever you cd into a project, puts pnpm on the PATH, and lets fnm switch Node per project:

# Auto-activate Python virtual environment if .venv exists (no auto-deactivate)

function auto_activate_env() {
  local dir=$PWD
  while [ "$dir" != "/" ]; do
    if [ -d "$dir/.venv" ]; then
      source "$dir/.venv/bin/activate"
      echo "✅ Activated virtual environment ($dir/.venv)"
      return
    fi
    dir=$(dirname "$dir")
  done
}

autoload -U add-zsh-hook
add-zsh-hook chpwd auto_activate_env

# Also activate immediately on shell startup
auto_activate_env

# pnpm
export PNPM_HOME="$HOME/Library/pnpm"
case ":$PATH:" in
  *":$PNPM_HOME:"*) ;;
  *) export PATH="$PNPM_HOME:$PATH" ;;
esac
# pnpm end

# fnm: per-project Node versions from .nvmrc (Homebrew's node@24 stays the default)
eval "$(fnm env --use-on-cd --version-file-strategy=recursive --corepack-enabled --log-level=error --shell zsh)"
# zsh caches command paths; re-hash after fnm switches Node on cd
_fnm_rehash() { rehash }
add-zsh-hook chpwd _fnm_rehash

Ghostty Terminal Configuration

Essential Ghostty Settings

My full Ghostty config, in ~/.config/ghostty/config:

# Restore windows, tabs, and splits on relaunch
window-save-state = always

# ~75 MB of scrollback per terminal (the value is in bytes; agent logs get long)
scrollback-limit = 75000000

cursor-style = bar
cursor-style-blink = true

background-opacity = 0.95
background-blur-radius = 20

What this does: Ghostty remembers your window positions, sizes, open tabs, and split configurations across sessions, and keeps enough scrollback that long agent runs never fall off the top. Config reference

Make Ghostty the Default Terminal

Ghostty is my default terminal. Point executables and .command / .tool scripts at it so a double-click opens Ghostty instead of Terminal (needs duti from the Brewfile):

GHOSTTY=com.mitchellh.ghostty

duti -s "$GHOSTTY" public.unix-executable all
duti -s "$GHOSTTY" com.apple.terminal.shell-script all
duti -s "$GHOSTTY" command all
duti -s "$GHOSTTY" tool all

# Verify: both should print Ghostty
duti -x command
duti -x tool

.sh and .zsh files stay with Zed for editing (see the Zed defaults below).

Hyper Key Setup & Macros

Ultimate Productivity Shortcuts

Using BetterTouchTool's Hyper Key (⌘⌥⌃⇧). Never use your eyes for navigation (vision search is slow), use your muscle memory:

Configure these shortcuts in BetterTouchTool:

  • Caps Lock → Act as Hyper Key (⌘⌥⌃⇧)
  • Hyper + Q → Launch Arc
  • Hyper + W → Launch Zen Browser
  • Hyper + E → Launch Claude
  • Hyper + R → Launch WhatsApp
  • Hyper + A → Pumba on Notes / to-dos (BetterTouchTool "Open URL" with pumba://notes, which also launches it)
  • Hyper + S → Launch ChatGPT (includes Codex)
  • Hyper + D → Launch Obsidian
  • Hyper + F → Launch Discord
  • Hyper + G → Launch YouTube Music
  • Hyper + N → Launch Figma
  • Hyper + P → PixelSnap (set this one in PixelSnap's own settings, not BetterTouchTool)
  • Hyper + 1 / 2 → Switch to Desktop 1 / 2. Two desktops max: add the second one in Mission Control
  • Pumba's own (set in Pumba's settings, not BetterTouchTool, or BetterTouchTool swallows them): Hyper + T dictation, Y paste last dictation, C calendar, X mail, Z Panel, M recording, V Splinter

Tip: The Hyper Key eliminates conflicts with existing shortcuts while giving you instant access to any app. It's the most efficient way to navigate your Mac! On a new machine, export your BetterTouchTool preset and import it instead of rebuilding these by hand.

Development Environment Setup

Bun - Fast JavaScript Runtime

Install Bun, a fast all-in-one JavaScript runtime and toolkit:

brew install bun

Bun is in homebrew-core now, so brew upgrade keeps it current. The old curl -fsSL https://bun.sh/install | bash installer still works if you prefer ~/.bun

What is Bun? Bun is a modern JavaScript runtime that's significantly faster than Node.js. It includes a bundler, test runner, and package manager all in one. Perfect for modern web development!

Python Environment with uv

We already installed uv via Homebrew earlier. Now let's use it to manage Python versions:

uv python install 3.12

Homebrew already brings a current Python 3.13/3.14 for scripts; uv manages the per-project versions. Run uv python pin 3.12 inside a project to write its .python-version

Why uv? uv is an extremely fast Python package and project manager written in Rust. It's 10-100x faster than pip and handles both package management and Python version management in one tool!

Git Configuration

Set up your Git identity and preferences:

git config --global user.name "Your Name"git config --global user.email "your.email@example.com"git config --global init.defaultBranch maingit config --global pull.rebase true

SSH Keys for GitHub

Generate and add SSH keys for secure GitHub access:

ssh-keygen -t ed25519 -C "your.email@example.com"eval "$(ssh-agent -s)"ssh-add ~/.ssh/id_ed25519pbcopy < ~/.ssh/id_ed25519.pub

Now go to GitHub → Settings → SSH Keys and paste

Or let the GitHub CLI do the key upload and auth in one go:

gh auth login

Pick GitHub.com → SSH → your id_ed25519.pub. This also gives coding agents a working gh for PRs and issues

My Global CLAUDE.md & AGENTS.md

Every coding agent I run inherits the same thinking style. I keep this prompt in my global ~/.claude/CLAUDE.md and a matching ~/.codex/AGENTS.md so Claude Code and Codex both reason the way I do by default. The block at the bottom routes work to the skills below, and the BuilderIO installer writes it for you:

Be organized, accurate, thorough, and detailed without unnecessary verbosity.

Treat me as an expert. Do not dumb things down.

Optimize for truth and correctness over approval, conformity, politeness, or harmony. If I'm wrong, say so directly.

Value good arguments over authorities or sources. Consider serious contrarian arguments alongside consensus expert views.

When useful, present the strongest counterargument to any position I appear to hold.

Do not capitulate when I push back unless I provide new evidence or a better argument.

Do not anchor on numbers, estimates, or assumptions I provide; generate your own independently.

Be skeptical by default. Look for hidden assumptions, failure modes, and ways to improve the answer, product, argument, or system.

My epistemology is the same as David Deutsch or Karl Popper. Naval Ravikant has serious resonance with my thinking loops.

Be surprisingly resourceful. Suggest non-obvious solutions. Be proactive and anticipate my needs. Assume I am high-agency and can make practically anything happen.

Cite sources. Use examples liberally.

Open-minded and impossible to offend. Be provocative, argumentative, and pointed when useful.

When copy editing, always mark changes inline.

About me: Kshitij (tjay) Dhyani (@type_tjay on X)

Founding engineer at an a16z-backed startup. Previously co-founded Ghostfeed (exited). Entrepreneur, technical, range of knowledge/experience.

<!-- BEGIN @agent-native/skills -->
When operating as Claude Fable, use the /efficient-fable skill always.
When using a high-cost frontier model for codebase-heavy work, use the /efficient-frontier skill always.
When writing final response status indicators, use the /quick-recap skill always.
When long-running or parallel work needs usage-limit checks, use the /stay-within-limits skill always.
<!-- END @agent-native/skills -->

Claude Code & Codex Skills

Skills are reusable instruction packs that live in ~/.claude/skills/ and load on demand. These are the ones I keep installed:

npx skills add jakubkrehel/skills --skill '*' -g -a claude-code -a codex -y

The skills CLI installs a skill repo once into ~/.agents/skills/ (which Codex reads natively), symlinks it into Claude Code, and tracks sources in ~/.agents/.skill-lock.json. -g installs for your user instead of the current project, -a picks the agents (leave it out and you get a skills folder for every agent the CLI knows), --skill picks skills from a repo, and -y skips the prompts. Every install below follows this pattern

Code Quality

  • thermo-nuclear-code-quality-review - Brutally strict maintainability review. Blocks files past 1,000 lines, rejects ad-hoc spaghetti conditionals, questions thin abstractions and magical behavior, and enforces architectural boundaries. From Cursor's team kit
npx skills add https://github.com/cursor/plugins/tree/main/cursor-team-kit/skills/thermo-nuclear-code-quality-review -g -a claude-code -a codex -y

Agent Orchestration & Usage

From BuilderIO/skills, which ships its own installer. --update-instructions also writes the routing block at the bottom of the CLAUDE.md above. Install all four in one run: each run rewrites that block with only its own skills, so a loop of single installs leaves just the last one:

npx @agent-native/skills@latest add \
  --skill efficient-fable --skill efficient-frontier --skill stay-within-limits --skill quick-recap \
  --client claude-code --client codex --scope user --update-instructions --no-connect
  • efficient-fable - Run Claude Fable as the orchestrator while cheaper subagents do token-heavy research, coding, and testing
  • efficient-frontier - Same orchestration pattern for any high-cost frontier model: delegate heavy lifting, keep planning and final review on the expensive model
  • stay-within-limits - Respects 5-hour and weekly usage limits — pauses near the cap and resumes when the window clears
  • quick-recap - Red/yellow/green status block convention for final agent responses

Frontend & Design

npx skills add jakubkrehel/skills --skill '*' -g -a claude-code -a codex -y
npx skills add jakubkrehel/make-interfaces-feel-better -g -a claude-code -a codex -y
npx skills add anthropics/skills --skill frontend-design -g -a claude-code -a codex -y
npx skills add vercel-labs/agent-skills --skill vercel-react-best-practices --skill web-design-guidelines -g -a claude-code -a codex -y
npx skills add ibelick/ui-skills --skill '*' -g -a claude-code -a codex -y
  • jakubkrehel/skills - The set I use most after the BuilderIO four. better-interface runs one review across better-accessibility, better-colors, better-layout, better-typography, better-writing, and better-ui (concentric border radius, optical alignment, surface depth, hit areas). Also break, explain-interface, interface-review, and variant
  • frontend-design - Distinctive, production-grade frontend interfaces that avoid generic AI aesthetics (anthropics/skills)
  • ibelick/ui-skills - Opinionated constraints for building interfaces. ui-skills-root routes to the smallest useful set: baseline-ui, improve-ui, fixing-accessibility, fixing-metadata, fixing-motion-performance, and create-design-md
  • web-design-guidelines - Reviews UI code for Web Interface Guidelines compliance — accessibility, UX, and design audits (vercel-labs/agent-skills)
  • vercel-react-best-practices - React and Next.js performance optimization guidelines from Vercel Engineering (vercel-labs/agent-skills)
  • make-interfaces-feel-better - Design-engineering details that make interfaces feel polished: micro-interactions, enter/exit animations, shadows, typography, tabular numbers

Writing & Content

npx skills add blader/humanizer -g -a claude-code -a codex -y
  • humanizer - Strips signs of AI-generated writing, based on Wikipedia's "Signs of AI writing" guide
  • tiktok-hooks - Generates Gen-Z / college-apps TikTok hooks for the first 1-3 seconds of a video

No public source for tiktok-hooks and create-plan (a concise read-only planner): copy their folders from the previous Mac's ~/.claude/skills.

Claude Code Plugins

From the official claude-plugins-official marketplace. A fresh install only knows the built-in directory, so add the marketplace first, then install each one:

claude plugin marketplace add anthropics/claude-plugins-official
for p in commit-commands code-simplifier context7 playwright github figma vercel frontend-design swift-lsp; do
  claude plugin install "$p@claude-plugins-official"
done
  • commit-commands - /commit and /commit-push-pr in one step
  • code-simplifier - Agent that simplifies recently changed code without changing behavior
  • context7 - Pulls current library docs instead of relying on stale training data
  • playwright - Browser automation for testing and clicking through flows
  • github, figma, vercel - First-party integrations for repos, design files, and deploys
  • frontend-design, swift-lsp - Design guidance and Swift language server support

The github plugin's MCP server needs a GITHUB_PERSONAL_ACCESS_TOKEN in your environment, and figma and vercel sign in through /mcp inside Claude Code. Rather than minting a separate token, I hand it the gh login from the Keychain, in ~/.zshrc:

export GITHUB_PERSONAL_ACCESS_TOKEN="$(/opt/homebrew/bin/gh auth token 2>/dev/null)"

MCP Servers

claude mcp add --scope user --transport http linear https://mcp.linear.app/mcp

Linear issues and projects from inside any Claude Code session

claude mcp add --scope user --transport http supabase "https://mcp.supabase.com/mcp?features=docs%2Caccount%2Cdatabase%2Cdebugging%2Cdevelopment%2Cfunctions%2Cbranching"

Supabase docs, databases, logs, edge functions, and branches. Signs in through /mcp on first use

claude mcp add --scope user davinci-resolve -- "/Applications/DaVinci Resolve/DaVinci Resolve.app/Contents/Applications/ResolveMCP"

The MCP server built into DaVinci Resolve 21 (names can't contain spaces, hence davinci-resolve): scripting, LUTs, and DCTLs from inside Claude Code. Install Resolve first

System Maintenance

Regular Updates

Keep your system and applications up to date:

# Update Homebrew and all packagesbrew update && brew upgrade# Update Oh My Zshomz update# Update npm packages globallynpm update -g

Cloud Backup: Additionally, use iCloud to sync your important folders.

Mole - Deep Clean Your Mac

Mole deep cleans and optimizes your Mac — find large files, clear caches, and reclaim disk space with a clean, fast UI.

brew install --cask mole-app

Mole - Multi-language Mac cleaner and optimizer. Mole now lives in Homebrew proper: the mole-app cask is the desktop app, and brew install mole gets the CLI. I keep it menu bar only, out of the Dock and ⌘Tab (quit Mole first):

defaults write com.tw93.MoleApp hideDockIcon -bool true
Loading...

Final Tips & Tricks

Touch ID for sudo

Enable Touch ID for sudo commands:

sed "s/^#auth/auth/" /etc/pam.d/sudo_local.template | sudo tee /etc/pam.d/sudo_local

Don't edit /etc/pam.d/sudo directly: macOS updates overwrite it and silently turn Touch ID back off. sudo_local is included by it and survives updates

Paste Without Formatting

Set up ⌘⇧V for paste without formatting in every app:

System Settings → Keyboard → Keyboard Shortcuts → App Shortcuts

Add shortcut for "Paste and Match Style" with ⌘⇧V

Paste without formatting setup

Reference: Reddit guide on paste without formatting

CleanShot X Auto Copy Setup

Enable auto copy to clipboard in CleanShot X for seamless screenshot workflow:

CleanShot X → Preferences → General → Auto copy to clipboard

Position the setting on the right side for easy access

Make CleanShot X the Default Image Viewer

macOS keeps reverting image defaults back to Preview because the "Open With → Change All" Finder dialog only binds a single UTI at a time and silently breaks when LaunchServices gets out of sync. Fix it permanently by setting every image UTI via duti:

brew install duti

A CLI for binding default apps by UTI — what the macOS GUI should have been

# CleanShot X's bundle ID is pl.maketheweb.cleanshotx
duti -s pl.maketheweb.cleanshotx public.jpeg all
duti -s pl.maketheweb.cleanshotx public.png all
duti -s pl.maketheweb.cleanshotx public.tiff all
duti -s pl.maketheweb.cleanshotx public.heic all
duti -s pl.maketheweb.cleanshotx public.heif all
duti -s pl.maketheweb.cleanshotx public.webp all
duti -s pl.maketheweb.cleanshotx com.compuserve.gif all
duti -s pl.maketheweb.cleanshotx public.image all

# Verify it stuck
duti -x jpg
duti -x png

If it still reverts, your LaunchServices database is corrupt — rebuild it and re-run the binds:

/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user
killall Finder

Why this works: Finder's "Change All" writes to a per-extension preference that other apps (and macOS updates) can stomp on. duti writes directly to the LaunchServices preferences plist using the canonical UTI, which is the same mechanism macOS itself uses internally — so the binding survives reboots, app updates, and OS upgrades.

Make IINA the Default Audio & Video Player

Same playbook as CleanShot above, but for IINA — the only macOS video player worth running. Bind every common audio/video UTI to com.colliderli.iina so QuickTime and Music stop hijacking your double-clicks:

IINA=com.colliderli.iina

# --- Video UTIs ---
for uti in \
  public.movie public.video public.audiovisual-content \
  public.mpeg-4 public.mpeg public.mpeg-2-video \
  public.avi public.3gpp public.3gpp2 \
  com.apple.quicktime-movie com.apple.m4v-video \
  com.microsoft.windows-media-wmv com.microsoft.advanced-systems-format \
  org.webmproject.webm public.flc-animation; do
  duti -s "$IINA" "$uti" all
done

# --- Audio UTIs ---
for uti in \
  public.audio public.mp3 public.mpeg-4-audio public.aac-audio \
  public.aifc-audio public.aiff-audio \
  com.apple.m4a-audio com.apple.coreaudio-format \
  com.microsoft.waveform-audio \
  org.xiph.flac org.xiph.ogg-audio com.real.realaudio; do
  duti -s "$IINA" "$uti" all
done

# --- Extension fallbacks for formats with non-canonical UTIs ---
# (.ts is deliberately left out: it's TypeScript far more often than MPEG-TS video)
for ext in mkv opus webm flac ogg m2ts mts mxf wv ape \
           rm rmvb ra asf vob flv f4v divx dv mp2 m3u m3u8; do
  duti -s "$IINA" "$ext" all
done

# Force-register IINA so LaunchServices knows its claims
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "/Applications/IINA.app"
killall Finder

Verify with duti -x mp4, duti -x mkv, duti -x mp3 — all three should print IINA.

Gotchas: A few obscure formats (tak, amv, xvid) have no registered UTI on macOS and will fail silently — ignore them. .pls playlists are aggressively claimed by Apple Music and IINA doesn't even declare them; not worth fighting since you'll likely never see one. Everything that matters (mp4 / mov / mkv / webm / mp3 / m4a / flac / opus / wav) sticks permanently.

Same trick for PDFs, pointing them at PDF Gear:

duti -s com.pdfeditor.pdfeditormac com.adobe.pdf all

And Zen for web links (macOS asks you to confirm the browser change):

duti -s app.zen-browser.zen http
duti -s app.zen-browser.zen https

Make Zed the Default for Text & Code

Out of the box, macOS scatters text files everywhere: Markdown into whatever ebook app claimed it, JSON into the browser, CSV into ChatGPT, .ts into a video player. I want all of it in Zed: it opens fast, and its gutter shows what changed against git. One script fixes it, and routes Word docs to LibreOffice while it's at it:

ZED=dev.zed.Zed
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "/Applications/Zed.app"

# --- Text, code, config, and data types, including ones other apps grab ---
for uti in public.plain-text public.source-code public.script public.shell-script \
  public.json public.xml public.yaml public.comma-separated-values-text \
  net.daringfireball.markdown com.apple.property-list com.apple.log \
  com.microsoft.typescript public.toml com.microsoft.ini org.iso.sql; do
  duti -s "$ZED" "$uti" all
done

# --- Extensions: bind each through duti, and collect the ones it can't ---
NOTYPE=()
for ext in md markdown mdx txt log json jsonc yaml yml toml xml plist csv tsv \
           ini cfg conf env lock js mjs cjs ts tsx jsx py sh zsh bash swift \
           c h cpp hpp java rb php go rs kt lua css scss sass less sql graphql \
           vue svelte astro svg; do
  duti -s "$ZED" "$ext" all 2>/dev/null
  duti -x "$ext" 2>/dev/null | head -1 | grep -qx "Zed" || NOTYPE+=("$ext")
done

# --- No registered type: write those as extension handlers, the way Finder's
#     "Change All" does, then restart LaunchServices so it reloads them ---
D=com.apple.LaunchServices/com.apple.launchservices.secure
defaults export $D /tmp/ls.plist
python3 - "${NOTYPE[@]}" <<'EOF'
import plistlib, sys
p, exts = "/tmp/ls.plist", sys.argv[1:]
d = plistlib.load(open(p, "rb"))
hs = [h for h in d.get("LSHandlers", []) if h.get("LSHandlerContentTag") not in exts]
hs += [{"LSHandlerContentTag": e,
        "LSHandlerContentTagClass": "public.filename-extension",
        "LSHandlerRoleAll": "dev.zed.zed",
        "LSHandlerPreferredVersions": {"LSHandlerRoleAll": "-"}} for e in exts]
d["LSHandlers"] = hs
plistlib.dump(d, open(p, "wb"))
EOF
defaults import $D /tmp/ls.plist && killall lsd

# --- Word-processor docs -> LibreOffice (sheets and slides already go there) ---
for ext in docx doc rtf odt; do
  duti -s org.libreoffice.script "$ext" all
done

Gotchas: Run it as one script, after the IINA block above. Some extensions have a registered type (.tsx is com.microsoft.typescript, .toml and .cfg are public.toml), and macOS ignores an extension handler for those, which is why the first loop binds them by type. The rest make duti fail with error -50 and go through the plist. Editing the plist without the killall lsd doesn't stick: LaunchServices keeps its own copy in memory and writes it back over your change. macOS may pop a confirmation for a type another app already owns (.ts vs IINA); pick Zed. Verify with duti -x tsx. Installing Xcode later can hand .tsx to IINA again; fix it with duti -s dev.zed.Zed com.microsoft.typescript all.