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

skillsmp

v0.1.0

Published

CLI and Node.js library for the SkillsMP REST API (https://skillsmp.com) — search the SkillsMP skill index from your terminal, with disk caching and optional API key auth.

Downloads

231

Readme

skillsmp

CLI and Node.js library for the SkillsMP REST API — search the SkillsMP skill index (1.6M+ SKILL.md files pulled from GitHub) from your terminal, with on-disk caching and optional API key auth.

Zero runtime dependencies. Requires Node.js 20+.

Install

npm install -g skillsmp

or run it without installing:

npx skillsmp search "seo"

Two things about the API you should know before trusting stars

1. stars is the star count of the GitHub repo that contains the skill, not of the skill itself. Measured against the live API: a result reported stars: 240467; the containing repo (affaan-m/ECC) actually has 240743 stars — they match. A skill sitting inside a mega-repo inherits that repo's popularity even if it's auto-translated boilerplate, while a careful, standalone skill in its own small repo shows single digits. Sorting by stars surfaces "lives in a famous repo," not "is a good skill." (Example: searching backlink sorted by stars returned three of its first four results from one 28562-star note-taking app's repo, about that app's internal wiki-style backlinks — nothing to do with SEO backlinks.) Every star count this CLI prints is labelled repo★ for this reason.

2. pagination.total is unreliable. It ships with totalIsExact: false and has been observed drastically undercounting — searching SEO across the 1.6M-record index reported total: 5. This CLI paginates on hasNext only, never on a page count computed from total.

Commands

skillsmp search <query> [options]

--page <n>            page number (default 1)
--limit <n>            results per page, max 100 (default 20)
--sort <stars|recent>  sort order (default stars — see the stars caveat above)
--category <slug>      filter by category slug, e.g. data-ai, devops
--occupation <slug>    filter by SOC occupation slug, e.g. software-developers
--lang <code>          filter by content language: en, zh, ja, ...; mul = mixed, und = undetermined
--pages <n>            walk up to n pages, stopping when the API's hasNext is false
--json                 machine-readable output
--no-cache             bypass the cache read (the fresh result is still cached)
--api-key <key>        overrides SKILLSMP_API_KEY and the saved key for this call

Human output shows, per result: name, author, star count (labelled as the containing repo's stars), content language, last-updated date, a truncated description, and the GitHub URL. A trailing status line reports whether the result came from cache (and its age), current quota, and how many pages were fetched.

--json output carries the same cache/quota information in fields rather than mixing it into stdout, so it stays machine-parseable.

skillsmp login [--stdin]

The API has no OAuth flow, so this is a manual key entry:

  1. Prints https://skillsmp.com/docs/api and tries to open it in your default browser (open / xdg-open / start). If that fails, the printed URL is the fallback — nothing is broken.
  2. Prompts for your key without echoing it to the terminal. For scripting, pipe it in instead: echo "$KEY" | skillsmp login --stdin.
  3. Validates the key with one real API call before saving anything. If it's rejected, nothing is written.
  4. Saves it to the config file (see below) with file mode 0600.

skillsmp logout

Deletes the stored key and prints the config file path it removed it from.

skillsmp whoami

Reports whether a key is configured (and its source: flag / env / file), the last 4 characters only (never more), and current quota read from a live request's rate-limit headers.

skillsmp cache stats|clear|ttl [<duration>]

  • stats — entry count, total size on disk, oldest/newest entry timestamps.
  • clear — deletes all cached entries.
  • ttl — with no argument, prints the current effective TTL and its source; with an argument (ttl 24h, ttl 30m, ttl 604800), persists a new TTL into the config file.

skillsmp config [--json]

Prints the fully resolved configuration (API key masked, cache TTL, base URL, config/cache directories) and which source supplied each valueflag, env, file, default, or computed for paths — so an unexpected value can be traced.

Key resolution order (highest wins)

  1. --api-key flag
  2. SKILLSMP_API_KEY environment variable
  3. the config file
  4. none — anonymous access

The API works fine with no key: anonymous is 50 requests/day and 10/minute. An API key raises that to 500/day and 30/minute. The key is never written into the repository, cache files, logs, or error messages.

Config and cache locations

| What | Location | Override | |---|---|---| | Config file | $XDG_CONFIG_HOME/skillsmp/config.json (default ~/.config/skillsmp/config.json) | XDG_CONFIG_HOME | | Cache directory | $XDG_CACHE_HOME/skillsmp/ (default ~/.cache/skillsmp/) | XDG_CACHE_HOME |

The config file holds apiKey (mode 0600) and cacheTtl (seconds).

Caching

Every successful search response is cached to disk, keyed by a SHA-256 hash of the normalised request parameters (q, page, limit, sortBy, category, occupation, language) — the API key is deliberately excluded from the cache key, since the same query returns the same public data no matter who asked; this also means switching between anonymous and authenticated access reuses the same cache entries instead of doubling disk usage.

  • Default TTL: 7 days. Configurable via skillsmp cache ttl <duration>, the SKILLSMP_CACHE_TTL env var, or a cacheTtl field in the config file. Durations accept 30m, 24h, 7d, or a plain number of seconds.
  • --no-cache skips the cache read but still writes the fresh result, so the next normal call benefits from it.
  • Entries store the fetch timestamp, so expiry is evaluated at read time — changing the TTL takes effect on existing entries immediately, no rewrite needed.
  • Error responses are never cached. Caching a DAILY_QUOTA_EXCEEDED for a week would make the CLI insist the quota is exhausted long after it actually reset.

Programmatic use

import { searchOnePage, searchPages, resolveConfig } from "skillsmp";

const config = resolveConfig({});
const { data, cache } = await searchOnePage({
  q: "seo",
  apiKey: config.apiKey.value,
  cacheTtlSeconds: config.cacheTtl.value,
});
console.log(data.skills, cache.hit);

See index.js for the full exported surface: searchSkills (raw API call), searchOnePage / searchPages (cache-aware, hasNext-driven pagination), resolveConfig, cache helpers, duration parsing, and explainError.

Exit codes

  • 0 — success
  • 1 — usage error or API error (invalid key, bad occupation/language slug, etc.)
  • 2 — daily quota exceeded

Errors

API error codes are translated into actionable messages rather than printed raw:

| Code | CLI behavior | |---|---| | INVALID_API_KEY | Suggests skillsmp logout + skillsmp login, or unsetting SKILLSMP_API_KEY | | MISSING_QUERY | Usage hint with an example | | INVALID_OCCUPATION / INVALID_LANGUAGE | Surfaces the API's message about the bad slug | | DAILY_QUOTA_EXCEEDED | States the 50/day anonymous vs 500/day keyed limits and points at skillsmp login; exit code 2 | | INTERNAL_ERROR | Suggests retrying |

Network failures, timeouts, and malformed JSON responses are also caught and reported as plain error messages — never a stack trace.

Testing

npm test

Runs the built-in node:test suite. All network calls are stubbed (a fake fetch implementation is injected); the suite makes no real requests.

License

MIT