Skip to content
Skill Authoring
Skill

/npmjs

npm package maintenance and lifecycle management for monorepo extensions. Covers health audits, dependency sync, version bumping, changelog updates, pre-publish checks, coordinated publishing, and post-publish verification. **Triggers — use this skill when:** - User asks to

BOOST
From plugin
pi
12238 skills5 agents
Install
$ npx -y skills add espennilsen/pi --skill npmjs --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/npmjs

Context preview

The summary Claude sees to decide when to auto-load this skill.

npm package maintenance and lifecycle management for monorepo extensions. Covers health audits, dependency sync, version bumping, changelog updates, pre-publish checks, coordinated publishing, and post-publish verification. **Triggers — use this skill when:** - User asks to

SKILL.md

npmjs.SKILL.md
name: npmjs
description: >
  npm package maintenance and lifecycle management for monorepo extensions.
  Covers health audits, dependency sync, version bumping, changelog updates,
  pre-publish checks, coordinated publishing, and post-publish verification.

  **Triggers — use this skill when:**
  - User asks to "publish", "release", or "version bump" extensions/packages
  - User says "audit packages", "check package health", "dependency sync"
  - User asks to "update changelogs", "prepare release", "pre-publish check"
  - User mentions "npm publish", "version management", "package lifecycle"
  - User wants to "sync dependencies" or "align versions" across packages
  - User asks "what needs publishing" or "which packages changed"

  **Covers:** Monorepo with multiple npm packages under `extensions/`.
  Each package has its own package.json, CHANGELOG.md, README.md, and version.
  Packages are scoped (e.g. `@e9n/pi-*`) and published individually.

npmjs — Package Maintenance & Lifecycle Management

Manage npm packages in a monorepo: audit health, sync dependencies, bump versions, update changelogs, run pre-publish checks, and coordinate publishing.

---

Commands Reference

Health & Audit

# List all extension packages with versions and private status
for ext in extensions/pi-*/; do
  name=$(basename "$ext")
  pkg=$(cat "$ext/package.json")
  version=$(echo "$pkg" | jq -r '.version')
  private=$(echo "$pkg" | jq -r '.private // false')
  echo "$name@$version (private: $private)"
done

# Check what's published vs local
for ext in extensions/pi-*/; do
  local_name=$(cat "$ext/package.json" | jq -r '.name')
  local_ver=$(cat "$ext/package.json" | jq -r '.version')
  private=$(cat "$ext/package.json" | jq -r '.private // false')
  [ "$private" = "true" ] && continue
  remote_ver=$(npm view "$local_name" version 2>/dev/null || echo "not published")
  status="✅"
  [ "$local_ver" != "$remote_ver" ] && status="⚠️  local=$local_ver npm=$remote_ver"
  echo "$local_name $status"
done

# Full dependency audit
for ext in extensions/pi-*/; do
  name=$(basename "$ext")
  # Check for missing imports (imported but not declared)
  imports=$(grep -rh "from ['\"]@" "$ext/src/" 2>/dev/null | sed "s/.*from ['\"]//;s/['\"].*//" | grep "^@" | sort -u)
  for imp in $imports; do
    in_deps=$(cat "$ext/package.json" | jq -r --arg p "$imp" '(.dependencies // {})[$p] // (.peerDependencies // {})[$p] // empty')
    [ -z "$in_deps" ] && echo "MISSING: $name imports $imp"
  done
  # Check for unused deps (declared but not imported)
  deps=$(cat "$ext/package.json" | jq -r '.dependencies // {} | keys[]' 2>/dev/null)
  for dep in $deps; do
    grep -rq "from ['\"]$dep\|require(['\"]$dep\|import(['\"]$dep" "$ext/src/" 2>/dev/null || \
      echo "UNUSED: $name has $dep in dependencies"
  done
done

# Check for phantom peer deps
for ext in extensions/pi-*/; do
  name=$(basename "$ext")
  peers=$(cat "$ext/package.json" | jq -r '.peerDependencies // {} | keys[]' 2>/dev/null)
  for peer in $peers; do
    grep -rq "from ['\"]$peer" "$ext/src/" 2>/dev/null || \
      echo "PHANTOM PEER: $name declares $peer but never imports it"
  done
done

# Shared dependency version consistency
echo "=== Dependency Version Report ==="
for ext in extensions/pi-*/; do
  cat "$ext/package.json" | jq -r --arg ext "$(basename "$ext")" \
    '.dependencies // {} | to_entries[] | "\(.key) \(.value) \($ext)"'
done | sort | awk '{
  key=$1; ver=$2; ext=$3
  if (key != prev) { if (prev && count > 1 && versions > 1) print ""; prev=key; count=0; versions=0; delete seen }
  if (!seen[ver]) { seen[ver]=1; versions++ }
  count++
  print "  " ext ": " key "@" ver
}'

Detecting Changed Packages

# Find extensions with changes since last publish (compare to npm registry)
for ext in extensions/pi-*/; do
  name=$(cat "$ext/package.json" | jq -r '.name')
  private=$(cat "$ext/package.json" | jq -r '.private // false')
  [ "$private" = "true" ] && continue
  version=$(cat "$ext/package.json" | jq -r '.version')
  # Check git diff since last tag or version bump
  last_tag=$(git tag -l "${name}@*" --sort=-creatordate | head -1)
  if [ -z "$last_tag" ]; then
    echo "NEW: $name@$version (never tagged)"
  else
    changes=$(git diff --name-only "$last_tag" -- "$ext" 2>/dev/null | grep -v 'CHANGELOG\|README\|AGENTS' | head -5)
    [ -n "$changes" ] && echo "CHANGED: $name ($last_tag → now)" && echo "$changes" | sed 's/^/  /'
  fi
done

# Simpler: find extensions with uncommitted or recent source changes
for ext in extensions/pi-*/; do
  name=$(basename "$ext")
  # Check for source changes in last N commits
  changes=$(git log --oneline -10 -- "$ext/src/" | head -5)
  [ -n "$changes" ] && echo "$name:" && echo "$changes" | sed 's/^/  /'
done

---

Lifecycle Operations

1. Pre-publish Checks

Run these before every publish. All must pass.

EXTENSION="pi-example"  # Set target

# 1. TypeScript check
cd "extensions/$EXTENSION" && npx tsc --noEmit

# 2. Required files exist
for f in README.md CHANGELOG.md package.json .npmignore; do
  [ -f "extensions/$EXTENSION/$f" ] || echo "MISSING: $f"
done

# 3. Package.json has required fields
cat "extensions/$EXTENSION/package.json" | jq '{
  name: .name,
  version: .version,
  description: .description,
  license: .license,
  author: .author,
  keywords: .keywords,
  files: .files,
  repository: .repository,
  pi: .pi
}' | jq 'to_entries[] | select(.value == null or .value == "") | "MISSING: \(.key)"' -r

# 4. Verify tarball contents (dry run)
cd "extensions/$EXTENSION" && npm pack --dry-run

# 5. No AGENTS.md in tarball (should be in .npmignore)
grep -q "AGENTS.md" "extensions/$EXTENSION/.npmignore" || echo "WARNING: AGENTS.md not in .npmignore"

**Batch pre-publish check for all packages:**

failed=0
for ext in extensions/pi-*/; do
  name=$(basename "$ext")
  private=$(cat "$ext/package.json" | jq -r '.private // false')
  [ "$private" = "true" ] && continue
Read more
Ships withpi

This repository is my Pi coding agent home directory. I keep it under version control and symlink it to ~/.pi/agent so Pi loads configuration, extensions, skills, and runtime state from here.

Get the whole plugin

Other skills on pi.