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

@zyoung-ff/pando

v0.1.0

Published

A TypeScript-based CLI for managing Git worktrees with automation-first design

Readme

Pando

A TypeScript-based CLI for managing Git worktrees with automation-first design

Pando makes it effortless to work on multiple branches simultaneously using Git worktrees. Built for modern developer workflows, it provides both human-friendly commands and machine-readable output for CI/CD automation.

Features

  • 🌳 Worktree Management: Create, list, and remove git worktrees with ease
  • 🤖 Automation-First: Every command supports --json flag for scripting and AI agents
  • 🎯 Developer-Friendly: Interactive prompts when flags aren't provided
  • Fast: Built with TypeScript for type safety and performance
  • 🔧 Extensible: Clean architecture makes adding new commands simple

Installation

Using Homebrew (macOS/Linux)

brew tap zpyoung/pando
brew install pando

Using pnpm

pnpm install -g @zyoung-ff/pando

Using npm

npm install -g @zyoung-ff/pando

From source

git clone https://github.com/zpyoung/pando.git
cd pando
pnpm install
pnpm build
pnpm link

Quick Start

# Initialize configuration (optional but recommended)
pando config init

# Create a new worktree for a feature branch
pando add --path ../feature-x --branch feature-x

# List all worktrees
pando list

# Remove a worktree (interactive selection or direct with --path)
pando remove
pando remove --path ../feature-x

# View current configuration and sources
pando config show

Commands

pando add

Create a new git worktree (supports both creating new branches and checking out existing branches)

Flags:

  • -p, --path: Path for the new worktree (optional if worktree.defaultPath is configured)
  • -b, --branch: Branch to checkout or create
  • -c, --commit: Commit hash to base the new branch on
  • -f, --force: Force create branch even if it exists (uses git worktree add -B)
  • --no-rebase: Skip automatic rebase of existing branch onto source branch
  • -j, --json: Output in JSON format

Automatic Rebase: When checking out an existing branch, pando automatically rebases it onto the current branch. This keeps your feature branches up-to-date. If the rebase fails (e.g., conflicts), a warning is shown but the worktree is still created. Use --no-rebase to skip this behavior, or set worktree.rebaseOnAdd = false in config.

Examples:

# Create new branch in worktree
pando add --path ../feature-x --branch feature-x

# Checkout existing branch into worktree
pando add --path ../existing --branch existing-branch

# Using config default path (if worktree.defaultPath is set in .pando.toml)
pando add --branch feature-x
# OR using shorthand (positional argument)
pando add feature-x

# From specific commit
pando add --path ../hotfix --branch hotfix --commit abc123

# Force reset existing branch to commit
pando add --path ../feature --branch feature-x --commit abc123 --force

pando list

List all git worktrees

Flags:

  • -v, --verbose: Show detailed information
  • -j, --json: Output in JSON format

Examples:

pando list
pando list --json

pando remove

Remove a git worktree

Flags:

  • -p, --path: Path to the worktree to remove (optional - will prompt interactively if omitted)
  • -f, --force: Force removal even with uncommitted changes
  • -k, --keep-branch: Keep the local branch (do not delete it)
  • -d, --delete-branch: Delete associated branch after removing worktree (none|local|remote)
    • none: Don't delete any branches
    • local: Delete local branch only (default)
    • remote: Delete both local and remote branches
  • -j, --json: Output in JSON format (requires --path)

Branch Deletion:

  • By default, the local branch is deleted when removing a worktree
  • Use --keep-branch to preserve the branch
  • Before deleting, checks if branch is merged (use --force to skip this check)
  • Remote branch deletion requires confirmation unless --force is used
  • Use worktree.deleteBranchOnRemove in config to change default behavior

Examples:

# Interactive selection (select from list)
pando remove

# Direct removal with path (deletes local branch by default)
pando remove --path ../feature-x
pando remove --path ../feature-x --force

# Keep the branch when removing worktree
pando remove --path ../feature-x --keep-branch

# Remove worktree and delete both local and remote branches
pando remove --path ../feature-x --delete-branch remote --force

# Interactive multi-select with force flag
pando remove --force

pando clean

Clean stale git worktrees (merged branches, gone upstream, prunable)

Detection Categories:

  • Merged: Branch fully merged into main/master (or specified target branch)
  • Gone: Remote tracking branch was deleted upstream
  • Prunable: Worktree directory was already deleted

Flags:

  • --fetch: Run git fetch --prune before detection to update remote tracking branch state (configurable: clean.fetch)
  • -f, --force: Skip confirmation prompts and clean all stale worktrees
  • -k, --keep-branch: Keep local branch after worktree removal (configurable: worktree.deleteBranchOnRemove = "none")
  • --dry-run: Show what would be removed without acting
  • -t, --target-branch: Branch to check merges against (default: main or master) (configurable: worktree.targetBranch)
  • -j, --json: Output in JSON format

Examples:

# Interactive selection of stale worktrees
pando clean

# Fetch latest and detect stale worktrees
pando clean --fetch

# See what would be cleaned without acting
pando clean --dry-run

# Clean all stale worktrees without prompts
pando clean --force

# Check merges against develop branch
pando clean --target-branch develop

# Keep branches after removing worktrees
pando clean --keep-branch

# JSON output for scripting
pando clean --json

pando symlink

Move a file from the current worktree to the main worktree and replace it with a symlink. Useful for keeping configuration files, dependencies, or other shared files in sync across all worktrees.

Arguments:

  • FILE: File to symlink (required)

Flags:

  • -f, --force: Overwrite file in main worktree if it exists
  • --dry-run: Simulate the operation without making changes
  • -j, --json: Output in JSON format

Examples:

# Move .env file to main worktree and symlink it
pando symlink .env

# Preview what would happen
pando symlink package.json --dry-run

# Overwrite existing file in main worktree
pando symlink config.json --force

# Use with JSON output
pando symlink .env --json

Use Cases:

  • Environment files (.env, .env.local): Share environment configuration across worktrees
  • Lock files (package-lock.json, pnpm-lock.yaml): Ensure consistent dependency resolution
  • IDE settings (.vscode/settings.json): Share editor configuration
  • Build cache directories: Avoid duplicate downloads/compilation

pando branch backup

Create a timestamped backup of a branch. Backup branches are named backup/<sourceBranch>/<timestamp> where timestamp is UTC YYYYMMDD-HHmmss format.

Flags:

  • -b, --branch: Source branch to backup (default: current branch)
  • -m, --message: Optional message to store with the backup
  • -j, --json: Output in JSON format

Examples:

# Backup the current branch
pando branch backup

# Backup with a descriptive message
pando branch backup -m "Before risky refactor"

# Backup a specific branch
pando branch backup --branch main

# Backup with JSON output for scripts
pando branch backup --branch feature/auth -m "Pre-merge backup" --json

Use Cases:

  • Before rebasing: Create a safety net before interactive rebase
  • Before merging: Snapshot a feature branch before merging to main
  • Experimenting: Save current state before trying something risky
  • Checkpointing: Regular backups during long-running work

pando branch restore

Restore a branch to a previous backup state. Resets the target branch to match the commit of a selected backup branch.

Flags:

  • -b, --branch: Target branch to restore (default: current branch)
  • --backup: Backup branch to restore from (interactive selection if omitted)
  • -f, --force: Skip confirmation prompt
  • -d, --delete-backup: Delete the backup branch after successful restore
  • -j, --json: Output in JSON format (requires --backup)

Safety Features:

  • Checks for uncommitted changes before restoring current branch
  • Prevents restoring branches checked out in other worktrees
  • Shows commits that will become unreachable before confirmation
  • Requires explicit --backup flag with --json (no interactive mode)

Examples:

# Interactive restore - select from available backups
pando branch restore

# Restore from a specific backup
pando branch restore --backup backup/main/20250117-153045

# Restore a specific branch with force (no confirmation)
pando branch restore --branch main --backup backup/main/20250117-153045 --force

# Restore and delete the backup afterward
pando branch restore --backup backup/feature/20250117-100000 -f -d

# JSON output for automation (requires explicit backup)
pando branch restore --backup backup/feature/20250117-100000 --force --json

Use Cases:

  • Undo a rebase: Restore to pre-rebase state if conflicts are too complex
  • Recover from mistakes: Quickly get back to a known good state
  • A/B testing approaches: Restore and try a different implementation

Configuration

Pando supports flexible configuration through multiple sources with a clear priority hierarchy.

Config Commands

pando config init

Generate a configuration file with defaults and helpful comments.

Flags:

  • -g, --global: Create user-level config at ~/.config/pando/config.toml
  • --git-root: Create config at git repository root
  • -f, --force: Overwrite existing config file
  • -m, --merge: Merge missing defaults into existing config (default behavior)
  • --no-merge: Error if config already exists
  • -j, --json: Output in JSON format

Examples:

# Create project config in current directory
pando config init

# Create user-level (global) config
pando config init --global

# Create config at git repository root
pando config init --git-root

# Overwrite existing config
pando config init --force

# Add missing defaults to existing config
pando config init --merge

pando config show

Display the current effective configuration with source information.

Flags:

  • -j, --json: Output in JSON format

Examples:

# Show current config with sources
pando config show

# JSON output for scripts
pando config show --json

Configuration Locations

Pando discovers configuration from multiple locations:

| Location | File | Use Case | |----------|------|----------| | Current directory | .pando.toml | Project-specific settings | | Git root | .pando.toml | Repository-wide defaults | | Project files | pyproject.toml, package.json, etc. | Embedded in existing config | | User home | ~/.config/pando/config.toml | User-level defaults |

Configuration Priority

Settings are merged with the following priority (highest to lowest):

  1. CLI flags - Always win (e.g., --path, --no-rebase)
  2. Environment variables - PANDO_* prefixed variables
  3. Project .pando.toml - In current directory or parent directories
  4. Project files - pyproject.toml [tool.pando], package.json "pando", etc.
  5. Global config - ~/.config/pando/config.toml
  6. Built-in defaults - Sensible defaults for all options

Project vs User Config

Project config (.pando.toml in repo):

  • Shared with team via version control
  • Project-specific worktree paths and patterns
  • Checked into git

User config (~/.config/pando/config.toml):

  • Personal preferences across all projects
  • Default behaviors you always want
  • Not shared with team
# Create user-level config
pando config init --global

Config File Format

Pando uses TOML format for configuration:

# Rsync Configuration
[rsync]
enabled = true
flags = ["--archive", "--exclude", ".git"]
exclude = ["dist/", "node_modules/"]

# Symlink Configuration
[symlink]
patterns = ["package.json", ".env*"]
relative = true
beforeRsync = true

# Worktree Configuration
[worktree]
defaultPath = "../worktrees"  # Default parent directory for worktrees
rebaseOnAdd = true            # Rebase existing branches when adding worktree
deleteBranchOnRemove = "none" # Delete branch on worktree remove: "none", "local", "remote"
targetBranch = "main"         # Target branch for merge checks (used by clean command)

# Clean Configuration
[clean]
fetch = false                 # Run git fetch --prune before detection

Embedding in Project Files

Instead of a separate .pando.toml, you can embed configuration in existing project files:

pyproject.toml (Python projects):

[tool.pando]
[tool.pando.worktree]
defaultPath = "../worktrees"

package.json (Node.js projects):

{
  "pando": {
    "worktree": {
      "defaultPath": "../worktrees"
    }
  }
}

Cargo.toml (Rust projects):

[package.metadata.pando]
[package.metadata.pando.worktree]
defaultPath = "../worktrees"

Worktree Default Path

The worktree.defaultPath setting allows you to specify a default parent directory for worktrees:

  • Relative paths are resolved from the git repository root
  • Absolute paths are used as-is
  • When creating a worktree with --branch but no --path, the branch name is appended to the default path
  • Branch name sanitization: Forward slashes (/) in branch names are automatically converted to underscores (_) for filesystem safety

Example:

[worktree]
defaultPath = "../worktrees"
# Creates worktree at ../worktrees/feature-x (relative to git root)
pando add --branch feature-x

# Branch names with slashes are sanitized
pando add --branch feature/auth
# Creates: ../worktrees/feature_auth

Environment Variables

All configuration options can be set via environment variables using the PANDO_ prefix:

# Set default worktree path
export PANDO_WORKTREE_DEFAULT_PATH="../worktrees"

# Disable automatic rebase on existing branches
export PANDO_WORKTREE_REBASE_ON_ADD=false

# Delete local branch when removing worktree
export PANDO_WORKTREE_DELETE_BRANCH_ON_REMOVE=local

# Set target branch for merge checks (clean command)
export PANDO_WORKTREE_TARGET_BRANCH=main

# Always fetch before detecting stale worktrees
export PANDO_CLEAN_FETCH=true

# Now you can omit --path
pando add --branch feature-x

Environment variable format:

  • Prefix: PANDO_
  • Pattern: PANDO_SECTION_KEY
  • Example: PANDO_WORKTREE_DEFAULT_PATHworktree.defaultPath

Environment variables override file-based configuration but are overridden by explicit command-line flags.

Automation & JSON Output

All commands support the --json flag for machine-readable output:

# Use in scripts
worktrees=$(pando list --json)

# Parse with jq
pando list --json | jq '.[] | select(.branch == "feature-x")'

Development

# Install dependencies
pnpm install

# Run in development mode
pnpm dev list

# Build
pnpm build

# Run tests
pnpm test

# Lint & format
pnpm lint
pnpm format

Project Structure

pando/
├── src/
│   ├── commands/       # Command implementations
│   ├── utils/          # Shared utilities
│   └── index.ts        # Main entry point
├── test/               # Tests
├── bin/                # Executable scripts
└── dist/               # Compiled output

Requirements

  • Node.js >= 18.0.0
  • Git >= 2.5.0 (for worktree support)

Troubleshooting

Error Messages and Stack Traces

Pando uses clean error messages for expected errors (like "file already exists" or "not a git repository"). You should not see stack traces for these errors.

If you see a stack trace for a validation error, this indicates a bug - please report it!

Common error types:

  • Validation Errors: Clean error messages without stack traces (use --force, missing files, invalid arguments)
  • Operation Errors: Runtime failures with context (network errors, permission issues, git command failures)
  • Internal Errors: Stack traces indicating bugs that should be reported

JSON Output for Scripts

All commands support --json flag for machine-readable output:

# Merge missing defaults into existing config
pando config init --json
# Output: {"status":"success","action":"merged","added":[...],"addedCount":2}

# Check exit codes in scripts
pando add --path ../feature --branch feature --json
if [ $? -ne 0 ]; then
  echo "Command failed"
fi

Debug Mode

For detailed debugging, run commands with Node.js debug environment:

# Enable debug output
NODE_DEBUG=pando pnpm dev list

# Or with node inspector
node --inspect bin/dev.js list

Common Issues

"Not a git repository"

  • Make sure you're running pando from within a git repository
  • Check git status works in your current directory

"Worktree path already exists"

  • The target path already has a directory/file
  • Use a different path or remove the existing path first

"Worktree has uncommitted changes"

  • The worktree you're trying to remove has uncommitted changes
  • Commit or stash changes first, or use --force to remove anyway (WARNING: will lose changes)

"rsync is not installed"

  • Install rsync for file syncing features
  • macOS: brew install rsync
  • Ubuntu/Debian: apt install rsync
  • Or use --skip-rsync to disable file syncing

Contributing

Contributions are welcome! Please read ARCHITECTURE.md and DESIGN.md to understand the project structure and design decisions.

License

MIT © zpyoung

Why "Pando"?

Pando is a clonal colony of aspen trees that shares a single root system - much like how git worktrees share a single repository!