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

@axnic/pi-extension-settings-sdk

v0.2.0

Published

Type-safe SDK for interacting with the pi-extension-settings panel (for extension authors).

Readme

pi-extension-settings SDK

A type-safe, declarative settings management SDK for pi extensions. Define your schema once — get typed accessors, validation, autocompletion, live updates, and a rendered settings panel for free.


Why this SDK?

Most extensions need settings. Most extensions end up writing the same plumbing: storage, validation, change events, UI wiring, and a set of TypeScript types that drift from the storage format over time.

This SDK removes all of that. You write one schema and get:

| Without the SDK | With the SDK | | ----------------------------------------------- | -------------------------------------------------- | | Hand-rolled storage keys and JSON parsing | settings.get("key") returns the right type | | Manual validation scattered across the codebase | One validation field per node | | UI boilerplate for every new setting | A settings panel rendered automatically | | Silent type drift between storage and code | InferConfig<T> enforces the type at compile time | | Wire listeners by hand, remember to clean up | onChange(), session-scoped, no cleanup required |


Feature highlights

  • End-to-end type safety. InferConfig<T> derives a flat key → value map from your schema. Every get(), set(), and onChange() is type-checked against that map.
  • Declarative schema. One call to S.settings({...}) describes defaults, validation, transformation, autocompletion, and display format.
  • Rich node types. Text, Boolean, Enum, List (structured rows), Dict (key/value pairs), and Section (nestable groups).
  • 20 validators, 16 transforms, 2 completers, 5 display functions out of the box. Compose them with v.all, v.any, t.pipe, t.compose.
  • Live updates. Subscribe to per-key events with onChange(). Session-scoped — no listener cleanup required.
  • Strict runtime checks. S.settings() validates tooltip length and enum defaults at construction time, so schema bugs fail fast.
  • Renders on GitHub and GitBook. Documentation is pure CommonMark with Mermaid diagrams — no platform lock-in.

Architecture at a glance

flowchart LR
    Schema["Schema<br/>(S.settings)"] --> ES["ExtensionSettings"]
    ES --> Storage[("Storage")]
    ES --> Panel["Settings Panel<br/>(auto-rendered)"]
    Panel -- "user edits" --> ES
    ES -- "onChange event" --> Ext["Your extension"]
    Ext -- "settings.set()" --> ES
    Ext -- "settings.get()" --> ES

Your extension never touches storage directly. It talks to ExtensionSettings, which brokers reads and writes, fires change events, and keeps the UI synchronized.


60-second example

import { S, ExtensionSettings } from "pi-extension-settings/sdk";
import { v, t, d } from "pi-extension-settings/sdk/hooks";

// 1. Declare the schema
const schema = S.settings({
  "api-url": S.text({
    tooltip: "API base URL",
    default: "https://api.example.com",
    validation: v.url(),
    transform: t.normalizeUrl(),
  }),
  theme: S.enum({
    tooltip: "Color theme",
    default: "dark",
    values: ["dark", "light", "system"],
  }),
  enabled: S.boolean({
    tooltip: "Enable extension",
    default: true,
  }),
});

// 2. Create the accessor
const settings = new ExtensionSettings(pi, "my-extension", schema);

// 3. Read — fully typed
const url = settings.get("api-url"); // inferred as string
const on = settings.get("enabled"); // inferred as boolean

// 4. Write — fully typed
settings.set("theme", "light"); // ok
// settings.set("theme", 42);          // compile error

// 5. React to changes
settings.onChange("theme", (t) => applyTheme(t));

Tip: The settings panel UI is generated from your schema automatically. You do not write any UI code.


Documentation map

Get going

| Page | What you'll learn | | --------------------------------------- | --------------------------------------------------------------------- | | Getting Started | Install the SDK and ship your first integration in under five minutes |

Concepts

| Page | What you'll learn | | ----------------------------------------------------- | -------------------------------------------------------- | | Concepts Overview | The three core abstractions and how they fit together | | Schema Builder | The S namespace, runtime validation, and InferConfig | | Node Types | Every node type, field by field, with a decision tree | | ExtensionSettings | Class lifecycle, get / set / onChange / getAll |

Hooks

| Page | What you'll learn | | --------------------------------------- | ------------------------------------------------------------- | | Hooks Overview | The four namespaces, execution order, composition | | Validators | All 20 built-in validators with examples | | Transforms | All 16 built-in transforms with examples | | Completers | c.filePath and c.staticList | | Display Functions | d.color, d.badge, d.path, d.dictEntry, d.keybinding |

Examples

| Page | Complexity | What it shows | | ---------------------------------------------- | ------------ | ----------------------------------------------------- | | Weather Widget | Beginner | Text, Boolean, Enum; basic validators | | Code Formatter | Intermediate | Sections, List with Struct, numeric validation | | AI Assistant | Advanced | Nested sections, Dict, InferConfig, full hook stack |

Reference

| Page | Use when | | ---------------------------------------- | ------------------------------------------------- | | API Reference | You want the full list of exports at a glance | | Type Reference | You need the exact TypeScript signature of a type | | Error Reference | You need to catch a specific error class |


Quick links


Documentation drafted with AI assistance — Claude Opus 4.6 (Anthropic). Reviewed by a human maintainer before publishing.