Lines 16-56javascript
16// Claude Code expands+runs headless (verified §2) — the same stdin path we already use.
18// Curation (which skills are pinned/hidden + their order) lives under
19// ~/.wild-workspace/powers/ (CLAUDE.md #1 — never the synced repo, never localStorage).
21import fs from 'node:fs';
22import path from 'node:path';
23import os from 'node:os';
25// Bounds so a workspace stuffed with skills can't bloat the store/UI.
26const CAP = { skills: 80, name: 64, desc: 280 };
28// --- frontmatter parse -----------------------------------------------------
29// Minimal, dependency-free. We only need a few scalar keys; the description often
30// CONTAINS colons ("Usage: /foo"), so we split on the FIRST colon only. Never throws.
32export function parseFrontmatter(text = '') {
34 if (typeof text !== 'string') return out;
35 // Frontmatter is the block between the first two `---` fences at the top.
36 const m = text.match(/^?---\s*\r?\n([\s\S]*?)\r?\n---/);
CriticalTrojan Source Unicode
Source contains bidi control or invisible Unicode characters associated with Trojan Source attacks.
server/src/skills.mjsView on unpkg · L36 38 for (const rawLine of m[1].split(/\r?\n/)) {
39 const line = rawLine.trim();
40 if (!line || line.startsWith('#')) continue;
41 const i = line.indexOf(':');
43 const key = line.slice(0, i).trim();
44 let val = line.slice(i + 1).trim();
45 // strip matching surrounding quotes
46 if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
47 val = val.slice(1, -1);
54function asBool(v, dflt) {
55 if (v === undefined) return dflt;
56 const s = String(v).trim().toLowerCase();