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

@xilo-org/sdk

v0.1.0

Published

Pay for and read Xilo intelligence from an AI agent: quotes checked against your spending policy before anything is signed.

Readme

@xilo-org/sdk

Pay for and read Xilo intelligence from an agent. The safe way is the default:

  • Keys stay out of the model. The signer lives inside the SDK and is read from XILO_AGENT_PRIVATE_KEY. Your model only sees method names and results.
  • Spending rules run outside the model. Every price is quoted first and checked against your policy before anything is signed. These limits apply on top of the owner limits Xilo enforces server-side.
  • Untrusted text never reaches the acting model unless you choose to pass it through a tool-less reader.
npm install @xilo-org/sdk
export XILO_AGENT_PRIVATE_KEY=0x…   # the agent's own wallet, funded with a little USDG

network picks Xilo's public endpoint: "testnet" (the default) uses the public sandbox at https://xilo-staging.vercel.app, and "mainnet" uses https://www.xilomarkets.xyz (from launch). To point somewhere else, set XILO_API_URL or pass apiUrl.

Example: a sniper that checks before every buy

import { createXiloClient, stripUntrusted, XiloPolicyError } from "@xilo-org/sdk";

const xilo = createXiloClient({
  network: "testnet",
  policy: {
    maxPerCallUsdg: 0.25,
    maxPerDayUsdg: 20,
    maxPerTaskUsdg: 5,
    allowedPayTo: ["0x…xilo-collector"], // only Xilo's collector
  },
});

// Pick the most accurate contract-safety seller once.
const { results } = await xilo.search({ category: "contract_safety", type: "lookup" });
const safety = results[0] as { id: string; versionHash: string };

async function shouldBuy(token: `0x${string}`) {
  try {
    const r = await xilo.lookup({ listingId: safety.id, subject: token });
    const out = stripUntrusted(r.result) as { verdict: "SAFE" | "RISKY" | "RUG"; honeypot?: boolean };
    return out.verdict === "SAFE" && out.honeypot !== true;
  } catch (e) {
    if (e instanceof XiloPolicyError) return false; // over budget or a suspicious quote: skip, don't pay
    throw e;
  }
}

Paying

| Mode | How | When | | --- | --- | --- | | payment: "x402" (default) | A USDG authorization (EIP-3009), signed per call and settled only after the seller delivers | Simple setups; no balance to manage | | payment: "balance" | Your prepaid Xilo balance, via a signed agent key | Many small calls, alerts (watch), MCP. Top up with xilo.topup(10) |

In both modes the SDK asks for a quote first and refuses before signing anything if:

  • the payee isn't in allowedPayTo;
  • the network, asset or scheme is wrong;
  • the price is over maxPerCallUsdg;
  • the day's spend would go over maxPerDayUsdg. Parallel calls reserve their spend first, so they can't overshoot.

Calls that fail after payment aren't settled by Xilo, and the SDK doesn't count them. Free trial calls count as 0.

Daily spend is kept in memory. Long-running agents should pass spendStore (get(day) and add(day, micro)) backed by a file or a database.

Methods

| Method | Paid | Notes | | --- | --- | --- | | search(q) | free | Ranked by measured accuracy | | lookup({ listingId, subject }) | ✅ | One token or wallet | | getList({ listingId }) | ✅ | | | batch({ lookups }) | ✅ | Up to 50, all or nothing | | hire({ listingId, input, capUsdg? }) | ✅ | capUsdg defaults to, and can't exceed, maxPerTaskUsdg | | task(taskId, readToken?) | free | Status, plus the result for the buyer | | watch({ listingId, subjects }) / unwatch(id) | balance | Live alerts | | balance() / topup(usdg) | — / ✅ | | | spentToday() | — | USDG spent through this client today | | prepareSwap({ tokenIn, tokenOut, amountIn, slippageBps?, acceptRisk? }) | free | Unsigned swap for this wallet; see below |

Version pinning: set policy.pinnedVersions (listingId → versionHash). Calls then fail with a 409 if the seller changed the listing, until the owner approves the new version in the dashboard.

Acting on it: non-custodial swaps

prepareSwap() returns an unsigned swap for the agent's own wallet. Xilo never signs, never holds funds and adds no fee. The rails are enforced by Xilo's API, not by your prompt:

  • Buying any token except native ETH (0xeeee…eeee) or USDG needs a contract_safety lookup on that token by this agent in the last 24 hours.
    • RUG, honeypot, or a deployer who rugged before (dev_history) refuses the swap.
    • RISKY, or a sell tax over 10%, needs acceptRisk: true.
  • The output always goes to the calling wallet. Slippage is capped at 5%. Only known aggregator routers are used. Approvals are for the exact amount.
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";

const r = await xilo.lookup({ listingId: safety.id, subject: token }); // the check
const swap = await xilo.prepareSwap({
  tokenIn: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
  tokenOut: token,
  amountIn: "10000000000000000", // 0.01 ETH, in wei
  slippageBps: 100,
});
// Check swap.quote, then send from your own wallet:
const wallet = createWalletClient({ account: privateKeyToAccount(process.env.XILO_AGENT_PRIVATE_KEY as `0x${string}`), transport: http(RPC_URL) });
if (swap.approval) await wallet.sendTransaction({ to: swap.approval.to, data: swap.approval.data, chain: null });
await wallet.sendTransaction({ to: swap.tx.to, data: swap.tx.data, value: BigInt(swap.tx.value), chain: null });

Swap routing is available on mainnet (KyberSwap's aggregator); on testnet the endpoint answers 503.

Seller rewards

Staked sellers whose calls were right share 20% of the pool's trading fees, in ETH, through the daily Pulse report (see /pulse on the site). They're payment for accurate work, not for holding.

const rewards = await xilo.rewards(); // every day you earned, newest first
for (const c of await xilo.prepareRewardClaims()) {
  // Unsigned, like prepareSwap: send each from the seller wallet. Only final days are included.
  await wallet.sendTransaction({ to: c.tx.to, data: c.tx.data, value: 0n });
}

A claim needs an active stake, reverts if that day was already claimed, and stays open for 90 days.

Untrusted text: two-step reading

Outputs are structured. Free text only arrives as { untrusted: true, text }. Either strip it:

const safe = stripUntrusted(r.result);   // every untrusted text becomes "[untrusted text removed]"

or read it with a model that has no tools and no wallet. Anything outside your schema is dropped:

import { readUntrusted } from "@xilo-org/sdk";
const { risk } = await readUntrusted(r.result.note, z.object({ risk: z.enum(["low", "high"]) }), myToolessLLM);

Registering the agent with its owner

The owner starts registration on xilo's /agents page, which shows a one-time message. The agent signs it with its own key:

XILO_AGENT_PRIVATE_KEY=0x… npx @xilo-org/sdk sign "Xilo: register agent 0x… to owner 0x…
Nonce: …"

Paste the signature back on the page. sign only signs Xilo's register-agent message for this key's own address, so it can't be used to sign anything else (a token permit, for example).

MCP (Claude Code, Cursor, …)

XILO_NETWORK=mainnet npx @xilo-org/sdk mcp-config   # or leave XILO_NETWORK unset for the testnet sandbox

This prints the mcpServers block. Its Authorization header is your agent key, a signature rather than the private key, but it can spend your prepaid balance, so keep it out of shared files.

For Claude Code, print the install command instead and run it:

npx @xilo-org/sdk mcp-config --claude-code
# claude mcp add --scope user --transport http xilo https://…/mcp --header 'Authorization: XiloKey …'

--key prints only the agent key (wallet:signature), for the Xilo Claude Code plugin's XILO_AGENT_KEY.

Try a listing from the terminal

XILO_AGENT_PRIVATE_KEY=0x… npx @xilo-org/sdk try <listingId> <0x…token> --max 0.1

One real lookup. It uses a free trial call if the wallet has one, otherwise the prepaid balance, and refuses before signing anything if the price is over --max (0.1 USDG by default). Pin a version with --version 0x…. The same flow is tryLookup() in code.

Publishing

The package is ready to publish:

  • @xilo/shared is bundled in: tsup bundles the code, and scripts/bundle-types.mjs ships the types under dist/shared.
  • viem and zod are its only runtime dependencies.

Checked from outside the monorepo: npm pack gives a 40 KB tarball. Installed into an empty project, it imports, type-checks under strict with skipLibCheck off, runs the xilo-sdk CLI, and does a live search.

To publish:

  1. The npm organization is xilo-org (free for public packages); your npm user must be a member.
  2. Run npm login.
  3. From packages/sdk: pnpm build && npm publish. publishConfig.access is already public.

Bump version for every release.