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

@f440/git-zone

v0.2.3

Published

CLI for managing git worktrees by branch, ref, and commit

Downloads

61

Readme

git-zone

git-zone is a command-line tool for creating, listing, and removing Git worktrees with a simpler workflow than raw git worktree commands.

It is designed for the common cases developers reach for every day:

  • open a worktree for an existing branch
  • create a new branch in its own worktree
  • inspect all worktrees in a repository at a glance
  • remove a worktree by path, branch name, or directory name
  • open a worktree from a tag or commit

Installation

Install from npm:

npm install -g @f440/git-zone

After installation, the command is available as:

git-zone

Zsh completion

git-zone ships with a zsh completion file at completions/_git-zone.

For a global npm install, add the package completion directory to your fpath and initialize completions:

fpath+=("$(npm root -g)/@f440/git-zone/completions")
autoload -Uz compinit && compinit

When working from a local checkout of this repository, point fpath at the repository copy instead:

fpath+=("/path/to/git-zone/completions")
autoload -Uz compinit && compinit

After reloading your shell, git-zone completes subcommands, flags, Git refs for add, and existing worktree targets for remove.

For local development from this repository:

npm install
bun run build
npm install -g .

Quick Start

Create a detached worktree from the current HEAD explicitly:

git-zone add HEAD --detach

Create a worktree for an existing branch:

git-zone add feature/login-fix

Create a new branch from main in a new worktree:

git-zone add main -b spike/new-idea

Show all worktrees for the current repository:

git-zone list
git-zone list --json

Remove a worktree:

git-zone remove pr-123
git-zone remove /full/path/to/worktree
git-zone remove feature/login-fix -b

Commands

git-zone add <target>

Creates a new worktree for the current repository.

The target can be:

  • a local branch
  • a remote-tracking branch such as origin/main
  • a tag
  • a commit or revision

When the target is a local branch, the new worktree checks out that branch. When the target is a plain branch name and only a matching remote-tracking branch exists, git-zone creates a local tracking branch by default. When the target is an explicit remote branch, tag, commit, or HEAD, the new worktree is created in detached HEAD state unless you choose a branch explicitly.

Use -b to create a new branch, -B to reset or reuse a branch name, --detach or -d to force detached HEAD, and -f or --force to ask Git to allow a branch that is already checked out in another worktree:

git-zone add main -b spike/new-idea
git-zone add origin/main -B feature/from-remote
git-zone add HEAD --detach
git-zone add HEAD -d
git-zone add main -f

-f does not bypass existing local branch collisions for -b, default branch names guessed from remote-tracking branches, or zone path collisions.

Worktree placement is controlled by the Git config key zone.workspace.pathTemplate. The template supports ${repo}, ${workspace}, and environment variables such as ${HOME}. Relative paths are resolved from the main worktree root. ${workspace} must be the final path segment. Undefined environment variables are rejected as configuration errors.

git config zone.workspace.pathTemplate '../.zone/${repo}/${workspace}'
git config zone.workspace.pathTemplate '${HOME}/.local/share/git-zone/${workspace}'

If you want compatibility with Claude Code's claude --worktree layout, configure:

git config zone.workspace.pathTemplate '.claude/worktrees/${workspace}'

Optional: gh zone alias for pull requests

If you use GitHub CLI, you can install an optional gh zone alias that fetches a pull request head ref and opens it with git-zone.

gh alias set --shell zone - <<'SH'
sel=$1
shift || { echo "usage: gh zone <pr-url-or-number> [git-zone args...]" >&2; exit 1; }

repo_of_remote() {
  url=$(git remote get-url "$1" 2>/dev/null) || return 1
  case "$url" in
    https://github.com/*) repo=${url#https://github.com/} ;;
    [email protected]:*) repo=${url#[email protected]:} ;;
    ssh://[email protected]/*) repo=${url#ssh://[email protected]/} ;;
    *) return 1 ;;
  esac
  printf '%s\n' "${repo%.git}"
}

base_remote() {
  for r in $(git remote); do
    [ "$(git config --get "remote.$r.gh-resolved" 2>/dev/null)" = "base" ] || continue
    [ -z "$found" ] || return 1
    found=$r
  done
  [ -n "$found" ] && printf '%s\n' "$found"
}

pick_remote_for_repo() {
  want=$1
  for r in $(git remote); do
    [ "$(repo_of_remote "$r")" = "$want" ] || continue
    if [ "$(git config --get "remote.$r.gh-resolved" 2>/dev/null)" = "base" ]; then
      printf '%s\n' "$r"
      return
    fi
    [ -z "$first" ] && first=$r || {
      echo "gh zone: multiple remotes match $want; mark one as gh-resolved=base" >&2
      return 1
    }
  done
  [ -n "$first" ] && printf '%s\n' "$first" || {
    echo "gh zone: no git remote matches $want" >&2
    return 1
  }
}

meta=$(gh pr view "$sel" --json number,headRefName --jq '[.number,.headRefName] | @tsv') || exit $?
pr=$(printf '%s\n' "$meta" | cut -f1)
branch=$(printf '%s\n' "$meta" | cut -f2-)

case "$sel" in
  https://github.com/*/pull/*|http://github.com/*/pull/*)
    path=${sel#https://github.com/}
    path=${path#http://github.com/}
    owner=${path%%/*}
    rest=${path#*/}
    repo=${rest%%/*}
    remote=$(pick_remote_for_repo "$owner/$repo") || exit 1
    ;;
  *)
    remote=$(git config --get checkout.defaultRemote 2>/dev/null || true)
    [ -n "$remote" ] || remote=$(base_remote 2>/dev/null || true)
    [ -n "$remote" ] || remote=origin
    ;;
esac

git fetch "$remote" "refs/pull/$pr/head" || exit $?

for a in "$@"; do
  case "$a" in
    -b|-B|--detach|-d) exec git zone add FETCH_HEAD "$@" ;;
  esac
done

exec git zone add FETCH_HEAD -b "$branch" "$@"
SH

Usage:

gh zone 12345
gh zone https://github.com/owner/repo/pull/12345
gh zone 12345 -B my/local-branch

git-zone list

Shows every worktree registered for the current repository.

The output includes:

  • the current worktree marker
  • the checked out branch or detached
  • the current short commit SHA
  • upstream branch information
  • ahead/behind status
  • whether the worktree is clean or dirty
  • the absolute path

Use --json for machine-readable output that is easier to consume from tools such as fzf and jq. The command returns a JSON array of worktree objects.

git-zone remove <name-or-path>...

Removes one or more worktrees from the current repository.

Each target can be resolved by:

  • full path
  • local branch name
  • worktree directory name

Use -b or --delete-branch to delete the corresponding local branch after removing the worktree. Use -f or --force to force removal when Git would normally refuse it.

Hooks

git-zone can run user-defined commands when a worktree is added or removed.

Configure hooks with Git config:

git config zone.hooks.postAdd './scripts/zone-post-add'
git config zone.hooks.preRemove './scripts/zone-pre-remove'
git config zone.hooks.postRemove './scripts/zone-post-remove'

Hook commands are executed by /bin/sh -c from the main worktree directory.

postAdd runs after a worktree has been created successfully. preRemove runs before a worktree is removed. A non-zero exit aborts removal for that target. postRemove runs after a worktree has been removed successfully.

Hooks receive the following environment variables:

  • ZONE_EVENT
  • ZONE_MAIN_WORKTREE
  • ZONE_WORKTREE_PATH
  • ZONE_ZONE_NAME
  • ZONE_BRANCH

Example postAdd hook:

#!/bin/sh
set -eu

ln -sf "$ZONE_MAIN_WORKTREE/.env.local" "$ZONE_WORKTREE_PATH/.env.local"

Example postRemove hook:

#!/bin/sh
set -eu

tmux kill-session -t "zone-$ZONE_ZONE_NAME" || true

Example preRemove hook:

#!/bin/sh
set -eu

docker compose -p "zone-$ZONE_ZONE_NAME" down

Examples

Create worktrees from different targets:

git-zone add main
git-zone add origin/main
git-zone add v1.2.3
git-zone add abc1234

Create a branch directly into a new worktree:

git-zone add origin/main -b feature/from-remote

Remove by branch name or directory name:

git-zone remove feature/login-fix
git-zone remove pr-123

Help

git-zone --help
git-zone add --help
git-zone list --help
git-zone remove --help

Release

git-zone is published to npm as @f440/git-zone through GitHub Actions trusted publishing.

Trusted Publisher should be configured in npm for:

  • GitHub user: f440
  • Repository: git-zone
  • Workflow filename: publish.yml

To publish a new version:

npm version patch --no-git-tag-version
git commit -am "Prepare vX.Y.Z release"
git push origin main
npm run release:draft

Then open the draft GitHub Release, review the generated notes, and click Publish release. The publish.yml workflow runs tests, builds the CLI, verifies the release tag matches package.json, and publishes to npm.