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

@rozoai/checkout

v0.1.15

Published

Pay OpenRouter, or any Coinbase invoice, with the crypto you already hold: USDT/USDC on Solana, BNB Chain, Ethereum or Polygon, USDC on Base or Stellar, or BTC over Lightning. No Coinbase account.

Readme

rozo-checkout

English | 简体中文 | 日本語 | Español

When your agent needs to pay OpenRouter (or any Coinbase invoice) with the crypto you already hold

OpenRouter crypto top-ups and other Coinbase-hosted invoices settle in USDC on Base. This skill pays them from whatever you hold instead, and it does three things the official path cannot:

  • Pay from the chain you are already on. USDT or USDC on Solana, BNB Chain, Ethereum or Polygon, USDC on Base or Stellar, or BTC over Lightning. Coinbase's own direct pay takes USDC on Base.
  • No Coinbase account. Pay the deposit address from any wallet or straight from an exchange withdrawal. No sign-up, no API key, no browser.
  • Scriptable. OpenRouter's crypto credits API (POST /api/v1/credits/coinbase) now returns 410 Gone, so top-ups can no longer be automated there. Once you have the payment link, paying it is one command an agent or a cron job can run: without a terminal it stops for confirmation, so an unattended caller reviews the quote and then passes --yes.

Merchants we have been paid through so far: OpenRouter, Venice.ai, Porkbun and Alchemy. Any payments.coinbase.com link is quoted the same way.

Before you pay, know two things:

  • The fee is in the live quote. You pay the full invoice, no discount and no markup on it; the bridge and network fee is added to the deposit amount, which is shown in the order summary before the deposit address is released. Send exactly that amount, nothing more is charged.
  • Crypto payments to OpenRouter are never refundable. That is OpenRouter's policy, not ours; check the credit amount before you send.
npx @rozoai/checkout pay <coinbase-link>

It asks which coin you want to pay with — paste your wallet address at the prompt and it will mark which coins you can actually afford — then prints a deposit address for you to pay from any wallet — no private key, no environment variable, no configuration — and waits until the invoice is settled.

Paying a Bitrefill invoice instead? Create it on Bitrefill with "USDC on Base", then pass its id, address and amount (Coinbase payment links and Bitrefill invoices are the two supported targets; Stripe is not):

npx @rozoai/checkout pay --bitrefill-invoice <id> --to <0x…> --amount 7.90 --expires-at <ISO> --with usdc-stellar

Know your coin already? Skip the question:

npx @rozoai/checkout pay <coinbase-link> --with usdt-solana

Coins you can pay with

| Chain | --with | Chain id | Notes | |---|---|---|---| | Ethereum | usdt-ethereum usdc-ethereum | 1 | 6 decimals | | BNB Chain | usdt-bnb usdc-bnb | 56 | 18 decimals | | Polygon | usdt-polygon usdc-polygon | 137 | 6 decimals | | Base | usdc-base | 8453 | 6 decimals | | Solana | usdt-solana usdc-solana | 900 | SPL; native SOL not supported | | Stellar | usdc-stellar | 1500 | MEMO_TEXT memo required — shown in the deposit block | | Bitcoin Lightning | btc-lightning | lightning | BOLT11; amounts in satoshis. Any wallet that can pay an invoice works, including Cashu/ecash wallets — the mint melts your ecash into the Lightning payment. |

Native gas coins (SOL, BNB, ETH, MATIC) and on-chain BTC are not accepted.

Which wallet do I need?

One wallet, on one chain — not one per chain. Pick whichever coin above you already hold and pay from wherever it already lives.

  • Any wallet works, and so does an exchange withdrawal. The default path just prints a deposit block: send exactly that amount of that tokenSymbol, on that chain, to that receiverAddress. Nothing connects to a site and nothing is approved in a browser. In practice people use MetaMask or Rabby on the EVM chains, Phantom or Solflare on Solana, and a Lightning wallet such as Phoenix or Wallet of Satoshi for BTC.
  • Stellar is the one to be careful with. Its deposits route through a shared address plus receiverMemo, so whatever you send from — exchange or wallet — must let you set a memo. Omit it and the payment is lost.
  • Lightning pays an invoice, not an address. Scan or paste deposit.lnInvoice; there is no address to send to. A Cashu/ecash wallet works here too — paying the invoice melts the ecash on your behalf, and this route settles against ROZO's own Lightning node rather than a third-party swap, so no special handling is needed on our side.
  • Only --send needs a private key, read from ROZO_CHECKOUT_EVM_KEY or ROZO_CHECKOUT_SOL_KEY, and it covers EVM chains and Solana only. Everything else is keyless.

Use it from your agent

Install it as a skill, or just run the CLI:

# Claude Code
/plugin marketplace add RozoAI/rozo-checkout-skill
/plugin install rozo-checkout@rozo

# OpenClaw / ClawHub
clawhub install rozo-checkout

# Any agent that can run a shell: review the quote, then pay unattended
npx @rozoai/checkout quote <coinbase-link>
npx @rozoai/checkout pay <coinbase-link> --with usdt-solana --yes

The payload is the same everywhere: the one-liner above, or point the agent at llms.txt. Agents and scripts should always pass --with — the picker only appears on a terminal, and there is deliberately no default coin. Paying from your own wallet never needs a key. Only the optional --send flag signs locally: on Solana it uses the ~/.config/solana/id.json that solana-keygen already created, and on EVM an encrypted JSON keystore whose passphrase is prompted. A raw key in the environment (or a gitignored .env) still works for unattended automation.

Distributing this CLI? --utm-source <label> (or ROZO_CHECKOUT_UTM_SOURCE) is an optional channel label for reporting; no identity, no privilege.

Want ROZO to be able to reach you if a payment needs attention? Add the optional --email [email protected] to pay.

Need help? Email [email protected], or reach us on X or Discord.

You very likely do not need any of this: the default path needs no key, and for Stellar the stellar-agent-wallet skill sends with its own key handling — this .env setup is only for unattended EVM/Solana automation with a dedicated low-balance hot wallet.

None of this is needed for the default path. Paying from your own wallet needs no key and no configuration, and works with wallets that can never be used here — including hardware wallets and exchange accounts.

A .env in the directory you run from, with every variable this tool reads:

# None of this is needed to pay from your own wallet. These are read only
# when you use --send.

# Solana secret key: a base58 string, or a JSON byte array. Only needed if you
# do NOT have ~/.config/solana/id.json, which is picked up automatically.
ROZO_CHECKOUT_SOL_KEY=REPLACE_ME_base58_secret_key

# EVM raw private key: 64 hex characters, 0x prefix optional. The least safe
# option — prefer the keystore below.
ROZO_CHECKOUT_EVM_KEY=0x0000000000000000000000000000000000000000000000000000000000000000

# EVM encrypted V3 keystore: path to the file. Preferred over the raw key.
ROZO_CHECKOUT_EVM_KEYSTORE=/replace/me/keystores/my-hot-wallet

# Passphrase for that keystore. Only for unattended runs; on a terminal you
# are prompted instead, and nothing is stored.
ROZO_CHECKOUT_KEYSTORE_PASSPHRASE=REPLACE_ME_not_a_real_passphrase

# Optional RPC overrides, one per chain id. 8453 = Base, 900 = Solana.
ROZO_CHECKOUT_RPC_8453=https://mainnet.base.org
ROZO_CHECKOUT_RPC_900=https://api.mainnet-beta.solana.com

Then lock it down and keep it out of git:

chmod 600 .env
echo '.env' >> .gitignore

Solana

  • solana-keygen new writes ~/.config/solana/id.json. Nothing to configure — it is found automatically. This is the path we recommend.
  • Phantom → Settings → Export Private Key gives a base58 string. Put it in ROZO_CHECKOUT_SOL_KEY.
  • Solflare exports a base58 string in current versions and a JSON byte array in older ones. Both are accepted as-is.

EVM

  • MetaMask and Rabby → Export private key gives 64 hex characters. Paste it into ROZO_CHECKOUT_EVM_KEY as-is; the 0x prefix is optional.
  • Encrypted keystore (safer). Browser wallets export raw keys, not keystores. To turn one into an encrypted keystore, use Foundry: cast wallet import my-hot-wallet --interactive prompts for the key and writes an encrypted V3 keystore to ~/.foundry/keystores/my-hot-wallet (--keystore-dir changes where). Point ROZO_CHECKOUT_EVM_KEYSTORE at that file. geth account import also produces a V3 keystore.

Wallets that cannot be used with --send: hardware wallets (Ledger, Trezor), WalletConnect-only mobile wallets, and exchange accounts. None of them hand over a signing key, by design. Use the default keyless path instead — it works with all of them.

This repo is a Claude Code skill: it ships SKILL.md plus the executables in scripts/dist/. Clone it into your skills directory and Claude Code picks it up automatically.

git clone https://github.com/RozoAI/rozo-checkout-skill ~/.claude/skills/rozo-checkout

Or skip the install and just ask it to run:

Pay this OpenRouter link with USDT on Solana:
npx @rozoai/checkout pay <coinbase-link> --with usdt-solana

Wallet: any wallet, no key. Add --send only if you want Claude to sign from a hot wallet, which needs the env key.

Codex reads AGENTS.md from the project root. Add a standing instruction so it knows how to pay without being told each time:

To pay an OpenRouter / Coinbase payment link, run:
npx @rozoai/checkout pay <coinbase-link> --with usdt-solana

Wallet: any wallet, no key. --send signs locally using your Solana CLI keypair or an encrypted keystore, and supports EVM chains and Solana only — Stellar and Lightning are Mode A only.

OpenCode also reads AGENTS.md from the project root, so the Codex snippet above works unchanged. The shortest path is still the command itself:

npx @rozoai/checkout pay <coinbase-link> --with usdt-solana

Wallet: any wallet, no key. --send signs locally using your Solana CLI keypair or an encrypted keystore, and supports EVM chains and Solana only — Stellar and Lightning are Mode A only.

Cline reads standing instructions from .clinerules in the project root:

To pay an OpenRouter / Coinbase payment link, run:
npx @rozoai/checkout pay <coinbase-link> --with usdt-solana

Wallet: any wallet, no key. --send signs locally using your Solana CLI keypair or an encrypted keystore, and supports EVM chains and Solana only — Stellar and Lightning are Mode A only.

Add a project rule at .cursor/rules/rozo-checkout.mdc:

To pay an OpenRouter / Coinbase payment link, run:
npx @rozoai/checkout pay <coinbase-link> --with usdt-solana

Wallet: any wallet, no key. --send signs locally using your Solana CLI keypair or an encrypted keystore, and supports EVM chains and Solana only — Stellar and Lightning are Mode A only.

Hermes Agent (Nous Research) has shell access and its own skill system. Start it with hermes and ask:

Fetch https://checkout.rozo.ai/llms.txt, then pay this OpenRouter link:
npx @rozoai/checkout pay <coinbase-link> --with usdt-solana

Wallet: any wallet, no key. --send signs locally using your Solana CLI keypair or an encrypted keystore, and supports EVM chains and Solana only — Stellar and Lightning are Mode A only.

OpenClaw's headless entry point runs a one-off task, which suits a payment you trigger from a script or a chat channel:

openclaw agent exec "Pay this OpenRouter link with USDT on Solana by running: npx @rozoai/checkout pay <coinbase-link> --with usdt-solana"

Wallet: any wallet, no key. --send signs locally using your Solana CLI keypair or an encrypted keystore, and supports EVM chains and Solana only — Stellar and Lightning are Mode A only.

Pi is a BYOK terminal agent whose built-in tools include bash, so it can run the command directly. Start it with pi and ask:

Pay this OpenRouter link with USDT on Solana by running:
npx @rozoai/checkout pay <coinbase-link> --with usdt-solana

Wallet: any wallet, no key. --send signs locally using your Solana CLI keypair or an encrypted keystore, and supports EVM chains and Solana only — Stellar and Lightning are Mode A only.

Drive each step yourself. The bundles are self-contained; nothing to install beyond Node 20.18+.

git clone https://github.com/RozoAI/rozo-checkout-skill && cd rozo-checkout-skill
LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID"

# Read-only quote, costs nothing
node scripts/dist/quote.js --url "$LINK"

# Create the order. The full deposit address is WITHHELD here; you get a
# masked summary to review first.
node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT

# Once you have decided to pay, re-run with --confirm to release it
node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT --confirm

# Pay the deposit block from any wallet, then watch it settle
node scripts/dist/status.js --rozo-payment-id <uuid> --watch

Each script prints exactly one JSON object on stdout. Exit 0 success, 1 refused/failed (read error.code), 2 usage, 3 submitted but unconfirmed. Full walkthrough: QUICKSTART.

Wallet: any wallet, no key. For hot-wallet sending see send-evm.js / send-sol.js, which use your Solana CLI keypair or an encrypted keystore.

Any agent that can fetch a URL and run a command can do this:

Fetch https://checkout.rozo.ai/llms.txt into your context, then use it
to pay this OpenRouter link: <coinbase-link>

If the agent has no shell but can make HTTP requests, it can drive the four public endpoints directly — see how it works.

Wallet: any wallet, no key. --send signs locally using your Solana CLI keypair or an encrypted keystore, and supports EVM chains and Solana only — Stellar and Lightning are Mode A only.

Paying many invoices (batch / resellers)

Each OpenRouter top-up is its own Coinbase link, so paying many is a loop: one pay per link, one logged result per link. Install once (npm i -g @rozoai/checkout) so each run skips the npx download, run the links one at a time, and pay each deposit right after it is created.

#!/usr/bin/env bash
# links.txt: one Coinbase link per line (payment-links/pl_* or payment-sessions/paymentSession_*)
mkdir -p runs
while IFS= read -r link; do
  link="${link%$'\r'}"; link="${link%%\?*}"
  [ -n "$link" ] || continue
  id="${link##*/}"
  rozo-checkout pay "$link" --with btc-lightning --yes --json --no-watch \
    --email [email protected] </dev/null > "runs/$id.json"
  code=$?
  row=$(jq -r --arg id "$id" --arg code "$code" '[$id, $code,
      (.order.rozoPaymentId // .error.details.body.rozoPaymentId // "-"),
      (if .success then "pending: pay before " + (.order.expiry.effectiveDeadlineIso // "?")
       else (.error.code // .send.error.code // "FAILED") end)] | @tsv' \
    "runs/$id.json" 2>/dev/null) || row="$id	$code	-	NO_OUTPUT"
  printf '%s\n' "$row" >> runs/batch.tsv
done < links.txt
  • --yes is required when stdin is not a terminal, --json prints exactly one JSON object, and --no-watch returns as soon as the deposit details exist. Without --no-watch, pay --json first waits for settlement (up to --timeout, default 900 s) and prints nothing until then, invoice included.
  • Without --send (the loop above), a successful pay --no-watch means the order and its deposit details exist. No money has moved yet, which is why the log says pending. With --send, the CLI may already have broadcast your payment, so never pay that deposit by hand as well. A link is paid only when status later reports settled.
  • order.rozoPaymentId names the order and order.deposit says what to pay. Lightning: deposit.lnInvoice (the BOLT11) for deposit.amount sats. Other coins: deposit.receiverAddress and deposit.amount, plus deposit.receiverMemo on Stellar. --send cannot pay Lightning or Stellar.
  • The deadline to watch is order.expiry.effectiveDeadlineIso, not deposit.expiresAt: it is the earlier of our order expiry and the Coinbase link expiry. Stop paying at least order.expiry.marginMinutes before it, since settlement needs that much time.
  • If time has passed since you created the order, do not pay saved deposit details blindly. Re-run the same pay command (same --with): while the order is still payable it re-checks the link and the deadline and hands back the same order. Pay only if that succeeds.

Check settlement by rozoPaymentId (a link alone is only resolved from this machine's own records in ~/.rozo-checkout/state):

rozo-checkout status <rozoPaymentId> --json | jq -r '.state, .escalate'
rozo-checkout status <rozoPaymentId> --watch --timeout 900 --json   # poll every 10 s

Exit 0 means the check itself ran cleanly, not that the invoice settled: expired_unfunded also exits 0. Always read state.

Retrying without paying twice. Running pay again on the same link does not create a second order while its order is open: you get the same order back, and once money has arrived pay refuses with ORDER_ALREADY_ACTIVE or ORDER_ALREADY_FUNDED. Only after an order expired with nothing received does pay on the same link create a new order. The risk is paying a deposit twice, so before acting on a link again, run status on its rozoPaymentId:

| status result | What to do | | --- | --- | | escalate: true (includes underpaid, stuck_after_payment; exit 1) | Do not pay again. Contact support with the link, rozoPaymentId and any tx hash or payment preimage. | | state: settled | Done. Skip this link. | | state: awaiting_deposit | Still open, but a payment you just sent may not be detected yet. First check your wallet: if a send or Lightning payment to this deposit exists or is pending, wait and poll. Only if nothing was sent, re-run the same pay to re-check it, then pay the deposit once. | | state: payin_detected, payin_confirmed, bridging, paying_coinbase | Money is in flight. Wait and poll; do not pay again. | | state: expired_unfunded | Nothing has arrived and this order is dead. First check your own wallet: if you sent anything to the old deposit, or a Lightning payment is still pending, do not pay again; contact support with the link and rozoPaymentId (we cannot see a pending Lightning payment). If nothing was sent, re-run the same pay on the same link with the same --with: it creates a new order. If that answers PAYMENT_EXPIRED, see below. | | state: unknown (exit 1) | The backend could not be read. Not proof that nothing was paid: retry status, not pay. |

  • Exit codes: 0 ok, 1 refused or failed (read error.code), 2 usage error (nothing was created), 3 the watch window ended before a final state. Exit 3 means money may still be in flight: keep polling, do not pay again.
  • Use the same --with coin on every run for a link. A different coin can be refused with REUSED_SOURCE_MISMATCH or change the open order's deposit.
  • LINK_USED_OR_EXPIRED or LINK_NO_LONGER_PAYABLE: the Coinbase link itself is already paid or expired. Check your OpenRouter balance and get a new link if it was not credited.
  • PAYMENT_EXPIRED: an earlier order for this link expired. Read error.details.body: with retryable: true (confirmed: false) the old order cannot be proved unfunded yet, so wait a few minutes and retry the same pay; with confirmed: true the link has used all its re-orders, so get a new link from OpenRouter.
  • RATE_LIMITED: order creation is capped per IP per hour (currently 30 requests, and each pay makes two), so plan on about 15 links per hour from one IP. Wait for the next hour and resume with the links not yet settled. Need more? Email us.

Questions about a batch? Email [email protected], or reach us on X or Discord.

Three rules worth knowing

  • The deposit address is one-time. Never reuse one from an older order, a cached response or a screenshot.
  • Send the exact amount shown. It is normally larger than the invoice — it includes the bridge and network fees.
  • Stellar deposits carry a memo, and it is MEMO_TEXT — even when it looks like a number (65371582 is text, not an id). Sending it as MEMO_ID produces a different memo and the payment will not be matched. The deposit block states the type as receiverMemoType.
  • Never pay a funded order twice. If a payment has already been detected, stop and get a human to reconcile it; a second payment to a one-time address is not guaranteed to be credited.

The full list of what this refuses to do, and why, is in docs/safety.md.

Links

Changelog

  • 0.1.15: corrected guidance after an order expires unpaid. First check your own wallet that nothing was sent to the old deposit and no Lightning payment is pending; if nothing was sent, re-run the same pay on the same link (the router opens a new order once it has verified the old one is unfunded). PAYMENT_EXPIRED with retryable: true means try again in a few minutes; LINK_USED_OR_EXPIRED or PAYMENT_EXPIRED with confirmed: true means get a new link from the merchant. New README section on paying many invoices (batch / resellers).
  • 0.1.14: optional --email <addr> on pay (and on the create-order scripts) stores a contact email with the order so ROZO can reach you if the payment needs attention. Never required; an invalid address is rejected before any order is created. Support channels ([email protected], X, Discord) are shown at order creation and whenever an order is not clean.
  • 0.1.13: optional --utm-source <label> / ROZO_CHECKOUT_UTM_SOURCE adds attribution.utm_source to created orders so distribution channels can be measured. Invalid values are dropped, never failing an order.
  • 0.1.12: pay Bitrefill invoices. pay --bitrefill-invoice <id> --to <0x…> --amount <USDC> --expires-at <ISO> creates a Rozo exactOut order through mpprouter that delivers the exact USDC on Base straight to the Bitrefill invoice address, payable from Stellar USDC or any supported coin.
  • 0.1.11: each order now carries attribution.client (rozo-checkout-skill/<version>) so skill-created orders can be told apart from the web checkout. Installable as a Claude Code plugin (/plugin marketplace add RozoAI/rozo-checkout-skill). README and skill description rewritten around paying Coinbase invoices from the crypto you already hold.
  • 0.1.3 — fixes found by the first real payment. The built bundles no longer crash with __filename is not defined on Node 22+ (the esbuild banner now shims __filename/__dirname as well as require, and every bundle is now executed by the test suite). Stellar deposits state their memo type (MEMO_TEXT, even when the memo looks numeric). Orders show remaining validity as a duration ("expires in 47m") in the deposit block and in status, with the exact command to make a fresh one. Reusing an existing unpaid order, and asking for a coin that differs from it, are both explained instead of reading as errors.
  • 0.1.2 — Mode B no longer needs a raw private key in an environment variable. On Solana it uses the ~/.config/solana/id.json that solana-keygen already wrote; on EVM an encrypted V3 keystore whose passphrase is prompted. --keyfile names either explicitly, and settings can come from a gitignored .env. Raw env keys still work for unattended automation. Key files and .env must be chmod 600 and untracked by git.
  • 0.1.1 — one spend limit instead of two: a single payment may not exceed $1,100 (sized for a $1,000 credit purchase plus its 5% fee), the cumulative session cap and the --yes-large override are removed. Docs make it explicit that paying from your own wallet needs no key or configuration.
  • 0.1.0 — first release: npx @rozoai/checkout.

License

MIT.

Secret scanning

Enable the local gitleaks pre-commit hook once per clone: brew install gitleaks pre-commit && pre-commit install (config in .pre-commit-config.yaml). CI also runs a report-only scan in .github/workflows/secret-scan.yml.