MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / parseSkill

Function parseSkill

src/skills/loader.ts:106–146  ·  view source on GitHub ↗
(
  raw: string,
  name: string,
  dir: string,
  origin: SkillSpec['origin'],
)

Source from the content-addressed store, hash-verified

104
105/** Parse a SKILL.md into a SkillSpec. Returns null if the spec is unusable. */
106export function parseSkill(
107 raw: string,
108 name: string,
109 dir: string,
110 origin: SkillSpec['origin'],
111): SkillSpec | null {
112 let body = raw;
113 const fmMatch = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\r?\n?([\s\S]*)$/);
114 const fm = fmMatch ? fmMatch[1] ?? '' : '';
115 if (fmMatch) body = fmMatch[2] ?? '';
116
117 const fields = parseFrontmatter(fm);
118
119 const description = (fields.description as string | undefined) ?? '';
120 if (!description) {
121 logger.warn('Skill missing description, skipping', { name, dir });
122 return null;
123 }
124
125 // name in frontmatter is advisory — directory name wins so installer collisions stay safe.
126 return {
127 name,
128 dir,
129 origin,
130 description,
131 version: fields.version as string | undefined,
132 body: body.trim(),
133 allowedTools: asStringArray(fields['allowed-tools'] ?? fields['allowed_tools']),
134 triggers: asStringArray(fields.triggers),
135 slashAliases: asStringArray(fields['slash-aliases'] ?? fields['slash_aliases']),
136 model: fields.model as string | undefined,
137 files: asStringArray(fields.files),
138 author: fields.author as string | undefined,
139 source: fields.source as string | undefined,
140 // Anti-self-congratulation: an ABSENT provenance means a human authored/installed
141 // it → protected. Only the capture loop writes `provenance: machine`.
142 provenance: fields.provenance === 'machine' ? 'machine' : 'user',
143 humanEdited: String(fields['humanedited'] ?? fields['human-edited'] ?? '').toLowerCase() === 'true',
144 status: fields.status === 'candidate' ? 'candidate' : 'active',
145 };
146}
147
148/** Minimal YAML-ish parser. Same shape as custom-commands.ts for consistency. */
149function parseFrontmatter(fm: string): Record<string, string | string[]> {

Callers 11

loadShippedFunction · 0.85
loadFunction · 0.85
loadShippedFunction · 0.85
mkFunction · 0.85
loadShippedFunction · 0.85
loadShippedFunction · 0.85
copyIntoFunction · 0.85
installOneSkillDirFunction · 0.85
loadSkillsFunction · 0.85
loadSkillByNameFunction · 0.85
listAllSkillsWithStateFunction · 0.85

Calls 3

parseFrontmatterFunction · 0.85
asStringArrayFunction · 0.85
warnMethod · 0.80

Tested by 6

loadShippedFunction · 0.68
loadFunction · 0.68
loadShippedFunction · 0.68
mkFunction · 0.68
loadShippedFunction · 0.68
loadShippedFunction · 0.68