github CLI extension for worktrees
Project description
gh-worktree
A CLI tool that helps you manage Git worktrees. Built as a GitHub CLI (gh) extension, but works standalone.
Dependencies: git, gh
Table of Contents
Quick Start
pip install gh-worktree
Or with uv:
uvx gh-worktree
Or download the PEX file from the releases page.
See recipes for hooks and templates.
Capabilities
| Feature | Description |
|---|---|
| Bare repository initialization | Clean separation of git metadata from worktrees |
| Lifecycle hooks | Custom scripts at key points with checksum validation |
| Global + project config | Hooks and templates at both levels |
| PR worktrees | Create worktrees directly from GitHub PRs |
| Project bootstrapping | Auto-copy hooks/templates from repo on init |
| Worktree templates | Pre-configured files copied to new worktrees |
| Environment variables | Template variables with allowlist support |
How It Works
Directory Structure
After initializing a repository (e.g., gh-worktree):
gh-worktree/
.bare/ # Bare git repository
.git # Points to .bare/
.gh/
worktree/
hooks/ # Project-level hooks
templates/ # Project-level templates
config.json # Project configuration
my-new-worktree/ # Created worktrees
README.md
...
Hooks
Hooks are executable scripts that run at specific lifecycle points. They can be configured at:
- Global level:
~/.gh/worktree/hooks/(or parent directories outside the project) - Project level:
.gh/worktree/hooks/(copied from repo on init if present)
Execution order: global hooks first, then project hooks.
| Hook | Executes At | Description |
|---|---|---|
pre_init |
Global only | Before initializing a repository for worktrees |
post_init |
Global + Project | After initializing a repository for worktrees |
pre_checkout |
Global + Project | Before checking out a PR or existing branch as a worktree |
post_checkout |
Global + Project | After checking out a PR or existing branch as a worktree |
pre_create |
Global + Project | Before creating a new worktree (branch) |
post_create |
Global + Project | After creating a new worktree (branch) |
pre_remove |
Global + Project | Before removing a worktree |
post_remove |
Global + Project | After removing a worktree |
Hooks must be executable and allowed (via checksum validation) to run.
Example: post_create hook
A hook for this project might look something like:
#!/usr/bin/env bash
WORKTREE_NAME="$1" # Full worktree name
BASE_REF="$2" # Format: remote/branch
WORKTREE_NAME_NORMALIZED="$3" # Worktree name with non-alphanumeric characters replaced by dashes
pushd "$WORKTREE_NAME"
uv venv
uv sync --group dev
prek install -f
popd
Templates
Files in .gh/worktree/templates/ are copied to new worktrees before post-hooks execute.
Tip: Add template files to .gitignore.
Templates support environment variable substitution using ${ENVVAR_NAME} syntax. Allowlist variable names in ~/.gh/worktree/config.json under allowed_envvars.
Provided variables:
| Variable | Description |
|---|---|
REPO_NAME |
Name of the git repository |
REPO_DIR |
Absolute path of the repo / project directory |
WORKTREE_NAME |
Name of the new worktree |
WORKTREE_NAME_NORMALIZED |
Worktree name with non-alphanumeric chars replaced by dashes |
WORKTREE_DIR |
Absolute path of the worktree directory |
Example: JetBrains project name template
Set a unique project name per worktree in JetBrains IDEs:
File: .gh/worktree/templates/.idea/.name
${REPO_NAME}.${WORKTREE_NAME_NORMALIZED}
Result in worktree: .idea/.name contains gh-worktree.feat-my-branch
Commands
Run gh-worktree without any arguments for usage information.
init — Initialize a repository for worktrees
Spec: init <repository_uri> [optional_clone_dir] [--yes]
Initializes a repository for use with worktrees. Similar to git clone — specify a directory name as the second argument, or it defaults to the repository name.
--yes: Automatically execute new or modified hooks without prompting
create — Create a new worktree
Spec: create <worktree_name> [base_ref] [--yes]
Creates a new worktree. Defaults to the default branch of the GitHub repository. Optionally specify a base reference.
--yes: Automatically execute new or modified hooks without prompting
checkout — Checkout a PR or branch as a worktree
Spec: checkout [--remote=<name>] [--yes] <branch_name|pr_number|pr_url>
Quickly create a worktree for a PR or existing branch. Works with fork PRs regardless of remote configuration.
--yes: Automatically execute new or modified hooks without prompting
remove — Remove a worktree
Spec: remove [--force] [--yes] <worktree_name>
Aliases: rm
Removes a worktree. Git refuses to delete worktrees with unmerged commits unless --force is used.
--yes: Automatically execute new or modified hooks without prompting
install — Install gh-worktree
Spec: install [--alias=<name>] [--gh-ext] [--path-bin] [--force]
Installs gh-worktree as a GitHub CLI extension or to your PATH. Without options, prompts for installation method.
--gh-ext: Install asghextension--path-bin: Install to~/.local/binor~/bin--alias: Custom name (e.g.,wktr)--force: Overwrite existing installation
Installation
Tested on Linux. Requires Python 3.10+ for PEX.
As a GitHub CLI extension (gh)
- Download the latest release binary.
- Make executable:
chmod +x gh-worktree - Install:
./gh-worktree install --gh-ext - Test:
gh worktree
Standalone
- Download the latest release binary or PEX.
- Make executable:
chmod +x gh-worktree* - Install:
./gh-worktree install --path-binor./gh-worktree.pex install --path-bin - Test:
gh-worktree version
Aliasing
./gh-worktree install --alias=wktr --path-bin
wktr version
From source
git clone https://github.com/bjester/gh-worktree.git
cd gh-worktree
uv venv
source .venv/bin/activate
uv sync --group dev
make dist/gh-worktree
./dist/gh-worktree install --path-bin
AI Disclosure
LLMs were used in the development of this project, mostly for brainstorming and bootstrapping code, particularly tests. The contribution proportion is roughly 80 / 20, human and AI code respectively. This may change over time as I try out agents!
License
MIT :: Copyright 2026 Blaine Jester
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gh_worktree-0.3.1-py3-none-any.whl.
File metadata
- Download URL: gh_worktree-0.3.1-py3-none-any.whl
- Upload date:
- Size: 23.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c30b92d727a0ee91f265fde67bb816406643789c5e84a5663a7dce539ccb4c9
|
|
| MD5 |
8b458c1ccb05589000c75d35eca3904d
|
|
| BLAKE2b-256 |
f6dc2031f3449754cff9765b4bb6c8bd178ad5fdb3bdd86d4b73a777819d8874
|
Provenance
The following attestation bundles were made for gh_worktree-0.3.1-py3-none-any.whl:
Publisher:
release.yml on bjester/gh-worktree
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gh_worktree-0.3.1-py3-none-any.whl -
Subject digest:
5c30b92d727a0ee91f265fde67bb816406643789c5e84a5663a7dce539ccb4c9 - Sigstore transparency entry: 1195473365
- Sigstore integration time:
-
Permalink:
bjester/gh-worktree@3cccc915979749c41fa17a72d163792624cc24e3 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/bjester
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3cccc915979749c41fa17a72d163792624cc24e3 -
Trigger Event:
release
-
Statement type: