A CLI tool that integrates GitHub issues with git worktrees for a streamlined development workflow.
# Using go install
go install github.com/enterprisemodules/gwi@latest
# Or build from source
git clone https://github.com/enterprisemodules/gwi
cd gwi
make installAdd to your ~/.zshrc or ~/.bashrc:
eval "$(gwi init zsh)"This enables gwi cd, gwi main, gwi list, gwi create, and gwi start to change your working directory.
git- Git version controlgh- GitHub CLI (authenticated)fzf- Fuzzy finder (optional, for better selection UI)tmux- Terminal multiplexer (optional, forgwi up/down/logs)direnv- Directory-specific environments (optional, for automatic env loading)
| Command | Description |
|---|---|
gwi start |
Select open issue interactively and create worktree |
gwi create [issue-number] |
Create worktree from GitHub issue |
gwi pr [issue-number] |
Push, create PR with "Closes #N", remove worktree |
gwi merge [issue-number] |
Merge PR, delete branch, remove worktree |
gwi rm [issue-number] |
Delete worktree (see flags below) |
gwi cd [number|pattern] |
Navigate to worktree (fuzzy match supported) |
gwi main |
Navigate back to main repository |
gwi list |
Interactive worktree selector (includes main) |
gwi status |
Show status of all worktrees with PR info |
gwi clean |
Remove orphaned worktrees and branches |
gwi activate |
Run setup hook (install deps, etc.) |
gwi up |
Start dev server in tmux session |
gwi down |
Stop dev server (runs down hook if present) |
gwi logs |
Attach to tmux session to view logs |
gwi completion [shell] |
Generate shell completions |
| Flag | Description |
|---|---|
-f, --force |
Force remove even with uncommitted changes |
-y, --yes |
Skip confirmation prompt |
-D, --delete-branch |
Also delete the local and remote branch |
# Start working on an issue (interactive selection)
gwi start
# Or create worktree for a specific issue
gwi create 42
# ... make your changes ...
# Create PR and clean up worktree
gwi pr
# After review, merge and clean up
gwi merge 42When using gwi start or gwi create without arguments, issues that already have worktrees are shown dimmed and cannot be selected. This prevents accidentally trying to create duplicate worktrees.
If you try to create a worktree for an issue that already exists:
gwi create 42
# Error: Worktree for issue #42 already exists.
#
# Path: ~/worktrees/github.com/org/repo/42-fix-bug
#
# Use 'gwi cd 42' to navigate to it, or 'gwi rm 42' to remove it first.Worktrees are organized by GitHub org and repo:
~/worktrees/
github.com/
<org>/
<repo>/
37-final-creation-of-product-fails/
42-add-user-authentication/
Configuration can be set via environment variables or YAML config file at ~/.config/gwi/config.yaml.
| Variable | Description | Default |
|---|---|---|
GWI_WORKTREE_BASE |
Base directory for worktrees | ~/worktrees |
GWI_MERGE_STRATEGY |
Merge strategy: squash, merge, rebase | squash |
GWI_AUTO_ACTIVATE |
Auto-run activate hook on cd/start | 0 |
GWI_HOOK_DIR |
Global hooks directory | ~/.config/gwi/hooks |
GWI_MAIN_BRANCH |
Default main branch name | main |
GWI_VERBOSE |
Enable verbose logging | 0 |
gwi automatically updates issue status in GitHub Projects (v2) during your workflow:
- Create worktree (
gwi create) → Move issue to "In Progress" - Create PR (
gwi pr) → Move issue to "In Review" - Merge PR (
gwi merge) → Move issue to "Done"
| Variable | Description | Default |
|---|---|---|
GWI_GITHUB_PROJECTS_ENABLED |
Enable automatic project status updates | true |
GWI_GITHUB_STATUS_FIELD |
Name of the status field in your project | Status |
GWI_GITHUB_IN_PROGRESS |
Status value for "in progress" | In Progress |
GWI_GITHUB_IN_REVIEW |
Status value for "in review" | In Review |
GWI_GITHUB_DONE |
Status value for "done" | Done |
GWI_GITHUB_CHECK_SCOPES |
Verify and prompt for required GitHub scopes | true |
-
Ensure required GitHub CLI scopes:
When you first use gwi with an issue in a GitHub Project, it will automatically prompt you to refresh your authentication with the required scopes. You can also do this manually:
gh auth refresh -s read:project,write:project
-
Add issues to your GitHub Project:
Issues must already be added to a GitHub Project for status updates to work. gwi will automatically update all projects that contain the issue.
-
Configure your project board:
Your GitHub Project should have a "Status" field (or custom field name) with the following options:
- "In Progress" (or custom value)
- "In Review" (or custom value)
- "Done" (or custom value)
Create ~/.config/gwi/config.yaml:
worktree_base: ~/projects/worktrees
merge_strategy: squash
auto_activate: true
verbose: true
github:
projects_enabled: true
status_field_name: Status
in_progress_value: In Progress
in_review_value: In Review
done_value: Done
check_scopes: trueIf you don't use GitHub Projects or want to disable the integration:
export GWI_GITHUB_PROJECTS_ENABLED=falseOr in ~/.config/gwi/config.yaml:
github:
projects_enabled: falseHooks are executable scripts searched in order:
<worktree>/.gwi/<hook>- Per-worktree override<main-repo>/.gwi/<hook>- Per-project hook (recommended)~/.config/gwi/hooks/<org>/<repo>/<hook>- Global fallback
Hook types:
| Hook | Description |
|---|---|
activate |
Setup script (install deps, configure env) |
create |
Runs after worktree creation |
up |
Command to start dev server (runs in tmux with direnv) |
down |
Cleanup script (runs before stopping server) |
.gwi/up:
#!/bin/bash
bundle install
bin/dev.gwi/down:
#!/bin/bash
docker-compose down
echo "Cleanup complete".gwi/activate:
#!/bin/bash
bundle install
yarn install
bin/rails db:migrateThe gwi up command starts your dev server in a background tmux session with full environment support:
- Loads your shell profile (
.zshrc/.bashrc) - Activates direnv environment (
.envrc) - Loads RVM/rbenv/asdf shims
gwi up # Start server in background tmux session
gwi logs # Attach to view logs (Ctrl+B D to detach)
gwi down # Run down hook and stop sessionEach worktree gets its own tmux session named after the directory, so you can run multiple dev servers simultaneously (use different ports via direnv).
# Interactive issue selection
gwi start # Select issue, create worktree, cd into it
# Create worktree for issue #37
gwi create 37
# → Creates ~/worktrees/github.com/org/repo/37-issue-title-slugified/
# Navigate to worktree
gwi cd 37 # by issue number
gwi cd auth # fuzzy match "auth" in title
gwi list # interactive selector
# Check status of all worktrees
gwi status
# ● 37-fix-bug (2 changes) ↑1 PR #42
# ● 38-add-feature no PR
# Create PR from current worktree (auto-detects issue number)
gwi pr
# Merge the PR
gwi merge 37
# Remove worktree (keeps branch)
gwi rm 37
# Remove worktree and delete branch (local + remote)
gwi rm 37 -D
# Force remove with uncommitted changes
gwi rm 37 --force
# Development server (requires tmux)
gwi up # Start server in background
gwi logs # View logs (Ctrl+B D to detach)
gwi down # Stop server# Generate completions
gwi completion zsh > "${fpath[1]}/_gwi"
gwi completion bash > /etc/bash_completion.d/gwi
gwi completion fish > ~/.config/fish/completions/gwi.fish# Build
make build
# Install to ~/.local/bin
make install
# Build for all platforms
make build-all
# Run tests
make testMIT