
Open Design
- 81 installs
- 13 repo stars
- Updated May 21, 2026
- sugarforever/open-design-skill
Helps with ai & agent building tasks during AI-assisted development.
About
open-design is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- open-design
- AI & Agent Building
- AI-coding skill
Open Design by the numbers
- 81 all-time installs (skills.sh)
- +8 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #5,179 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/sugarforever/open-design-skill --skill open-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 81 |
|---|---|
| repo stars | ★ 13 |
| Last updated | May 21, 2026 |
| Repository | sugarforever/open-design-skill ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Open Design — universal design-task substrate
This skill turns the Open Design catalogue (kept in a local clone of the OD repo) into a workflow you can follow inside any agent session. It mirrors what OD's own daemon does — bind a brand spec + a template, layer in craft rules, follow the workflow — without needing OD's daemon to be running. Preview / comment / slider features that live in OD's daemon are intentionally out of scope; use the agent's normal dev-server + browser-inspection tooling for that.
When to invoke
Trigger on requests like:
- "Make me a
<artifact>" where<artifact>is deck / prototype / landing /
dashboard / poster / brochure / video template / audio piece.
- "Apply
<brand>design system" or "make this look like X". - "Set up a design system / DESIGN.md".
- "Audit / critique my UI", "run a 5-dim review".
- Any request that mentions Open Design explicitly.
Do not invoke for non-design tasks (backend, infra, refactoring, bug fixes).
Cross-platform note
All helper scripts are Node.js (.mjs) and work the same on macOS, Linux, and Windows. The git clone step requires git on PATH. No bash dependency.
$SKILL_DIR — locating the helper scripts
The four list scripts live alongside this SKILL.md. When you invoke them, use the absolute path of the directory containing this SKILL.md as $SKILL_DIR. You already know this path — it is wherever the agent read this file from (e.g. ~/.claude/skills/open-design/ on Claude Code, ~/.codex/skills/open-design/ on Codex, etc.). Pass it explicitly to node in your Bash invocations.
$OPEN_DESIGN_ROOT — locating the OD content
ROOT = $OPEN_DESIGN_ROOT (if set and non-empty)
| ~/.open-design-skill/repo (default)The OD repo (https://github.com/nexu-io/open-design) is cloned here once and reused across all projects. The scripts default to ~/.open-design-skill/repo but honor OPEN_DESIGN_ROOT for users with an existing checkout.
Workflow
Three phases: setup → bind or pick → compose and execute.
Phase 1 — Setup (every invocation)
Check the OD content root:
ROOT="${OPEN_DESIGN_ROOT:-$HOME/.open-design-skill/repo}"
[ -d "$ROOT" ] && echo "OK: $ROOT" || echo "MISSING: $ROOT"If missing, use AskUserQuestion to confirm the clone:
Clone Open Design content to ~/.open-design-skill/repo? (a few hundred MB)Options (single-select): "Clone now" (recommended) / "Cancel".
On "Clone now", run:
mkdir -p "$(dirname "$ROOT")"
git clone https://github.com/nexu-io/open-design "$ROOT"On "Cancel", tell the user to set OPEN_DESIGN_ROOT to an existing checkout and stop.
Phase 2 — Bind or pick
Check for .open-design.json in the user's project (the agent's current working directory):
test -f .open-design.json && cat .open-design.jsonIf it exists (bound case): parse it, jump straight to Phase 3 with designSystem.path and skill.path as the bodies to load. Do not offer the refresh prompt or run the list scripts. Mid-project iteration should not change template content under the user.
If the user explicitly asks to switch ("switch design system to X", "re-pick template", "change brand"), delete .open-design.json first, then continue into the unbound flow.
If it does not exist (unbound case):
(a) Refresh prompt. AskUserQuestion:
Refresh Open Design content first? (git pull in the local clone)Options: "Pull latest" (recommended) / "Skip".
If "Pull latest":
git -C "$ROOT" pull --ff-only(b) Narrow intent. AskUserQuestion (one question, four options):
What are we building?
Options:
- Deck / slides / presentation
- Prototype / landing / dashboard / page
- Image, video, or audio artifact
- Set up or apply a design system (no artifact yet)
If none fit, the user can pick "Other" and you ask a follow-up that maps to one of these or to a functional skill.
(c) Scan the relevant subset. Run the appropriate list script with node, passing $SKILL_DIR as the absolute path to this skill's directory:
| Intent | Command | Filter |
|---|---|---|
| Deck | node "$SKILL_DIR/scripts/list-design-templates.mjs" | rows where column mode == deck |
| Prototype / landing / dashboard | node "$SKILL_DIR/scripts/list-design-templates.mjs" | rows where column mode == prototype |
| Image / video / audio | node "$SKILL_DIR/scripts/list-design-templates.mjs" | rows where mode in {image, video, audio, template} |
| Functional skill | node "$SKILL_DIR/scripts/list-skills.mjs" | (all; flag stub rows where upstream != "-") |
| Design system | node "$SKILL_DIR/scripts/list-design-systems.mjs" | filter by user-supplied keyword/mood |
All scripts emit TSV with a header line. Column count is stable; empty fields are written as -.
(d) Filter and present. Each list is too large to dump verbatim.
For design systems (150+): first AskUserQuestion for mood/brand keywords ("specific brand? minimal? bold? editorial? warm? technical?"), then grep-filter the TSV by that keyword across the title, category, and description columns, and only present the matches.
For templates (110+) and skills (130+): filter to the intended subset first, then show the top ~6 matches as a compact list inline (slug + one-line description) and use AskUserQuestion with three high-likelihood defaults plus "Other" for a free-text slug.
When presenting stub skills (rows with upstream != "-" from list-skills.mjs), explicitly mark them as "pointer to upstream — needs separate install" so the user can decide whether to install the upstream bundle or skip.
(e) Bind. Once the user has picked one design system and one template/skill, write .open-design.json to the agent's current working directory:
{
"version": 1,
"designSystem": {
"slug": "bmw",
"path": "design-systems/bmw"
},
"skill": {
"slug": "html-ppt-pitch-deck",
"path": "design-templates/html-ppt-pitch-deck",
"kind": "design-template",
"mode": "deck"
},
"boundAt": "2026-05-20T13:22:00Z"
}Notes on this file:
- Paths are always relative to
$OPEN_DESIGN_ROOTand use forward slashes
(portable across OSes).
skill.kindis"design-template"for entries underdesign-templates/,
"skill" for entries under skills/.
skill.modemirrors theod.modevalue from the chosen entry's
frontmatter; omit if absent.
- If the template's frontmatter has
od.design_system.requires: false
(it ships its own baked-in style), set designSystem: null and skip the design-system pick entirely.
boundAtis ISO 8601 in UTC.
Phase 3 — Compose and execute
Read the bound bodies from `$OPEN_DESIGN_ROOT`, not from this skill's directory:
1. Read "$OPEN_DESIGN_ROOT/<designSystem.path>/DESIGN.md" — full file (skip this step if designSystem is null). 2. Read "$OPEN_DESIGN_ROOT/<skill.path>/SKILL.md" — full file. Look at its frontmatter for:
od.craft.requires— a list of craft slugs the chosen entry opts
into (may be absent).
od.design_system.sections— which DESIGN.md sections actually
matter for this template (use to focus attention; the full DESIGN.md stays loaded). 3. For each slug in od.craft.requires: Read "$OPEN_DESIGN_ROOT/craft/<slug>.md". 4. If the template ships assets/ or references/ subdirectories, treat those as files to read on demand when the workflow body references them. Do not eagerly load.
Then execute the composed workflow with this authority order on conflict:
1. DESIGN.md — brand tokens win. 2. *craft/.md — universal rules cover what DESIGN.md does not override. 3. SKILL.md body** — the workflow specific to the artifact type (clarify brief → write files → self-check).
Write artifacts into the user's project (cwd), not into the OD clone or this skill's install dir. If the template specifies an output filename (typically index.html), write it relative to cwd.
Subsequent turns in the same project
Bound turns short-circuit Phase 2: read .open-design.json, re-read the same DESIGN.md + SKILL.md + craft bodies, follow the same workflow. The refresh prompt is not offered on bound turns — that would change template content under the user mid-project. To refresh OD content without re-picking, the user can manually git -C "$OPEN_DESIGN_ROOT" pull between sessions.
Edge cases
- Stub skills under `skills/`: ~half of entries are curated stubs
that point at upstream repos (their od.upstream frontmatter field is set, and the body says "go install upstream at X"). Surface the upstream URL when offered, and ask whether to install upstream separately or use the stub's metadata as design context only.
- `od.design_system.requires: false`: the template is self-contained
and does not need a DESIGN.md (e.g. guizang-ppt). Skip the design system pick and bind with designSystem: null.
- No DESIGN.md in the user's cwd: this skill never copies DESIGN.md
into the user's project. It reads from $OPEN_DESIGN_ROOT and feeds the contents through prompts. If the user explicitly wants a tangible DESIGN.md in their repo, copy it after binding: cp "$OPEN_DESIGN_ROOT/<designSystem.path>/DESIGN.md" ..
- Out-of-process preview / comment mode: these live in OD's daemon
and are not in scope for this skill. For preview/debug, use the agent's standard tools — start a dev server, use chrome-devtools MCP or playwright to inspect.
What .open-design.json does (recap)
Per-project record of "we chose X design system and Y template/skill". Plain JSON, hand-editable, intended to be committed to git so design choices persist across collaborators. It does not cache the bound bodies — those are always re-read from $OPEN_DESIGN_ROOT on every turn, so a git pull in the clone takes effect immediately on the next turn.
---
Maintained at https://github.com/sugarforever/open-design-skill. Open Design upstream: https://github.com/nexu-io/open-design.
* text=auto eol=lf
*.mjs text eol=lf
*.md text eol=lf
*.json text eol=lf
MIT License
Copyright (c) 2026 sugarforever
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Open Design Skill
A community SKILL.md companion to Open Design: a thin wrapper that brings Open Design's curated catalogue into any agent session following the SKILL.md convention (Claude Code, Codex, Cursor, Gemini CLI, OpenCode, …) — without running Open Design's local daemon.
What's in the catalogue
- 150+ brand DESIGN.md files (Airbnb, Apple, BMW, Bugatti, Claude,
Cursor, Discord, Figma, Framer, Stripe, …).
- 110+ rendering templates for decks, prototypes, dashboards, landing
pages, posters, image/video/audio.
- 130+ functional skills (briefs, audits, copywriting, critique, …).
- 11 craft references — universal brand-agnostic rules (typography,
color, anti-AI-slop, accessibility, animation, RTL, …).
What this skill does, in one sentence: lets the agent pick a design system plus a template/skill once per project, layer in the craft rules that template opts into, and follow the resulting composed workflow — the same prompt composition Open Design's daemon does, without needing the daemon to be running.
Install
Via Vercel's skills CLI (recommended)
npx skills add sugarforever/open-design-skillThe CLI auto-discovers the SKILL.md at the repo root and copies / symlinks it into your agent's skills directory (e.g. ~/.claude/skills/open-design/, ~/.codex/skills/open-design/, etc.). Works with Claude Code, Codex, Cursor Agent, OpenCode, Gemini CLI, and others that follow the SKILL.md convention.
Manual install (Claude Code)
git clone https://github.com/sugarforever/open-design-skill \
~/.claude/skills/open-designPrerequisite: clone the Open Design content repo
This skill is a thin wrapper. The actual content (design systems, templates, craft rules) lives in the Open Design repo and must be cloned locally. The skill will offer to do this on first use, but you can do it manually:
git clone https://github.com/nexu-io/open-design ~/.open-design-skill/repoOr, if you already have an Open Design checkout elsewhere, set the env var:
export OPEN_DESIGN_ROOT=/path/to/your/open-designOPEN_DESIGN_ROOT takes precedence over the default ~/.open-design-skill/repo.
Usage
Once installed, invoke implicitly by asking your agent to do design work:
"Make me a pitch deck for my seed round."
>
"Build a SaaS landing page with the Stripe design system."
>
"Apply the BMW brand to my homepage."
>
"Set up a design system for my project."
Or invoke explicitly:
"Use Open Design to build a dashboard."
The agent will:
1. Check that the Open Design content is cloned locally (offer to clone if not). 2. Look for .open-design.json in your project (the per-project binding). 3. If absent: offer to git pull the content first, then walk you through picking one design system and one template/skill via AskUserQuestion. Save the choice to .open-design.json. 4. If present: skip directly to following the bound workflow. 5. Compose the chosen DESIGN.md + opted-in craft rules + the template's SKILL.md body, and execute the workflow — writing artifacts (HTML, JSX, markdown, etc.) into your project directory.
How it differs from running Open Design itself
This skill is Stage 1 of bringing Open Design to existing projects. It proxies content (design systems, templates, craft) into the agent's session. It does not include:
- The in-browser iframe preview surface.
- Comment-mode surgical edits on the rendered artifact.
- Slider parameters that re-prompt the agent on change.
od.moderouting into different render surfaces.
Those features live in Open Design's local daemon. For preview and debugging while iterating on the artifact in your project, use your agent's standard tools — start a dev server, use the chrome-devtools MCP or playwright to inspect.
Per-project binding (.open-design.json)
After the first pick flow completes, the skill writes a small JSON file at the root of your project:
{
"version": 1,
"designSystem": {
"slug": "bmw",
"path": "design-systems/bmw"
},
"skill": {
"slug": "html-ppt-pitch-deck",
"path": "design-templates/html-ppt-pitch-deck",
"kind": "design-template",
"mode": "deck"
},
"boundAt": "2026-05-20T13:22:00Z"
}This is the same role as Open Design's project.skillId + project.designSystemId columns — a per-project record of "we picked X and Y." Subsequent agent turns short-circuit the pick flow and read these two files directly. To re-pick, delete the file or tell the agent to "switch design system" / "re-pick template".
Commit this file to git if you want design choices to persist across collaborators. Add to .gitignore if you'd rather each developer make their own pick.
Cross-platform support
The four list scripts are Node.js (.mjs) with no external dependencies. Works on macOS, Linux, and Windows (no bash, no awk, no shell-specific syntax). Requires Node 16+ and git on PATH.
Layout
open-design-skill/
├── SKILL.md ← skill entry: workflow runbook the agent follows
├── README.md ← this file
├── LICENSE
├── .gitattributes ← enforces LF line endings cross-platform
└── scripts/
├── _parse.mjs ← shared frontmatter + helpers
├── list-design-systems.mjs ← lists OD design systems (TSV)
├── list-design-templates.mjs ← lists OD rendering templates (TSV)
├── list-skills.mjs ← lists OD functional skills (TSV)
└── list-craft.mjs ← lists OD craft references (TSV)The scripts all read from $OPEN_DESIGN_ROOT (default ~/.open-design-skill/repo) and emit tab-separated values to stdout with a header row. You can run them yourself to inspect what's available:
node scripts/list-design-systems.mjs | column -t -s $'\t' | less
node scripts/list-design-templates.mjs | grep -P '\tdeck\t'
node scripts/list-skills.mjs | awk -F'\t' '$4 != "-"' # stubs only
node scripts/list-craft.mjsLicense
MIT — see LICENSE.
Open Design itself is maintained at https://github.com/nexu-io/open-design under its own license.
// Shared helpers for the four list scripts.
//
// Cross-platform Node.js (16+). No external dependencies.
// All scripts emit TSV to stdout: header line first, one entry per row.
// Missing fields are written as "-" so column counts stay stable.
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
// Gracefully exit when stdout is piped to a tool that closes early (e.g.
// `node list-*.mjs | head`). Without this, Node throws EPIPE and clutters
// the output the agent has to parse.
process.stdout.on('error', (err) => {
if (err.code === 'EPIPE') process.exit(0);
throw err;
});
const HEX_HOME = os.homedir();
export function resolveRoot() {
const env = process.env.OPEN_DESIGN_ROOT;
if (env && env.trim() !== '') {
return env.startsWith('~')
? path.join(HEX_HOME, env.slice(1))
: env;
}
return path.join(HEX_HOME, '.open-design-skill', 'repo');
}
export function failIfMissing(dir, label) {
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
const root = resolveRoot();
process.stderr.write(
[
`ERROR: ${label} not found at: ${dir}`,
`Hint: clone Open Design first, e.g.`,
` git clone https://github.com/nexu-io/open-design "${root}"`,
`Or set OPEN_DESIGN_ROOT to an existing checkout.`,
''
].join('\n')
);
process.exit(1);
}
}
export function nz(v) {
return v === undefined || v === null || v === '' ? '-' : v;
}
// Strip a single layer of matching surrounding quotes (single or double).
function unquote(s) {
const t = s.trim();
if (t.length >= 2) {
const a = t.charAt(0);
const b = t.charAt(t.length - 1);
if ((a === '"' && b === '"') || (a === "'" && b === "'")) {
return t.slice(1, -1);
}
}
return t;
}
// Collapse tabs/newlines/CRs to single spaces so the TSV stays clean.
function clean(s) {
return String(s).replace(/[\t\r\n]+/g, ' ').trim();
}
// Parse the YAML frontmatter at the top of a SKILL.md file.
// Returns an object with: name, description (first line of inline or block),
// triggers (string[]), od (object: mode, category, upstream — only the fields
// we care about). Robust to the small set of YAML shapes Open Design uses;
// not a general YAML parser.
export function parseSkillFrontmatter(filePath) {
const text = fs.readFileSync(filePath, 'utf8');
const lines = text.split(/\r?\n/);
// Find frontmatter boundaries
if (lines[0] !== '---') {
return { name: '', description: '', triggers: [], od: {} };
}
let end = -1;
for (let i = 1; i < lines.length; i++) {
if (lines[i] === '---') { end = i; break; }
}
if (end === -1) return { name: '', description: '', triggers: [], od: {} };
const out = { name: '', description: '', triggers: [], od: {} };
let i = 1;
while (i < end) {
const line = lines[i];
// Skip blank lines
if (line.trim() === '') { i++; continue; }
// name: <value>
const mName = line.match(/^name:\s+(.*)$/);
if (mName) { out.name = clean(unquote(mName[1])); i++; continue; }
// description: <value> (inline)
// description: | (block — take first non-empty content line)
// description: > (folded — same treatment)
const mDescInline = line.match(/^description:\s+(.+)$/);
const mDescBlock = line.match(/^description:\s*[|>]\s*$/);
if (mDescBlock) {
i++;
while (i < end) {
const cont = lines[i];
if (!/^\s/.test(cont)) break;
const stripped = cont.replace(/^\s+/, '');
if (stripped !== '' && out.description === '') {
out.description = clean(stripped);
// Continue to consume the rest of the block but don't overwrite.
}
i++;
}
continue;
}
if (mDescInline) {
out.description = clean(unquote(mDescInline[1]));
i++;
continue;
}
// triggers: <list>
if (/^triggers:\s*$/.test(line)) {
i++;
while (i < end) {
const cont = lines[i];
const mItem = cont.match(/^\s+-\s+(.*)$/);
if (!mItem) break;
out.triggers.push(clean(unquote(mItem[1])));
i++;
}
continue;
}
// od: <block>
if (/^od:\s*$/.test(line)) {
i++;
while (i < end) {
const cont = lines[i];
// End of od block when a line has no leading whitespace
if (!/^\s/.test(cont)) break;
const mKv = cont.match(/^\s+([A-Za-z_][\w-]*)\s*:\s*(.*)$/);
if (mKv) {
const k = mKv[1];
const vRaw = mKv[2];
if (k === 'mode' || k === 'category' || k === 'upstream') {
out.od[k] = clean(unquote(vRaw));
}
}
i++;
}
continue;
}
// Unknown top-level key — skip
i++;
}
return out;
}
// Parse design-systems/<slug>/DESIGN.md for: title, category, description.
// The convention is:
// # <Title>
// (blank)
// > Category: <Category>
// > <one-line description>
// Falls back gracefully if the header shape differs.
export function parseDesignSystemHeader(filePath) {
const text = fs.readFileSync(filePath, 'utf8');
const lines = text.split(/\r?\n/);
const out = { title: '', category: '', description: '' };
if (lines.length > 0) {
const m = lines[0].match(/^#\s*(.+?)\s*$/);
if (m) out.title = clean(m[1]);
}
let seenCategory = false;
for (let i = 1; i < lines.length && i < 20; i++) {
const line = lines[i];
if (/^#/.test(line)) break; // entered the first section
if (!seenCategory) {
const mC = line.match(/^>\s*Category:\s*(.+?)\s*$/);
if (mC) { out.category = clean(mC[1]); seenCategory = true; continue; }
} else {
const mD = line.match(/^>\s*(.+?)\s*$/);
if (mD) { out.description = clean(mD[1]); break; }
}
}
return out;
}
// Parse craft/<slug>.md for: title (line 1), description (first content line).
export function parseCraftHeader(filePath) {
const text = fs.readFileSync(filePath, 'utf8');
const lines = text.split(/\r?\n/);
const out = { title: '', description: '' };
if (lines.length > 0) {
const m = lines[0].match(/^#\s*(.+?)\s*$/);
if (m) out.title = clean(m[1]);
}
for (let i = 1; i < lines.length && i < 40; i++) {
const line = lines[i];
if (line.trim() === '' || /^#/.test(line)) continue;
out.description = clean(line);
break;
}
return out;
}
// Walk one level of subdirectories, returning [slug, fullPath].
export function listSubdirs(dir) {
return fs.readdirSync(dir, { withFileTypes: true })
.filter((e) => e.isDirectory() && !e.name.startsWith('_'))
.map((e) => [e.name, path.join(dir, e.name)])
.sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
}
// Print one TSV row to stdout.
export function row(cols) {
process.stdout.write(cols.map((c) => nz(c)).join('\t') + '\n');
}
#!/usr/bin/env node
// List Open Design craft references — universal brand-agnostic rules
// (typography, color, anti-ai-slop, accessibility-baseline, etc.) that a
// chosen template/skill opts into via `od.craft.requires`.
//
// Output: TSV with header. Columns:
// slug title description
//
// Reads from $OPEN_DESIGN_ROOT (default ~/.open-design-skill/repo).
import fs from 'node:fs';
import path from 'node:path';
import { resolveRoot, failIfMissing, parseCraftHeader, row } from './_parse.mjs';
const dir = path.join(resolveRoot(), 'craft');
failIfMissing(dir, 'craft');
row(['slug', 'title', 'description']);
const entries = fs.readdirSync(dir, { withFileTypes: true })
.filter((e) => e.isFile() && e.name.endsWith('.md'))
.map((e) => e.name)
.filter((n) => n.toUpperCase() !== 'README.MD' && !n.startsWith('_'))
.sort();
for (const name of entries) {
const slug = name.replace(/\.md$/, '');
const h = parseCraftHeader(path.join(dir, name));
row([slug, h.title, h.description]);
}
#!/usr/bin/env node
// List Open Design design systems (DESIGN.md brand specifications).
// Output: TSV with header. Columns:
// slug title category description
//
// Reads from $OPEN_DESIGN_ROOT (default ~/.open-design-skill/repo).
import fs from 'node:fs';
import path from 'node:path';
import { resolveRoot, failIfMissing, listSubdirs, parseDesignSystemHeader, row } from './_parse.mjs';
const dir = path.join(resolveRoot(), 'design-systems');
failIfMissing(dir, 'design-systems');
row(['slug', 'title', 'category', 'description']);
for (const [slug, full] of listSubdirs(dir)) {
const designPath = path.join(full, 'DESIGN.md');
if (!fs.existsSync(designPath)) continue;
const h = parseDesignSystemHeader(designPath);
row([slug, h.title, h.category, h.description]);
}
#!/usr/bin/env node
// List Open Design rendering templates (decks, prototypes, image/video/audio).
// Output: TSV with header. Columns:
// slug mode category upstream name description triggers
//
// Reads from $OPEN_DESIGN_ROOT (default ~/.open-design-skill/repo).
import fs from 'node:fs';
import path from 'node:path';
import { resolveRoot, failIfMissing, listSubdirs, parseSkillFrontmatter, row } from './_parse.mjs';
const dir = path.join(resolveRoot(), 'design-templates');
failIfMissing(dir, 'design-templates');
row(['slug', 'mode', 'category', 'upstream', 'name', 'description', 'triggers']);
for (const [slug, full] of listSubdirs(dir)) {
const skillPath = path.join(full, 'SKILL.md');
if (!fs.existsSync(skillPath)) continue;
const fm = parseSkillFrontmatter(skillPath);
row([
slug,
fm.od.mode,
fm.od.category,
fm.od.upstream,
fm.name,
fm.description,
fm.triggers.length ? fm.triggers.join(', ') : '',
]);
}
#!/usr/bin/env node
// List Open Design functional skills (utilities, briefs, audits).
// Note: ~half of these are "stub" pointers (od.upstream is set) — they
// advertise the capability but the runnable workflow lives in the upstream
// repo. The agent should flag those in the picker so users can install the
// upstream bundle if they actually want to run it.
//
// Output: TSV with header. Columns:
// slug mode category upstream name description triggers
//
// Reads from $OPEN_DESIGN_ROOT (default ~/.open-design-skill/repo).
import fs from 'node:fs';
import path from 'node:path';
import { resolveRoot, failIfMissing, listSubdirs, parseSkillFrontmatter, row } from './_parse.mjs';
const dir = path.join(resolveRoot(), 'skills');
failIfMissing(dir, 'skills');
row(['slug', 'mode', 'category', 'upstream', 'name', 'description', 'triggers']);
for (const [slug, full] of listSubdirs(dir)) {
const skillPath = path.join(full, 'SKILL.md');
if (!fs.existsSync(skillPath)) continue;
const fm = parseSkillFrontmatter(skillPath);
row([
slug,
fm.od.mode,
fm.od.category,
fm.od.upstream,
fm.name,
fm.description,
fm.triggers.length ? fm.triggers.join(', ') : '',
]);
}