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

npm-skills

v0.5.1

Published

Extract skills from installed npm packages into a local skills folder.

Readme

npm-skills helps npm packages ship AI skills in a way that's easy to version, distribute, and extract. Put SKILL.md-based skills in a package, then copy them into your workspace with one command.

Prefer the polished version of this guide? Browse the docs site at npm-skills.com.

It gives package authors a predictable convention and gives consuming teams a clean way to keep skills alongside the projects that use them. Skills travel with your dependencies, stay compatible with AGENTS.md and SKILL.md workflows, land locally in .agents/skills, and stay fully customizable when your team needs different source paths, output paths, filters, or package mappings.

Overview

npm-skills is for shipping skills inside ordinary npm packages, versioning them with package.json, moving them through private registries, and extracting them into the workspace where they are actually used.

It follows conventions people already recognize from the skills.sh ecosystem, the SKILL.md-based format used by the open skills tool, and AGENTS.md-style repos:

  • any directory containing SKILL.md is treated as a skill root
  • support files live beside that SKILL.md
  • packages usually publish from skills/
  • consuming projects usually extract into .agents/skills/

skills.sh is a strong fit when you want a hosted catalog and public discovery. npm-skills is for distributing skills as part of your dependency graph.

npm-skills officially targets Node >=22.

  • Node: officially supported for both the CLI and programmatic API
  • Bun: supported for CLI usage, including --skip-production
  • Deno: supported for CLI usage through the CommonJS entry, including the NODE_ENV fallback via Deno.env.get("NODE_ENV") for --skip-production

The CLI is the primary way this package is meant to be used. In most projects you will not need the programmatic API at all, which is nice because we all deserve at least one tool in life that does not begin with "first, write a wrapper."

Quick Start

Install it in your project:

npm install npm-skills

Or use it directly:

npm-skills extract
npm-skills --help

Bun users can also run the packaged CLI directly:

bunx npm-skills extract

Deno users can run the package directly through Deno's npm support:

deno run -A npm:npm-skills@latest extract --skip-production

Add a script:

{
  "scripts": {
    "skills:extract": "npm-skills extract"
  }
}

Then run:

npm run skills:extract

If you want skills to stay automatically synced after installs, install npm-skills as a regular dependency and wire it into postinstall:

{
  "scripts": {
    "postinstall": "npm-skills extract --skip-production --override"
  }
}

That keeps the binary available in environments where postinstall runs, and --skip-production makes the command exit cleanly and silently when NODE_ENV is production.

If you prefer to avoid automatic overwrites, keep extraction as an explicit script instead of postinstall.

Maintainers can verify the Bun and Deno CLI paths locally with:

npm run qa:local

That runs the normal QA flow plus runtime smoke tests for Bun and Deno. The smoke step skips automatically on CI.

Skill Sharing Pattern

If your repo both authors its own skills and extracts skills from dependencies, prefer giving extracted content its own lane under .agents/skills/extracted.

This is a recommended pattern, not the default. If you do nothing, extraction still defaults to .agents/skills.

That keeps local skills easy to curate, keeps sync cleanup scoped to imported content, and keeps Git from collecting extracted folders like a very enthusiastic raccoon.

Recommended layout:

.agents/
  skills/
    my-local-skill/
      SKILL.md
    extracted/
      .gitignore
      bluelibs-runner-release-notes/

Use a dedicated .gitignore in that extraction folder:

*

Quick setup:

Make sure .agents/skills/extracted exists, then run:

npx npm-skills extract --output .agents/skills/extracted

Script example:

{
  "scripts": {
    "skills:extract": "npm-skills extract --output .agents/skills/extracted"
  }
}

package.json setting example:

{
  "npmSkills": {
    "consume": {
      "output": ".agents/skills/extracted"
    }
  }
}

--output still overrides the package setting when you need a one-off destination.

How Extraction Works

Skill discovery stays predictable:

  • scan under a configured source folder
  • treat any directory containing SKILL.md as a skill root
  • copy that directory recursively as-is

Package-side layout usually looks like this:

my-package/
  package.json
  skills/
    release-notes/
      SKILL.md
      template.md
    bug-hunt/
      SKILL.md
      checklist.md

Extracted skills are copied into package-prefixed folders to avoid collisions:

@bluelibs/runner + skills/release-notes
=> .agents/skills/bluelibs-runner-release-notes

Overwrite behavior is intentionally conservative:

  • if the destination folder does not exist, it copies the skill
  • if the destination exists and you pass --override, it replaces it fully
  • if the destination exists in an interactive terminal, it asks y/N
  • if the destination exists in non-interactive mode, it skips and warns
  • if a package simply has no discoverable skills source, it skips quietly by default because that is normal
  • if a listed package is not currently resolvable from node_modules, it skips and warns instead of aborting the whole run
  • full syncs also remove stale folders from earlier extractions in the chosen output directory, without touching unrelated folders there

By default, npm-skills scans:

  • dependencies
  • optionalDependencies
  • peerDependencies
  • devDependencies

Pass --devDependencies=false or includeDevDependencies: false to exclude dev dependencies.

Generated local skills include a LICENSE.txt.

Configuration

You can configure both sides of the workflow with a dedicated npm-skills.policy.json file or from package.json using the npmSkills key.

npm-skills.policy.json uses the same schema as package.json.npmSkills, but at the JSON file root:

{
  "consume": {
    "only": ["@scope/*", "my-package"],
    "output": ".agents/skills/extracted",
    "map": {
      "@bluelibs/runner": ".agents/skills",
      "some-package": "resources/skills"
    }
  },
  "publish": {
    "source": ".agents/skills",
    "export": ["public", "react"],
    "refs": [
      {
        "source": "readmes",
        "destination": "skills/core/references/readmes"
      }
    ]
  }
}

Config precedence is:

  • --policy <path> on the CLI or policyPath in the API
  • ./npm-skills.policy.json
  • package.json.npmSkills

If you prefer to keep config in package.json, the equivalent shape is:

  • consume: how this project reads skills from installed dependencies
  • publish: how this package exposes its own skills to others

Example:

{
  "npmSkills": {
    "consume": {
      "only": ["@scope/*", "my-package"],
      "output": ".agents/skills/extracted",
      "map": {
        "@bluelibs/runner": ".agents/skills",
        "some-package": "resources/skills"
      }
    },
    "publish": {
      "source": ".agents/skills",
      "export": ["public", "react"],
      "refs": [
        {
          "source": "readmes",
          "destination": "skills/core/references/readmes"
        }
      ]
    }
  }
}

consume.only

  • Optional array of package filters
  • Supports exact package names and * wildcards
  • Used when CLI filters are not provided

consume.map

  • Optional per-package source folder overrides
  • Default source folder is skills
  • Values are resolved relative to the installed package folder

consume.output

  • Optional default extraction destination for this consumer project
  • Defaults to .agents/skills
  • Useful when you want extracted skills to live under .agents/skills/extracted
  • --output on the CLI and outputDir in the API still override it

publish.source

  • Optional source folder for skills this package publishes
  • Defaults to skills
  • Useful when your repo authors skills under .agents/skills

publish.export

  • Optional list of top-level skill folders to expose
  • If omitted, every discovered skill under publish.source can be published
  • If set to false, this package opts out of skill publishing

publish.refs

  • Optional list of shared docs or assets that should appear inside published skills
  • Each entry uses a project-relative source and destination
  • Intended for repos that keep canonical docs in places like readmes/ or docs/, then link them into skills/.../references/... during development
  • Pair it with npm-skills refs materialize in prepack and npm-skills refs restore in postpack

Example:

{
  "scripts": {
    "prepack": "npm-skills refs materialize",
    "postpack": "npm-skills refs restore"
  },
  "npmSkills": {
    "publish": {
      "refs": [
        {
          "source": "readmes",
          "destination": "skills/core/references/readmes"
        },
        {
          "source": "guide-units",
          "destination": "skills/core/references/guide-units"
        }
      ]
    }
  }
}

This matches the pattern used in repos like runner: keep the docs authored once in top-level folders, symlink them into skill references while developing, materialize real files for the packed tarball, then restore the symlinks afterward.

If a package wants to export only some skill folders:

{
  "npmSkills": {
    "publish": {
      "source": ".agents/skills",
      "export": ["runner"]
    }
  }
}

With this structure:

.agents/skills/
  runner/
    architecture/
      SKILL.md
    testing/
      SKILL.md
  internal/
    notes/
      SKILL.md

publish.export: ["runner"] will export everything under the top-level runner/ folder and skip internal/.

If a package wants to disable skill export entirely:

{
  "npmSkills": {
    "publish": false
  }
}

Consumer-side config and package-side config are separate:

  • consumer config decides where to read skills from for a given installed package
  • package config decides where this package publishes skills from, and which skill folders can be published

CLI

extract

npm-skills extract [package-a package-b ...] [options]

Options:

  • --cwd <dir>: project root to operate from, defaults to the current working directory
  • --policy <path>: read config from a dedicated JSON policy file
  • --output <dir>: destination folder, overrides consume.output from the selected config or defaults to .agents/skills
  • --only <patterns>: comma-separated package filters such as @scope/*,pkg-a
  • --skip-production: skip extraction when NODE_ENV is production
  • --devDependencies <true|false>: include dev dependencies in the package scan, defaults to true
  • --dev <true|false>: deprecated alias for --devDependencies
  • --override: replace existing extracted skills without prompting
  • --verbose: show normal skip diagnostics such as packages without a skills/ folder

Examples:

npm-skills extract
npm-skills --cwd packages/app extract
npm-skills extract --policy config/npm-skills/policy.json
npm-skills extract @bluelibs/runner my-package
npm-skills extract --only "@bluelibs/*" --output .agents/skills
npm-skills extract --skip-production
npm-skills extract --devDependencies=false
npm-skills extract --override
npm-skills extract --verbose

--skip-production only skips extraction when the current NODE_ENV is production. If NODE_ENV is unset, extraction still runs. --devDependencies controls whether devDependencies are included in the package scan. The old --dev flag is still accepted as an alias for compatibility, but --devDependencies is the clearer name going forward.

In a monorepo, the default stays local to the package you run from, so packages/app extracts into packages/app/.agents/skills.

new

npm-skills new <skill-name> [options]

Options:

  • --cwd <dir>: project root to operate from, defaults to the current working directory
  • --folder <dir>: destination root for the new skill, defaults to .agents/skills

What it creates:

  • a skill folder named after the sanitized skill name
  • SKILL.md with Agent Skills-style frontmatter plus a practical starter template
  • LICENSE.txt with an MIT license using ${currentYear}-present
  • references/README.md with prompts for longer examples, checklists, and notes

Examples:

npm-skills new my-skill
npm-skills --cwd packages/app new my-skill
npm-skills new release-notes --folder ./

refs

npm-skills refs <materialize|restore> [options]

Modes and options:

  • --cwd <dir>: project root to operate from, defaults to the current working directory
  • --policy <path>: read config from a dedicated JSON policy file
  • materialize: replace each configured destination with a copied snapshot of its source
  • restore: replace each configured destination with a symlink back to its source

Examples:

npm-skills refs materialize
npm-skills refs restore
npm-skills refs restore --policy config/npm-skills/policy.json
npm-skills --cwd packages/runner refs materialize

Recommended everyday commands:

npm-skills extract
npm-skills extract --override
npm-skills extract --only "@bluelibs/*"
npm-skills new my-skill
npm-skills refs materialize

Programmatic API

This exists for integrations and tooling, but it is secondary to the CLI.

Extract skills directly:

import { extractSkills } from "npm-skills";

const report = await extractSkills({
  cwd: process.cwd(),
  policyPath: "config/npm-skills/policy.json",
  outputDir: ".agents/skills",
  only: ["@bluelibs/*"],
  skipProduction: true,
  includeDevDependencies: true,
  override: false,
  verbose: false,
});

console.log(report.extracted);
console.log(report.skipped);

Create a local skill template:

import { createSkillTemplate } from "npm-skills";

const report = await createSkillTemplate({
  cwd: process.cwd(),
  skillName: "my-skill",
});

console.log(report.skillDir);

Sync shared publish refs:

import { syncSkillPublishRefs } from "npm-skills";

await syncSkillPublishRefs({
  cwd: process.cwd(),
  policyPath: "config/npm-skills/policy.json",
  mode: "materialize",
});

extractSkills() returns:

interface ExtractReport {
  outputDir: string;
  scannedPackages: string[];
  extracted: Array<{
    packageName: string;
    sourceDir: string;
    destinationDir: string;
    destinationName: string;
  }>;
  skipped: Array<{
    packageName: string;
    sourceDir: string;
    destinationDir: string;
    reason:
      | "declined"
      | "missing-package"
      | "non-interactive"
      | "missing-source"
      | "package-opt-out";
  }>;
  skippedEnvironment?: {
    reason: "production";
    received: string;
  };
}

The package is built with tsup and ships:

  • CommonJS via .cjs
  • ESM via .mjs
  • Type declarations via dist/types

If you are running under Deno today, prefer the CommonJS entry.

import { extractSkills } from "./node_modules/npm-skills/dist/index.cjs";

Notes for Package Authors

If you want your package to expose skills cleanly:

  1. Put them in skills/ unless you have a strong reason not to.
  2. Make every skill a folder with a SKILL.md.
  3. Keep related assets beside the SKILL.md.
  4. Avoid surprising dynamic generation when a plain file tree will do.

This package is built with a strict QA pipeline:

  • 100% code coverage
  • linting
  • type checking
  • build verification

Run it locally with:

npm run qa

License

MIT