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

@zindexzero/sdk

v0.5.2

Published

Official SDK for Zero — Z-index Zero's metered, tenant-isolated AI API.

Readme

@zindexzero/sdk

The official SDK for building on Zero — Z-index Zero's metered, tenant-isolated AI API. Add Zero to your own app: chat, your own private knowledge base (RAG), and key/usage management.

Status: shipped & stable — full surface. @zindexzero/sdk covers: the server data-plane (chat, docs.*), the control-plane (signIn → manage keys, caps, usage, style profile, and per-key persona), the browser/mobile client (ZizHosted + publishable-key Ziz), the useZero React/React-Native hook (@zindexzero/sdk/react), and CDN delivery (esm.sh / jsDelivr). Zero deps, typed, works in Node and browsers. It's a thin typed wrapper over a plain HTTP API, so a hand-rolled fetch works too. Design/architecture: ../SDK-SCOPE.md.

Get a key (required — there is no anonymous access)

The SDK does nothing without a key, and keys come only from us:

  1. Sign up at https://zindexzero.org/start and submit your project.
  2. Once your account is approved, your keys are issued in the portal.
  3. Use a secret key (ziz_live_…) on your server, or a publishable key (ziz_pub_…) in a browser/mobile app (chat-only, origin-locked).

New keys start disabled and are enabled from your account. No key, no calls — the API returns 403 and the SDK routes you to the signup page.

Quick start (server)

import { Ziz } from "@zindexzero/sdk";

const ziz = new Ziz({ apiKey: process.env.ZIZ_KEY! }); // ziz_live_… — server only

// Chat — returns { text, modelId, escalated, usage, retrieved? }
const { text } = await ziz.chat("Summarize this contract");

// With media (vision keys) + prior turns
await ziz.chat(
  { text: "What's in this?", attachments: [{ type: "image", format: "png", data: b64 }] },
  [{ role: "user", text: "earlier message" }],
);

// Private knowledge base (RAG-enabled secret keys)
await ziz.docs.add({ text: "Internal policy …", title: "Policy" });
const { documents } = await ziz.docs.list();
await ziz.docs.delete(documents[0].docId);

No key, or a disabled one? The constructor throws ZizNoKeyError and 401/403 throw ZizApiError, both carrying .urlZiz.signupUrl() so your app can route the user to sign up. usage is token counts, never cost (see below).

First-party (our own apps): pass a ziz_app_ key and the SDK auto-routes to the full-Zero /v1/app tier — same chat/docs methods. Frontend-only first-party apps (no server to hold a secret) go through a proxy; see ../SDK-SCOPE.md §10.

Prefer no dependency? It's a plain POST with an Authorization: Bearer header — hand-rolled fetch against /v1/client/chat works identically.

Browser / mobile (no secret key)

An untrusted app must never hold a ziz_live_ secret. Two browser-safe options:

1. Publishable key (chat only) — origin-locked, quota-fenced:

import { Ziz } from "@zindexzero/sdk";
const ziz = new Ziz({ apiKey: "ziz_pub_…" }); // safe to ship; locked to your origins
const { text } = await ziz.chat("Hello");

2. Hosted proxy (full surface — chat + RAG docs) — ZiZ holds your secret server-side; your app calls the proxy. Register once with scripts/register-hosted-client.mjs:

import { ZizHosted } from "@zindexzero/sdk";
// Browser: just the client slug — the browser's Origin is the gate.
const zh = new ZizHosted({ client: "acme" });
// Native / React Native (no enforced Origin): add the app-token from registration.
// const zh = new ZizHosted({ client: "acme", appToken: "hat_…" });

const { text } = await zh.chat("Summarize my docs");
await zh.docs.add({ text: "Internal note…", title: "note" });
const { documents } = await zh.docs.list();

The app-token ships in the bundle — a low-value surface gate, not a secret; the real spend cap is the upstream key's monthly quota. No ziz_live_ key ever reaches the client.

React / React Native

useZero manages chat state for any client (Ziz, ZizHosted, …). react is a peer dependency.

import { useMemo } from "react";
import { ZizHosted } from "@zindexzero/sdk";
import { useZero } from "@zindexzero/sdk/react";

function Chat() {
  const client = useMemo(() => new ZizHosted({ client: "acme" }), []);
  const { messages, send, status } = useZero(client);
  // render messages; call send(text) on submit; status is "idle" | "sending"
}

From a CDN (<script type="module">)

The package is zero-deps pure ESM, so the public npm CDNs serve it browser-ready — no build step, nothing to self-host:

<script type="module">
  import { ZizHosted } from "https://esm.sh/@zindexzero/sdk";
  const zh = new ZizHosted({ client: "acme" });
  console.log(await zh.chat("hi"));
</script>

(https://cdn.jsdelivr.net/npm/@zindexzero/sdk/+esm works too.) A self-hosted classic-<script> global build is deferred until a non-module consumer needs it.

Manage your account (control-plane, server-only)

Sign in with your ZiZ account (same email/password as zindexzero.org/start) to manage keys, request caps, read usage, and edit your style profile. Server-only — it holds account credentials; never ship it in a browser/mobile bundle.

import { signIn } from "@zindexzero/sdk";

const account = await signIn({ email: process.env.ZIZ_EMAIL!, password: process.env.ZIZ_PW! });

// Keys — first list() may include `provisioned` (starter keys, raw, shown once)
const { keys } = await account.keys.list();
const { key } = await account.keys.create({ kind: "secret", label: "prod server" }); // raw key, once
await account.keys.setFeature(key /* or keyId */, { smart: true, vision: true });
await account.keys.disable(keyId);

// Public widget key locked to origins
await account.keys.create({ kind: "public", origins: ["https://acme.com"], label: "site widget" });

// Usage (already +20% marked up) · cap request · style profile
const { totalCostUsd } = await account.usage();
await account.caps.request(keyId, 50_000, "launch traffic");
await account.profile.set("Friendly, concise, no emoji.");

// Persona — the assistant ROLE/VOICE for this key (both server + widget keys). "" clears it.
await account.keys.setPersona(keyId, "You are Acme's friendly support agent. Be warm and brief.");

A persona shapes role/tone only — it's injected as fenced data, never the system prompt, and can't override Zero's isolation/safety rules or make it speak for ZiZ.

Sessions auto-refresh while the SDK lives; an expired/invalid session throws ZizApiError (401) carrying .url to re-auth.

Cost & the +20% rule

  • chat().usage gives token counts only — never a dollar figure.
  • Your cost (already including our +20% service fee) comes from GET /v1/portal/usage. The SDK reads that number; it never computes cost and ships no pricing table.

Security — your data is yours, and only yours

These guarantees are enforced server-side (IAM credential fences + the authorizer), so they hold no matter what the SDK — or a hand-rolled curl — does. Verified against the live handlers:

  • You can only ever reach your own tenant. Your tenant is resolved server-side from your key (data plane) or your validated account token (control plane) — there is no field in any request that names a tenant, so you cannot ask for someone else's. (zero-client/authorizer.mjs, zero-portal resolveTenant.)
  • You cannot read Z-index Zero's data or any other client's data. The role behind the chat endpoint can write only your own usage rows and read/query nothing — no other client, no ZiZ projects/finances/keys, no first-party app data. (zero-client-iam-policy.json.)
  • Your knowledge base is credential-isolated. RAG runs in a separate service that pins each request to your one private index via a per-request scoped session — a bug passing another index's id fails closed, it does not leak.
  • Our own apps are a different, walled tier. A client key on the first-party endpoints is rejected (403), and this SDK has no type or method that can even name them.
  • The assistant itself knows nothing about us. Zero's client persona has no knowledge of or access to Z-index Zero's operations or other clients, and refuses to answer about them. Retrieved docs and style hints are injected as data, never as instructions.

In short: the SDK is a pure consumer. It holds no privileged credentials and has no code path that bypasses the server-side fences — security never depends on the SDK behaving.

Prove your isolation (ziz proof)

Don't take "tenant-isolated" on faith — run the leak test. Given two RAG-enabled keys on different tenants, it plants a unique secret in each tenant's private KB, then proves each tenant retrieves only its own and neither can reach the other's:

ZIZ_PROOF_KEY_A=ziz_live_…  ZIZ_PROOF_KEY_B=ziz_live_…  npx @zindexzero/sdk proof

Exit 0 = fenced, 1 = leak detected, 2 = setup error — so it drops straight into CI. The tenant is resolved server-side from the key, so a request has no field to name another tenant; a foreign secret can't appear in a reply it was never given. Check just the detector logic (no network, no keys) with:

npx @zindexzero/sdk proof --selfcheck

Scope, honestly: this exercises the API fence (B never sees A's data). The deeper "fails closed at the credential layer" guarantee — a bug passing another tenant's index ARN returns AccessDenied rather than leaking — is the per-request literal-ARN STS session, verified by our IAM policy-sim isolation gate, which the public API can't reach.

Design & internals

All phases (0–5) are shipped. The phased build-out, the security model (the secret-vs-publishable key fence, the hosted proxy, the persona injection fence), and the design rationale live in ../SDK-SCOPE.md.