npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@shivanshshrivas/gwit

v0.2.3

Published

Fully isolated git worktrees for parallel development

Readme

gwit

npm version npm downloads CI Node >=20 License: MIT

Fully isolated git worktrees, in one command.

gwit wraps git worktree to turn a fresh checkout into a fully working environment - gitignored files copied, unique port assigned, per-worktree env vars injected, and setup scripts run automatically.

Built for parallel development with multiple branches and AI coding agents - no database collisions, no port conflicts, no manual setup.

Install

npm install -g @shivanshshrivas/gwit

Requires Node.js >= 20 and git >= 2.5.

Quick start

# Set up gwit for this repo (run once, commit the output)
gwit init

# Create an isolated worktree
gwit feature/auth             # existing branch
gwit -b fix/login-page        # create a new branch from HEAD

# Day-to-day
gwit list                     # show all active worktrees
gwit status                   # see ahead/behind, dirty state, PR info
gwit sync feature/auth        # re-copy files after .env changes
gwit sync --back feature/auth # three-way merge .gwitinclude files back to main
gwit open feature/auth        # re-open editor for an existing worktree

# Merge and clean up
gwit merge feature/auth       # merge branch back into main
gwit remove feature/auth      # run cleanup hooks and remove worktree
gwit sweep                    # bulk-remove all merged worktrees
gwit rename old/name new/name # rename a worktree branch

How it works

gwit adds three layers on top of git worktree add:

  1. Files - copies gitignored files listed in .gwitinclude (.env, node_modules/, certs) so the new worktree starts complete instead of broken.

  2. Isolation - assigns a unique port and injects $GWIT_* env vars into your setup scripts, so each worktree can create its own database, Docker project, Redis namespace, and anything else your stack needs.

  3. Automation - runs .gwitcommand after creation and .gwitcleanup before removal, giving your team a shared, repeatable isolation setup committed to the repo.

Commands

gwit <branch>

Create an isolated worktree for branch (local or remote).

gwit feature/auth                    # check out existing branch
gwit -b fix/login-page               # create a new branch from HEAD
gwit feature/auth --editor cursor    # override editor for this run
gwit feature/auth --no-editor        # skip opening editor
gwit feature/auth --no-commands      # skip .gwitcommand

What it does, in order:

  1. Resolves the branch (local -> remote tracking -> error)
  2. Runs git worktree add
  3. Copies files listed in .gwitinclude from the main worktree
  4. Allocates a unique port (scans from basePort, up to 100 ports)
  5. Injects $GWIT_* variables and runs .gwitcommand inside the new worktree
  6. Writes the registry entry to ~/.gwit/worktrees.json
  7. Opens the editor

gwit init

Interactive wizard that scaffolds the three per-repo hook files. Run once per repo and commit the output so every teammate gets the same isolation setup automatically.

gwit init           # creates .gwitinclude, .gwitcommand, .gwitcleanup
gwit init --force   # overwrite existing files

The wizard:

  • Shows a checklist of gitignored files/directories to copy (pre-selects .env*)
  • Asks about your package manager, database, Redis, Docker Compose
  • Asks for any extra setup and teardown commands
  • Generates ready-to-edit hook files

gwit list

Show all active worktrees for this repo.

Branch              Path                              Port   Index  Created
feature/auth        ../myapp-feature_auth             3001   1      2026-01-15
fix/login-page      ../myapp-fix_login_page           3002   2      2026-01-16

gwit remove <branch>

Run cleanup hooks, remove the worktree, and free the port from the registry.

gwit remove feature/auth
gwit remove feature/auth --force   # skip uncommitted-changes check

gwit sync [branch]

By default, re-copy .gwitinclude files from main into an existing worktree.
With --back, sync in the reverse direction using snapshot-aware three-way merge.

gwit sync feature/auth   # sync a specific branch
gwit sync                # auto-detect from current directory (when inside a worktree)
gwit sync --back feature/auth  # three-way merge worktree -> main
gwit sync --back               # auto-detect branch, then merge back

--back compares three versions of each snapshot-tracked file:

  1. base - file content captured when the worktree was created
  2. main - current file in the main worktree
  3. worktree - current file in the linked worktree

If both sides changed different text regions, gwit applies a clean merge.
If both sides changed the same region, gwit writes git-style conflict markers
(<<<<<<<, =======, >>>>>>>). Binary conflicts are skipped with a warning. Files currently matched by .gwitinclude but not present in the snapshot (for example, new files created later inside an included ignored directory) are reverse-copied directly from worktree to main.

gwit open <branch>

Re-open the editor for an existing worktree. Useful when the editor window was closed.

gwit open feature/auth
gwit open feature/auth --editor cursor

gwit merge <branch>

Merge a worktree branch back into the target branch. Combines git-tracked changes (via real git merge) with gitignored files (via reverse .gwitinclude sync) in a single command.

gwit merge feature/auth               # standard merge into default branch
gwit merge feature/auth --into dev    # merge into a specific branch
gwit merge feature/auth --squash      # squash all commits into one
gwit merge feature/auth --rebase      # rebase onto target, then fast-forward
gwit merge feature/auth --no-ff       # force a merge commit
gwit merge feature/auth --cleanup     # remove worktree after successful merge
gwit merge feature/auth --no-sync-back  # skip reverse .gwitinclude copy

What it does, in order:

  1. Validates the worktree exists in the registry
  2. Resolves the target branch (default: repo's default branch)
  3. Three-way syncs .gwitinclude files back to main (falls back to direct copy if no snapshot; unless --no-sync-back)
  4. Checks out the target branch in the main worktree
  5. Merges the feature branch using the chosen strategy
  6. Optionally removes the worktree (--cleanup)

If the merge fails with conflicts, gwit exits with a helpful message so you can resolve manually.

gwit status

Show detailed status of all active gwit worktrees.

gwit status          # rich table output
gwit status --json   # machine-readable JSON

Displays per-worktree: branch, path, port, ahead/behind counts, dirty-file count, and PR info (if gh CLI is installed).

gwit sweep

Bulk-remove worktrees whose branches are fully merged into the default branch or whose GitHub PRs are merged/closed.

gwit sweep             # interactive confirmation
gwit sweep --dry-run   # show what would be removed
gwit sweep --force     # skip confirmation

Runs cleanup hooks for each removed worktree, just like gwit remove.

gwit rename <old-branch> <new-branch>

Rename a worktree's git branch, move the directory (if the slug changes), and update the registry atomically.

gwit rename feature/auth feature/authentication

gwit config

Show or update global configuration stored in ~/.gwitrc.

gwit config                        # show all settings
gwit config get editor             # get one setting
gwit config set editor cursor      # change editor
gwit config set location sibling   # or: subdirectory
gwit config set basePort 4000      # starting port for auto-assignment

| Key | Values | Default | | --- | --- | --- | | editor | any editor command | code | | location | sibling, subdirectory | sibling | | basePort | 1-65535 | 3001 |

location controls where worktrees are placed:

  • sibling - next to the repo: ../myapp-feature_auth
  • subdirectory - inside the repo: myapp/.worktrees/feature_auth

File formats

.gwitinclude

List of gitignored files and directories to copy into every new worktree. One entry per line, comments with # ignored. Supports glob patterns via minimatch.

# .gwitinclude - files to copy into each new worktree
.env
.env.local
certs/
*.pem
secrets/**

Glob patterns (*, ?, [...], **) are expanded against the set of gitignored files in the repo. Literal entries are copied directly.

Only gitignored files are eligible to copy. Tracked files are silently skipped - gwit is an allowlist for files that must be present but cannot be committed.

.gwitcommand

Shell commands run inside the worktree after creation. One command per line.

# .gwitcommand - setup commands
# $GWIT_* variables are available here
npm install
createdb myapp$GWIT_DB_SUFFIX
npm run db:migrate
echo "PORT=$GWIT_PORT"                                         >> .env
echo "DATABASE_URL=postgres://localhost/myapp$GWIT_DB_SUFFIX"  >> .env
echo "REDIS_URL=redis://localhost:6379/$GWIT_INDEX"            >> .env

Commands run sequentially. If any command fails, the rest are skipped and gwit exits with an error.

.gwitcleanup

Shell commands run inside the worktree before removal. Mirrors .gwitcommand.

# .gwitcleanup - teardown commands
dropdb --if-exists myapp$GWIT_DB_SUFFIX

Commands run sequentially. Errors are printed as warnings and execution continues - cleanup is best-effort.

Environment variables

All $GWIT_* variables are available inside .gwitcommand and .gwitcleanup:

| Variable | Example value | Description | | --- | --- | --- | | $GWIT_BRANCH | feature/auth | Raw branch name | | $GWIT_SLUG | feature_auth | Filesystem/DB-safe slug | | $GWIT_PORT | 3001 | Auto-assigned unique port | | $GWIT_DB_SUFFIX | _feature_auth | Underscore-prefixed slug for DB names | | $GWIT_WORKTREE_PATH | /home/user/myapp-feature_auth | Absolute path to this worktree | | $GWIT_MAIN_PATH | /home/user/myapp | Absolute path to the main repo | | $GWIT_INDEX | 1 | Stable, never-reused index per repo |

$GWIT_INDEX is monotonically increasing and never reused after removal - safe to use as a Redis DB number, a Docker Compose project suffix, or any resource that must survive across separate worktree sessions.

Example: full-stack isolation

A complete setup for a Node.js app with Postgres and Redis:

.gwitinclude

.env

.gwitcommand

npm install
createdb myapp$GWIT_DB_SUFFIX
npm run db:migrate
echo "PORT=$GWIT_PORT"                                         >> .env
echo "DATABASE_URL=postgres://localhost/myapp$GWIT_DB_SUFFIX"  >> .env
echo "REDIS_URL=redis://localhost:6379/$GWIT_INDEX"            >> .env

.gwitcleanup

dropdb --if-exists myapp$GWIT_DB_SUFFIX

With this setup, gwit feature/auth spins up a worktree with its own database (myapp_feature_auth), its own Redis DB (redis://.../1), and its own port (3001) - no collisions, no manual steps.

Registry and config files

| File | Purpose | | --- | --- | | ~/.gwitrc | Global config (editor, location, basePort) | | ~/.gwit/worktrees.json | Active worktrees registry (paths, ports, indices) |

Both files are user-owned and never shared. The registry is written atomically using a write-and-rename strategy to handle concurrent gwit runs safely.

License

MIT