(dir string)
| 1007 | } |
| 1008 | |
| 1009 | func localSkillFromDir(dir string) (*Skill, error) { |
| 1010 | skillFile := filepath.Join(dir, "SKILL.md") |
| 1011 | data, err := os.ReadFile(skillFile) |
| 1012 | if err != nil { |
| 1013 | return nil, fmt.Errorf("could not read %s: %w", skillFile, err) |
| 1014 | } |
| 1015 | |
| 1016 | name := filepath.Base(dir) |
| 1017 | var description string |
| 1018 | |
| 1019 | result, parseErr := frontmatter.Parse(string(data)) |
| 1020 | if parseErr == nil { |
| 1021 | if result.Metadata.Name != "" { |
| 1022 | name = result.Metadata.Name |
| 1023 | } |
| 1024 | description = result.Metadata.Description |
| 1025 | } |
| 1026 | |
| 1027 | if !validateName(name) { |
| 1028 | return nil, fmt.Errorf("invalid skill name %q in %s", name, dir) |
| 1029 | } |
| 1030 | |
| 1031 | return &Skill{ |
| 1032 | Name: name, |
| 1033 | Description: description, |
| 1034 | Path: filepath.Base(dir), |
| 1035 | }, nil |
| 1036 | } |
| 1037 | |
| 1038 | // validateName checks if a skill name is safe for use (filesystem-safe). |
| 1039 | func validateName(name string) bool { |
no test coverage detected