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] [-f] [-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. |
-f, --fork |
Target the fork's own issue tracker instead of upstream (forks only). |
-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. Pass-f/--forkto instead create/reuse issues on the fork itself;-i <N>then resolves against whichever target is in effect. - 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. - Calls
splt(opens Cursor at the worktree, tiles left, shows the PICK ME banner), 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.
ghwtb [-c] [-b <branch>] [<branch-name-or-description>]Same worktree + Cursor + Claude/Grok flow as ghwt, but skips GitHub issue creation. Creates a new branch (or reuses an existing one), checks it out at ~/.claude/worktrees/{repo}-{sanitised-branch}, and launches the AI agent. Pass a description with spaces to auto-slugify the branch name (e.g. "Add dark mode" → add-dark-mode).
| Flag | Description |
|---|---|
-c, --current |
Branch from the current branch (default: repo's default branch). |
-b <branch> |
Use an explicit branch name; any remaining text is passed to the AI as context. |
Source: functions/ghwtb.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. Opens Cursor at the current directory (or a path you pass), then tiles that window 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, zoxide, 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, OpenCode, and Grok Build 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, initialises zoxide (z,zi), 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
├── ghwtb.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.ghwt,ghwtb, andwtassume 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, Grok, GPG key generation, etc.).