Skip to content

Commit 917d5e4

Browse files
nsheapsclaude
andcommitted
feat: initial commit - worktree-switcher CLI tool
Interactive TUI for git worktree management with: - Branch selection with priority ranking (your PRs first) - Worktree creation for local/remote/new branches - Repository scanning and GitHub clone integration Includes CI workflow to auto-update homebrew-devsetup formula on release. Co-Authored-By: Claude Code (~/src/nsheaps/ai.worktrees/nate-worktree-switcher-improvements) <noreply@anthropic.com>
0 parents  commit 917d5e4

4 files changed

Lines changed: 838 additions & 0 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: "GitHub App Authentication"
2+
description: "Authenticate as a GitHub App and configure git user settings"
3+
4+
branding:
5+
icon: "lock"
6+
color: "blue"
7+
8+
inputs:
9+
app-id:
10+
description: "GitHub App ID"
11+
required: true
12+
13+
private-key:
14+
description: "GitHub App private key"
15+
required: true
16+
17+
owner:
18+
description: "Repository owner (defaults to current repository owner)"
19+
required: false
20+
default: ${{ github.repository_owner }}
21+
22+
outputs:
23+
token:
24+
description: "GitHub App token"
25+
value: ${{ steps.app-token.outputs.token }}
26+
27+
app-slug:
28+
description: "GitHub App slug name"
29+
value: ${{ steps.app-token.outputs.app-slug }}
30+
31+
user-id:
32+
description: "GitHub App bot user ID"
33+
value: ${{ steps.get-user-id.outputs.user-id }}
34+
35+
user-name:
36+
description: "GitHub App bot user name (app slug with [bot] suffix)"
37+
value: ${{ steps.get-user-id.outputs.user-name }}
38+
39+
runs:
40+
using: "composite"
41+
steps:
42+
- name: Generate GitHub App token
43+
id: app-token
44+
uses: actions/create-github-app-token@v2
45+
with:
46+
app-id: ${{ inputs.app-id }}
47+
private-key: ${{ inputs.private-key }}
48+
owner: ${{ inputs.owner }}
49+
50+
- name: Get GitHub App User ID
51+
id: get-user-id
52+
shell: bash
53+
run: |
54+
echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
55+
echo "user-name=${{ steps.app-token.outputs.app-slug }}[bot]" >> "$GITHUB_OUTPUT"
56+
env:
57+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
58+
59+
- name: Configure git
60+
shell: bash
61+
env:
62+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
63+
run: |
64+
gh auth setup-git
65+
echo "GH_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
66+
echo "GITHUB_TOKEN=${GH_TOKEN}" >> $GITHUB_ENV
67+
git config --global user.name '${{ steps.get-user-id.outputs.user-name }}'
68+
git config user.name '${{ steps.get-user-id.outputs.user-name }}'
69+
git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.get-user-id.outputs.user-name }}@users.noreply.github.com'
70+
git config user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.get-user-id.outputs.user-name }}@users.noreply.github.com'
71+
72+
- name: Configure repo checkout token
73+
uses: actions/checkout@v6
74+
with:
75+
token: ${{ steps.app-token.outputs.token }}
76+
clean: false
77+
persist-credentials: true

.github/workflows/release.yaml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
release:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Create Release
18+
uses: softprops/action-gh-release@v2
19+
with:
20+
files: bin/worktree-switcher
21+
generate_release_notes: true
22+
23+
update-homebrew:
24+
needs: release
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v4
28+
29+
- name: Authenticate as GitHub App
30+
id: auth
31+
uses: ./.github/actions/github-app-auth
32+
with:
33+
app-id: ${{ secrets.AUTOMATION_GITHUB_APP_ID }}
34+
private-key: ${{ secrets.AUTOMATION_GITHUB_APP_PRIVATE_KEY }}
35+
36+
- name: Get release info
37+
id: release
38+
run: |
39+
VERSION="${GITHUB_REF_NAME#v}"
40+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
41+
42+
# Get SHA256 of the script
43+
SHA256=$(curl -sL "https://github.com/${{ github.repository }}/releases/download/${GITHUB_REF_NAME}/worktree-switcher" | shasum -a 256 | cut -d' ' -f1)
44+
echo "sha256=$SHA256" >> "$GITHUB_OUTPUT"
45+
echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
46+
47+
- name: Clone homebrew-devsetup
48+
run: |
49+
gh repo clone nsheaps/homebrew-devsetup homebrew-devsetup
50+
51+
- name: Update formula
52+
run: |
53+
cd homebrew-devsetup
54+
55+
cat > Formula/worktree-switcher.rb << 'FORMULA_EOF'
56+
# typed: false
57+
# frozen_string_literal: true
58+
59+
class WorktreeSwitcher < Formula
60+
desc "Interactive TUI for git worktree management"
61+
homepage "https://github.com/nsheaps/git-wt"
62+
url "https://github.com/nsheaps/git-wt/releases/download/${{ steps.release.outputs.tag }}/worktree-switcher"
63+
sha256 "${{ steps.release.outputs.sha256 }}"
64+
version "${{ steps.release.outputs.version }}"
65+
license "MIT"
66+
67+
head do
68+
url "https://github.com/nsheaps/git-wt.git", branch: "main"
69+
end
70+
71+
depends_on "gum"
72+
depends_on "gh"
73+
depends_on "jq"
74+
75+
def install
76+
if build.head?
77+
bin.install "bin/worktree-switcher"
78+
else
79+
bin.install "worktree-switcher"
80+
end
81+
end
82+
83+
test do
84+
assert_match "worktree-switcher", shell_output("#{bin}/worktree-switcher --help")
85+
end
86+
end
87+
FORMULA_EOF
88+
89+
- name: Commit and push formula update
90+
run: |
91+
cd homebrew-devsetup
92+
git add Formula/worktree-switcher.rb
93+
git commit -m "chore: update worktree-switcher to ${{ steps.release.outputs.version }}" || exit 0
94+
git push

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# git-wt
2+
3+
Interactive TUI for git worktree management.
4+
5+
## Installation
6+
7+
### Homebrew (recommended)
8+
9+
```bash
10+
brew tap nsheaps/devsetup
11+
brew install worktree-switcher
12+
```
13+
14+
### Manual
15+
16+
```bash
17+
# Clone and add to PATH
18+
git clone https://github.com/nsheaps/git-wt.git
19+
export PATH="$PATH:$(pwd)/git-wt/bin"
20+
```
21+
22+
## Usage
23+
24+
```bash
25+
worktree-switcher [OPTIONS] [BRANCH]
26+
```
27+
28+
### Arguments
29+
30+
| Argument | Description |
31+
| -------- | -------------------------------------------------------------- |
32+
| `BRANCH` | Branch name to create/switch to worktree for (skips selection) |
33+
34+
### Options
35+
36+
| Option | Description |
37+
| ---------------- | ------------------------------------------------ |
38+
| `--no-status` | Skip fetching branch status (faster) |
39+
| `--scan-dir DIR` | Directory to scan for git repos (default: ~/src) |
40+
| `--repo REPO` | GitHub repo (owner/name) to clone if not in repo |
41+
| `-h, --help` | Show help message |
42+
43+
### Examples
44+
45+
```bash
46+
# Interactive mode - select from branches
47+
worktree-switcher
48+
49+
# Direct branch switch - find or create worktree for branch
50+
worktree-switcher feature/my-branch
51+
52+
# Clone a repo and create worktree
53+
worktree-switcher --repo nsheaps/git-wt feature/my-branch
54+
55+
# Faster mode without status checks
56+
worktree-switcher --no-status
57+
```
58+
59+
## Features
60+
61+
- **Direct branch argument**: Pass a branch name to skip interactive selection
62+
- **Smart branch detection**: Finds local, remote, or creates new branches
63+
- **Repo discovery**: When not in a git repo, offers to:
64+
- Scan `~/src` (or custom dir) for existing repos
65+
- Clone from GitHub by selecting from org/user repos
66+
- Enter a path manually
67+
- **"Switch repository" option**: Step up to change repos during selection
68+
- Shows banner if already in a worktree
69+
- Create new worktrees with new branches
70+
- Select from existing worktrees
71+
- Branch priority (your PRs > your branches > other branches)
72+
- Worktrees created at: `../${repo}.worktrees/${branch}`
73+
74+
## Dependencies
75+
76+
| Tool | Purpose | Installation |
77+
| ----- | ------------------- | --------------------- |
78+
| `gum` | Interactive prompts | `brew install gum` |
79+
| `gh` | GitHub CLI | `brew install gh` |
80+
| `jq` | JSON processing | `brew install jq` |
81+
| `git` | Version control | Usually pre-installed |
82+
83+
## License
84+
85+
MIT

0 commit comments

Comments
 (0)