Track weekly npm downloads across all your packages

Every Monday: last week's npm downloads summed across your packages, the change against the week before, and the package that moved most.

Runs
Mondays at 9:00
Uses
npm
Posts
Stat tile

From your apps to your board

How the skill works: your agent reads last week from npm; packages from What you tell it, mondays at 9:00, and gives you weekly downloads, all packages and the report in the chat.

Reads

  • npmLast week
  • What you tell itPackages
reads
Your agentClaude Code, Codex, Cursor or GeminiMondays at 9:00
posts

You get

  • Weekly downloads, all packagesA stat tile on your board, with its trend
  • The report in the chatEvery run, with or without Briefkin

What you get

  • Downloads last week across all packages, and the change.
  • Per package: downloads and change, largest first.
  • Biggest mover, up or down, with a likely reason if one is visible (a release, a dependent that added you).
  • An 8-week trend of the total.

The card on the right is a sample. Yours shows your own numbers and updates in place every run.

What lands on your board

acmeWeekly downloads, all packages48,920+9% vs previous period, bettervs last report
vs week before9.4%
Packages6
Top mover@acme/cli
An example with made-up numbers. Your agent posts your real ones.

What it does

npmjs.com shows one package's weekly downloads in a small sparkline, and that number is a rolling 7 days, so it changes every time you look. With five packages under a scope, getting one honest week-over-week figure means a spreadsheet.

The agent asks the public npm downloads API for fixed Monday-to-Sunday weeks, so this Monday's number never moves, sums every package and ranks them by change. It needs no token: download counts are public. Maintainers use it to see whether a release or a blog post moved adoption; founders use it as the open-source line in the weekly update.

How it works

  1. 1

    1List your packages

    Use the list in the prompt, or npm access list packages <user-or-scope> --json for everything a user or scope publishes. Leave out deprecated packages unless you want them counted.

  2. 2Count last week

    GET https://api.npmjs.org/downloads/point/<monday>:<sunday>/<package> with last week's dates (UTC, both inclusive). Unscoped packages can go in one call, comma-separated, up to 128 at a time; scoped ones like @acme/cli need one call each.

  3. 3Count the week before and the daily shape

    Repeat for the previous Monday to Sunday. For the chart, GET https://api.npmjs.org/downloads/range/<start>:<end>/<package> returns one row per day; 8 weeks is plenty.

  4. 4

    4Report

    Total downloads and the change, one row per package with its count and change, and the biggest mover in either direction. A drop on one package right after a release can mean a broken version; say so if the dates line up.

  5. Post it to the board

    With BRIEFKIN_TOKEN set, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.

Install and run it

Pick your agent, where the data comes from and how to schedule it; the commands below follow.

Agent
Data
Schedule
  1. Install the skill

    One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.

    shellcurl -fsSL https://briefkin.dev/skills/npm-weekly-downloads/install | sh
  2. Run it

    Ask Claude Code:

    promptRun the npm-weekly-downloads skill

    Or paste the prompt instead of installing:

    promptUsing the public npm downloads API (https://api.npmjs.org, no token), get last week's downloads, Monday to Sunday in UTC, for each of my packages: <list or scope>. Use /downloads/point/<start>:<end>/<package>; unscoped packages can be batched comma-separated, scoped packages need one call each. Do the same for the week before. Give me the total and its change in percent, one row per package with downloads and change sorted by downloads, and the biggest mover up and down. If a package dropped sharply, check whether a new version was published that week and mention it. Finish with the weekly totals for the last 8 weeks.
  3. Put it on a schedule

    Mondays at 9:00, from cron on any machine where Claude Code is signed in:

    crontab0 9 * * 1 claude -p "Run the npm-weekly-downloads skill"

    Add it with crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.

  4. Send it to your board

    Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a stat tile. How setup works

View the SKILL.mdRaw file
SKILL.md---
name: npm-weekly-downloads
description: "Every Monday: last week's npm downloads summed across your packages, the change against the week before, and the package that moved most. Use when the user asks for this, or when it runs on a schedule."
---

# npm weekly downloads

Every Monday: last week's npm downloads summed across your packages, the change against the week before, and the package that moved most.

npmjs.com shows one package's weekly downloads in a small sparkline, and that number is a rolling 7 days, so it changes every time you look. With five packages under a scope, getting one honest week-over-week figure means a spreadsheet.

The agent asks the public npm downloads API for fixed Monday-to-Sunday weeks, so this Monday's number never moves, sums every package and ranks them by change. It needs no token: download counts are public. Maintainers use it to see whether a release or a blog post moved adoption; founders use it as the open-source line in the weekly update.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- Nothing secret: the downloads API at `api.npmjs.org` is public and needs no token.
- The npm CLI only if you want the agent to find your packages with `npm access list packages`.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **List your packages**: Use the list in the prompt, or `npm access list packages <user-or-scope> --json` for everything a user or scope publishes. Leave out deprecated packages unless you want them counted.
2. **Count last week** (npm): `GET https://api.npmjs.org/downloads/point/<monday>:<sunday>/<package>` with last week's dates (UTC, both inclusive). Unscoped packages can go in one call, comma-separated, up to 128 at a time; scoped ones like `@acme/cli` need one call each.
3. **Count the week before and the daily shape** (npm): Repeat for the previous Monday to Sunday. For the chart, `GET https://api.npmjs.org/downloads/range/<start>:<end>/<package>` returns one row per day; 8 weeks is plenty.
4. **Report**: Total downloads and the change, one row per package with its count and change, and the biggest mover in either direction. A drop on one package right after a release can mean a broken version; say so if the dates line up.

## Route B: the browser

### What you need

- No sign-in: download counts are public. A signed-in npm session only helps the agent find your packages from your profile.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://www.npmjs.com/. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **List the packages**: Open your profile at `https://www.npmjs.com/~<username>` or the scope at `https://www.npmjs.com/org/<scope>` and read the **Packages** tab for the names. Skip packages marked deprecated unless you want them counted.
2. **Read last week's count per package**: The download counts are public JSON that opens in any tab: `https://api.npmjs.org/downloads/point/<last Monday>:<last Sunday>/<package>` with UTC dates, for example `2026-10-05:2026-10-11`. Read the `downloads` number. Unscoped names can be joined with commas in one URL; scoped names like `@acme/cli` need their own.
3. **Read the week before and the trend**: Change the dates to the previous Monday to Sunday and read again. For the 8-week trend, open `https://api.npmjs.org/downloads/range/<8 Mondays ago>:<last Sunday>/<package>` and add the daily rows up by week.
4. **Report**: Total downloads and the change, one row per package largest first with its change, and the biggest mover each way. If a package dropped sharply, open its npmjs.com page and check the **Versions** tab for a release that week.

Note: The **Weekly Downloads** figure on an npmjs.com package page is a rolling 7 days, so it never matches a fixed week; the JSON URLs above are the same data npmjs.com draws from and give fixed weeks. Each day is final shortly after midnight UTC.

## The report

- **Downloads last week** across all packages, and the change.
- **Per package**: downloads and change, largest first.
- **Biggest mover**, up or down, with a likely reason if one is visible (a release, a dependent that added you).
- An 8-week trend of the total.

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "npm-weekly-downloads/<date of this run, e.g. 2026-10-16>",
  "item_key": "npm-weekly-downloads",
  "project": "acme",
  "source": "npm weekly downloads skill",
  "kind": "metric",
  "title": "48,920 downloads last week, up 9.4%",
  "metric": {
    "label": "Weekly downloads, all packages",
    "value": 48920,
    "better": "higher",
    "period_start": "<start of the period, ISO 8601>",
    "period_end": "<end of the period, ISO 8601>"
  },
  "glance": [
    {
      "type": "Grid",
      "props": {
        "columns": 3
      },
      "children": [
        {
          "type": "Stat",
          "props": {
            "label": "vs week before",
            "value": 9.4,
            "unit": "%"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Packages",
            "value": 6
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Top mover",
            "value": "@acme/cli"
          }
        }
      ]
    }
  ],
  "widget": [
    {
      "type": "Table",
      "props": {
        "columns": [
          "Package",
          "Last week",
          "Change"
        ],
        "align": [
          "left",
          "right",
          "right"
        ],
        "rows": [
          [
            "acme-ui",
            "21,480",
            "+6%"
          ],
          [
            "@acme/cli",
            "12,310",
            "+18%"
          ],
          [
            "acme-hooks",
            "8,920",
            "+2%"
          ],
          [
            "@acme/eslint-config",
            "4,105",
            "+31%"
          ],
          [
            "acme-icons",
            "1,640",
            "-4%"
          ],
          [
            "@acme/legacy-client",
            "465",
            "-22%"
          ]
        ]
      }
    },
    {
      "type": "Callout",
      "props": {
        "text": "@acme/cli grew 18% after the 3.0 release on Tuesday. @acme/legacy-client keeps falling as users move to the new client.",
        "tone": "info"
      }
    }
  ],
  "size": "md"
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).

## Run it on a schedule

Suggested: Mondays at 9:00 (`0 9 * * 1`). From cron, with the agent signed in on that machine:

```bash
0 9 * * 1 claude -p "Run the npm-weekly-downloads skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/npm-weekly-downloads#schedule

Source: https://briefkin.dev/skills/npm-weekly-downloads

What your agent needs

  • Nothing secret: the downloads API at api.npmjs.org is public and needs no token.

  • The npm CLI only if you want the agent to find your packages with npm access list packages.

Connecting npm

  1. MCP server. npm doesn't publish an official MCP server for the registry, and an agent with a shell doesn't need one: the npm CLI and the public endpoints cover these reports. Community servers that search the registry exist, and GitHub's MCP server covers Dependabot alerts for repositories on GitHub.
  2. npm CLI and public APIs. Run npm outdated --json, npm audit --json and npm view <package> time --json in the project, and curl the registry and downloads API; public packages need no token.
  3. Granular access token for private packages. Create a granular access token on npmjs.com with Read-only permission on just the packages or organization the report covers, store it in NPM_TOKEN, and reference it in .npmrc as //registry.npmjs.org/:_authToken=${NPM_TOKEN}.

A read-only granular token can install and inspect packages but never publish; don't reuse a publish token for reports.

Questions

Why fixed weeks instead of last-week?

last-week means the last 7 available days, so the number shifts daily and two runs on different days disagree. Fixed Monday-to-Sunday dates give each week one value that never changes, which is what a trend needs. npm processes each UTC day shortly after midnight, so Monday morning has the full week.

Do download counts mean users?

No. They count tarball downloads, including CI runs, mirrors and bots, and a cached install counts zero. Treat the number as a trend: a steady rise means more projects depend on you, and a flat week after a release is worth a look.

Do I need Briefkin to use the npm weekly downloads skill?

No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a stat tile, so you can glance at it instead of asking again.

Which agents can run it?

Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.

Can it work without an API or MCP server, from my browser?

Yes. Switch the data source to "Your browser" and the steps change to the npm pages themselves: the agent opens www.npmjs.com in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.

Watch weekly downloads, all packages on your board, run after run

Skills are free to use with any agent. Briefkin is where their results land: one board for every report, number and question your agents send, with a ping when something needs you.

Free during the open beta. No card.