Lines 17-57javascript
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';
24import { KNOWN_ACTION_COMMANDS, bucketOf, friendlyLabel, friendlyDesc, prettifyName } from './capabilities.mjs';
26// Bounds so a workspace stuffed with skills can't bloat the store/UI.
27const CAP = { skills: 80, name: 64, desc: 280, label: 48 };
29// --- frontmatter parse -----------------------------------------------------
30// Minimal, dependency-free. We only need a few scalar keys; the description often
31// CONTAINS colons ("Usage: /foo"), so we split on the FIRST colon only. Never throws.
33export function parseFrontmatter(text = '') {
35 if (typeof text !== 'string') return out;
36 // Frontmatter is the block between the first two `---` fences at the top.
37 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 · L37 39 for (const rawLine of m[1].split(/\r?\n/)) {
40 const line = rawLine.trim();
41 if (!line || line.startsWith('#')) continue;
42 const i = line.indexOf(':');
44 const key = line.slice(0, i).trim();
45 let val = line.slice(i + 1).trim();
46 // strip matching surrounding quotes
47 if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
48 val = val.slice(1, -1);
55function asBool(v, dflt) {
56 if (v === undefined) return dflt;
57 const s = String(v).trim().toLowerCase();