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

@apisurf/rig

v1.0.3

Published

CLI that sets up the workspace for a task: git worktrees, diffs, and LLM prompt files

Readme

rig

A small CLI that sets up the rig for a piece of work: it manages git worktrees, captures diffs, and assembles LLM prompt files from reusable guides and local working docs.

Overview

rig provides a few focused commands:

  • wt — create, list, cd into, remove, and copy files into git worktrees
  • path — pick from your repositories and print their absolute paths
  • diff — write a diff into DEV/diffs/ for an LLM to read
  • files — list the files a saved diff touches, with line counts
  • folders — show the folders a saved diff touches, as a tree
  • prompt — build a prompt file that links selected guides and local docs
  • init — create the directories referenced by your config
  • clean — remove the DEV/ working tree

Installation

Prerequisites

  • Node.js 20.12 or newer — ink and @inquirer/prompts both require it
  • Git
  • pnpm, for local development only

Install from npm

pnpm add -g @apisurf/rig
# or: npm install -g @apisurf/rig

# Verify
rig --version

Local development

# From the repo root
pnpm install
pnpm build
pnpm link --global

# Verify
rig --version

Configuration

Create a configuration file at ~/.apisurf/rig.config.json:

{
  "worktreesPath": "/path/to/worktrees",
  "guidesPath": "/path/to/guides",
  "repoParents": ["/path/to/repos", "/path/to/more/repos"]
}

Configuration Options

| Field | Type | Needed by | Description | | --------------- | -------- | ---------------------- | ------------------------------------------------------------------- | | worktreesPath | string | every wt subcommand | Root directory where rig creates and manages git worktrees | | guidesPath | string | optional, for prompt | Folder of guide files (two-level: <guidesPath>/<folder>/*.md) | | repoParents | string[] | path | Folders whose direct children are the repositories rig path lists |

wt, path, init, and prompt read the config file and exit with an error when it is missing. diff, files, folders, and clean need no config at all. Without guidesPath, prompt still runs — it just offers only the local diffs and plans.

Run rig init to create any configured directories that don't yet exist.

Guides folder layout

guidesPath is scanned two levels deep — each top-level folder groups related guides:

guides/
  ├── backend/
  │   ├── api-setup.md
  │   └── database.md
  └── frontend/
      └── components.md
  • Folders whose name starts with _ are ignored.
  • A README.md inside a guide folder is skipped.

Commands

rig wt

Git worktree management. Worktrees are organized under <worktreesPath>/<repo>/<branch>.

rig wt new <source_branch> <dest_branch>   # new worktree branched from origin/<source_branch>
rig wt new-remote <branch_name>            # new worktree tracking an existing remote branch
rig wt ls                                  # list worktrees for a selected project
rig wt cd                                  # print a cd command: eval "$(rig wt cd)"
rig wt cp <paths...>                       # copy files/folders into a selected worktree
rig wt rm [branches...]                    # remove worktree(s) (interactive if no args)
rig wt rmall                               # remove all worktrees for the current repo

The repo name comes from git remote get-url origin, so wt needs the current project to have an origin remote. new-remote fetches origin before adding the worktree.

ls, cd, cp, and an argument-less rm start by asking which project — the list is every directory under worktreesPath that currently holds at least one worktree, not just the repo you are standing in. rm with branch names, and rmall, act on the current repo only.

cp preserves each path's location relative to the repo root, creating parent directories in the destination as needed; a path outside the repo is refused.

When git refuses to remove a worktree because the directory still has leftover files, rm offers to delete the directory outright. Answering yes destroys everything under it, including untracked and ignored files such as .env and build output; the default is no.

rig path (alias rig pp)

Pick from your repositories and print the absolute path of each one selected, one per line. The list is every git repository sitting directly inside a repoParents folder — nested repositories and plain folders are left out.

Search and select in one go: type to filter, ↑/↓ to move, and Tab to toggle the highlighted repository — which also clears the search, ready for the next one. Enter finishes; Esc cancels and prints nothing.

rig path                # prints e.g. /path/to/repos/my-project
cd "$(rig pp)"          # jump into the single repository selected

The picker is drawn on stderr, so stdout carries nothing but the paths.

rig diff

Write a diff into DEV/diffs/ for an agent to read. It takes no arguments — it asks what you want to diff, then what to diff it against:

rig diff

| You pick | It runs | It writes | | ---------------- | ------------------- | ------------------------------- | | Staged <> HEAD | git diff --cached | DEV/diffs/diff-staged-NNN.txt | | HEAD <> branch | git diff <branch> | DEV/diffs/diff-branch-NNN.txt | | HEAD <> commit | git diff <hash> | DEV/diffs/diff-commit-NNN.txt |

Both lists are searchable, so nothing has to be typed exactly — branches are your local ones, commits the last 50, shown as hash subject. NNN counts up from the files already in DEV/diffs/, so an earlier diff is never overwritten. An empty diff writes nothing and says so.

rig files [diffFile]

Read a saved diff back and list the files it touches, with per-file line counts and a total. With no argument, you pick one from DEV/diffs/ — newest first, and searchable. A path is taken as given, relative to the working directory or absolute.

rig files
rig files DEV/diffs/diff-branch-002.txt
src/commands/diff.ts  +48 -12
src/config.ts         +6 -0

2 files changed, +54 -12

rig folders [diffFile]

The same diff, reduced to the folders it touches and drawn as a tree. Each folder carries the number of changed files and the line counts for everything beneath it, so . holds the totals for the whole diff. The diff file is chosen the same way as for rig files.

rig folders
rig folders DEV/diffs/diff-branch-002.txt
.                 4 files  +71 -12
├── docs          1 file   +9 -0
└── src           3 files  +62 -12
    └── commands  2 files  +56 -12

3 folders, 4 files changed, +71 -12

rig prompt (alias rig p)

Build a prompt file under DEV/ that links selected guides and local docs.

rig prompt

What it does:

  1. Loads guides from your configured guidesPath (if set), diffs from DEV/diffs/, and plans from DEV/plans/.
  2. Asks you to multi-select from each of those three, in that order, via a TUI. Any list that is empty is skipped; cancelling out of a step abandons the whole run.
  3. Copies the selected guides into DEV/doc/ and writes a numbered DEV/prompt-NNN.md linking everything relative to itself. Diffs and plans are linked where they already are, not copied.

Each selection step searches and selects in one go: type to fuzzy-filter, ↑/↓ to move, Tab to toggle the highlighted item — which also clears the search, ready for the next one — Enter to confirm (an empty selection is allowed), Esc to cancel.

The prompt ends with a TASK_DESCRIPTION_HERE placeholder — that is the one part you write yourself before handing the file over. It opens in Sublime Text if subl is on your PATH, and is left on disk either way.

A guide whose filename is already in DEV/doc/ is reused rather than overwritten, and reported as (reused). That is what lets you run prompt repeatedly through a task without a guide you have since edited being reverted to the shared copy.

DEV/diffs/ and DEV/plans/ are scanned one level deep only, skipping entries that start with . or _; guides follow the two-level layout above. With nothing in any of the three, it exits non-zero rather than writing an empty prompt.

rig init

Create the directories referenced by your config (worktreesPath, guidesPath), reporting each as created or exists. A config with neither path set is reported as nothing to do. The config file itself is not created for you — init exits with an error when it is missing, naming the shape to write.

rig clean

Remove the entire DEV/ tree in the current project.

Development

pnpm install

# Run from source without building
pnpm dev <command> [args]

pnpm typecheck      # tsc --noEmit
pnpm lint           # oxlint (lint:fix applies what it can)
pnpm fmt            # oxfmt (fmt:check to verify without writing)

# Build to dist/
pnpm build

Before you push

Nothing runs these for you — there is no CI on push — so run them locally:

make check          # lint, typecheck, test (if present), fmt:check, build

lint fails on anything in oxlint's correctness category. The maintainability limits below are reported as warnings and do not fail the command, so read its output rather than trusting the exit code.

What the linter enforces

Beyond oxlint's correctness and suspicious categories, four structural limits are set in .oxlintrc.json:

| Rule | Limit | What it catches | | ---------------------- | ------------- | ------------------------------------------------------ | | complexity | 15 (modified) | a function with too many branches to hold in your head | | max-depth | 4 | nesting that wants an early return or a helper | | max-params | 5 | an argument list that wants to be an object | | max-nested-callbacks | 3 | callback pyramids |

The thresholds come from this codebase's own distribution: the median function scores 3 and the 95th percentile is around 14, so a hit is a real outlier rather than ordinary branching. Splitting the function is almost always the right fix — promptCommand is the worked example, now a sequence of named steps. If splitting genuinely does not apply, suppress the one rule and say why:

/* oxlint-disable complexity -- exhaustive protocol switch, flat by nature */

Releasing

@apisurf/rig is a single package. Releases run from the Makefile; make on its own prints the steps.

make changeset                         # describe the change: patch, minor or major
make version                           # apply it: bump versions, write CHANGELOGs
git add -A && git commit -m "Version 1.0.1"
make release                           # check, build, publish to npm, tag
git push --follow-tags

Changesets runs with commit: false, so make version leaves the bumps and CHANGELOG entries in the working tree for you to review. Commit them first: make release refuses a dirty tree, because changeset publish tags whatever commit is checked out.

make release asks for an npm granular access token (or reads NPM_TOKEN) and keeps it in memory; .release.npmrc holds only the ${NPM_TOKEN} reference. The token needs read and write on the whole @apisurf scope — one limited to selected packages cannot create new ones — and Bypass 2FA checked, or the registry rejects the publish with EOTP.

Publishing is per package and not atomic, while the git tags are written either way. Confirm on npm rather than trusting the tags; re-running make release publishes only what is missing. make pack shows what would ship without publishing anything.

FAQ

Q: What is a "guide" in rig?

A: A guide is a markdown file containing conventions, instructions, or context that the prompt command links into a generated prompt so an LLM follows it. Guides live in folders within your guidesPath directory.

Q: Do I need both config paths?

A: No. worktreesPath is only needed for wt; guidesPath is only needed to surface guides in prompt; repoParents is only needed for path. Set whichever commands you use.

License

ISC


Need help? Check the configuration at ~/.apisurf/rig.config.json or run rig --help for command usage.