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

@getnotisxyz/sdk

v0.9.1

Published

SDK for Notis. 3 lines to connect your AI agent to your phone.

Readme

@getnotisxyz/sdk

The official SDK for Notis — the agent-to-human communication channel.

Let your AI agents send push notifications to your phone, receive replies, and maintain conversations. Zero dependencies. TypeScript-first.

Install

npm install @getnotisxyz/sdk

Quick Start

import { Notis } from '@getnotisxyz/sdk';

const notis = new Notis(); // reads NOTIS_API_KEY from env
await notis.send("I'm alive"); // push notification on your phone

Don't have an API key yet? Run npx @getnotisxyz/cli login then npx @getnotisxyz/cli init to create an agent and save a key to .env automatically.

Getting Your API Key

Recommended (CLI):

npx @getnotisxyz/cli login    # authenticate via browser
npx @getnotisxyz/cli init     # name your agent, key saved to .env

Manual (mobile app):

  1. Download the Notis app
  2. Create an agent channel
  3. Copy the API key (shown once)

API

new Notis(config?)

// Zero-config — reads NOTIS_API_KEY from env
const notis = new Notis();

// Explicit config
const notis = new Notis({
  apiKey: 'png_live_...', // your API key
  baseUrl: 'https://www.getnotis.xyz', // optional
});

notis.send(body) — Send a message

// String shorthand
await notis.send("ETH broke $4,000");

// With options
await notis.send("ETH broke $4,000", { priority: 'urgent' });

// Full object form
await notis.send({
  title: 'Trade Alert',
  body: 'ETH broke $4,000. Want to take profit?',
  priority: 'high',
  actions: [
    { id: 'sell', label: 'Sell 50%' },
    { id: 'hold', label: 'Hold' },
  ],
});

Priority levels:

| Name | Value | Behavior | |------|-------|----------| | lowest | -2 | Silently delivered | | low | -1 | Quiet delivery | | normal | 0 | Standard push notification | | high | 1 | Prominent notification | | urgent | 2 | Bypasses quiet hours |

notis.listen(handler) — Listen for human messages (Realtime)

Subscribes via Supabase Realtime WebSocket. Messages arrive in <100ms. Auto-falls back to polling if Realtime is unavailable.

Requires @supabase/supabase-js as a peer dependency:

npm install @supabase/supabase-js
const stop = await notis.listen(async (message, recentHistory) => {
  console.log(message.body); // "What's the portfolio looking like?"

  // recentHistory = last 10 messages (both directions)
  for (const turn of recentHistory) {
    console.log(`[${turn.role}] ${turn.body}`);
  }
});

stop(); // disconnect

Options:

await notis.listen(handler, {
  fallbackToPoll: true,   // fall back to polling on failure (default: true)
  pollIntervalMs: 5000,   // polling interval if falling back (default: 5000)
  onError: (err) => {},   // called on Realtime errors
});

notis.onMessage(handler) — Listen for human messages (polling)

Deprecated. Use listen() for instant delivery. onMessage() still works for environments where WebSockets are blocked.

const stop = notis.onMessage(async (message, recentHistory) => {
  console.log(message.body);
}, 5000); // poll every 5s

stop(); // stop polling

notis.onReply(handler) — Listen for action button taps

const stop = notis.onReply(async (reply) => {
  console.log(reply.action);     // 'sell' | 'hold' | null
  console.log(reply.reply_text); // free-text reply or null
}, 5000);

stop();

notis.context() — Get user preferences

const ctx = await notis.context();

console.log(ctx.channel);     // Channel name
console.log(ctx.preferences); // "Alert me on markets closing within 2 hours"
console.log(ctx.timezone);    // "America/Los_Angeles"
console.log(ctx.threshold);   // Minimum priority level
console.log(ctx.quiet_hours); // { start: "22:00", end: "08:00" }

notis.getHistory(options?) — Load conversation history

const history = await notis.getHistory({ limit: 100 });

for (const msg of history.messages) {
  const who = msg.direction === 'agent_to_human' ? 'Agent' : 'Human';
  console.log(`[${who}] ${msg.body}`);
}

Memory — remember(), recall(), forget()

// Store persistent memory (max 32KB, survives restarts)
await notis.remember({
  summary: 'User prefers conservative trades',
  preferences: { risk: 'low' },
});

// Read memory
const memory = await notis.recall();

// Clear memory
await notis.forget();

notis.ping() — Health check

const alive = await notis.ping(); // true if API key is valid

Two-Way Agent Example

import { Notis } from '@getnotisxyz/sdk';
import Anthropic from '@anthropic-ai/sdk';

const notis = new Notis();
const claude = new Anthropic();

await notis.listen(async (msg, recentHistory) => {
  const messages = recentHistory.map((turn) => ({
    role: turn.role === 'agent' ? 'assistant' as const : 'user' as const,
    content: turn.body,
  }));

  const response = await claude.messages.create({
    model: 'claude-sonnet-4-5-20250929',
    max_tokens: 1024,
    system: 'You are a helpful trading assistant.',
    messages,
  });

  const reply = response.content[0].type === 'text'
    ? response.content[0].text : 'Done.';

  await notis.send(reply);
});

console.log('Agent is listening...');

REST API (No SDK)

# Send a message
curl -X POST https://www.getnotis.xyz/api/notify \
  -H "Authorization: Bearer png_live_..." \
  -H "Content-Type: application/json" \
  -d '{"body": "Something happened", "priority": 1}'

# Poll for human messages
curl https://www.getnotis.xyz/api/inbox \
  -H "Authorization: Bearer png_live_..."

# Get user context
curl https://www.getnotis.xyz/api/context \
  -H "Authorization: Bearer png_live_..."

Upgrading from v0.5

The Ping and PingClient class names still work — no breaking changes:

// Old (still works)
import { Ping } from '@getnotisxyz/sdk';
const ping = new Ping({ apiKey: '...' });

// New (recommended)
import { Notis } from '@getnotisxyz/sdk';
const notis = new Notis(); // reads from env

Method renames (old names still work):

  • getContext()context()
  • getMemory()recall()
  • setMemory()remember()
  • clearMemory()forget()

Error Handling

import { Notis, NotisError } from '@getnotisxyz/sdk';

try {
  await notis.send('Test');
} catch (err) {
  if (err instanceof NotisError) {
    console.error(err.message); // Human-readable error
    console.error(err.status);  // HTTP status code
  }
}

License

MIT