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

@pdsjs/oci

v0.1.3

Published

Host OCI container images natively in an atproto account. Tags, manifests and layers live in the account's PDS as a `dev.pdsjs.oci.repo` record plus blob storage, so an image rides along in CAR backups, migrates with the account, and needs no separate reg

Readme

@pdsjs/oci

Host OCI container images natively in an atproto account. Tags, manifests and layers live in the account's PDS as a dev.pdsjs.oci.repo record plus blob storage, so an image rides along in CAR backups, migrates with the account, and needs no separate registry service:

docker login pds.example.com -u alice.example.com
docker push pds.example.com/my-app:v1

docker pull pds.example.com/my-app:v1   # anonymous

How it works

  • An OCI digest is sha256:<hex>; an atproto blob CID is CIDv1 + raw codec
    • a sha256 multihash. Both hold the same 32 hash bytes, so a layer is one blob and a blob fetch is a digest re-encoding plus getBlob. No mapping table exists.
  • Manifest bytes are stored as blobs exactly as pushed, because a digest covers the exact serialization. The record carries each manifest's media type so pulls are served with the right Content-Type.
  • One record per image repository (collection dev.pdsjs.oci.repo, rkey = name with / encoded as :). It holds the tag list and a blob reference for every stored manifest, config and layer, which keeps those blobs out of the PDS's orphan cleanup. Deleting a manifest drops the references and the orphan sweep frees the bytes.
  • Layer uploads stream through the blob writer with an incremental hash, so a layer is never held in memory whole. Monolithic and chunked uploads, cross-repository mounts, ranged blob reads and multi-arch indexes all work.

Authentication

Pulls are anonymous. Pushes authenticate with the account password or an app password, sent the way docker login sends them; the username is the account's handle or DID. The server issues Bearer tokens from /v2/token — the flow docker requires for anonymous pulls — and also accepts Basic credentials directly, so curl -u works.

Enabling

Node:

const server = await createServer({
  // ...
  experimental: { oci: true },
});

Cloudflare: set PDS_EXPERIMENTAL_OCI = "true".

Both mount createOciExtension() through core's extensions option. A platform that builds PersonalDataServer itself does the same:

import { createOciExtension } from '@pdsjs/oci/extension';

new PersonalDataServer({
  // ...
  extensions: [createOciExtension({ maxBlobSize: 512 * 1024 * 1024 })],
});

The registry serves under /v2/ on the PDS hostname. Docker requires TLS for any registry that is not localhost; a PDS behind HTTPS already satisfies that.

Limits

  • Layers stream, but each layer arrives in one request unless the client chunks. A platform's per-request body cap (100 MB on the lowest Cloudflare plan) bounds the largest layer such a deployment accepts.
  • The referrers API is not served; clients fall back to the tag schema.
  • _catalog lists the first hundred repositories.