pi-heartbeat
Configure periodic health checks via HEARTBEAT.md and the /heartbeat command.
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
$ npx -y skills add espennilsen/pi --skill npmjs --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/npmjsContext 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
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.
Manage npm packages in a monorepo: audit health, sync dependencies, bump versions, update changelogs, run pre-publish checks, and coordinate publishing.
---
# 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
}'# 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---
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
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.
Configure periodic health checks via HEARTBEAT.md and the /heartbeat command.
Manage persistent memory across sessions. Use when asked to remember, recall, forget, or review what was stored. Covers long-term…
Track and manage projects with git status via dashboard and tool.
Delegate tasks to specialized subagents for parallel or sequential execution.
Audit, generate, update, and lint AGENTS.md files across all projects. Use when asked to check project context files, scaffold…