Skill Discovery Skill indexing, metadata parsing, and search define efficient skill library navigation. Available Scripts skill_index_generator.gd Expert skill indexer that parses SKILL.md files and generates searchable metadata. NEVER Do in Skill Discovery NEVER rely on filename for skill identification — filesystem-advanced.md vs SKILL.md ? Use frontmatter name field as source of truth, not filename. NEVER skip keyword extraction — Skill without keywords? Impossible to discover via search. MUST extract from description OR maintain keyword list. NEVER cache without invalidation — Skill index cached, SKILL.md updated? Stale results. Invalidate cache on file modification OR version changes. NEVER use full-text search without ranking — Searching 100 skills for "input"? Returns everything. Use TF-IDF OR keyword weighting for relevance. NEVER forget to handle missing frontmatter — Malformed SKILL.md without
delimiter? Parser crash. Validate YAML frontmatter before parsing. Skill Metadata Format
name : skill - name description : Expert blueprint for X including [ features ] . Use when [ scenarios ] . Keywords topic , action , domain.
Indexing Pattern
skill_indexer.gd
class_name SkillIndexer extends RefCounted var skill_registry : Dictionary = { } func index_skills ( skills_dir : String ) -> void : var dir := DirAccess . open ( skills_dir ) if not dir : return dir . list_dir_begin ( ) var file_name := dir . get_next ( ) while file_name != "" : if dir . current_is_dir ( ) : var skill_path := skills_dir . path_join ( file_name ) . path_join ( "SKILL.md" ) if FileAccess . file_exists ( skill_path ) : index_skill ( skill_path ) file_name = dir . get_next ( ) func index_skill ( path : String ) -> void : var file := FileAccess . open ( path , FileAccess . READ ) if not file : return var content := file . get_as_text ( ) var metadata := parse_frontmatter ( content ) if metadata . has ( "name" ) : skill_registry [ metadata . name ] = { "path" : path , "description" : metadata . get ( "description" , "" ) , "keywords" : extract_keywords ( metadata . get ( "description" , "" ) ) } func parse_frontmatter ( content : String ) -> Dictionary : var lines := content . split ( "\n" ) if lines [ 0 ] . strip_edges ( ) != "---" : return { } var frontmatter_lines : Array [ String ] = [ ] for i in range ( 1 , lines . size ( ) ) : if lines [ i ] . strip_edges ( ) == "---" : break frontmatter_lines . append ( lines [ i ] ) var metadata := { } for line in frontmatter_lines : var parts := line . split ( ":" , true , 1 ) if parts . size ( ) == 2 : metadata [ parts [ 0 ] . strip_edges ( ) ] = parts [ 1 ] . strip_edges ( ) return metadata func search_skills ( query : String ) -> Array [ Dictionary ] : var results : Array [ Dictionary ] = [ ] var query_lower := query . to_lower ( ) for skill_name in skill_registry : var skill_data := skill_registry [ skill_name ] var relevance := 0.0
Check name match
if skill_name . to_lower ( ) . contains ( query_lower ) : relevance += 10.0
Check description match
if skill_data . description . to_lower ( ) . contains ( query_lower ) : relevance += 5.0
Check keyword match
for keyword in skill_data . keywords : if keyword . to_lower ( ) == query_lower : relevance += 20.0
Exact keyword match
elif keyword . to_lower ( ) . contains ( query_lower ) : relevance += 3.0 if relevance
0 : results . append ( { "name" : skill_name , "relevance" : relevance , "data" : skill_data } )
Sort by relevance
results . sort_custom ( func ( a , b ) : return a . relevance
b . relevance ) return results func extract_keywords ( description : String ) -> Array [ String ] : var keywords : Array [ String ] = [ ]
Extract from "Keywords X, Y, Z" pattern
var keyword_marker := "Keywords " var keyword_index := description . find ( keyword_marker ) if keyword_index != - 1 : var keyword_section := description . substr ( keyword_index + keyword_marker . length ( ) ) var parts := keyword_section . split ( "." , true , 1 ) var keyword_str := parts [ 0 ] if parts . size ( )
0 else keyword_section for word in keyword_str . split ( "," ) : keywords . append ( word . strip_edges ( ) ) return keywords Best Practices Version Skill Index — Include skill version in metadata for compatibility checks Cache Aggressively — Parse SKILL.md on index build, cache results for fast search Support Fuzzy Matching — Allow typos in search (e.g., Levenshtein distance) Category Grouping — Organize skills by category for browsing (2D, 3D, Genre, etc.) Reference Related: godot-project-foundations , godot-gdscript-mastery Related Master Skill: godot-master