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

@andocorp/buzz-import

v0.3.0

Published

Move a Buzz community's history into an Ando workspace.

Readme

ando-buzz-import

Copies a Buzz community's chat history into an Ando workspace.

It runs in two steps. export reads the Buzz relay and writes a JSONL snapshot of raw signed Nostr events. import turns that snapshot into Ando import records and uploads them. migrate does both. You can run the two steps on different machines, and you can build the snapshot from a Postgres dump instead of the relay.

What moves

| Buzz | Ando | | --- | --- | | Channels (kind 39000 metadata, 39002 roster) | Channels with name, description, public/private, archived state and members | | DMs and group DMs (39000 with hidden / t=dm) | Direct messages | | Messages: kind 9, 40002, forum posts 45001, diffs 40008 | Messages. A diff is wrapped in a diff code block | | Replies: NIP-10 e tags, forum comments 45003 | Thread replies. Ando threads are one level deep, so nested replies attach to the top-level message | | Edits (40003) | The latest edit's text, with edited_at set | | Reactions (kind 7) | Reactions. + becomes 👍 and - becomes 👎 | | Profiles (kind 0) | Members: display name and avatar URL | | Agents: roster role bot, kind 10100, NIP-OA auth tag, or "bot": true in kind 0 | Members of kind bot | | Archived identities (kind 13535) | Deactivated members | | nostr:npub… / nostr:nprofile… mentions | @Display Name text | | Attachments (NIP-92 imeta) | Files on the message. Files on the Buzz relay are downloaded with your Buzz key (Blossom get auth), checked against their sha256, and uploaded to Ando |

Channels come from the relay's channel list plus your own membership rosters, so every channel you belong to is included even on large relays.

What does not move

  • Files that can't be copied stay as links. A file larger than --max-file-mb (default 100), one the relay no longer has, one that fails its checksum, or every file when you pass --skip-files, stays a 📎 [filename](url) line, as before. The summary lists each under files.failed with a reason. Files on the Buzz relay need BUZZ_PRIVATE_KEY, including for import --from. Links to any other host are fetched without credentials and only from public addresses (checked on every redirect), so a message can't make the importer read a service on your network.
  • Custom emoji become shortcodes. A :partyparrot: reaction is sent as partyparrot. Ando skips shortcodes it doesn't support and lists them under skipped in the summary. Custom emoji inside message text stay as :shortcode: text.
  • Deleted messages and reactions. Anything removed by kind 5 or 9005 is dropped.
  • Private channels and DMs you are not in. The relay only returns what the exporting key can read. To include every private channel and DM, use the operator dump below.
  • Other Buzz data: forum votes, pins, bookmarks, canvases, huddles, workflows, system messages (40099), user status and read state. The summary's dropped.unknown_kinds counts the skipped kinds.
  • Past channel membership. Rosters are each channel's current 39002 snapshot. A channel with no roster gets the people who posted in it.
  • Email addresses. Buzz has none. Members are created with email: null. NIP-05 identifiers are not used as emails because they are not verified addresses.

Members with no kind 0 profile are still imported. Their display name is the first 12 characters of their npub (npub1 plus 7 more).

Prerequisites

  • Node.js 22 or later.
  • A Buzz key that belongs to a member of the community, set in BUZZ_PRIVATE_KEY as hex or nsec1…. An agent key that relies on its owner's membership also needs BUZZ_AUTH_TAG, the same NIP-OA tag JSON the Buzz CLI uses. It is sent as the x-auth-tag header.
  • An Ando API key with the Import history permission (imports:write and files:write), created by a workspace owner or admin, set in ANDO_API_KEY. Without the role or imports:write, Ando returns 403 and the tool stops; without files:write, files stay as links. ANDO_API_URL defaults to https://api.ando.so.

Never pass keys as command-line arguments. The CLI refuses anything that looks like an nsec.

Install

npx @andocorp/buzz-import <command>    # run without installing
npm install -g @andocorp/buzz-import   # or install the ando-buzz-import command

Commands

# 1. Snapshot the relay (wss:// or https://; ws:// and http:// only for localhost)
BUZZ_PRIVATE_KEY=nsec1... ando-buzz-import export --relay wss://buzz.example.com --out buzz.jsonl

# 2. Check what will be imported. This makes no calls to Ando.
ando-buzz-import import --from buzz.jsonl --dry-run

# 3. Import
ANDO_API_KEY=... ando-buzz-import import --from buzz.jsonl --map-self --self npub1...

# Or run steps 1 and 3 together (the snapshot goes to a temp file unless --out is given)
BUZZ_PRIVATE_KEY=... ANDO_API_KEY=... ando-buzz-import migrate --relay wss://buzz.example.com --map-self

Progress lines go to stderr. The final JSON summary goes to stdout: counts, dropped items, records written, and every record Ando skipped with its reason.

Mapping people onto existing Ando members

By default, every Buzz identity becomes an imported placeholder member. To attach an identity to someone who already has an Ando account:

  • --map <npub|hex>=<ando_member_id> maps one identity. Repeat the flag for more people.
  • --map-self maps your own Buzz identity to the Ando member who owns the API key. migrate gets your identity from BUZZ_PRIVATE_KEY. import needs it passed as --self <npub|hex>.

What people see in Ando

  • Imported history notifies no one and adds no unread badges. Messages keep their Buzz time, author and edit time.
  • A placeholder member shows the person's Buzz name and avatar on their messages. It is not an invitation and gets no email. Deactivated Buzz members stay archived.
  • An imported channel never takes over an existing channel's name. If #general already exists, Buzz's arrives as #general-buzz.
  • Every Buzz DM and group DM becomes its own imported conversation, even when the same people already have an Ando DM.
  • Running the import again also brings over renames, archiving and visibility changes made in Buzz since the last run.

Other options

  • --source-workspace-id <host>: the Buzz relay host recorded on the Ando import. It defaults to the host in the snapshot, so you only need it for operator dumps.
  • --source-workspace-name <name>: defaults to the relay's NIP-11 name.

Bring over your own agents

Any workspace member, not only an owner or admin, can bring the Buzz agents they own into Ando:

BUZZ_PRIVATE_KEY=nsec1... ANDO_API_KEY=... ando-buzz-import agents --relay wss://buzz.example.com --dry-run
BUZZ_PRIVATE_KEY=nsec1... ANDO_API_KEY=... ando-buzz-import agents --relay wss://buzz.example.com
  • It reads your own agent records (kind 30177) and the definitions they link to (kind 30175), so each agent keeps its name, instructions and model. A model Ando doesn't offer falls back to Ando's default. An agent set to answer only you answers only you in Ando.
  • Each agent arrives as an Ando agent you created. No messages, channels or other people are written, which is why it doesn't need an owner or admin. It needs an Ando API key with Manage agents (agents:write).
  • Ando checks ownership itself: each agent must have signed an event carrying its NIP-OA owner tag naming you, and the request carries a fresh proof signed by your Buzz key for that API key. An agent that never named you, or one another member already brought over, is skipped with a reason.
  • Running it again returns the agents you already brought over instead of making copies. If an owner or admin later imports the community's history, those agents' Buzz messages are attributed to them.
  • Not moved: avatars, the runtime or harness the agent ran on in Buzz (Goose, Claude Code), its secrets, and its memory.

Operator dump (all channels and DMs)

A relay operator can build the snapshot straight from Buzz's Postgres. Every private channel and DM is included, whoever runs it. Each output line is one event in the same shape export writes.

COMMUNITY=$(psql "$BUZZ_DATABASE_URL" -At -c \
  "SELECT id FROM communities WHERE host = 'buzz.example.com' AND deleted_at IS NULL")

psql "$BUZZ_DATABASE_URL" -At -c "
  SELECT json_build_object(
    'id', encode(id, 'hex'),
    'pubkey', encode(pubkey, 'hex'),
    'created_at', extract(epoch from created_at)::bigint,
    'kind', kind,
    'tags', tags,
    'content', content,
    'sig', encode(sig, 'hex'))
  FROM events
  WHERE deleted_at IS NULL
    AND community_id = '$COMMUNITY'
    AND kind IN (0, 5, 7, 9, 9005, 10100, 13535, 39000, 39002, 40002, 40003, 40008, 45001, 45003)
" > buzz.jsonl

ando-buzz-import import --from buzz.jsonl --source-workspace-id buzz.example.com --dry-run

The column names and types come from schema/schema.sql in the Buzz repo (events.id, pubkey and sig are BYTEA, created_at is TIMESTAMPTZ, tags is JSONB). The kind list only keeps the file small; without it, the importer ignores the other kinds anyway.

Use psql -At -c "SELECT …", not COPY (SELECT …) TO STDOUT. COPY's default text format escapes backslashes, so JSON like "a\nb" comes out as "a\\nb", and every newline and quote in a message would turn into literal backslash sequences. If you must use COPY, use COPY (…) TO STDOUT WITH (FORMAT csv, QUOTE E'\x01', DELIMITER E'\x02'), which writes each row unescaped.

Safe to rerun

  • Ando identifies each record by its Buzz id: pubkey hex for members, channel UUID for conversations, event id hex for messages. Rerunning import or migrate updates records instead of duplicating them. Starting again against the same relay host reuses the existing Ando import, and reopens it if it was completed.
  • If an upload fails partway through, run the same command again. When migrate wrote its snapshot to a temp file, it keeps that file on failure and prints an import --from command, so the retry skips the export. Everything is resent in dependency order: members, then conversations, then messages oldest first (a thread root always comes before its replies), then reactions.
  • Files are keyed by their sha256. A rerun asks Ando which files this import already uploaded and only downloads and uploads the rest. A message is never stripped of files an earlier run attached.
  • export writes to <out>.partial and renames the file only when it finishes. An interrupted export never leaves a file that looks complete.
  • Relay requests are retried on 429 (using the relay's retry in Ns hint or Retry-After) and on 5xx. Ando requests are retried on 429 (using Retry-After) and on 5xx.

Limits

  • The whole snapshot is held in memory during import, so memory use grows with the size of the community.
  • Messages longer than 40,000 characters are cut off, with a note at the end.
  • Files up to 100 MB by default (--max-file-mb), at most 10 per message. Each file is held in memory while it uploads.
  • Ando's per-request limits: 100 members, 10 conversations with at most 250 member ids in total, 100 messages, 200 reactions. A roster larger than 250 is sent as repeated slices of the same conversation.

Development

pnpm --filter @andocorp/buzz-import test       # node --experimental-strip-types --test src/*.test.ts
pnpm --filter @andocorp/buzz-import typecheck
pnpm --filter @andocorp/buzz-import pack:npm   # build, pack, and run the CLI from a clean npm install

Releasing

Merging a version change to main publishes it. .github/workflows/publish-buzz-import.yml skips versions already on npm, runs the tests, typecheck and pack:npm, then publishes that exact tarball through npm trusted publishing (no stored token; npm records provenance). Versions with a prerelease suffix (0.2.0-next.0) go to the next tag instead of latest.

The workflow only works once @andocorp/buzz-import exists on npm with a trusted publisher of Ando-Corporation/ando, workflow publish-buzz-import.yml, environment npm-buzz-import. The first version therefore goes out by hand, from a clean checkout of main, by someone with publish rights on the @andocorp org:

pnpm --filter @andocorp/buzz-import pack:npm
npm publish artifacts/buzz-import/npm/andocorp-buzz-import-0.1.0.tgz --access public

Settings > Buzz import is shown to every workspace admin and tells them to run npx @andocorp/buzz-import, so publish the version you need to npm before relying on it.