@rien7/gwt
v1.1.5
Published
A CLI for managing Git worktrees with a bare-repo workspace layout
Maintainers
Readme
@rien7/gwt
gwt is a CLI for managing Git worktrees with a bare-repo workspace layout.
Install it from npm as @rien7/gwt. The installed command is gwt.
The goal is to make multi-branch Git work more predictable:
- one workspace root per repository
- one shared
.bare/Git database - one directory per active branch
- one command surface for the common worktree flows
Install
Install globally with npm:
npm install -g @rien7/gwtOr with pnpm:
pnpm add -g @rien7/gwtAfter installation, check the command:
gwt --helpIf you use zsh, install completion once:
gwt completion install zshFor bash or fish:
gwt completion install bash
gwt completion install fishIf you install gwt from npm, the package includes a shell-aware completion hint. Some npm setups hide lifecycle script output; in that case gwt prints the same hint once on first interactive run.
Workspace Layout
After gwt init, a workspace looks like this:
my-project/
├── .bare/
├── .git
├── main/
├── feature-auth/
└── bugfix-login-crash/How it works:
.bare/contains the shared Git repository.gitpoints Git to.bare/- each worktree lives as a sibling directory in the workspace root
- branch names map to directory names by replacing
/with-
Branch names map to directory names like this:
| Branch | Directory |
| --- | --- |
| main | main |
| feature/auth | feature-auth |
| bugfix/login-crash | bugfix-login-crash |
Quick Start
Initialize a workspace from a remote repository:
gwt init [email protected]:owner/repo.gitCreate a new local branch worktree:
cd my-project/main
gwt new feature/exampleAttach a worktree for an existing branch:
gwt get feature/existingList active worktrees:
gwt lsUpdate shared remote tracking branches:
gwt syncCommands
gwt init <repoUrl> [dirName]
Create a new bare-repo workspace.
Useful options:
-b, --branch <name>: use a default branch other thanmain
Examples:
gwt init [email protected]:owner/repo.git
gwt init [email protected]:owner/repo.git my-project --branch mastergwt new <branch>
Create a new local branch and its worktree from origin/<default-branch>.
Useful options:
-p, --push: push the new branch and set upstream--from <ref>: start from a custom ref--no-fetch: skipgit fetch --all--print-path: print the created worktree path only
Examples:
gwt new feature/example
gwt new feature/example --from origin/release/1.0
gwt new feature/example --push
cd "$(gwt new feature/example --print-path)"gwt get <branch>
Create or attach a worktree for an existing branch. If the local branch already exists, gwt get attaches a worktree to it. Otherwise it creates the local branch from origin/<branch>.
Useful options:
--no-fetch: skipgit fetch --all--print-path: print the created worktree path only
Example:
gwt get feature/existing
cd "$(gwt get feature/existing --print-path)"gwt rm <branch>
Remove a worktree and delete its local branch.
Useful options:
-f, --force: force removal when the worktree has local changes-r, --remote: also delete the remote branch
gwt completion [shell]
Print a shell completion script for zsh, bash, or fish.
gwt completion install [shell]
Install the completion file for zsh, bash, or fish and update shell config when needed.
gwt sync
Run git fetch --all --prune for the shared workspace.
Useful option:
--rebase: after fetching, rebase the current worktree branch onto its remote
gwt pull
Fetch and update the current worktree branch from origin.
Useful option:
--merge: use merge instead of rebase
gwt ls
List active worktrees using paths relative to the workspace root.
gwt prune
Clean stale worktree metadata after directories were removed manually.
Configuration
You can configure workspace defaults in either:
<workspace-root>/.gwtrc<workspace-root>/.bare/config
Supported keys under [gwt]:
[gwt]
default_branch = "main"
protected_branches = ["main", "develop"]
auto_push = false
post_new = "code {path}"
post_get = "cd \"$1\" && npm install"Meaning:
default_branch: base branch used bygwt newprotected_branches: branches thatgwt rmrefuses to deleteauto_push: whethergwt newshould push by defaultpost_new: shell command to run aftergwt newpost_get: shell command to run aftergwt get
Hook placeholders:
{path}: absolute path to the created worktree{branch}: branch name{workspace_root}: workspace root{event}:post_neworpost_get
Hook positional arguments:
$1: absolute worktree path$2: branch name$3: workspace root$4: event name
The same values are also exported as environment variables:
GWT_HOOK_PATHGWT_HOOK_BRANCHGWT_HOOK_WORKSPACE_ROOTGWT_HOOK_EVENT
If a hook exits non-zero, gwt prints a warning but keeps the created worktree.
Hooks run in a child shell rooted at the workspace root, so cd "$1" only affects the hook itself, not your current shell.
For example, post_get = "cd \"$1\" && npm install" runs dependency installation inside the new worktree. Hook output streams live to the terminal; with --print-path, the path stays on stdout and hook logs go to stderr.
Shell Completion
Install completion:
gwt completion install zsh
gwt completion install bash
gwt completion install fishCompletion includes:
- command completion
- option completion
- dynamic branch completion for
gwt get, excluding branches that already have a worktree - dynamic removable branch completion for
gwt rm - dynamic ref completion for
gwt new --from
Dynamic branch and ref candidates only appear when the current directory is inside a gwt workspace.
Development
Install dependencies and build locally:
pnpm install
pnpm buildDuring local development you can run:
node dist/index.mjs --helpOr link the package globally:
pnpm link --global