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

@syncsuite/sdk

v0.1.0

Published

Client SDK for SyncSuite — discover + call any service, connection, env var, custom tool, or agent with one verb.

Readme

@syncsuite/sdk

The customer-code SDK for SyncSuite. Two verbs (discover, call) give your code access to every SyncSuite capability — services (email, SMS, storage, AI…), OAuth connections, env vars, your own custom tools, and agent handoffs — all behind one consistent shape.

You never need to update this SDK when new services launch. Capability names are strings; the catalog is fetched at runtime. The shape only changes if we change the dispatcher itself (rare).

Install

pnpm add @syncsuite/sdk
# or
npm install @syncsuite/sdk

Setup

The default singleton reads two env vars on first use:

| Env var | Required? | Default | Description | |---|---|---|---| | SYNCSUITE_API_KEY | Yes | — | Your ssk_… key. Already injected into every SyncSuite project VM. | | SYNCSUITE_SERVICES_URL | No | https://app.syncsuite.com | Internal vSwitch bridge URL for SyncSuite-hosted VMs; auto-injected. |

Both are pre-set inside SyncSuite-managed customer VMs. For local dev or custom deployments, set them yourself.

Quick start

import { sync } from "@syncsuite/sdk";

// What can my account do right now?
const caps = await sync.discover();
// → [{ fqn: "service:email.send_personal", … }, { fqn: "agent:billing-bot", … }, …]

// Send an email (billed to wallet):
const r = await sync.call("service:email.send_personal", {
  to: "[email protected]",
  from: "[email protected]",
  subject: "Welcome",
  body: "Glad you're here.",
});
if (!r.ok) throw new Error(r.error);

// Get authenticated headers for a connected provider (your code does the fetch):
const conn = await sync.call("connection:google");
const r2 = await fetch("https://www.googleapis.com/...", {
  headers: (conn.data as { headers: Record<string, string> }).headers,
});

// Hand off to a specialty agent on your account:
const refund = await sync.call("agent:billing-bot", {
  message: "User wants a refund on invoice #1234",
});

// Pause-resume on external signal (e.g. waiting for a webhook):
const inbox = await sync.call("core:await_external", {
  reason: "Stripe webhook for refund",
  ttlSeconds: 3600,
});
// inbox.data.callback_url → give to Stripe
// Later:
const status = await sync.call("core:check_external", { token: inbox.data.token });

Capability namespaces

| Prefix | What | Example | |---|---|---| | service: | SyncSuite-managed, wallet-billed | service:email.send_personal | | connection: | OAuth or API-key passthrough — returns headers | connection:google | | env: | Read from the account env vault | env:STRIPE_KEY (params: { key: "STRIPE_KEY" }) | | custom: | User-defined HTTP endpoints in your project | custom:my-pdf-builder | | agent: | Handoff to another agent | agent:billing-bot | | core: | Built-in verbs (fanout, await_external, etc.) | core:fanout |

Call sync.discover() to see what's actually granted to your account.

Why this shape

  • Strings as identifiers = adding a new service on the SyncSuite side doesn't require an SDK release. Your day-1 SDK works forever.
  • Single call() verb = one mental model. No need to remember useConnection() vs services.send() vs process.env.X.
  • Same surface the AI uses internally = if you've taught the AI to do something with call, you can do it the same way from your code.
  • Wallet billing is automaticcall returns { ok, data, cost?, error } and the wallet ledger is updated server-side on each successful service invocation.

Advanced: multiple accounts / custom config

import { SyncSuite } from "@syncsuite/sdk";

const customerA = new SyncSuite({ apiKey: "ssk_aaa..." });
const customerB = new SyncSuite({ apiKey: "ssk_bbb..." });
await customerA.call("service:email.send_personal", { ... });

TypeScript

Result shapes are typed loosely (data: unknown) because capability payloads vary by FQN. Pass a generic to call<T>() when you know the shape:

const r = await sync.call<{ messageId: string }>(
  "service:email.send_personal",
  { to, from, subject, body },
);
if (r.ok) console.log("Sent:", r.data.messageId);

What changed from the legacy v1 API

The old surface had three different shapes:

// OLD: services
await fetch(`${SYNCSUITE_SERVICES_URL}/api/services/email/send_personal`, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.SYNCSUITE_API_KEY}` },
  body: JSON.stringify({ params: { to, body } }),
});

// OLD: connections
await fetch(`${SYNCSUITE_SERVICES_URL}/api/me/connections/google`, ...);

// OLD: env
process.env.STRIPE_KEY;

All three (and agent invocation + custom tools) now go through sync.call. The legacy routes still work — feel free to migrate at your pace.