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

@projectpac/protocol-skills

v0.1.3

Published

Part of PAC: @projectpac/protocol-skills.

Downloads

73

Readme

@projectpac/protocol-skills

Each node holds instruction documents, advertises some of them, and a peer can ask for one to be applied to something.

A skill arrives as a markdown document with a little front matter, because a skill is something a human writes and edits. The two halves then live apart, and that split is the design: the body becomes a source, so this protocol names it and never holds it, and the front matter stays a declaration the protocol can read without reading the skill. Describing a skill must not mean reading it, the same way describing an extension must not mean running it.

Every call runs in a box both sides verify and neither owns. The caller stakes its request and whichever of its own private sources the human consented to; the owner stakes the skill, the model, and the key that pays for it. Each side gets back only what it is entitled to: the caller an answer, the owner the fact that a run happened. Neither node's material passes through the other, and this protocol holds none of it -- every step that touches material is an apply, and the box program is proposed byte for byte so both sides approve the same bytes. The program is the box's own canonical manifest, unchanged: it names which provider may see plaintext and how much output comes back, and renaming a field of it would mean proposing a program the box does not run.

There is no local mode. A skill run on the owner's own model would mean the caller's input leaving the caller's machine, and the body sitting in protocol memory to be put in a prompt -- so removing it is what lets the body be a source at all.

What a skill declares

---
description: Builds a music-taste profile from someone's listening history.
provider: openrouter
model: anthropic/claude-sonnet-4.5
key: openrouter-key
requiredSources: spotify_songs
---

description and provider and requiredSources are advertised; model and key are not. requiredSources names the caller's sources, not the owner's: it is what a caller is being asked to disclose, published so it can be read before anything is disclosed. A call may narrow that list and may never widen it, and naming a source outside it is refused rather than quietly dropped.

Starting a call takes three answers. A list is exactly those sources. An empty list is none of them, and the call runs on its request text alone. Omitted is what the skill declares and this node holds -- the router's case, since it picks the skill and names no sources.

Nothing here asks a human. Which sources a call may apply is policy's question, asked once on jc.submit by every protocol that stakes anything, so a node that wants to be asked says so in one place and a node that does not is not asked twice -- the same way joint search works. What is refused where it starts is a skill that reads only sources this node does not hold, because a call over none of the data comes back saying the data was missing and costs a box run to learn it.

A skill whose body or key source is missing is declared but not offered: a peer that called it would get a failure this node could have predicted.

| | | | --------- | ------------------------------------------------------------------------------------------------------- | | routes | POST /calls, GET /calls, GET /board, GET /skills, POST /skills | | payloads | call.request, call.failed, call.accepted, call.session | | schedules | advertise 60s (presence), advance 2s (the box state machine), sweep 30s (terminate what stalled) | | needs | any source (the body, the key, and what a caller consents to), the jc.* operations, jc.submit gated | | intents | skill -- picked only for something the board is offering right now |

library.ts is the document grammar and the declaration, calls.ts the durable records, index.ts the state machine. Driving it by hand: devtools/README.md.