Up To Date Rule Before writing ANY code that touches an external package or API, fetch the real documentation first. Never rely on training data — it is stale by definition. When This Triggers - Installing a package ( , , ) - Importing or using any third-party library - Calling any external API (REST, GraphQL, SDK methods) - Modifying existing integration code - Debugging API calls that silently fail Mandatory Steps 1. Check Version Update if more than 1 major version behind. 2. Fetch Real Docs (pick one or more) Context7 (preferred for popular libraries): Browser ( ): DeepWiki (if available)…

)\n\n\ndef validate_package_name(name: str) -> str:\n \"\"\"Validate and sanitize package name to prevent path traversal and injection.\"\"\"\n name = name.strip()\n if not name:\n print(\"❌ Package name cannot be empty\")\n sys.exit(1)\n if '..' in name or name.startswith('/') or name.startswith('\\\\'):\n print(f\"❌ Invalid package name (path traversal detected): {name}\")\n sys.exit(1)\n if not VALID_PACKAGE_RE.match(name):\n print(f\"❌ Invalid package name: {name}\")\n print(\" Expected format: 'package-name' or '@scope/package-name'\")\n sys.exit(1)\n return name\n\n\ndef run_cmd(cmd: List[str]) -> Optional[str]:\n \"\"\"Run a command and return stdout, or None on failure.\"\"\"\n try:\n result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)\n return result.stdout.strip() if result.returncode == 0 else None\n except (subprocess.TimeoutExpired, FileNotFoundError):\n return None\n\n\ndef parse_semver(version: str) -> Optional[Tuple[int, int, int]]:\n \"\"\"Parse a semver string into (major, minor, patch).\"\"\"\n match = re.match(r'(\\d+)\\.(\\d+)\\.(\\d+)', version.strip().lstrip('v^~>=\u003c'))\n if match:\n return int(match.group(1)), int(match.group(2)), int(match.group(3))\n return None\n\n\ndef check_npm(package: str) -> Dict[str, Optional[str]]:\n \"\"\"Check npm package version.\"\"\"\n package = validate_package_name(package)\n\n # Installed version — resolve path and verify it stays within node_modules\n installed = None\n pkg_json = Path(\"node_modules\", package, \"package.json\").resolve()\n node_modules_root = Path(\"node_modules\").resolve()\n if not str(pkg_json).startswith(str(node_modules_root)):\n print(f\"❌ Path traversal blocked: {package}\")\n sys.exit(1)\n if pkg_json.exists():\n try:\n data = json.loads(pkg_json.read_text())\n installed = data.get(\"version\")\n except (json.JSONDecodeError, IOError):\n pass\n\n # Latest version\n latest = run_cmd([\"npm\", \"info\", package, \"version\"])\n\n return {\"package\": package, \"manager\": \"npm\", \"installed\": installed, \"latest\": latest}\n\n\ndef check_pip(package: str) -> Dict[str, Optional[str]]:\n \"\"\"Check pip package version.\"\"\"\n package = validate_package_name(package)\n # Installed version\n installed = None\n output = run_cmd([\"pip\", \"show\", package])\n if output:\n for line in output.split(\"\\n\"):\n if line.startswith(\"Version:\"):\n installed = line.split(\":\", 1)[1].strip()\n break\n\n # Latest version\n latest = None\n output = run_cmd([\"pip\", \"index\", \"versions\", package])\n if output:\n match = re.search(r'\\((.+?)\\)', output)\n if match:\n latest = match.group(1)\n\n return {\"package\": package, \"manager\": \"pip\", \"installed\": installed, \"latest\": latest}\n\n\ndef check_all_npm() -> List[Dict[str, Optional[str]]]:\n \"\"\"Check all packages in package.json.\"\"\"\n pkg_json = Path(\"package.json\")\n if not pkg_json.exists():\n print(\"❌ No package.json found in current directory\")\n return []\n\n data = json.loads(pkg_json.read_text())\n deps = {}\n deps.update(data.get(\"dependencies\", {}))\n deps.update(data.get(\"devDependencies\", {}))\n\n results = []\n for package in sorted(deps.keys()):\n result = check_npm(package)\n results.append(result)\n\n return results\n\n\ndef get_verdict(installed: Optional[str], latest: Optional[str]) -> str:\n \"\"\"Determine update verdict.\"\"\"\n if not installed:\n return \"NOT_INSTALLED\"\n if not latest:\n return \"UNKNOWN\"\n\n inst = parse_semver(installed)\n lat = parse_semver(latest)\n\n if not inst or not lat:\n return \"UNKNOWN\"\n\n if inst[0] \u003c lat[0]:\n return \"MAJOR_BEHIND\"\n elif inst[1] \u003c lat[1]:\n return \"MINOR_BEHIND\"\n elif inst[2] \u003c lat[2]:\n return \"PATCH_BEHIND\"\n else:\n return \"UP_TO_DATE\"\n\n\ndef format_result(result: Dict[str, Optional[str]]) -> str:\n \"\"\"Format a single check result.\"\"\"\n verdict = get_verdict(result[\"installed\"], result[\"latest\"])\n installed = result[\"installed\"] or \"not installed\"\n latest = result[\"latest\"] or \"unknown\"\n\n icons = {\n \"UP_TO_DATE\": \"✅\",\n \"PATCH_BEHIND\": \"✅\",\n \"MINOR_BEHIND\": \"⚠️ \",\n \"MAJOR_BEHIND\": \"🚨\",\n \"NOT_INSTALLED\": \"❌\",\n \"UNKNOWN\": \"❓\",\n }\n\n icon = icons.get(verdict, \"❓\")\n line = f\"{icon} {result['package']}: {installed} → {latest} [{verdict}]\"\n\n if verdict == \"MAJOR_BEHIND\":\n line += \"\\n ⚡ MAJOR version behind — check migration guide before updating!\"\n \n return line\n\n\ndef main():\n if len(sys.argv) \u003c 2:\n print(__doc__)\n sys.exit(1)\n\n manager = sys.argv[1]\n\n # --all flag: check everything in package.json\n if manager == \"npm\" and (len(sys.argv) \u003c 3 or sys.argv[2] == \"--all\"):\n if len(sys.argv) >= 3 and sys.argv[2] == \"--all\":\n results = check_all_npm()\n if not results:\n sys.exit(1)\n \n major_behind = []\n for r in results:\n print(format_result(r))\n if get_verdict(r[\"installed\"], r[\"latest\"]) == \"MAJOR_BEHIND\":\n major_behind.append(r[\"package\"])\n \n print(f\"\\n📊 Checked {len(results)} packages\")\n if major_behind:\n print(f\"🚨 {len(major_behind)} packages are MAJOR versions behind: {', '.join(major_behind)}\")\n print(\" Run version check on each before updating!\")\n sys.exit(0)\n else:\n print(\"Usage: check_versions.py npm \u003cpackage> or check_versions.py npm --all\")\n sys.exit(1)\n\n if len(sys.argv) \u003c 3:\n print(\"Usage: check_versions.py \u003cnpm|pip> \u003cpackage-name>\")\n sys.exit(1)\n\n package = sys.argv[2]\n\n checkers = {\"npm\": check_npm, \"pip\": check_pip}\n checker = checkers.get(manager)\n\n if not checker:\n print(f\"❌ Unknown package manager: {manager}. Supported: npm, pip\")\n sys.exit(1)\n\n result = checker(package)\n print(format_result(result))\n\n verdict = get_verdict(result[\"installed\"], result[\"latest\"])\n sys.exit(1 if verdict in (\"MAJOR_BEHIND\", \"NOT_INSTALLED\") else 0)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":7105,"content_sha256":"f97c68f81d2b6036d9f7a5a28b4c503763d49592c9bafa7bfe1e4746def41cf5"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Up To Date","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Rule","type":"text"}]},{"type":"paragraph","content":[{"text":"Before writing ANY code that touches an external package or API, fetch the real documentation first.","type":"text","marks":[{"type":"strong"}]},{"text":" Never rely on training data — it is stale by definition.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When This Triggers","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Installing a package (","type":"text"},{"text":"npm install","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"pip install","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"brew install","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Importing or using any third-party library","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Calling any external API (REST, GraphQL, SDK methods)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Modifying existing integration code","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Debugging API calls that silently fail","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Mandatory Steps","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"1. Check Version","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# What's installed?\ncat node_modules/\u003cpkg>/package.json | grep '\"version\"'\n# or: pip show \u003cpkg> | grep Version\n\n# What's latest?\nnpm info \u003cpkg> version\n# or: pip index versions \u003cpkg>","type":"text"}]},{"type":"paragraph","content":[{"text":"Update if more than 1 major version behind.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"2. Fetch Real Docs (pick one or more)","type":"text"}]},{"type":"paragraph","content":[{"text":"Context7","type":"text","marks":[{"type":"strong"}]},{"text":" (preferred for popular libraries):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"resolve-library-id → query-docs with specific endpoint/method question","type":"text"}]},{"type":"paragraph","content":[{"text":"Browser","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"fetch_webpage","type":"text","marks":[{"type":"code_inline"}]},{"text":"):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Fetch the official API reference page for the specific endpoint or method being used","type":"text"}]},{"type":"paragraph","content":[{"text":"DeepWiki","type":"text","marks":[{"type":"strong"}]},{"text":" (if available):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Fetch from deepwiki.com for GitHub-based packages","type":"text"}]},{"type":"paragraph","content":[{"text":"Do NOT skip this step. Do NOT write integration code from memory.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"3. Compare Code vs Docs","type":"text"}]},{"type":"paragraph","content":[{"text":"Check for mismatches:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Parameters code sends vs parameters docs accept","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Endpoint paths code hits vs current paths","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Response shape code expects vs current shape","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Required vs optional fields","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Removed or renamed parameters","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"4. After Changes","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Remove deprecated env vars and parameters","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Update ","type":"text"},{"text":"all","type":"text","marks":[{"type":"strong"}]},{"text":" call sites","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Build to verify types","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Test live and ","type":"text"},{"text":"verify the actual downstream effect","type":"text","marks":[{"type":"strong"}]},{"text":" — don't just check the HTTP status code. Confirm the resource appears where expected (dashboard, database, UI). A 200 with a valid-looking response body can still mean nothing happened.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Why This Matters","type":"text"}]},{"type":"paragraph","content":[{"text":"Real incident:","type":"text","marks":[{"type":"strong"}]},{"text":" Resend deprecated Audiences and replaced them with Segments. ","type":"text"},{"text":"contacts.create()","type":"text","marks":[{"type":"code_inline"}]},{"text":" without a ","type":"text"},{"text":"segments","type":"text","marks":[{"type":"code_inline"}]},{"text":" parameter still returned 200 and a valid contact object — but the contact was a global orphan invisible in the dashboard. First fix removed ","type":"text"},{"text":"audienceId","type":"text","marks":[{"type":"code_inline"}]},{"text":" (training data said it was gone). Second fix added ","type":"text"},{"text":"segments: [{ id }]","type":"text","marks":[{"type":"code_inline"}]},{"text":" after fetching real docs. The 200 OK trap delayed discovery twice.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Anti-Patterns","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pattern","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Risk","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Writing API code from memory","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Parameters may not exist anymore","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"catch (e) { return { success: true } }","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Hides failures completely","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"if (CONFIG) { callAPI() }","type":"text","marks":[{"type":"code_inline"}]},{"text":" with no else-log","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Silent skip when config is missing","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Passing extra params API won't reject","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Silently ignored, feature broken","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Trusting 200 + valid response body = success","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resource may exist but be orphaned/invisible","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Verifying only the API response, not the dashboard/DB","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Missed side effects go undetected","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Bundled Resources","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"scripts/check_versions.py","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Automated version checker for npm and pip packages. Run it to quickly identify outdated dependencies:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check a single npm package\npython3 scripts/check_versions.py npm resend\n# Check all package.json dependencies\npython3 scripts/check_versions.py npm --all\n# Check a pip package\npython3 scripts/check_versions.py pip requests","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"references/doc-urls.md","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Quick-reference table of official API documentation and changelog URLs for 30+ popular packages (email, payments, AI, databases, auth, cloud, analytics, frameworks). Consult this before searching — the correct URL may already be listed.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Related Skills","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"dependency-management","type":"text","marks":[{"type":"strong"}]},{"text":" — use alongside when resolving version conflicts or managing lockfiles","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"third-party-integration","type":"text","marks":[{"type":"strong"}]},{"text":" — use alongside when implementing the actual integration patterns after verifying docs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"api-versioning-strategy","type":"text","marks":[{"type":"strong"}]},{"text":" — use when designing your own API's versioning, not checking upstream","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"up-to-date","author":"@skillopedia","source":{"stars":2,"repo_name":"claude-code-security-review","origin_url":"https://github.com/leonmelamud/claude-code-security-review/blob/HEAD/.github/skills/up-to-date/SKILL.md","repo_owner":"leonmelamud","body_sha256":"4c6878b2788eeaabf97dbcaeedabd4e9a0721bc39fb3679841ce8068ab7f1248","cluster_key":"ef28ca05d99f3dae6bd88ca51fa7ac5bc56f8e0efcc3301f75cade7466b29edf","clean_bundle":{"format":"clean-skill-bundle-v1","source":"leonmelamud/claude-code-security-review/.github/skills/up-to-date/SKILL.md","attachments":[{"id":"954195d7-fedb-5a32-bf0d-83f49d50f705","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/954195d7-fedb-5a32-bf0d-83f49d50f705/attachment.md","path":"references/doc-urls.md","size":4117,"sha256":"b303a5dd9e648e3c1971fa3aa6c618139549405558de0937fa5c2537f9455fb1","contentType":"text/markdown; charset=utf-8"},{"id":"c4f5b654-78f0-50f2-a3bc-764eb67d4c4a","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c4f5b654-78f0-50f2-a3bc-764eb67d4c4a/attachment.py","path":"scripts/check_versions.py","size":7105,"sha256":"f97c68f81d2b6036d9f7a5a28b4c503763d49592c9bafa7bfe1e4746def41cf5","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"425c87b9bc747c5412e81034c34ad18170517f3b8baa5d477da589cf421250cd","attachment_count":2,"text_attachments":2,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":".github/skills/up-to-date/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"integrations-apis","category_label":"Integrations"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"integrations-apis","import_tag":"clean-skills-v1","description":"Fetch real, current API docs and verify package versions before installing packages, calling external APIs, using SDKs, or integrating any third-party library. Triggers on npm install, pip install, package.json changes, import statements for external packages, API calls (fetch, axios, SDK methods), \"integrate with\", \"connect to\", \"use X library\", or debugging silent API failures where code returns 200 but produces no effect."}},"renderedAt":1782981085134}

Up To Date Rule Before writing ANY code that touches an external package or API, fetch the real documentation first. Never rely on training data — it is stale by definition. When This Triggers - Installing a package ( , , ) - Importing or using any third-party library - Calling any external API (REST, GraphQL, SDK methods) - Modifying existing integration code - Debugging API calls that silently fail Mandatory Steps 1. Check Version Update if more than 1 major version behind. 2. Fetch Real Docs (pick one or more) Context7 (preferred for popular libraries): Browser ( ): DeepWiki (if available)…