diff --git a/CATALOG.md b/CATALOG.md index 743fdb94..6488a794 100644 --- a/CATALOG.md +++ b/CATALOG.md @@ -1,6 +1,6 @@ # Skill Catalog -Generated at: 2026-01-29T12:07:33.859Z +Generated at: 2026-01-29T12:12:48.100Z Total skills: 553 diff --git a/data/aliases.json b/data/aliases.json index 91287e25..c38fc812 100644 --- a/data/aliases.json +++ b/data/aliases.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-01-29T12:07:33.859Z", + "generatedAt": "2026-01-29T12:12:48.100Z", "aliases": { "accessibility-compliance-audit": "accessibility-compliance-accessibility-audit", "active directory attacks": "active-directory-attacks", diff --git a/data/bundles.json b/data/bundles.json index 25a9d2b4..045f6207 100644 --- a/data/bundles.json +++ b/data/bundles.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-01-29T12:07:33.859Z", + "generatedAt": "2026-01-29T12:12:48.100Z", "bundles": { "core-dev": { "description": "Core development skills across languages, frameworks, and backend/frontend fundamentals.", diff --git a/data/catalog.json b/data/catalog.json index 591cbf09..c513137a 100644 --- a/data/catalog.json +++ b/data/catalog.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-01-29T12:07:33.859Z", + "generatedAt": "2026-01-29T12:12:48.100Z", "total": 553, "skills": [ { diff --git a/scripts/update_readme.py b/scripts/update_readme.py index f67afbff..f7d23043 100644 --- a/scripts/update_readme.py +++ b/scripts/update_readme.py @@ -3,140 +3,63 @@ import json import os import re + def update_readme(): base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) readme_path = os.path.join(base_dir, "README.md") index_path = os.path.join(base_dir, "skills_index.json") print(f"📖 Reading skills index from: {index_path}") - with open(index_path, 'r', encoding='utf-8') as f: + with open(index_path, "r", encoding="utf-8") as f: skills = json.load(f) total_skills = len(skills) print(f"🔢 Total skills found: {total_skills}") print(f"📝 Updating README at: {readme_path}") - with open(readme_path, 'r', encoding='utf-8') as f: + with open(readme_path, "r", encoding="utf-8") as f: content = f.read() # 1. Update Title Count content = re.sub( - r'(# 🌌 Antigravity Awesome Skills: )\d+(\+ Agentic Skills)', - f'\\g<1>{total_skills}\\g<2>', - content + r"(# 🌌 Antigravity Awesome Skills: )\d+(\+ Agentic Skills)", + rf"\g<1>{total_skills}\g<2>", + content, ) # 2. Update Blockquote Count content = re.sub( - r'(Collection of )\d+(\+ Universal)', - f'\\g<1>{total_skills}\\g<2>', - content + r"(Collection of )\d+(\+ Universal)", + rf"\g<1>{total_skills}\g<2>", + content, ) # 3. Update Intro Text Count content = re.sub( - r'(library of \*\*)\d+( high-performance skills\*\*)', - f'\\g<1>{total_skills}\\g<2>', - content + r"(library of \*\*)\d+( high-performance skills\*\*)", + rf"\g<1>{total_skills}\g<2>", + content, ) - # 4. Update Registry Header Count + # 4. Update Browse section header content = re.sub( - r'(## Full Skill Registry \()\d+/\d+(\))', - f'\\g<1>{total_skills}/{total_skills}\\g<2>', - content + r"## Browse \d+\+ Skills", + f"## Browse {total_skills}+ Skills", + content, ) - # 5. Ensure Curated Collections section exists (idempotent) - # - # Historical note: we previously used "## 📦 Curated Collections" in some runs. - # If the README already contains "## Curated Collections", inserting the emoji header creates duplicates. - canonical_collections_header = "## Curated Collections" - canonical_collections_body = "[Check out our Starter Packs in docs/BUNDLES.md](docs/BUNDLES.md) to find the perfect toolkit for your role." - - # Normalize any emoji variant to the canonical header - content = content.replace("## 📦 Curated Collections", canonical_collections_header) - - # If the section is missing entirely, insert it right before the Full Skill Registry section - if canonical_collections_header not in content: - registry_header_match = re.search(r'^## Full Skill Registry', content, flags=re.MULTILINE) - if registry_header_match: - insert_block = f"{canonical_collections_header}\n\n{canonical_collections_body}\n\n" - content = content[:registry_header_match.start()] + insert_block + content[registry_header_match.start():] - - # De-dupe repeated Curated Collections blocks (e.g. after a previous buggy insert) - escaped_body = re.escape(canonical_collections_body) - dedupe_pattern = re.compile( - rf'(?:{re.escape(canonical_collections_header)}\s*\n\s*\n{escaped_body}\s*\n\s*){{2,}}', - flags=re.MULTILINE + # 5. Update TOC link for Browse (anchor matches header-derived slug) + content = re.sub( + r"\[📚 Browse \d+\+ Skills\]\(#browse-\d+-skills\)", + f"[📚 Browse {total_skills}+ Skills](#browse-{total_skills}-skills)", + content, ) - content = dedupe_pattern.sub(f"{canonical_collections_header}\n\n{canonical_collections_body}\n\n", content) - # 6. Generate New Registry Table - print("🔄 Generating new registry table...") - - # Store the Note block to preserve it - note_pattern = r'(> \[!NOTE\].*?)\n\n\| Skill Name' - note_match = re.search(note_pattern, content, re.DOTALL) - note_block = "" - if note_match: - note_block = note_match.group(1) - else: - note_block = "> [!NOTE] > **Document Skills**: We provide both **community** and **official Anthropic** versions. Locally, the official versions are used by default." + with open(readme_path, "w", encoding="utf-8") as f: + f.write(content) - table_header = "| Skill Name | Risk | Description | Path |\n| :--- | :--- | :--- | :--- |" - table_rows = [] + print("✅ README.md updated successfully.") - for skill in skills: - name = skill.get('name', 'Unknown') - desc = skill.get('description', '').replace('\n', ' ').strip() - path = skill.get('path', '') - risk = skill.get('risk', 'unknown') - - # Risk Icons - risk_icon = "⚪" - if risk == "official": risk_icon = "🟣" # Mapping official to purple - if risk == "none": risk_icon = "🟢" - if risk == "safe": risk_icon = "🔵" - if risk == "critical": risk_icon = "🟠" - if risk == "offensive": risk_icon = "🔴" - - # Escape pipes - desc = desc.replace('|', r'\|') - - row = f"| **{name}** | {risk_icon} | {desc} | `{path}` |" - table_rows.append(row) - - new_table_section = f"{note_block}\n\n{table_header}\n" + "\n".join(table_rows) - - # Replace the old table section - header_pattern = r'## Full Skill Registry \(\d+/\d+\)' - header_match = re.search(header_pattern, content) - - if not header_match: - print("❌ Could not find 'Full Skill Registry' header.") - return - - start_pos = header_match.end() - - # Find the next section (## ...) or end of file - next_section_match = re.search(r'\n## ', content[start_pos:]) - - if next_section_match: - end_pos = start_pos + next_section_match.start() - rest_of_file = content[end_pos:] - else: - rest_of_file = "" - - before_header = content[:header_match.start()] - new_header = f"## Full Skill Registry ({total_skills}/{total_skills})" - - new_content = f"{before_header}{new_header}\n\n{new_table_section}\n{rest_of_file}" - - with open(readme_path, 'w', encoding='utf-8') as f: - f.write(new_content) - - print("✅ README.md updated successfully with Collections link and Risk columns.") if __name__ == "__main__": update_readme()