macOS dev environment focused on a GitHub-issue → git-worktree → Claude Code workflow.
dotfiles_video.mov
Custom shell functions live in functions/. bootstrap.sh symlinks the directory to ~/.zsh_functions/, and .zshrc auto-sources every *.zsh file inside it.
The main workflow. One command turns an idea into a checked-out worktree with Claude already running in plan mode against the issue.
ghwt [-c] [-b <branch>] [-i <number>] "Issue title"| Flag | Description |
|---|---|
-c, --current |
Branch from the current branch (default: repo's default branch). |
-b <branch> |
Use an existing branch instead of creating one. |
-i <number> |
Develop an existing issue instead of creating a new one. |
What it does:
- Detects whether you're in a fork (compares
originURL with whatghresolves) and routes issue creation to the upstream repo if so. - Fetches all remote refs.
- Creates the issue (or reuses
-i <N>) and creates the branch — viagh issue developfor direct repos, or manually for forks. - Creates a worktree at
~/.claude/worktrees/{repo}-{issue-number}. - Runs
_worktree_setup— executes."setup-worktree"[]from.cursor/worktrees.jsonif present, otherwise copies.env.localandlocal.dbif they exist. - Opens a new Cursor window, calls
spltto draw attention while Cursor loads, then launchesclaude --permission-mode plan "Implement GitHub issue #N..."in a new tmux window if$TMUXis set, otherwise in the current terminal.
Source: functions/ghwt.zsh.
ghwtrm [<issue-number>]Removes the worktree at ~/.claude/worktrees/{repo}-{N} and prunes the branch metadata. With no argument it auto-detects the issue number by parsing the current working directory, so you can just run ghwtrm from inside the worktree you want to clean up.
Source: functions/ghwtrm.zsh.
wt <branch-name>Same worktree + Cursor + Claude flow as ghwt, but for a branch that isn't tied to a GitHub issue. Fetches the branch from origin if it isn't local, sanitises slashes and other shell-unfriendly characters, and creates a worktree at ~/.claude/worktrees/{repo}-{sanitised-branch}.
Source: functions/wt.zsh.
ght [command...]Opens a new Ghostty window in $PWD. If a command is supplied, it runs it after opening. Reuses a running Ghostty instance via osascript instead of launching a second app.
Source: functions/ght.zsh.
spltBig yellow ASCII banner used by ghwt so it's obvious which terminal to look at while Cursor opens. Also tiles Cursor to the left half of the screen. Press Enter to dismiss.
Source: functions/splt.zsh.
functions/_worktree_setup.zsh and functions/_cursor_tile_left.zsh are sourced by the commands above and aren't meant to be called directly.
git clone https://github.com/tombeckenham/dotfiles.git ~/dotfiles
cd ~/dotfiles
./bootstrap.shOpen a new terminal afterwards so the shell config loads.
Prerequisites: macOS, your admin password (the script calls sudo pmset), and a browser for the GitHub OAuth login that runs partway through.
bootstrap.sh is idempotent — re-run it any time you pull new changes.
- Installs Xcode Command Line Tools and Homebrew if either is missing.
- Runs
brew bundleagainstBrewfile— installs starship, fnm, pnpm, pyenv, gh, jq, gnupg, lefthook, tmux, pinentry-mac, doppler, plus the Ghostty, Cursor and OrbStack casks. - Clones Antidote (zsh plugin manager) into
~/.antidote. - Symlinks
.zshrc,.zsh_plugins.txt,starship.toml,gpg.conf,gpg-agent.confandfunctions/into$HOME(and~/.config,~/.gnupg). - Authenticates
ghwith theuserandwrite:gpg_keyscopes (refreshes the token if those scopes aren't already granted). - Configures git globally: LFS filters,
commit.gpgsign=true,tag.gpgSign=true, andgh auth setup-gitfor HTTPS token auth. - If git identity isn't set, prompts for name/email (auto-detected from existing config and the GitHub API), offers to generate an Ed25519 GPG signing key, and registers the key with GitHub via
gh gpg-key add. - Installs Node LTS via
fnm, Python 3.12 viapyenv, and Bun via the official installer. bun install -g vercel wrangler, then installs the Claude Code and OpenCode CLIs.pmsetfor always-on server mode (sleep 0,displaysleep 5,autorestart 1).lefthook install— wires up the pre-commit secret scanner fromlefthook.yml.
.zshrc— loads Antidote plugins, sets up the Starship prompt, adds Bun / pnpm / fnm toPATH, lazy-loads pyenv on firstpython/pipuse, and auto-sources every*.zshfile in~/.zsh_functions/..zsh_plugins.txt—zsh-autosuggestions,zsh-syntax-highlighting,zsh-completions,zsh-history-substring-search, plus thegit,node,npmandmacosohmyzsh plugin paths.starship.toml— fast prompt: directory (truncated to repo root), git branch and status, command duration if it took longer than 2s. Language modules are disabled to keep prompt rendering quick.gpg.conf/gpg-agent.conf—auto-key-retrieve,pinentry-mac, 10-minute default cache (2-hour max).lefthook.yml— pre-commit hook that greps staged files for private keys, OpenAI keys (sk-…), GitHub tokens (ghp_…) and PEM headers, and blocks the commit if any are found.
.
├── bootstrap.sh # Installer (run once, safe to re-run)
├── Brewfile # Homebrew packages
├── .zshrc # Shell config
├── .zsh_plugins.txt # Antidote plugin list
├── starship.toml # Prompt
├── gpg.conf # GPG settings
├── gpg-agent.conf # GPG agent
├── lefthook.yml # Pre-commit hooks
└── functions/ # Custom zsh commands
├── ghwt.zsh
├── ghwtrm.zsh
├── wt.zsh
├── ght.zsh
├── splt.zsh
├── _worktree_setup.zsh
└── _cursor_tile_left.zsh
- macOS only — uses
xcode-select,pmset,osascript,pinentry-macand/opt/homebrewpaths. bootstrap.shcallssudo pmsetto keep the machine awake. Remove that block if you don't want always-on power management.ghwtandwtassume Claude Code is installed and onPATH(bootstrap.shinstalls it). Worktrees live under~/.claude/worktrees/.- If you fork this repo, prune
Brewfileand skip the steps inbootstrap.shyou don't want (Vercel, Wrangler, OpenCode, GPG key generation, etc.).