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

@bacnh85/pi-config-panel

v0.1.4

Published

Shared interactive config-panel kernel for Pi extensions — arrow-key toggle/edit overlay panels (PanelRow/PanelGroup/PanelAction row model + ConfigPanelModel TUI shell) rendered via ctx.ui.custom.

Downloads

906

Readme

pi-config-panel

Shared interactive config-panel kernel for Pi extensions — the arrow-key toggle/edit overlay panel behind pi-a2a's /a2a-config, extracted as a library so every extension gets the same panel without duplicating TUI code.

Pure library — no pi field in package.json, installs nothing into Pi itself. Consumer extensions declare @bacnh85/pi-config-panel as a dependency and Pi resolves it transitively at load time.

Usage

import { openConfigPanel, row, type BuildRows } from "@bacnh85/pi-config-panel";

interface MyCfg { baseUrl: string; port: number; enabled: boolean; }

const build: BuildRows<MyCfg> = (cfg, actions) => [
  {
    key: "main", label: "Main", rows: [
      row("baseUrl", "Base URL", "string", cfg.baseUrl, (v) => { cfg.baseUrl = String(v ?? ""); }),
      row("port", "Port", "number", cfg.port, (v) => { cfg.port = Number(v) || cfg.port; }),
      row("enabled", "Enabled", "toggle", cfg.enabled, (v) => { cfg.enabled = Boolean(v); }),
    ],
  },
];

pi.registerCommand("my-config", {
  handler: async (_args, ctx) => {
    const working = structuredClone(currentCfg);
    await openConfigPanel({ ctx, cfg: working, build, title: "My Extension", onSave: (saved) => {
      if (saved) persistToSettingsJson(working);
    }});
  },
});

API

| Export | What it does | |---|---| | openConfigPanel(opts) | Open the panel via ctx.ui.custom; resolves on close. Esc saves when dirty. | | ConfigPanelModel | The TUI component (headless-testable — all kernel tests drive it without a TUI). | | row(key, label, kind, value, set, opts?) | Row factory; setter syncs both the backing config and row.value. opts.mask hides secrets (••••, blank submit keeps the old value). | | toInt(v, fallback) | Integer coercion keeping the fallback on garbage. | | applyRows(cfg, groups) | Re-apply every row's value (tests / "apply" flows). | | kindValue(kind, raw) | Coerce a raw input string to a toggle/number/string value. | | makeOnAction(model, cfg, build, actions, onError) | Action-row handler factory (rebuilds rows after add/remove actions). | | PanelRow / PanelGroup / PanelAction / BuildRows<T> | Row-model types. |

Rules the kernel enforces (learned the hard way)

  • No nested dialogs. The panel never calls ctx.ui.input()/select()/confirm() while displayed — they render under the overlay and fight its focus. Action rows use the built-in inline prompt() instead; string/number rows edit inline via an embedded Input.
  • Esc = save & close when dirty (no confirmation dialog); Esc inside an inline edit cancels the edit.
  • Whole-group windowing — a group header never renders without all its rows.
  • Width-safe render — every line is truncated to the overlay width (the TUI throws on wider lines).
  • Secrets stay masked — masked rows never render the raw value; an empty submit keeps the existing secret instead of wiping it.

Config placement convention (for consumer extensions)

  • Non-secret config (baseUrl, toggles, ports) → settings.json under the extension's key (router.baseUrl, commandcode.baseUrl, …). Never write to a repo-controlled .pi/settings.json.
  • Secrets / API keys → auth.json via Pi's built-in /login (apiKey: "$ENV_VAR" provider pattern). Never settings.json.

Development

npm test        # mocha + tsx (cd extensions && mocha)
npm run typecheck