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

@elianiva/pi-ckers

v1.1.0

Published

Modular namespace pickers for pi: @file:, @git:, @jj:

Readme

@elianiva/pi-ckers

Namespace-prefixed pickers for pi. This is a library package, not an auto-loading extension.

Why Namespaced Pickers?

Dumb models struggle to differentiate between directories and files purely based on trailing /. By using explicit prefixes like @dir: and @file:, you give the agent a clear hint about what you're referring to. No more ambiguous paths. This also allows me to scope my suggestions, when I want to search for dirs I don't want to also get file suggestions.

This also makes it extensible because you can have different namespaces, for example I use @git: or @jj: to point the agent to changes/revisions so it can review the diff, without having me to copy/paste the ID myself.

Why a Library Package?

Extensibility: This is intentionally designed as a library you compose, not a ready-to-use extension. You build your own editor by combining pickers with other packages.

No hard dependencies: This extension was made alongside my other extension, @elianiva/pi-starship, which also overrides the editor, but I want to compose them and not have them have hard dependencies for each other.

Overrides editor: Since this wraps/replaces the editor component, it can't be an auto-loading extension because you may have other extension that already overrides the editor. The extension loading in Pi have no particular order, so you can't stack overriding editors. The way you use this extension is explicitly opt-in by wrapping your editor with withPickers().

See how I use it in my configuration.

Installation

bun add @elianiva/pi-ckers

Usage

Create your own extension in ~/.pi/extensions/my-extension/:

import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { withPickers } from "@elianiva/pi-ckers";
import { filePicker, dirPicker } from "@elianiva/pi-ckers/builtin/fff";
import { grepPicker } from "@elianiva/pi-ckers/builtin/grep";
import { gitPicker } from "@elianiva/pi-ckers/builtin/git";
import { jjPicker } from "@elianiva/pi-ckers/builtin/jj";

// Wrap any editor with picker support
const EditorWithPickers = withPickers(YourEditorClass, [
  filePicker(),
  dirPicker(),
  grepPicker(),
  gitPicker(),
  jjPicker(),
]);

export default function myExtension(pi: ExtensionAPI) {
  pi.on("session_start", async (_event, ctx) => {
    if (!ctx.hasUI) return;
    ctx.ui.setEditorComponent(
      // Pass ExtensionContext as 5th argument to initialize pickers
      (tui, theme, kb) => new EditorWithPickers(tui, theme, kb, undefined, ctx)
    );
  });
}

Features

Type any namespace prefix in the editor:

| Prefix | Description | Example | |--------|-------------|---------| | @file: | Fuzzy file picker | @file:src/index | | @dir: | Fuzzy directory picker | @dir:components | | @grep: | Grep file contents | @grep:foo | | @git: | Git revision picker | @git:main | | @jj: | Jujutsu change picker | @jj:abc |

API

withPickers(EditorClass, pickers)

Higher-order function that adds picker autocomplete to any editor that extends CustomEditor. Make sure the constructor receives ctx as the 5th parameter.

import { CustomEditor } from "@mariozechner/pi-coding-agent";
import { withPickers } from "@elianiva/pi-ckers";
import { filePicker, grepPicker } from "@elianiva/pi-ckers/builtin/fff";

const MyEditor = withPickers(CustomEditor, [
  filePicker(),
  grepPicker(),
  gitPicker(),
]);

createPicker(config)

import { createPicker } from "@elianiva/pi-ckers";

// Static picker - handles filtering internally
const staticPicker = createPicker({
  type: "static",
  prefix: "@emoji:",
  items: [
    { value: "@emoji:rocket", label: "🚀", description: "rocket" },
    { value: "@emoji:fire", label: "🔥", description: "fire" },
  ],
  maxResults: 20,
});

// Sync picker - you provide the search function
const syncPicker = createPicker({
  type: "sync",
  prefix: "@my:",
  search(query, ctx) {
    return [
      { value: "@my:result", label: "Result", description: "Details" }
    ];
  },
  init(ctx) {
    // Optional: setup cache, watchers, etc.
  },
  clearCache() {
    // Optional: clear cached data
  },
  destroy() {
    // Optional: cleanup when session ends
  }
});

Picker types:

  • type: "static" - Provide items array, picker handles filtering
  • type: "sync" - Provide search(query, ctx) function

Common options for all types:

  • prefix - The namespace prefix (e.g., "@my:")
  • minQueryLength - Minimum query length before showing completions (default: 0)
  • init(ctx) - Called once when picker is initialized
  • clearCache() - Called to clear cached data
  • destroy() - Called when session ends

Built-in Pickers

filePicker() / dirPicker()

import { filePicker, dirPicker } from "@elianiva/pi-ckers/builtin/fff";

filePicker({
  maxResults?: 20,  // Maximum results to show
})

Uses fff (fast fuzzy finder by Dmitriy Kovalenko) for fast file searching and typo-resistant algorithm.

The native binary is auto-downloaded on first use from the fff.nvim releases, verified against upstream sha256, and cached in node_modules/@elianiva/pi-ckers/bin/.

Supported Platforms:

| Architecture | OS | Binary | |--------------|-----|--------| | aarch64 | macOS | c-lib-aarch64-apple-darwin.dylib | | x86_64 | macOS | c-lib-x86_64-apple-darwin.dylib | | aarch64 | Linux | c-lib-aarch64-unknown-linux-gnu.so | | x86_64 | Linux | c-lib-x86_64-unknown-linux-gnu.so | | aarch64 | Android | c-lib-aarch64-linux-android.so | | x86_64 | Android | c-lib-x86_64-linux-android.so | | x86_64 | Windows | c-lib-x86_64-pc-windows-msvc.dll |

If your platform is not supported, the picker will gracefully fall back to a basic implementation.

Testing Status: Currently only tested on macOS ARM64 (aarch64). Other platforms should work but may have issues. Please report any problems if you have any.

grepPicker()

import { grepPicker } from "@elianiva/pi-ckers/builtin/grep";

grepPicker({
  maxResults?: 20,      // Maximum results to show
  minQueryLength?: 2,   // Minimum query length before searching
})

Searches file contents using fff's live grep. Returns results in @grep:path:line format. Requires fff binary (same as file/dir pickers).

gitPicker()

import { gitPicker } from "@elianiva/pi-ckers/builtin/git";

gitPicker()

Shows branches, tags, and recent commits. Requires git in PATH.

jjPicker()

import { jjPicker } from "@elianiva/pi-ckers/builtin/jj";

jjPicker()

Shows Jujutsu changes. Requires jj in $PATH.

Credits

  • fff.nvim — Fast fuzzy file finder by Dmitriy Kovalenko. The file/directory picker uses fff binaries which are auto-downloaded from the upstream releases.

License

MIT