#!/usr/bin/env python3 """ Fixed Hermes Skills Inventory Tool Lists all available skills with their descriptions and linked files. Corrected to scan the correct profile-specific skills directory. """ import os import json from pathlib import Path def get_skills(profile="spark"): """Get list of skills from the profile-specific skills directory.""" skills_dir = f"/root/.hermes/profiles/{profile}/skills" if not os.path.exists(skills_dir): print(f"No skills directory found at {skills_dir}") return [] skills = [] base_path = Path(skills_dir) # Category directories that contain skill subdirectories category_names = {'apple', 'autonomous-ai-agents', 'creative', 'devops', 'email', 'media', 'note-taking', 'productivity', 'research', 'social-media', 'software-development', 'web'} for item in base_path.iterdir(): if item.is_dir(): # Case 1: Category directory (has DESCRIPTION.md, contains skill subdirs) if item.name in category_names: desc_md = item / 'DESCRIPTION.md' if desc_md.exists(): with open(desc_md, 'r') as f: content = f.read() # Parse frontmatter for description lines = content.split('\n') description = "" for line in lines: if line.startswith('description:'): description = line.split(':', 1)[1].strip() break # List skill subdirectories within this category for subdir in item.iterdir(): if subdir.is_dir(): skill_md = subdir / 'SKILL.md' if skill_md.exists(): with open(skill_md, 'r') as f: skill_content = f.read() skill_lines = skill_content.split('\n') skill_desc = "" for sline in skill_lines: if sline.startswith('description:'): skill_desc = sline.split(':', 1)[1].strip().strip('"\'') break link_files = {"references": [], "templates": [], "scripts": [], "assets": []} for link_dir in ["references", "templates", "scripts", "assets"]: link_path = subdir / link_dir if link_path.exists(): for f in link_path.iterdir(): if f.is_file(): link_files[link_dir].append(f.name) skills.append({ "name": subdir.name, "description": skill_desc, "has_skill_md": True, "linked_files": link_files, "category": item.name }) # Case 2: Direct skill directory else: skill_md = item / 'SKILL.md' if skill_md.exists(): with open(skill_md, 'r') as f: content = f.read() lines = content.split('\n') description = "" for line in lines: if line.startswith('description:'): description = line.split(':', 1)[1].strip().strip('"\'') break link_files = {"references": [], "templates": [], "scripts": [], "assets": []} for link_dir in ["references", "templates", "scripts", "assets"]: link_path = item / link_dir if link_path.exists(): for f in link_path.iterdir(): if f.is_file(): link_files[link_dir].append(f.name) skills.append({ "name": item.name, "description": description, "has_skill_md": True, "linked_files": link_files, "category": None }) return sorted(skills, key=lambda x: x['name']) def main(): skills = get_skills("spark") print(f"Hermes Skills Inventory (spark profile)") print(f"=" * 60) print(f"Total skills found: {len(skills)}") print() for skill in skills: print(f"• {skill['name']}") print(f" {skill['description']}") if skill.get('category'): print(f" Category: {skill['category']}") if skill.get('linked_files'): has_content = [] for link_type, files in skill['linked_files'].items(): if files: has_content.append(f"{link_type}({len(files)})") if has_content: print(f" Linked: {', '.join(has_content)}") print() # Write JSON output output = { "profile": "spark", "generated_at": __import__('datetime').datetime.now().isoformat(), "total_skills": len(skills), "skills": skills } output_path = "/root/.hermes/wizard-outputs/spark/skills_inventory_fixed.json" with open(output_path, 'w') as f: json.dump(output, f, indent=2) print(f"JSON inventory written to: {output_path}") return 0 if __name__ == "__main__": exit(main())