# Claude Focus Workflow Automated workflow that creates an isolated git worktree, tmux session, and Claude Code instance per task. Each issue gets its own branch, directory, and AI session — fully isolated from other work. Config files: `~/.zsh/aliases/claude.zsh`, `~/.local/bin/claude-review` > [!info] Mental Model > One task = one worktree = one branch = one tmux session = one Claude session. The session ID is deterministic (uuid5 of `repo/branch`), so reconnecting to the same branch always resumes the same Claude conversation. ## Quick Reference | Alias | Command | Purpose | |-------|---------|---------| | `cf` | `claude-focus` | Create worktree + tmux + Claude Code | | `cfd` | `claude-focus-done` | Tear down worktree + session + branch | | `cfl` | `claude-focus-list` | List active focus sessions | | `cfr` | `claude-focus-resume` | Re-attach to a focus session | | `cfgc` | `claude-focus-gc` | Garbage-collect merged/closed sessions | | `csb` | `claude-session-branch` | Claude session tied to current branch | ## Setup The workflow is defined in two files: - **`~/.zsh/aliases/claude.zsh`** — all shell functions and aliases - **`~/.local/bin/claude-review`** — standalone review script for neovim Both are sourced/available automatically via `~/.zshrc`. ### Requirements - `git` with worktree support (2.5+) - `tmux` (any recent version) - `python3` (for uuid5 generation) - `nvim` (for review panes) - `fzf` (optional, for session picker in `cfr`) ## Usage ### Start a Focus Session ```bash # From any git repository — always forks from main/master/trunk cf issue-42 # named session cf # auto-named: <repo>-<timestamp> # Fork from a specific branch cf --current fix # fork from whichever branch is currently checked out cf --from develop x # fork from "develop" explicitly ``` This creates: 1. A git worktree at `~/Workspace/.worktrees/<repo>/<name>/` 2. A new branch forked from `main` (default), current branch (`--current`), or a named branch (`--from`) 3. A tmux session named after the branch 4. Claude Code running with a deterministic session ID ### Resume a Session ```bash cfr issue-42 # by name cfr # fzf picker (if fzf is installed) ``` ### List Active Sessions ```bash cfl # Output: # issue-42 branch=issue-42 ~/Workspace/.worktrees/myrepo/issue-42/ # feature-auth branch=feature-auth ~/Workspace/.worktrees/myrepo/feature-auth/ ``` ## Review ### tmux Keybindings | Keys | Action | Mode | |------|--------|------| | `prefix + R` | Split right with branch review | All changes since diverging from main | | `prefix + E` | Split below with working review | Staged + unstaged + untracked | Both open neovim with changed files. The pane closes when you exit neovim. > [!tip] Prefix Key > The tmux prefix is `Ctrl+Space`. So `Ctrl+Space` then `R` opens a branch review pane. ### Standalone Review Script The `claude-review` script works independently of tmux: ```bash claude-review # working mode (default) claude-review --staged # only staged changes claude-review --branch # all changes since main + uncommitted ``` For 4 or fewer files, neovim opens with vertical splits (`-O`). For more files, it opens a plain buffer list. ## Cleanup ### Single session (`cfd`) ```bash cfd issue-42 # interactive confirmation cfd # current session (when inside tmux) cfd --force issue-42 # skip confirmation + force-delete unmerged branch ``` Removes the tmux session, worktree directory, branch, and empty parent dirs. ### Bulk garbage-collect (`cfgc`) Scans all worktrees under `~/Workspace/.worktrees/` and removes those whose branches are merged or closed. ```bash cfgc # interactive — prompts per session cfgc --dry-run # preview only, nothing touched cfgc --all # clean everything merged/closed without prompts ``` Merge detection (in priority order): 1. **GitHub PR state** via `gh pr view` — handles regular, squash, and rebase merges 2. **Git ancestry** — `git merge-base --is-ancestor` for regular merges 3. **Diff fingerprint** — `cksum` match against commits in `main` (catches squash merges without a PR) ## How It Works ### Directory Structure ``` ~/Workspace/ ├── Sandbox/ │ └── myrepo/ ← main clone (origin) └── .worktrees/ └── myrepo/ ├── issue-42/ ← worktree (branch: issue-42) └── feature-auth/ ← worktree (branch: feature-auth) ``` ### Session ID Generation Claude Code session IDs are generated deterministically using uuid5: ``` session_id = uuid5(NAMESPACE_DNS, "<repo-name>/<branch-name>") ``` This means the same repo + branch combination always produces the same session ID. Resuming a worktree reconnects to the exact same Claude conversation. ### tmux Metadata Each focus session stores metadata as tmux environment variables: | Variable | Example | Purpose | |----------|---------|---------| | `CF_WORKTREE_PATH` | `~/Workspace/.worktrees/myrepo/issue-42/` | Worktree location | | `CF_BRANCH_NAME` | `issue-42` | Branch name | | `CF_GIT_ROOT` | `~/Workspace/Sandbox/myrepo` | Original repo path | | `CF_SESSION_ID` | `a1b2c3d4-...` | Claude session ID | | `CF_BASE_BRANCH` | `main` | Branch this worktree was forked from | Read by `cfd` for cleanup, `cfl` for listing, and `cfgc` for merge-back flows. ### Session Branch (csb) The `csb` alias is a simpler variant — it launches Claude Code with a session ID tied to the current branch, without creating a worktree or tmux session. Useful when you want session continuity but not full isolation: ```bash cd ~/Workspace/Sandbox/myrepo git checkout feature-x csb # launches Claude with session tied to "feature-x" ```