Skip to content

Instantly share code, notes, and snippets.

@fclairamb
Created January 13, 2026 12:27
Show Gist options
  • Select an option

  • Save fclairamb/a536c23b37d8ad1c10a1da93fc081e76 to your computer and use it in GitHub Desktop.

Select an option

Save fclairamb/a536c23b37d8ad1c10a1da93fc081e76 to your computer and use it in GitHub Desktop.
Simple worktrees (+ claude & zed)
#!/usr/bin/env python3
import os
import sys
import subprocess as run
import shutil
# Get the directory where this script is located
script_dir = os.path.dirname(os.path.abspath(__file__))
# Handle clean command directly
if len(sys.argv) >= 2 and sys.argv[1] in ['--clean', '-c']:
wt_cmd = [os.path.join(script_dir, 'wt'), '--clean']
run.run(wt_cmd)
sys.exit(0)
if len(sys.argv) < 2:
print("Usage: claudewt <branch-name> [query...] | --clean")
sys.exit(1)
# Use wt with claude command
branch = sys.argv[1]
query_args = sys.argv[2:] # Everything after the branch name
# Build the wt command with claude
wt_cmd = [os.path.join(script_dir, 'wt'), branch]
# Add claude command if available, otherwise just shell
if shutil.which('claude'):
wt_cmd.extend(['claude', '--dangerously-skip-permissions'])
# Add query arguments if provided
if query_args:
wt_cmd.extend(query_args)
run.run(wt_cmd)
#!/usr/bin/env python3
import os
import sys
import re
import subprocess as run
def clean_worktrees():
"""Remove worktrees with no uncommitted files or unpushed commits"""
git_root = run.check_output(['git', 'rev-parse', '--show-toplevel']).decode().strip()
repo = os.path.basename(git_root)
# List all worktrees
worktrees = run.check_output(['git', 'worktree', 'list', '--porcelain']).decode().strip().split('\n\n')
for worktree_info in worktrees:
lines = worktree_info.strip().split('\n')
if not lines:
continue
worktree_path = lines[0].replace('worktree ', '')
# Skip main worktree
if worktree_path == git_root:
continue
# Check if it's one of our managed worktrees
if not os.path.basename(worktree_path).startswith(f"{repo}-"):
continue
print(f"Checking worktree: {worktree_path}")
# Change to worktree directory
try:
os.chdir(worktree_path)
except FileNotFoundError:
print(f" Worktree path missing, removing: {worktree_path}")
run.run(['git', 'worktree', 'remove', '--force', worktree_path])
continue
# Check for uncommitted changes
status = run.run(['git', 'status', '--porcelain'], capture_output=True).stdout.decode().strip()
if status:
print(" Has uncommitted changes, keeping")
continue
# Check for unpushed commits
try:
# Get current branch
branch = run.check_output(['git', 'branch', '--show-current']).decode().strip()
if not branch:
print(" No current branch, removing")
run.run(['git', 'worktree', 'remove', '--force', worktree_path])
continue
# Check if branch has upstream
upstream = run.run(['git', 'rev-parse', '--abbrev-ref', f'{branch}@{{upstream}}'],
capture_output=True, text=True)
if upstream.returncode != 0:
# No upstream - check if branch has any commits beyond main
try:
result = run.run(['git', 'rev-list', '--count', f'main..{branch}'],
capture_output=True, text=True)
if result.returncode == 0:
commits = int(result.stdout.strip())
if commits > 0:
print(f" Has {commits} commits vs main, keeping")
continue
else:
print(" No upstream and no new commits, removing")
run.run(['git', 'worktree', 'remove', '--force', worktree_path])
continue
except Exception:
print(" No upstream, removing")
run.run(['git', 'worktree', 'remove', '--force', worktree_path])
continue
# Check for unpushed commits
ahead = run.check_output(['git', 'rev-list', '--count', f'{branch}@{{upstream}}..{branch}']).decode().strip()
if int(ahead) > 0:
print(f" Has {ahead} unpushed commits, keeping")
continue
except Exception as e:
print(f" Error checking push status: {e}, keeping")
continue
print(" Clean worktree, removing")
run.run(['git', 'worktree', 'remove', '--force', worktree_path])
if len(sys.argv) < 2:
print("Usage: wt <branch-name> [command] | --clean")
print(" wt <branch-name> - Create/switch to worktree and start shell")
print(" wt <branch-name> [command] - Create/switch to worktree and run command")
print(" wt --clean - Clean up empty worktrees")
sys.exit(1)
# Handle clean command
if sys.argv[1] in ['--clean', '-c']:
clean_worktrees()
sys.exit(0)
# Get current state
git_root = run.check_output(['git', 'rev-parse', '--show-toplevel']).decode().strip()
rel_path = os.path.relpath(os.getcwd(), git_root)
branch = re.sub(r'[^a-zA-Z0-9/_-]', '-', sys.argv[1]).strip('-')
repo = os.path.basename(git_root)
wt_path = f"{git_root}/../{repo}-{branch.replace('/', '-')}"
# Check if branch already exists (before creating worktree)
branch_exists = run.run(['git', 'show-ref', '--verify', '--quiet', f'refs/heads/{branch}'],
capture_output=True).returncode == 0
# Create or switch to worktree
if os.path.isdir(wt_path):
print(f"Switching to existing worktree: {wt_path}")
os.chdir(wt_path)
# Ensure we're on the right branch
if branch_exists:
run.run(['git', 'checkout', branch])
else:
run.run(['git', 'checkout', '-b', branch, 'origin/main'])
else:
if branch_exists:
print(f"Creating worktree with existing branch '{branch}': {wt_path}")
run.run(['git', 'worktree', 'add', wt_path, branch])
else:
print(f"Creating worktree with new branch '{branch}' from origin/main: {wt_path}")
run.run(['git', 'worktree', 'add', '-b', branch, wt_path, 'origin/main'])
os.chdir(wt_path)
# Navigate to same relative path
target_path = f"{wt_path}/{rel_path}"
if os.path.isdir(target_path):
print(f"Navigating to: {target_path}")
os.chdir(target_path)
else:
print(f"Warning: {target_path} not found, staying in worktree root")
# Execute command if provided, otherwise start shell
if len(sys.argv) > 2:
# Run the provided command with all remaining arguments
command = sys.argv[2:]
run.run(command)
else:
# Start shell
run.run([os.environ.get('SHELL', '/bin/sh')])
#!/usr/bin/env python3
import os
import sys
import subprocess as run
import shutil
# Get the directory where this script is located
script_dir = os.path.dirname(os.path.abspath(__file__))
# Handle clean command directly
if len(sys.argv) >= 2 and sys.argv[1] in ['--clean', '-c']:
wt_cmd = [os.path.join(script_dir, 'wt'), '--clean']
run.run(wt_cmd)
sys.exit(0)
if len(sys.argv) < 2:
print("Usage: zedwt <branch-name> | --clean")
sys.exit(1)
# Use wt with zed command
branch = sys.argv[1]
# Build the wt command with zed
wt_cmd = [os.path.join(script_dir, 'wt'), branch]
# Add zed command if available, otherwise just shell
if shutil.which('zed'):
wt_cmd.extend(['zed', '.'])
else:
print("Warning: 'zed' command not found, starting shell instead")
run.run(wt_cmd)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment