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/source-skills

v0.6.0

Published

Part of PAC: @projectpac/source-skills.

Readme

@projectpac/source-skills

The principal's skills: procedures they own, offered to a peer the same way anything else they hold is.

A skill is a markdown document with a little front matter. The body is the instructions a model is given; the front matter is what a peer is allowed to know. The two are stored apart, and that split is the point -- describing a skill must not mean reading it, exactly as describing a plugin must not mean running it.

  • It is a source, not a flow's private library. A skill used to live inside the flow that called one, with its own store and its own board, which meant no other flow could plan against one and the flow that owned it had to know what a skill was in order to stake it. Here inventory() says what this node offers and stake() puts it where a box can be pointed at it, so a flow names a skill and never learns that it is one.
  • It holds the instructions and nothing else. The model a skill runs on and the key that pays for it used to live here too, named by the front matter. They are @projectpac/source-llm's now -- because a credential pinned to a skill means only the skill's owner can ever pay to run one, and who supplies the model is a term of the computation rather than one party's private arrangement. A design names an access beside the skill, from either side.
  • provider is a hostname. openrouter.ai, not openrouter -- the same word a box session's declared egress speaks, so one name carries from the document, through the descriptor a peer reads, to the cage the program runs in.
  • A document without a provider is refused at the door, through the same parser that will serve it: it describes a disclosure nobody could consent to. A key this parser does not read is ignored rather than refused, so a document still carrying model: from when a skill named its own comes through as a skill that names none -- which is the right answer, not leniency.

The document

---
description: Plans multi-day trip itineraries tuned to the traveler's tastes.
provider: openrouter.ai
needs: trips
---

# Trip planner

You plan trips the way a well-travelled friend does...

Deliberately not YAML: the grammar is key: value lines, so a document cannot carry a tag, an anchor, or a nested document. needs is the one list, and it is comma-separated for the same reason. It names the caller's files, not this node's.

The two routes

POST /skills takes {name, document} and writes the body into this plugin's own folder with mode 0600. It is the one moment a body passes through this code. GET /skills answers the declarations, with servable false for one whose body has gone -- declared but no longer held.

Whether anybody can pay to run a skill is a separate question and no longer asked here: a node holding a skill and no access to its provider still offers the skill, and the refusal comes when a call is made, by name.