check-npm — Claude Code skill: audit npm, yarn and pnpm
Reads a JS/TS repo's package manager config and flags supply-chain gaps: tool version, lifecycle scripts, unsafe dependency protocols and release age.
npx skills add grafana/skills --skill check-npm -a claude-codeWhat check-npm does
The skill audits the workspace root and touches nothing. It first works out which package manager you use: the packageManager field in package.json, then a lockfile, otherwise npm. No package.json means it stops right there.
Four checks follow. The tool version has to clear a threshold: npm 11.15.0, yarn 4.14.0, pnpm 11.0.0. Then it looks for disabled lifecycle scripts — ignore-scripts=true on npm, enableScripts: false on yarn, strictDepBuilds on pnpm. Manifests get scanned for unsafe protocols: git URLs, tarballs, file:, link: and the rest. The last check is a minimum release age of 3 days, or 4320 minutes.
You get a table of PASS and FAIL rows plus paste-ready config snippets for every failure. One thing to watch: pnpm 11 and later ignore script settings in .npmrc and package.json#pnpm, so those lines do nothing there. When everything passes, the skill says so and stops.
What it helps with
- confirm dependency lifecycle scripts are turned off
- spot git URLs and tarballs hiding in dependencies
- check that npm or pnpm meets the minimum version
- set a 3-day minimum release age
- grab ready config lines for whatever failed
Example prompts for the agent
- audit this repo's npm config for supply-chain risks
- run the package manager audit and show me the PASS/FAIL table
- check whether lifecycle scripts are disabled and whether any git dependencies exist
How to install check-npm
1Skills CLI (Vercel)
npx skills add grafana/skills --skill check-npm -a claude-code2Manually: put the files in place
~/.claude/skills/check-npm/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/check-npm/
1Skills CLI (Vercel)
npx skills add grafana/skills --skill check-npm -a codex2Manually: put the files in place
.agents/skills/check-npm/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add grafana/skills --skill check-npm -a cursor2Manually: put the files in place
.cursor/skills/check-npm/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install grafana/skills check-npm2Manually: put the files in place
.github/skills/check-npm/SKILL.md1Skills CLI (Vercel)
npx skills add grafana/skills --skill check-npm -a gemini-cli2Platform CLI
gemini skills install https://github.com/grafana/skills --path skills/grafana-plugins/check-npmManually: put the files in place
.devin/skills/check-npm/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add grafana/skills --skill check-npm -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about check-npm
How do I install check-npm in Claude?
Run npx skills add grafana/skills --skill check-npm -a claude-code. The skill lands at ~/.claude/skills/check-npm/SKILL.md.
What does check-npm do?
It checks an npm, yarn or pnpm setup on four points: tool version, disabled lifecycle scripts, unsafe dependency protocols, and a minimum release age of at least 3 days. It only reads files.
Why do .npmrc script settings not work on pnpm 11?
pnpm 11 and later ignore script settings in .npmrc and package.json#pnpm. Those checks and fixes belong in pnpm-workspace.yaml.
Source text
SKILL.md · Apache-2.0
---
name: check-npm
license: Apache-2.0
disable-model-invocation: false
description: >-
Audit a JavaScript/TypeScript repo's npm, yarn, or pnpm configuration for
supply-chain hardening: tool version, lifecycle scripts, unsafe dependency
protocols, and minimum release age ≥3 days. Use when the user invokes
/check-npm or asks to audit package manager security, lifecycle scripts, git
dependencies, ignore-scripts, min-release-age, allow-git,
approvedGitRepositories, strictDepBuilds, or blockExoticSubdeps in a Grafana
plugin or JS/TS project.
---
# npm / yarn / pnpm supply-chain audit
Read-only audit of the workspace root. Do not modify any files.
## 0. Detect package manager
```bash
test -f package.json || { echo "STOP: no package.json at workspace root"; exit 1; }
jq -r '.packageManager // "unset"' package.json
ls -1 yarn.lock package-lock.json pnpm-lock.yaml 2>/dev/null || true
```
If no `package.json`, stop. Priority: `packageManager` → lockfile → default npm.
## 1. Tool version
```bash
npm --version # required ≥ 11.15.0
yarn --version # required ≥ 4.14.0
pnpm --version # required ≥ 11.0.0
```
Use semver comparison. Verify pinned `packageManager` meets threshold.
| Manager | Minimum |
|---------|---------|
| npm | 11.15.0 |
| yarn | 4.14.0 |
| pnpm | 11.0.0 |
## 2. Lifecycle scripts disabled
```bash
grep -E '^ignore-scripts=' .npmrc 2>/dev/null
grep -E 'enableScripts:' .yarnrc.yml 2>/dev/null
grep -E 'strictDepBuilds:|dangerouslyAllowAllBuilds:|allowBuilds:' pnpm-workspace.yaml 2>/dev/null
```
| Manager | PASS | FAIL |
|---------|------|------|
| npm | `.npmrc` has `ignore-scripts=true` | missing or `false` |
| yarn | `enableScripts: false` or key absent | `enableScripts: true` |
| pnpm ≥ 11 | `strictDepBuilds` unset/`true`, `dangerouslyAllowAllBuilds` unset/`false`, and `allowBuilds` unset/`[]` | `strictDepBuilds: false`, `dangerouslyAllowAllBuilds: true`, or `allowBuilds` non-empty |
| pnpm 10 | `.npmrc` `ignore-scripts=true` OR `strictDepBuilds: true` | neither |
pnpm 11+ ignores script settings in `.npmrc` and `package.json#pnpm`. pnpm 10 / yarn edge cases: [references/managers.md](references/managers.md).
## 3. Unsafe dependency protocols
Registry:
```bash
grep -E '^allow-git=' .npmrc 2>/dev/null
grep -E 'approvedGitRepositories:' .yarnrc.yml 2>/dev/null
grep -E 'blockExoticSubdeps:' pnpm-workspace.yaml 2>/dev/null
```
Scan workspace `package.json` files (`dependencies`, `devDependencies`, `optionalDependencies`, `peerDependencies`). Prefer workspace-member discovery (pnpm-workspace.yaml / root workspaces / lerna / rush) per [references/protocols.md](references/protocols.md), then scan only those manifests. Fallback (may overmatch non-workspace manifests):
find . -name package.json -not -path '*/node_modules/*'
**Safe values only:** semver range, `workspace:`, `patch:`, `npm:` alias to semver. Flag everything else (git URLs, tarballs, `user/repo` shorthand, `file:`, `link:`, `exec:`, …) as `path → name → value (protocol)`.
| Manager | PASS | FAIL |
|---------|------|------|
| npm | `allow-git=none` or `root` | missing or `all` |
| yarn | `approvedGitRepositories: []` or grafana-scoped list, or omitted with policy comment + clean scan | unsafe entries or broad allow-list |
| pnpm ≥ 11 | `blockExoticSubdeps` unset/`true` | `false` |
| pnpm 10.x | `blockExoticSubdeps: true` | unset (default `false`) or `false` |
Protocol detection order and yarn posture details: [references/protocols.md](references/protocols.md).
## 4. Minimum release age ≥ 3 days
3 days = 4320 minutes. npm uses **days**; yarn and pnpm use **minutes**.
```bash
grep -E '^min(imum)?-release-age=' .npmrc 2>/dev/null
grep -E 'npmMinimalAgeGate:' .yarnrc.yml 2>/dev/null
grep -E 'minimumReleaseAge:|minimumReleaseAgeStrict:' pnpm-workspace.yaml 2>/dev/null
```
| Manager | PASS | FAIL |
|---------|------|------|
| npm | `min-release-age` ≥ `3` | missing |
| yarn | `npmMinimalAgeGate` ≥ 4320 min | missing or below |
| pnpm ≥ 11 | `minimumReleaseAge` ≥ `4320` | unset (default `1440`) or below |
| pnpm 10 | `minimum-release-age` / `minimumReleaseAge` ≥ `4320` | missing |
Flag `minimumReleaseAgeStrict: false` on pnpm 11.
## 5. Report
| # | Check | Status | Detail |
|---|---|---|---|
| 0 | Package manager | (npm / yarn / pnpm) | version: x.y.z (pinned: y.y.y if set) |
| 1 | Tool version ≥ threshold | PASS / FAIL | `actual` vs `required` |
| 2 | Scripts disabled | PASS / FAIL | config line or "missing" |
| 3 | Unsafe dep protocols | PASS / FAIL | registry state + flagged entries |
| 4 | Min release age ≥ 3 days | PASS / FAIL | config + value |
Use `PASS` / `FAIL` only — no emojis.
For each FAIL, one paste-ready fix:
```ini
# npm — .npmrc
ignore-scripts=true
allow-git=none
min-release-age=3
```
```yaml
# pnpm 11 — pnpm-workspace.yaml
strictDepBuilds: true
dangerouslyAllowAllBuilds: false
allowBuilds: []
minimumReleaseAge: 4320
blockExoticSubdeps: true
```
```yaml
# yarn — .yarnrc.yml
npmMinimalAgeGate: 4320
```
More fixes (tool upgrades, yarn git allow-list, pnpm 10): [references/fix-snippets.md](references/fix-snippets.md).
If all PASS: "All checks passed." and stop.
© grafana · Apache-2.0 · grafana/skills