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

git-arborist

v0.1.15

Published

Git Worktrees, Finally Simple

Readme

Git Arborist — Git Worktrees, Finally Simple

A fast, opinionated CLI for managing git worktrees. Zero friction.

arb wraps git's worktree commands with smart defaults, automated project setup, a plugin system for GitHub/Graphite integrations, and a live TUI dashboard.

Built with TypeScript + Bun. Ships as a single binary.

Install

Homebrew (macOS / Linux)

brew install rspencerfink/git-arborist/arb

curl one-liner

curl -fsSL https://raw.githubusercontent.com/rspencerfink/git-arborist/main/install.sh | bash

npm / bun

bun add -g git-arborist       # requires Bun runtime
# or
npm i -g git-arborist         # also requires Bun installed

GitHub Releases

Download the binary for your platform from Releases, then:

chmod +x arb-darwin-arm64     # or your platform
mv arb-darwin-arm64 /usr/local/bin/arb

From source (requires Bun)

git clone https://github.com/rspencerfink/git-arborist.git
cd git-arborist
bun install
bun run build    # produces ./arb binary
mv arb /usr/local/bin/

Shell integration

arb go and arb main need to change your shell's directory. Add this to your shell config:

# zsh (~/.zshrc)
eval "$(arb shell-init zsh)"

# bash (~/.bashrc)
eval "$(arb shell-init bash)"

# fish (~/.config/fish/config.fish)
arb shell-init fish | source

Shell completions

# zsh
arb completions zsh > ~/.zfunc/_arb

# bash
arb completions bash > /etc/bash_completion.d/arb

# fish
arb completions fish > ~/.config/fish/completions/arb.fish

Quick start

cd your-repo

# Create a worktree for a new branch
arb add -b my-feature

# Switch to it (requires shell integration)
arb go my-feature

# See all worktrees
arb ls

# Go back to the main worktree
arb main

# Done? Remove it
arb rm my-feature

Commands

Lifecycle

| Command | Description | |---------|-------------| | arb add <branch> | Create a worktree for an existing branch | | arb add -b <name> | Create a new branch + worktree | | arb add -b <name> --base <ref> | Create a new branch from a specific ref | | arb rm [name] | Remove a worktree (interactive picker if no name) | | arb rm <name> --force | Force remove even if dirty | | arb rm <name> --branch | Also delete the branch | | arb go [name] | Switch to a worktree (interactive picker if no name) | | arb ls | List all worktrees with status | | arb main | Switch back to the main worktree |

Status & cleanup

| Command | Description | |---------|-------------| | arb status | Formatted table with branch, head, dirty status, ahead/behind | | arb dash | Live TUI dashboard with auto-refresh | | arb prune | Remove worktrees whose branches are merged | | arb prune --dry-run | Preview what would be pruned | | arb gc | Prune stale refs + run git garbage collection | | arb clean <name> | Reset a worktree to a clean state |

Project setup

| Command | Description | |---------|-------------| | arb init | Scaffold a .arborist.toml config file in your repo | | arb setup <name> | Re-run setup hooks on an existing worktree | | arb clone <repo> | Clone a repository | | arb clone <repo> --bare | Clone in bare-worktree layout (.bare/ + worktrees as siblings) |

Utilities

| Command | Description | |---------|-------------| | arb run <name> -- <cmd> | Run a command inside a worktree's directory | | arb open <name> | Open a worktree in your editor | | arb tmux <name> | Open a worktree in a new tmux window | | arb config list | Show current configuration | | arb config get <key> | Get a config value | | arb config edit | Open project config in $EDITOR | | arb config edit --global | Open global config in $EDITOR | | arb plugin list | List available plugins and their status |

Configuration

arb uses TOML configuration with two levels:

  • Project: .arborist.toml in your repo root (commit this)
  • Global: ~/.config/arborist/config.toml

Project config takes precedence over global config.

Example .arborist.toml

# Where worktrees are created (relative to repo root)
# Available variables: {{ branch }}, with filters: {{ branch | sanitize }}
worktree_path = "../.worktrees/{{ branch | sanitize }}"

# Editor for `arb open`
editor = "code"

# Copy files from main worktree after creation
[[setup.copy]]
from = ".env.local"

# Symlink directories from main worktree
[[setup.symlink]]
from = "node_modules"

# Run commands after creation (conditional on file existence)
[[setup.run]]
command = "bun install --frozen-lockfile"
if_exists = "bun.lock"

[[setup.run]]
command = "cp .env.example .env"
if_exists = ".env.example"

# Enable plugins
[plugins.deps]
enabled = true
strategy = "symlink"   # "symlink" | "install" | "copy"

[plugins.env]
enabled = true

[plugins.tmux]
enabled = true

[plugins.github]
enabled = true

[plugins.graphite]
enabled = true

Template variables

The worktree_path setting supports template variables:

| Variable | Example input | Output | |----------|--------------|--------| | {{ branch }} | feature/auth | feature/auth | | {{ branch \| sanitize }} | feature/auth@v2! | feature/auth-v2 | | {{ branch \| lowercase }} | Feature/Auth | feature/auth | | {{ branch \| uppercase }} | feature/auth | FEATURE/AUTH |

Plugins

Plugins hook into worktree lifecycle events and can extend the command tree.

Built-in plugins

deps — Dependency management

Automatically handles node_modules when creating worktrees.

[plugins.deps]
enabled = true
strategy = "symlink"   # fast, disk-efficient (default)
# strategy = "install" # fresh install via detected package manager
# strategy = "copy"    # full copy of node_modules

Detects your package manager automatically (bun, pnpm, yarn, npm).

env — Environment files

Copies .env* files from the main worktree to new worktrees (skips .env.example).

[plugins.env]
enabled = true

tmux — Tmux integration

Automatically opens new worktrees in a tmux window (only when running inside tmux).

[plugins.tmux]
enabled = true

github — GitHub PR status

Shows PR status and CI checks in arb ls, arb dash, and on worktree creation. Requires the GitHub CLI (gh).

[plugins.github]
enabled = true

Adds the arb pr command to show PR status for all worktrees.

graphite — Stack awareness

Shows Graphite stack position and restack warnings. Requires the Graphite CLI (gt).

[plugins.graphite]
enabled = true

Adds commands:

  • arb stack — Show the current Graphite stack
  • arb submit — Submit the current stack

TUI Dashboard

arb dash launches a live, interactive dashboard:

 arb dashboard │ 3 worktrees │ refreshed 2:15:30 PM

     Branch                      Head      Status          Sync        Path
 ──────────────────────────────────────────────────────────────────────────────
 * main                          a1b2c3d   ✓ clean         —           /repo
   feature/auth                  d4e5f6a   ~2 ?1           ↑1          /worktrees/feature-auth
   bugfix/login                  g7h8i9j   +1              ↓2          /worktrees/bugfix-login

 [j/k] navigate  [r] refresh  [q] quit

Flags:

  • --pr — Show GitHub PR column (or enable the github plugin)
  • --graphite — Show Graphite stack column (or enable the graphite plugin)

Auto-refreshes every 5 seconds.

Worktree path layout

By default, worktrees are created as siblings to your repo:

projects/
├── my-repo/              # main worktree
├── .worktrees/
│   ├── feature-auth/     # arb add -b feature/auth
│   └── bugfix-login/     # arb add -b bugfix/login

With arb clone --bare, you get a flat layout:

projects/
├── my-repo/
│   ├── .bare/            # git object store
│   ├── .git              # gitdir pointer to .bare
│   └── main/             # main worktree

Plugin API

Create custom plugins as .ts files in .arborist/plugins/ or as npm packages named arborist-plugin-*.

import type { ArboristPlugin } from 'git-arborist/plugins/types';

const myPlugin: ArboristPlugin = {
  name: 'my-plugin',
  version: '1.0.0',

  hooks: {
    async 'worktree:created'(ctx, wt) {
      // Runs after a worktree is created
    },
    async 'worktree:removing'(ctx, wt) {
      // Return false to prevent removal
    },
    async 'status:extend'(ctx, wt) {
      // Add custom columns to arb ls / arb dash
      return [{ label: 'Deploy', value: 'staging' }];
    },
  },

  commands: [
    {
      name: 'my-command',
      description: 'Does something custom',
      async run(ctx, args) {
        // Available as `arb my-command`
      },
    },
  ],
};

export default myPlugin;

Available hooks

| Hook | When | Arguments | |------|------|-----------| | worktree:created | After worktree creation | (ctx, worktreeInfo) | | worktree:ready | After creation + setup complete | (ctx, worktreeInfo) | | worktree:removing | Before removal (return false to cancel) | (ctx, worktreeInfo) | | worktree:removed | After removal | (ctx, { name, branch }) | | worktree:switch | When switching worktrees | (ctx, from, to) | | status:extend | During status display | (ctx, worktreeInfo)StatusExtension[] | | prune:shouldRemove | During prune evaluation | (ctx, worktreeInfo)boolean \| null |

Development

bun install
bun run dev -- ls           # run commands during development
bun test                    # run test suite
bun run lint                # lint with biome
bun run build               # compile to standalone binary

License

MIT