// Package skill provides the Skill definition and management system. // // Skills are composable capabilities loaded from ~/.agents/skills/. // Each skill has a SKILL.md manifest with YAML frontmatter and optional // scripts in a scripts/ subdirectory. Skills can be discovered and // invoked by trigger keywords. package skill import ( "fmt" "strings" ) // Skill represents a composable capability loaded from the skills directory. // // Each Skill is defined by a SKILL.md file with YAML frontmatter containing // metadata (name, description, triggers) and optional executable scripts // in a scripts/ subdirectory. type Skill struct { // Name is the unique identifier for this skill (e.g., "dev-browser"). Name string `yaml:"name"` // Description is a human-readable explanation of what this skill does. Description string `yaml:"description"` // Triggers are keywords that activate this skill from natural language. Triggers []string `yaml:"triggers"` // Scripts is the list of script file names in the scripts/ directory. Scripts []string `yaml:"-"` // ScriptsDir is the absolute path to the scripts/ directory. ScriptsDir string `yaml:"-"` // Body is the markdown content after the YAML frontmatter. Body string `yaml:"-"` // Path is the absolute path to the SKILL.md file. Path string `yaml:"-"` } // MatchTrigger checks if the given query matches any of the skill's triggers. // Matching is case-insensitive and supports partial matches. func (s *Skill) MatchTrigger(query string) bool { query = strings.ToLower(query) for _, trigger := range s.Triggers { if strings.Contains(strings.ToLower(query), strings.ToLower(trigger)) { return true } } return false } // String returns a human-readable representation of the skill. func (s *Skill) String() string { return fmt.Sprintf("Skill{Name: %q, Triggers: %v, Scripts: %d}", s.Name, s.Triggers, len(s.Scripts)) } // HasScripts returns true if the skill has at least one script. func (s *Skill) HasScripts() bool { return len(s.Scripts) > 0 }