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.
Sandbox-oriented successor to the ghwt session layer. Ghostty stays your terminal; Herdr holds the agent session. Optional Cloudflare Sandbox provisions a remote preview/dev env. Wrap-up is push + PR unless you pass --video / --review-fix.
ghsb [-c] [-f] [-b <branch>] [-i <N>] [--local|--cf] [--video] [--review-fix] "Issue title"
ghsb finish [--video] [--review-fix] [session-id]
ghsb review <pr-number> # same as ghsbpr
ghsb status|attach|links|list|rm [session-id]| Piece | Role |
|---|---|
| Ghostty | Terminal UI (unchanged) |
| Herdr | Persistent agent panes (cockpit) |
| Local worktree | Herdr worktree at ~/.herdr/worktrees/{repo}/{branch-slug} |
Cloudflare Sandbox (--cf) |
Remote clone + dev server + preview URL |
ghsb finish |
Push + PR + ranked files. --video / --review-fix are opt-in. |
Finish pipeline (ghsb finish):
- Push branch and ensure a PR exists
- Rank changed files for manual review
--video: Playwright walkthrough if UI files changed--review-fix: prompt the same grok/claude session to review and fix- Print PR, github.dev, dev env, and preview links
# Local Herdr session (default wrap-up: push + PR)
ghsb "Add dark mode"
ghi --video --review-fix -i 42 # opt in to recording + self-review
ghsb finish --video --review-fix # from the worktree, or pass session id
ghsb linksCloudflare Worker lives in sandbox/ — see sandbox/README.md. Session state: ~/.ghsb/sessions/.
Agents use permission-mode auto (not always-approve).
Source: functions/ghsb.zsh, functions/_ghsb_common.zsh, scripts/ghsb-record-preview.mjs.
Same checkout as ghsb (issue → branch → Herdr worktree → setup). Run it from the repo root space (e.g. openstory). Creates a worktree grouped under that repo, switches you to it, and starts the agent there. Does not rename or cd the root space. Does not open Cursor.
# Inside Herdr, from the repo root space:
ghi [-c] [-f] [-b <branch>] [-i <N>] [--no-agent] [--video] [--review-fix] "Issue title"
ghi review <pr-number> # same as ghipr
ghi reviews # same as ghiprs
ghi branch "Add dark mode" # same as ghb (no GitHub issue)| 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 <N> |
Develop an existing issue instead of creating a new one. |
--no-agent |
Stop after the worktree (no agent). |
--video |
After the PR, record a Playwright walkthrough (ghsb finish --video). |
--review-fix |
After the PR, self-review and fix in this same agent. |
What it does:
- Requires
HERDR_PANE_ID— run it from inside Herdr (the repo root space is the usual place). - Creates or reuses the issue, branch, and Herdr worktree at
~/.herdr/worktrees/{repo}/{branch-slug}(grouped under the repo in the sidebar). - Runs
_worktree_setup, labels the worktree{N}-{slug}, and focuses that space. The space you ran it from stays as-is. - Starts grok/claude in the worktree pane once that shell is idle.
- Writes a
ghsbsession. Default agent wrap-up is push + PR only.
Source: functions/ghi.zsh.
Same Herdr flow as ghi (worktree grouped under the repo, focus that space, start the agent, open reviewr). Does not create a GitHub issue. ghwtb is the Cursor sibling.
ghb "Add dark mode" # slugs to add-dark-mode
ghb -b my-branch
ghb -c "from current"
ghib "Add dark mode" # same
ghi branch "Add dark mode" # sameSource: functions/ghb.zsh.
Same checkout as ghsbpr (PR Herdr worktree + ranked files + review prompt), but the review agent stays in the space you already opened. Does not open Cursor.
# Inside Herdr, in a new space:
ghipr <pr-number>
ghi review <pr-number> # same
ghipr --no-agent 42 # checkout + rank files only
ghipr --no-focus 42 # start the review without switching this paneWhat it does:
- Requires
HERDR_PANE_ID— run it from inside Herdr. - Checks out the PR into a Herdr worktree at
~/.herdr/worktrees/{repo}/{branch-slug}(same asghsbpr/ghwtpr), including fork PRs viagh pr checkout. - Ranks changed files, writes a review session, focuses the PR worktree space (repo root stays as-is), and opens herdr-reviewr in a right split.
- Starts grok/claude with
/review-pr(or/pr-review-toolkit:review-pr) in the worktree pane once the shell is idle.
Source: functions/ghipr.zsh.
From the repo root Herdr space. For each open PR assigned to you that does not already have a ghsb session, runs ghipr --no-focus (worktree + herdr-reviewr + review agent). This pane stays on the repo root.
ghiprs # start reviews
ghiprs --dry-run # print start/skip onlySkip rule: ~/.ghsb/sessions/{repo}-pr-{N}.json exists, or any {repo}-* session whose pr field is that number.
Source: functions/ghiprs.zsh.
Architecture A sibling of ghwtpr: checkout a PR, rank files for manual review, launch pr-review in Herdr, print links.
ghsbpr <pr-number>
ghsb review <pr-number> # sameSource: functions/ghsbpr.zsh.
Classic workflow. One command turns an idea into a checked-out worktree with an agent in tmux (or the current terminal).
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 Herdr worktree at
~/.herdr/worktrees/{repo}/{branch-slug}(grouped under the repo in the Herdr sidebar). Existing~/.claude/worktrees/{repo}-{N}checkouts are reused and opened as Herdr worktrees. - Runs
_worktree_setup— executes."setup-worktree"[]from.cursor/worktrees.jsonif present, otherwise copies.env.local,.dev.vars, andlocal.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.
Same issue → branch → worktree as ghwt, with grok/claude in Herdr. Does not open Cursor or terminal-code (tode). Pass --tode for the old split.
ghwtv [-c] [-f] [-b <branch>] [-i <number>] [--tode] [--video] [--review-fix] "Issue title"
ghwtv -e <number>Detection: HERDR_ENV=1 plus HERDR_PANE_ID means you are already inside Herdr.
| Where you run it | What happens |
|---|---|
| Inside Herdr | Starts grok/claude in this pane once the shell is idle. --tode also splits and opens terminal-code. |
| Outside Herdr | Uses the worktree workspace, same agent, prints herdr so you can attach. |
Source: functions/ghwtv.zsh.
Same PR checkout as ghwtpr (fork-aware gh pr checkout into a Herdr worktree), but opens herdr-reviewr in a Herdr split instead of Cursor.
ghwtprv [-i] <pr-number>Detection: HERDR_ENV=1 plus HERDR_PANE_ID means you are already inside Herdr.
| Where you run it | What happens |
|---|---|
| Inside Herdr | Opens reviewr in a right split on this pane (cwd = PR worktree), starts grok/claude with /review-pr in this pane once the shell is idle. |
| Outside Herdr | Creates a Herdr workspace at the worktree, same split + agent, prints herdr so you can attach. |
Needs the plugin once: herdr plugin install persiyanov/herdr-reviewr.
In reviewr: u/b/t switch uncommitted / branch / last-turn; 3 is the PR tab; s sends line comments to the agent.
Source: functions/ghwtprv.zsh.
ghwtrm [<issue-number>]Removes the Herdr worktree (herdr worktree remove) for that issue. With no argument it targets the current linked worktree, so you can just run ghwtrm from inside the checkout you want to clean up. Legacy ~/.claude/worktrees/{repo}-{N} paths still resolve.
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 as a Herdr worktree at ~/.herdr/worktrees/{repo}/{branch-slug}, and launches the AI agent. Pass a description with spaces to auto-slugify the branch name (e.g. "Add dark mode" → add-dark-mode). Inside Herdr, use ghb / ghi branch instead.
| 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 Herdr worktree at ~/.herdr/worktrees/{repo}/{branch-slug}.
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.
Opens an existing Herdr workspace for an issue or PR. Default: a new Ghostty window (PICK ME banner, Cursor left, herdr agent attach for that space). Two windows can show different spaces. --here uses this terminal instead. Does not create a worktree or start an agent.
hsplt 1220 # new Ghostty window
hsplt --here pr 1178 # this terminal
hsplt --remote workbox 1220
hsplt --remote workbox --session agents pr 46
hsplt # workspace for the current directory| Flag | Description |
|---|---|
-n, --new-window |
New Ghostty window (default). |
--here |
PICK ME + attach in this terminal. |
-r, --remote HOST |
herdr --remote HOST (SSH config Host or user@host). Workspace lookup runs over SSH. |
-s, --session NAME |
Named Herdr session (HERDR_SESSION / herdr --session). |
--pr |
Treat the number as a PR (hsplt pr 1178 is the same). |
Matching (live Herdr workspaces only): {N}-{slug}, {repo}-{N}, pr-{N}, {repo}-pr-{N}, or an exact label. A bare number tries the issue first, then the PR. Pass --remote when the Herdr server is on another machine.
Source: functions/hsplt.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
├── scripts/
│ └── ghsb-record-preview.mjs # Playwright PR preview video
├── sandbox/ # Cloudflare Sandbox Worker for ghsb --cf
└── functions/ # Custom zsh commands
├── ghsb.zsh
├── ghsbpr.zsh
├── ghi.zsh
├── ghb.zsh
├── ghipr.zsh
├── ghiprs.zsh
├── _ghsb_common.zsh
├── ghwt.zsh
├── ghwtv.zsh
├── ghwtprv.zsh
├── ghwtb.zsh
├── ghwtpr.zsh
├── ghwtrm.zsh
├── wt.zsh
├── ght.zsh
├── hsplt.zsh
├── splt.zsh
├── _worktree_setup.zsh
└── _cursor_tile_left.zsh
This repo is a Grok / Claude Code marketplace. The ghsb plugin exposes /ghi, /ghb, /ghipr, /ghiprs, and /ghwtb so an agent can call those functions (they live in ~/.zsh_functions via bootstrap.sh; a non-interactive shell will not have them unless it uses the plugin runner).
# Grok
grok plugin marketplace add tombeckenham/dotfiles
grok plugin install ghsb --trust
# Claude Code
claude plugin marketplace add tombeckenham/dotfiles
claude plugin install ghsb@dotfilesLocal checkout instead of GitHub:
grok plugin marketplace add ~/code/dotfiles/ghiprs is the fan-out: every open PR assigned to you with no ghsb session gets its own worktree and review agent, without leaving the current pane.
- 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,ghwtv,ghwtprv,ghwtb, andwtassume Claude Code is installed and onPATH(bootstrap.shinstalls it). New worktrees are Herdr worktrees under~/.herdr/worktrees/{repo}/{branch-slug}(legacy~/.claude/worktrees/{repo}-{N}checkouts are still opened).ghwtv --todeneedstodeandherdronPATH.ghwtprvneedsherdrand thepersiyanov.reviewrplugin (herdr plugin install persiyanov/herdr-reviewr).- If you fork this repo, prune
Brewfileand skip the steps inbootstrap.shyou don't want (Vercel, Wrangler, OpenCode, Grok, GPG key generation, etc.).