Scans your project for outdated npm, pip, Cargo, Go, or Ruby packages. Runs a CVE security audit. Fetches changelogs, summarizes breaking changes with Gemini, and opens one PR per risk group (patch, minor, major). Includes Diagnosis Mode for install conflicts. Use when asked to update dependencies, check for outdated packages, open dependency PRs, scan for package updates, audit for CVEs, or flag breaking changes in upgrades. Trigger when a user says "check for outdated packages", "update my dependencies", "open PRs for dependency updates", "scan for CVEs", or "which packages need upgrading".
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Scans your project for outdated npm, pip, Cargo, Go, or Ruby packages. Runs a CVE security audit. Fetches changelogs, summarizes breaking changes with Gemini, and opens one PR per risk group (patch, minor, major). Includes Diagnosis Mode for install conflicts. Use when asked to update dependencies, check for outdated packages, open dependency PRs, scan for package updates, audit for CVEs, or flag breaking changes in upgrades. Trigger when a user says "check for outdated packages", "update my dependencies", "open PRs for dependency updates", "scan for CVEs", or "which packages need upgrading".
compatibility
["claude-code","gemini-cli","github-copilot"]
author
OpenDirectory
version
1.0.0
Dependency Update Bot
Scan for outdated packages. Run a security audit. Fetch changelogs. Summarize breaking changes. Open one PR per risk group.
Critical rule: Only update packages that the package manager's outdated command actually reports. Never guess or invent version numbers. If a changelog cannot be fetched, note the gap rather than inventing content.
Step 1: Setup Check
echo"GEMINI_API_KEY: "
gh auth status 2>/dev/null | -1 ||
${GEMINI_API_KEY:+set}
echo
"GITHUB_TOKEN: ${GITHUB_TOKEN:-not set, changelog fetching rate-limited to 60/hour}"
head
echo
"gh: not authenticated"
If GEMINI_API_KEY is missing: Stop. Tell the user: "GEMINI_API_KEY is required. Get it at aistudio.google.com. Add it to your .env file."
If gh is not authenticated: Stop. Tell the user: "GitHub CLI must be authenticated. Run: gh auth login"
If multiple are found, ask: "Found [list]. Which should I scan? (all / npm / pip / cargo / go / ruby)"
Step 2: Detect Outdated Packages
npm:
npm outdated --json --long 2>/dev/null | python3 -c "
import sys, json
data = json.load(sys.stdin)
for name, info in data.items():
print(json.dumps({'name': name, 'current': info.get('current','?'), 'latest': info.get('latest','?'), 'dep_type': info.get('type','dependencies')}))
"
pip:
pip list --outdated --format=json 2>/dev/null | python3 -c "
import sys, json
for p in json.load(sys.stdin):
print(json.dumps({'name': p['name'], 'current': p['version'], 'latest': p['latest_version']}))
"
Cargo (Rust):
cargo outdated --format json 2>/dev/null || \
cargo outdated 2>/dev/null | grep -v "^---" | tail -n +3 | head -30
# If cargo-outdated not installed: cargo install cargo-outdated
Go modules:
go list -u -m -json all 2>/dev/null | python3 -c "
import sys, json
decoder = json.JSONDecoder()
buf = sys.stdin.read()
pos = 0
while pos < len(buf):
try:
obj, idx = decoder.raw_decode(buf, pos)
if obj.get('Update'):
print(json.dumps({'name': obj['Path'], 'current': obj['Version'], 'latest': obj['Update']['Version']}))
pos += idx
except: break
"
Ruby (Bundler):
bundle outdated --parseable 2>/dev/null | python3 -c "
import sys
for line in sys.stdin:
parts = line.strip().split()
if len(parts) >= 4:
print('{\"name\":\"' + parts[0] + '\",\"current\":\"' + parts[3].strip('()') + '\",\"latest\":\"' + parts[1] + '\"}')
"
If all return empty: "All packages are up to date." Stop.
State count before proceeding: "Found X outdated packages."
Step 3: Classify by Risk Level
Parse version bump (current → latest):
MAJOR: first digit changed (1.x.x → 2.x.x)
MINOR: second digit changed (1.2.x → 1.3.x)
PATCH: third digit changed (1.2.3 → 1.2.4)
python3 -c "
def classify(current, latest):
try:
c = [int(x) for x in current.lstrip('v').split('.')[:3]]
l = [int(x) for x in latest.lstrip('v').split('.')[:3]]
if l[0] > c[0]: return 'major'
if len(l) > 1 and len(c) > 1 and l[1] > c[1]: return 'minor'
return 'patch'
except: return 'unknown'
"
State the breakdown: "Patch: X packages. Minor: Y packages. Major: Z packages."
Step 4: Security Audit
Run a CVE scan before creating any PRs. This determines urgency.
npm:
npm audit --json 2>/dev/null | python3 -c "
import sys, json
d = json.load(sys.stdin)
vulns = d.get('vulnerabilities', {})
for pkg, info in vulns.items():
sev = info.get('severity', 'unknown')
via = [v.get('title','') for v in info.get('via',[]) if isinstance(v, dict)]
print(f' [{sev.upper()}] {pkg}: {via[0] if via else \"see npm audit\"}')
" 2>/dev/null || echo"No vulnerabilities found or npm audit not available"
pip:
pip-audit --format=json 2>/dev/null | python3 -c "
import sys, json
for vuln in json.load(sys.stdin):
print(f' [{vuln.get(\"aliases\",[\"\"])[0]}] {vuln[\"name\"]} {vuln[\"version\"]}: {vuln[\"description\"][:80]}')
" 2>/dev/null || echo"pip-audit not installed. Run: pip install pip-audit"
Cargo:
cargo audit 2>/dev/null | grep -E "^(ID|Package|Severity|URL)" | head -30 \
|| echo"cargo-audit not installed. Run: cargo install cargo-audit"
Escalation rule: If a PATCH or MINOR update has a Critical or High CVE, promote it to MAJOR priority: it gets its own PR and the CVE details go in the PR body.
If no source returns content: note "No changelog found" and continue.
Step 6: Summarize with Gemini
One request per risk group. Include security findings for any CVE-affected packages:
cat > /tmp/deps-summary-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "You are a developer writing a GitHub PR description for a dependency update. Given a list of packages being updated and their raw changelog content, write a concise PR body in Markdown. Rules: For each package, list only what changed between the OLD version and the NEW version. Use bullet points. Flag breaking changes with a BREAKING prefix. Flag CVE fixes with a SECURITY prefix and include the CVE ID. Keep each package section to 3-5 bullets maximum. If no changelog was found for a package, write 'No changelog available.' Do not use em dashes. Do not use these words: seamless, robust, leverage, transform, innovative. Output only the Markdown PR body, no commentary."
}]
},
"contents": [{
"parts": [{
"text": "PACKAGES_AND_CHANGELOGS_HERE"
}]
}],
"generationConfig": {
"temperature": 0.2,
"maxOutputTokens": 2048
}
}
ENDJSON
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/deps-summary-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
Step 7: Create PRs
One PR per non-empty risk group. One PR per package for major updates (individual review required).