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

6sky

v0.9.13

Published

BlueSky firehose/WebSocket and CAR in plain JavaScript

Downloads

66

Readme

Bski raw CAR/CBOR format parsing

Parsing raw binary content of the realtime firehose from WebSocket, and CAR account repository snapshot data.

Self-contained, zero dependencies.

Installation

npm install bski

Reading firehose

import { firehose } from 'bski'; // import from npm

const chunk = [];
for await(const msg of firehose.each()) {
  chunk.push(msg);
  if(chunk.length === 1000) break;
}

Example using bski to fetch 1000 messages from the firehose

Reading CAR

import { readCAR } from 'bski'; // import from npm

const did = 'did:plc:z72i7hdynmk6r22z27h6tvur';
const car = await fetch('https://puffball.us-east.host.bsky.network/xrpc/com.atproto.sync.getRepo?did=' + did)
  .then(x => x.arrayBuffer());

const records = readCAR(did, car);

Example using bski to fetch CAR snapshot file and parse it

API details

firehose

firehose(address = 'wss://bsky.network/xrpc/com.atproto.sync.subscribeRepos'):
  AsyncIterable<FirehoseRecord[]>

Connects to a firehose via WebSocket (defaults to the central server https://bsky.network/ or potentially a local server i.e. PDS if the address parameter is provided).

Yields records in batches FirehoseRecord[].

Batching lets you consume records at your own speed. If you're iterating and immediatelly processing — they will come in batches of one. If your code stalls in process, they will queue up and next iteration will come with whole pile at once.

Exiting the iterator loop disconnects from the WebSockets and discards any unprocessed records.

firehose.each(address?): AsyncIterable<FirehoseRecord>

Same as the firehose() above, but always reporting records one by one.

The queueing still happens behind the scene, but if your code stalls it will still receive each record separately. That comes with a small performance penalty.

readCAR

readCAR(messageBuf: ArrayBuffer | Uint8Array, did: string): FirehoseRepositoryRecord[]

Parses binary CAR/DAG/CBOR format that is the archive/database format for BlueSky account history.

The parser is pretty fast: 50Mb repository takes 1-2 seconds. However, for a web app that delay could be jarring. Enter sequenceReadCAR:

sequenceReadCAR(messageBuf: ArrayBuffer | Uint8Array, did: string):
  Iterable<FirehoseRepositoryRecord | undefined>

Parsing that binary, yielding the parsed records in implementation-defined batches.

This lets your code parse CAR even on the main thread incrementally, without freezing the app.

Additional metadata on the records

Apart from capturing the built-in BlueSky fields, both firehose and readCAR collect a couple extras:

  • repo the DID of the account making the record (post/like etc.)
  • uri standard at://<did>/<type>/<hash> way of referring to events in ATProto
  • cid another standard identifier, a bit longer and less useful
  • action mostly just create but can also be delete or update (think updating user profile)
  • time BlueSky-observed time (different from self-reported time that can be spoofed by a poster)
  • receiveTimestamp Unix-style time the message is received from WebSocket
  • parseTime useful for tracking performance, averages to 0.3 millisecond

History and references

The firehose functionality existed in colds.ky codebase for a while, using some of the packages referenced by the official @atproto/api:

But those are complex and broader-purpose libraries. Later @mary.my.id created leaner, more focused set of libraries to transcode some of the same formats, @atcute/* - MIT license.

And now this library here is taking in only few necessary bits, focusing on singular use case: parsing realtime firehose, and account repository CAR.

License and links

MIT Oleg Mihailik