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

aura-agent

v0.1.0

Published

Give an autonomous agent a real email address, a webhook URL, durable memory, and the ability to wait for an event without burning tokens. Paid per call in USDC over x402.

Readme

aura-agent

Give an autonomous agent a real email address, a webhook URL, durable memory, and the ability to wait for something without burning tokens.

npm install aura-agent

No account. No API key form. No human. An agent proves it controls a wallet with one signature, and is billed per call against a prepaid USDC balance on Base.


The three things an ephemeral agent cannot do

| Blocker | What normally happens | With Aura | | --- | --- | --- | | It has no address. | It cannot sign up for anything, because it cannot receive the verification code. | await client.awaitEmailCode() | | It cannot wait. | It polls in a loop, burning tokens on every turn, or it dies and loses the work. | One blocking call. Zero tokens while waiting. | | It dies at the end of a run. | Everything it learned is gone. | Durable memory keyed to the wallet. |

Quickstart

import { Aura, toSigner } from "aura-agent";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);

// Free. Rotates the token if this wallet already has an identity, so it is
// safe to run on every boot.
const { client, identity } = await Aura.claim(toSigner(account));

console.log(identity.email);        // [email protected]  <- a real mailbox
console.log(identity.webhook_base); // https://aura.rohnelt.dev/hook/ripe-harbor-91f2
console.log(identity.token);        // aura_sk_...  <- persist this

Already have a token:

const client = new Aura({ token: process.env.AURA_TOKEN });

AURA_TOKEN and AURA_URL are read from the environment when not passed.

Sign up for a third-party service, unattended

The whole point. The agent registers somewhere, blocks on the confirmation mail, and continues.

await signUpSomewhere({ email: identity.email });

const code = await client.awaitEmailCode({
  from: "[email protected]",
  timeoutSeconds: 600,
});

if (code) await submitVerification(code);

awaitEmailCode holds one HTTP connection open server-side. The agent is not running, so it spends nothing while it waits. If nothing arrives before the timeout, the call refunds itself.

There is awaitEmailLink() too, for the services that send a confirmation URL instead of a code.

Wait for anything, not just mail

// A webhook you own
await client.createHook("stripe");
const event = await client.awaitTrigger({ type: "hook", slug: "stripe" });

// Another agent
const event = await client.awaitTrigger({ type: "signal", name: "approved" });

// A moment in time
const event = await client.awaitTrigger({
  type: "time",
  at: "2026-09-01T09:00:00Z",
});

Wait longer than the process lives

When the wait could outlast the run, hand over the state and exit. Aura wakes you up with it.

// Run 1 — park and exit.
const { park_id } = await client.park(
  { orderId: "A-1183", step: "awaiting-approval" },
  { type: "email", match: "approved", extract: "none" },
  { expiresInHours: 72 },
);
process.exit(0);

// Run 2, tomorrow — pick up exactly where it stopped.
const parked = await client.resume();
if (parked.resumed) {
  console.log(parked.state); // { orderId: "A-1183", step: "awaiting-approval" }
  console.log(parked.event); // the mail that woke it
}

resume() is free when there is nothing to resume, so it is safe at the top of every run.

Memory that survives the process

await client.remember("customer.A-1183", JSON.stringify(profile), {
  tags: ["customer"],
});

const { value } = await client.recall("customer.A-1183");
const { results } = await client.searchMemory("who complained about shipping");

Paying

Operations cost fractions of a cent, so they are debited off-chain from a prepaid balance: one on-chain settlement covers hundreds of calls.

New identities get a small trial credit. After that:

import { wrapFetchWithPayment } from "@x402/fetch";

const client = new Aura({
  token: process.env.AURA_TOKEN,
  fetch: wrapFetchWithPayment(fetch, x402Client), // settles the 402 by itself
});

await client.deposit(5); // US$5.00 in USDC on Base

Without an x402-capable fetch, deposit() throws an AuraError whose fix holds the full payment requirements — so a caller that knows how to pay still has everything it needs.

Errors tell you how to fix them

Aura writes its errors for a reader with no human to ask, and this SDK keeps that intact.

import { AuraError } from "aura-agent";

try {
  await client.remember("k", "v");
} catch (err) {
  if (err instanceof AuraError && err.needsCredit) {
    console.log(err.fix); // the exact deposit call to make
  }
}

A 404 on memory carries the keys that do exist. A 400 carries the schema plus a working example.

Prices

| Call | Price | | --- | --- | | capabilities, whoami, claimIdentity, forget | free | | recall, listMemory | $0.0005 | | remember | $0.0008 | | inbox, readMail, createHook | $0.001 | | searchMemory, signal, resume | $0.002 | | awaitTrigger, awaitEmailCode | $0.004 | | park | $0.005 |

awaitTrigger refunds itself when it times out with nothing. resume is free when nothing is waiting.

Using it over MCP instead

Every operation is also an MCP tool. Point any MCP client at the endpoint:

{
  "mcpServers": {
    "aura": {
      "type": "http",
      "url": "https://aura.rohnelt.dev/mcp",
      "headers": { "Authorization": "Bearer aura_sk_..." }
    }
  }
}

Without the header you can still list the tools and call capabilities and identity_create, so a client can evaluate the service before committing to anything.

API

| Method | Does | | --- | --- | | Aura.claim(signer, options?) | Claim an identity and return a ready client | | claimIdentity(signer, label?) | Claim or rotate on an existing client | | whoami() | Handle, email, balance, trial status | | capabilities() | The full manifest: every operation, price and schema | | remember(key, value, opts?) | Store durable state | | recall(key) | Read it back | | searchMemory(q, opts?) | Semantic or full-text search | | listMemory(opts?) | List keys | | forget(key) | Delete (free) | | inbox(opts?) / readMail(id) | Received mail | | awaitTrigger(on, opts?) | Block until an event fires | | awaitEmailCode(opts?) | Block until a verification code arrives | | awaitEmailLink(opts?) | Block until a confirmation link arrives | | park(state, on, opts?) | Store state and a wake condition, then exit | | resume(opts?) | Collect whatever woke up while you were gone | | createHook(slug, description?) | A webhook URL you own | | signal(to, name?, payload?) | Wake another agent | | deposit(1 \| 5 \| 20) | Buy credit over x402 |

License

MIT