import { readdir, readFile } from "node:fs/promises"; import { fileURLToPath } from "node:url"; import { join } from "node:path"; function getSkillsDir() { return fileURLToPath(new URL("../../templates/.agent/skills", import.meta.url)); } function parseFrontmatter(content) { const match = content.match(/^---\n([\s\S]*?)\n---/); if (!match) return {}; const fm = {}; const lines = match[1].split("\n"); let currentKey = null; let currentValue = ""; for (const line of lines) { const keyMatch = line.match(/^(\w+):\s*(.*)$/); if (keyMatch) { if (currentKey) { fm[currentKey] = currentValue.trim(); } currentKey = keyMatch[1]; currentValue = keyMatch[2].replace(/^["']|["']$/g, ""); } else if (currentKey) { currentValue += " " + line.trim(); } } if (currentKey) { fm[currentKey] = currentValue.trim(); } return fm; } export async function listCommand({ stdout, stderr }) { const skillsDir = getSkillsDir(); let entries; try { entries = await readdir(skillsDir, { withFileTypes: true }); } catch { stderr.write("Could not read bundled skills directory.\n"); return 1; } const skills = []; for (const entry of entries) { if (!entry.isDirectory()) continue; const skillFile = join(skillsDir, entry.name, "SKILL.md"); try { const content = await readFile(skillFile, "utf8"); const fm = parseFrontmatter(content); skills.push({ name: fm.name || entry.name, description: fm.description || "(no description)", }); } catch { skills.push({ name: entry.name, description: "(SKILL.md not found)" }); } } skills.sort((a, b) => a.name.localeCompare(b.name)); stdout.write(`Antigravity Superpowers — ${skills.length} skills available:\n\n`); const maxName = Math.max(...skills.map((s) => s.name.length)); for (const skill of skills) { const desc = skill.description.length > 80 ? skill.description.slice(0, 77) + "..." : skill.description; stdout.write(` ${skill.name.padEnd(maxName + 2)} ${desc}\n`); } stdout.write("\n"); return 0; }