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

skills-handler

v0.1.2

Published

A framework-agnostic handler for serving Agent Skills via well-known URIs

Readme

skills-handler

A framework-agnostic handler for serving Agent Skills via well-known URIs. Implements the Agent Skills Discovery specification.

Repository: github.com/vercel-labs/skills-handler

Installation

npm install skills-handler

For file-based skill loading:

npm install skills-handler gray-matter

Quick Start (Next.js)

Create a catch-all route at app/.well-known/skills/[[...path]]/route.ts:

import { createSkillsHandler, createStaticProvider } from "skills-handler";

const handler = createSkillsHandler(
  createStaticProvider([
    {
      name: "git-workflow",
      description: "Follow team Git conventions for branching and commits.",
      body: `# Git Workflow

Create feature branches from \`main\`:

\`\`\`bash
git checkout -b feature/my-feature main
\`\`\``,
      files: ["SKILL.md"],
    },
  ])
);

export { handler as GET, handler as OPTIONS };

Your skills are now available at:

  • GET /.well-known/skills/index.json - Discovery index
  • GET /.well-known/skills/git-workflow/SKILL.md - Skill instructions

File-Based Skills

Load skills from the filesystem instead of defining them in code:

// app/.well-known/skills/[[...path]]/route.ts
import { createSkillsHandler, createFileProvider } from "skills-handler";
import path from "path";

const provider = await createFileProvider(path.join(process.cwd(), "skills"));
const handler = createSkillsHandler(provider);

export { handler as GET, handler as OPTIONS };

Directory structure:

project/
├── app/.well-known/skills/[[...path]]/route.ts
└── skills/
    ├── git-workflow/
    │   └── SKILL.md
    └── pdf-processing/
        ├── SKILL.md
        ├── scripts/
        │   └── extract.py
        └── references/
            └── TABLES.md

Each SKILL.md file requires YAML frontmatter:

---
name: git-workflow
description: Follow team Git conventions for branching and commits.
---

# Git Workflow

Your skill instructions here...

API Reference

createSkillsHandler(provider, config?)

Creates the request handler.

const handler = createSkillsHandler(provider, {
  basePath: "/.well-known/skills", // URL base path (default)
  verboseLogs: false,              // Enable debug logging
  cacheControl: "public, max-age=3600", // Cache header
  cors: "*",                       // CORS origin (* | string[] | false)
  onEvent: (event) => {},          // Analytics callback
});

createStaticProvider(skills, additionalFiles?)

Creates a provider from skills defined in code.

const provider = createStaticProvider([
  {
    name: "my-skill",
    description: "What the skill does and when to use it.",
    body: "# Skill Instructions\n\nMarkdown content...",
    files: ["SKILL.md"],
  },
]);

createFileProvider(directory)

Creates a provider that loads skills from the filesystem.

const provider = await createFileProvider("./skills");

createCompositeProvider(providers)

Merges multiple providers. Later providers override earlier ones for skills with the same name.

const provider = createCompositeProvider([
  await createFileProvider("./base-skills"),
  createStaticProvider([overrideSkill]),
]);

CLI

Initialize a skills endpoint in your project:

npx skills-handler init

Create a new skill:

npx skills-handler create-skill my-skill --description "What it does"

Validate skills:

npx skills-handler validate ./skills

Endpoints

The handler serves these endpoints relative to basePath:

| Endpoint | Description | |----------|-------------| | /index.json | Skills discovery index | | /{name}/SKILL.md | Skill instructions | | /{name}/{file} | Supporting resources |

Skill Format

Skills follow the Agent Skills specification:

  • name: 1-64 chars, lowercase alphanumeric and hyphens, no leading/trailing/consecutive hyphens
  • description: Max 1024 chars, explains what the skill does and when to use it
  • files: Array of files in the skill directory (must include SKILL.md)

Events

Subscribe to events for analytics:

const handler = createSkillsHandler(provider, {
  onEvent: (event) => {
    switch (event.type) {
      case "INDEX_REQUESTED":
        console.log(`Index served: ${event.skillCount} skills`);
        break;
      case "SKILL_REQUESTED":
        console.log(`Skill loaded: ${event.skillName}`);
        break;
      case "FILE_REQUESTED":
        console.log(`File served: ${event.skillName}/${event.filePath}`);
        break;
      case "NOT_FOUND":
        console.log(`404: ${event.path}`);
        break;
      case "ERROR":
        console.error(`Error: ${event.error.message}`);
        break;
    }
  },
});

Progressive Disclosure

Skills support progressive loading to manage context efficiently:

  1. Index metadata - Name and description loaded at startup (~100 tokens per skill)
  2. Skill instructions - Full SKILL.md loaded when skill activates (<5k tokens recommended)
  3. Supporting resources - Scripts, references, assets loaded on demand

Reference supporting files with relative links in SKILL.md:

For advanced usage, see [references/ADVANCED.md](references/ADVANCED.md).

Run `scripts/setup.sh` to configure the environment.

License

MIT