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

@veezee/sdk

v0.7.0

Published

Typed REST client and CLI for the Veezee API: LinkedIn, Reddit, and X data for AI agents, metered in credits with per-call receipts.

Readme

@veezee/sdk

Typed REST client and CLI for the Veezee API: LinkedIn, Reddit, and X (formerly Twitter) data for AI agents, metered in credits with per-call receipts. Zero runtime dependencies, built on Node 20's global fetch. Current version: 0.6.1.

The key spends; signing in adds a management token for key management. vz init mints a key with no signup: that key alone is enough to call every data endpoint. vz login is a separate, optional step that proves an email and stores a vzm_ management token for listing, creating, revoking, and rotating keys, and for setting a low-balance alert. The first sign-in that confirms an email claimed on a trial key also adds a one-time 10,000-credit grant (once per email, once per key), spent after the free daily budget.

Install

npm install @veezee/sdk

Node 20+ required.

Quickstart

Start with one command:

npx @veezee/sdk init

vz init (same command, shorter once installed) POSTs to /v1/keys/mint with no signup and no card, and writes the returned key to ~/.veezee/config (mode 0600). It never prints the raw key, only a masked hint: the key lives in a file and an env var, not in your terminal history or an agent's chat transcript. After that, every vz command and every SDK call in the same environment just works:

import { VeezeeClient } from "@veezee/sdk";

const client = new VeezeeClient();
await client.mint(); // reuses the key from `vz init`, or mints one the first time
const profile = await client.linkedin.getProfile({ identifier: "williamhgates" });
console.log(profile.common.full_name, profile.common.headline);

mint() is idempotent: it reuses VEEZEE_API_KEY or ~/.veezee/config if either already has a key, and only mints a new one when neither does. The trial key itself carries no balance; the free tier is a per-IP, per-day allowance (200 credits/day, recent data, first page only) checked against the calling IP, not the key. Claiming the key adds a free balance on top: attach an email, confirm it by signing in at veezee.io/login, and the account gets a one-time 10,000-credit grant (once per email, once per key) that spends at the same trial limits after each day's free allowance is used. Outgrow both and a call fails with TRIAL_CAP_EXCEEDED carrying upgrade_url: buy credits at veezee.io/upgrade (no login required) and they land on the same key you already have. Nothing to reconfigure: same key, same config file, same code, now with a real balance.

You can skip vz init and pass a key directly instead:

const client = new VeezeeClient({ apiKey: process.env.VEEZEE_API_KEY });

Auth

Every call sends Authorization: Bearer <apiKey>. A call with no resolvable key throws VeezeeError with code: "KEY_REQUIRED" and a mint_url: POST there (no auth, no body) to mint a key, or just run vz init or call client.mint(), then retry. get_usage always needs a key too.

The API surface

Platform tools live under client.linkedin, client.reddit, and client.x; account/billing tools (platform-independent) are top-level:

await client.linkedin.getProfile({ identifier: "williamhgates", sections: ["experience", "education"] });
// -> PersonEnvelope { common: { full_name, headline, experience, ... } }

await client.linkedin.searchPeople({ keywords: "CTO", current_company: "anthropic", limit: 20 });
// -> PeopleSearchEnvelope { common: { results, cursor, total_matches } }

await client.linkedin.getCompany({ identifier: "microsoft" });
// -> CompanyEnvelope { common: { name, industry, employee_count, ... } }

await client.linkedin.getPosts({ identifier: "microsoft" });
// -> PostsEnvelope { common: { results, cursor, author_type } }

await client.reddit.search({ query: "notion alternative", type: "comments" });
// -> RedditSearchEnvelope { common: { type: "comments", comments, cursor, returned_count } }

await client.reddit.getSubredditPosts({ subreddit_name: "selfhosted", sort: "new" });
// -> RedditPostsEnvelope { common: { results, cursor, returned_count } }

await client.x.getProfile({ identifier: "nasa" });
// -> XProfileEnvelope { common: { screen_name, name, followers, description, ... } }

await client.x.search({ query: "veezee api", type: "recent" });
// -> XSearchEnvelope { common: { type: "recent", tweets, cursor, returned_count } }

await client.resolveUrl({ url: "https://www.linkedin.com/in/williamhgates" });
// -> UrlResolutionEnvelope { common: { type: "person", id, handle, canonical_url } }
// client.reddit.resolveUrl and client.x.resolveUrl work the same way for their own URLs.

await client.getUsage();
// -> UsageEnvelope { common: { plan, platforms, balance_remaining, recent_receipts, upgrade_url, manage_url } }

await client.checkout({ pack: "flex" | "production" });
// -> { checkout_url }. Needs no key: paying with none mints a fresh account and its key.

Every response is an envelope: { entity, platform, canonical_url, data_as_of, schema_version, common, platform_fields, freshness, usage }. usage.credits_charged and usage.receipt_id are on every call; freshness tells you how old the data is. Free-tier trial-key calls also carry usage.free_tier_hint, explaining what budget the call drew from and that paying upgrades this same key.

Error handling

Non-2xx responses throw a typed VeezeeError (extends Error) carrying the API's problem+json body:

import { VeezeeError } from "@veezee/sdk";

try {
  await client.linkedin.getProfile({ identifier: "someone" });
} catch (err) {
  if (err instanceof VeezeeError) {
    console.error(err.code, err.message); // message is a next-turn instruction
    if (err.is_retriable) {
      // safe to retry as-is; the client already retried transient errors internally
    }
  }
}

The client retries RATE_LIMITED, CONCURRENCY_LIMIT, UPSTREAM_UNAVAILABLE, INTERNAL, and network/timeout failures up to 3 attempts with exponential backoff, honoring retry_after_seconds when present. Every metered call gets one Idempotency-Key (UUID), reused across its own retries: retries never double-charge. Terminal errors (bad input, insufficient credits, auth) throw immediately without retrying.

Errors a payment can fix also carry upgrade_url (give it to your human), credits_required (on INSUFFICIENT_CREDITS: the credits the call needed), and offer (typed OfferV1): pack prices, checkout_url (the same link as upgrade_url), and resume, which says exactly how to retry after payment.

A call made with no resolvable key throws code: "KEY_REQUIRED" carrying mint_url: run vz init or call client.mint(), then retry. A management call (listKeys, createKey, revokeKey, rotateKey, setBalanceAlert) made with no resolvable management token throws code: "AUTH_REQUIRED": run vz login, then retry.

CLI

The package ships a veezee bin, with vz as a short alias for the same binary (noun-verb, mirrors the methods above):

veezee init [--force]
veezee linkedin profile get <identifier> [--sections a,b] [--realtime]
veezee linkedin search [--keywords x] [--title x] [--company x] [--past-company x] [--school x] [--first-name x] [--last-name x] [--limit n] [--cursor x] [--freshness x]
veezee linkedin company get <identifier>
veezee linkedin posts get <identifier>
veezee reddit search <query> [--type posts|comments|subreddits|users] [--sort x] [--range x]
veezee reddit subreddit <name> [--include-settings]
veezee reddit subreddit-posts <name> [--sort x] [--range x] [--include-promoted]
veezee reddit user <username> [--sections comments,posts,subreddits]
veezee reddit post <id1,id2,...> [--detail concise|full] [--comment-id x]
veezee x search <query> [--type recent|popular|people]
veezee x profile <identifier> [--by screen_name|id]
veezee x tweets <identifier> [--mode posts|posts_and_replies|highlights] [--no-retweets]
veezee x tweet <tweet_id>
veezee resolve-url <url>
veezee usage
veezee login [--device] [--no-browser]
veezee logout
veezee keys list [--account <id>]
veezee keys create [--label <name>] [--account <id>]
veezee keys revoke <key_id> [--account <id>]
veezee keys rotate <key_id> [--account <id>]
veezee alert <threshold|off> [--account <id>]

Run vz init first (once): it mints a free trial key and writes it to ~/.veezee/config, masked hint only ever printed to stdout, never the raw key. vz init --json prints the same result as JSON (still no raw key) for scripting. vz init --force re-mints and overwrites the stored key.

For example, vz reddit search "notion alternative" --type comments or vz x profile nasa. Every platform namespace also has its own resolve-url: vz reddit resolve-url <url>, vz x resolve-url <url>.

Add --json on any command for machine-readable output (the raw envelope; errors print the full error shape as JSON too). Every data command takes --max-credits <n> to cap spend on that call: if the quote exceeds the cap the API returns a typed error and charges nothing. Unknown flags are rejected with the valid-flag list (exit 2), never silently ignored. Auth resolves in order: --key <apiKey>, then the VEEZEE_API_KEY env var, then ~/.veezee/config from vz init. --base-url overrides the API host. Exit codes: 0 success, 1 failure, 2 usage or invalid-input error, 4 auth required. vz --version prints the SDK version. Run vz --help (or no args) for examples.

vz login is a separate, optional step: it proves an email (browser callback by default, or --device for a headless code-entry flow) and stores a vzm_ management token in ~/.veezee/config, masked hint only ever printed to stdout. vz keys list|create|revoke|rotate and vz alert <threshold|off> use that token, resolved in order: --key <vzm_...>, then VEEZEE_MGMT_TOKEN, then the stored token. vz keys create and vz keys rotate print the raw api_key to stdout once (the "shown once" warning goes to stderr): store it immediately, it cannot be retrieved again. vz logout clears the locally stored token; it does not revoke it server-side.

Agent skills

The package ships eight installable SKILL.md packs under skills/: prospect-enrich, candidate-sourcing, company-enrichment, account-research, post-voice-research, reddit-monitoring, launch-sentiment-sweep, and outreach-list-builder. After npm install @veezee/sdk, add them to your agent with the skills CLI local-path syntax:

npx skills add ./node_modules/@veezee/sdk/skills

The same packs also install straight from GitHub (veezeehq/veezee-skills): npx skills add veezeehq/veezee-skills. Pack index and docs: veezee.io/docs/skills.

Development

npm install
npm run build   # tsc -> dist/
npm test        # compiles test/ and runs node --test
npm pack --dry-run

CI should run exactly this sequence (npm ci && npm run build && npm test) on Node 20+; this package has no separate lint step and no network calls in its test suite.

Docs

Full API reference: https://veezee.io/docs. SDK page: https://veezee.io/docs/sdk. CLI page: https://veezee.io/docs/cli. Hosted MCP servers (same tools, no install): https://veezee.io/docs/clients, listed in the MCP Registry as io.veezee/linkedin, io.veezee/reddit, and io.veezee/x-twitter.