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

@justram/pie

v0.2.7

Published

Structured extraction library and CLI built on @mariozechner/pi-ai.

Readme

pie

Structured extraction library and CLI built on @mariozechner/pi-ai.

  • Mini agent loop: think → respond → validate → retry
  • Schema-first with TypeBox + AJV
  • Layered validation (schema, sync/async functions, shell, HTTP)
  • Streaming events for observability
  • Unix-friendly CLI
  • Optional response caching

Installation

npm install @justram/pie

Getting Started

Pick a model

pie uses the provider/model registry from @mariozechner/pi-ai. In the CLI, pass --model provider/model:

cat input.txt | pie \
	-s schema.json \
	-p "Extract fields" \
	--model anthropic/claude-sonnet-4-5

List available models (with optional filters):

pie --list-models --models-provider google-antigravity
pie --list-models --models-provider google-antigravity --models-filter gemini

Authentication (API keys and OAuth)

pie does not require Pi to be installed. It uses the OAuth helpers from @mariozechner/pi-ai and stores credentials in ~/.pi/agent/auth.json (created automatically on first login).

Credential resolution order:

  1. ~/.pi/agent/auth.json (API keys or OAuth tokens)
  2. Environment variables (e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY)
  3. OAuth login (only for supported providers)

OAuth login

Run --login to authenticate with an OAuth-capable provider. The CLI prints a URL and prompts you to complete login in your browser.

pie --login openai-codex

SDK login (Node-only)

SDK users can trigger the same OAuth flow programmatically (uses Node prompts and writes to ~/.pi/agent/auth.json):

import { loginWithOAuthProvider } from "@justram/pie";

await loginWithOAuthProvider("openai-codex", process.stderr);

If you only need an API key and want auto-refresh, call resolveApiKeyForProvider(provider, process.stderr). These helpers are Node-only and are not intended for browser environments.

Supported OAuth providers:

  • anthropic
  • github-copilot
  • google-gemini-cli
  • google-antigravity
  • openai-codex

If you skip this step, pie will still prompt for OAuth the first time you run a command that requires it.

cat input.txt | pie \
	-s schema.json \
	-p "Extract fields" \
	--model github-copilot/gpt-4o

API keys (recommended for examples)

Use environment variables:

export ANTHROPIC_API_KEY=sk-ant-...

Or add API keys to ~/.pi/agent/auth.json:

{
  "anthropic": { "type": "api_key", "key": "sk-ant-..." },
  "openai": { "type": "api_key", "key": "sk-..." }
}

Auth file entries take precedence over environment variables. To switch from OAuth to API keys, remove the OAuth entry for that provider and add an api_key entry.

Already using Pi?

pie shares the same auth store as Pi: ~/.pi/agent/auth.json. If you have already run /login in Pi, pie will reuse those credentials automatically. You can also add API keys to the same file and both tools will pick them up.

Resetting credentials

Edit or delete ~/.pi/agent/auth.json to remove a provider and force re-login.

Release

See docs/release.md for the release checklist.

SDK Usage

import { extractSync, getModel, Type } from "@justram/pie";

const schema = Type.Object({
	sentiment: Type.Union([
		Type.Literal("positive"),
		Type.Literal("negative"),
		Type.Literal("neutral"),
	]),
	confidence: Type.Number({ minimum: 0, maximum: 1 }),
});

const model = getModel("anthropic", "claude-sonnet-4-5");

const data = await extractSync("I love this product!", {
	schema,
	prompt: "Classify the sentiment.",
	model,
});

console.log(data);

Streaming events

import { extract } from "@justram/pie";

const stream = extract("Example text", {
	schema,
	prompt: "Extract fields.",
	model: getModel("openai", "gpt-4o"),
});

for await (const event of stream) {
	if (event.type === "validation_error") {
		console.error(event.layer, event.error);
	}
}

const result = await stream.result();

Caching

import { createFileCache, warmCache } from "@justram/pie/cache";
import { getModel } from "@justram/pie";

const model = getModel("anthropic", "claude-sonnet-4-5");
const store = createFileCache({ directory: "./cache" });

await warmCache(["doc1", "doc2"], {
	schema,
	prompt: "Extract fields.",
	model,
	cache: { store },
});

Validation examples

Shell validator

const data = await extractSync(input, {
	schema,
	prompt: "Extract fields.",
	model,
	validateCommand: "jq -e '.score > 0.5'",
});
cat input.txt | pie -s schema.json -p "Extract" \
	--validate "jq -e '.score > 0.5'"

HTTP validator

const data = await extractSync(input, {
	schema,
	prompt: "Extract fields.",
	model,
	validateUrl: "https://api.example.com/validate",
});
cat input.txt | pie -s schema.json -p "Extract" \
	--validate-url "https://api.example.com/validate"

CLI Usage

pie --help

# Basic extraction
cat input.txt | pie \
	-s schema.json \
	-p "Extract fields" \
	--model anthropic/claude-sonnet-4-5

# Stream partial JSON to stderr
cat input.txt | pie -s schema.json -p "Extract" --stream 2>progress.jsonl

CLI Requirements

  • A configured model credential (see Authentication).
  • A JSON Schema (--schema) and prompt (--prompt/--prompt-file) unless you use --config or --recipe.

Recipes

Recipes live in ~/.pie/recipes or ./.pie/recipes and allow reusable setups.

pie --list-recipes
pie --recipe support-triage --input ticket.txt

Public API Surface

  • The package root (@justram/pie) exposes the SDK surface from src/index.ts (extract, models, recipes, cache, errors, types).
  • Cache helpers are also available via the @justram/pie/cache subpath.

CLI entry flow (contributors)

  • src/cli.ts is the executable entry (shebang) and delegates to src/main.ts.
  • src/cli/index.ts re-exports runCli for tests and internal callers.

Development

npm run build
npm run test

License

MIT