skillui 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,195 @@
1
+ # skillui
2
+
3
+ **Reverse-engineer any design system. Pure static analysis — no AI, no API keys.**
4
+
5
+ Point `skillui` at any website, git repo, or local project and get exact colors, fonts, spacing, components, and animations — packaged as a `.skill` file Claude can read.
6
+
7
+ ```bash
8
+ npm install -g skillui
9
+ skillui --url https://yoursite.com --mode ultra
10
+ ```
11
+
12
+ ---
13
+
14
+ ## What it does
15
+
16
+ skillui crawls your target and extracts:
17
+
18
+ | Output | Contents |
19
+ |--------|----------|
20
+ | `DESIGN.md` | Colors, typography, spacing, border radius, components |
21
+ | `ANIMATIONS.md` | CSS keyframes, scroll triggers, GSAP/Lottie/Three.js detection |
22
+ | `LAYOUT.md` | Flex/grid containers, page structure, spacing relationships |
23
+ | `COMPONENTS.md` | DOM patterns, HTML fingerprints, class analysis |
24
+ | `INTERACTIONS.md` | Hover/focus state diffs with before/after style snapshots |
25
+ | `VISUAL_GUIDE.md` | Master visual reference with all screenshots embedded |
26
+ | `screens/scroll/` | 7 cinematic scroll journey screenshots |
27
+ | `tokens/*.json` | Colors, spacing, typography as JSON tokens |
28
+ | `fonts/` | Google Fonts bundled locally |
29
+
30
+ Everything is packaged into a `.skill` ZIP file you drop into Claude Code.
31
+
32
+ ---
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ npm install -g skillui
38
+ ```
39
+
40
+ Requires Node.js 18+.
41
+
42
+ For ultra mode visual extraction, install Playwright separately:
43
+
44
+ ```bash
45
+ npm install playwright
46
+ npx playwright install chromium
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Usage
52
+
53
+ ### Crawl a website
54
+
55
+ ```bash
56
+ skillui --url https://linear.app
57
+ ```
58
+
59
+ ### Ultra mode (full cinematic extraction)
60
+
61
+ ```bash
62
+ skillui --url https://linear.app --mode ultra
63
+ ```
64
+
65
+ Ultra mode adds:
66
+ - 7 scroll journey screenshots showing the page at each scroll depth
67
+ - Hover/focus interaction state diffs
68
+ - Full CSS keyframe extraction
69
+ - Animation library detection (GSAP, Lottie, Three.js, AOS, etc.)
70
+ - Video background first-frame capture
71
+ - DOM component fingerprinting
72
+ - Flex/grid layout extraction
73
+
74
+ ### Scan a local project
75
+
76
+ ```bash
77
+ skillui --dir ./my-app
78
+ ```
79
+
80
+ ### Clone and scan a git repo
81
+
82
+ ```bash
83
+ skillui --repo https://github.com/org/repo
84
+ ```
85
+
86
+ ---
87
+
88
+ ## All flags
89
+
90
+ ```
91
+ skillui --url <url> Crawl a live website
92
+ skillui --dir <path> Scan a local project directory
93
+ skillui --repo <url> Clone and scan a git repository
94
+
95
+ --mode ultra Enable cinematic extraction (requires Playwright)
96
+ --screens <n> Pages to crawl in ultra mode (default: 5, max: 20)
97
+ --out <path> Output directory (default: ./)
98
+ --name <string> Override the project name
99
+ --format design-md|skill|both Output format (default: both)
100
+ --no-skill Output DESIGN.md only, skip .skill packaging
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Use with Claude Code
106
+
107
+ After running skillui, install the `.skill` file:
108
+
109
+ ```bash
110
+ claude skill install ./linear-design.skill
111
+ ```
112
+
113
+ Then ask Claude:
114
+
115
+ > "Build me a dashboard that matches the Linear design system"
116
+
117
+ Claude will read DESIGN.md, ANIMATIONS.md, LAYOUT.md, COMPONENTS.md, and all scroll journey screenshots to reconstruct the exact visual language of the site.
118
+
119
+ ---
120
+
121
+ ## Output structure
122
+
123
+ ```
124
+ linear-design/
125
+ ├── SKILL.md # Master skill file (loaded by Claude)
126
+ ├── DESIGN.md # Full design system tokens
127
+ ├── references/
128
+ │ ├── DESIGN.md # Extended design reference
129
+ │ ├── ANIMATIONS.md # Motion specs and keyframes
130
+ │ ├── LAYOUT.md # Layout containers and grid
131
+ │ ├── COMPONENTS.md # DOM component patterns
132
+ │ ├── INTERACTIONS.md # Hover/focus state diffs
133
+ │ └── VISUAL_GUIDE.md # All screenshots in sequence
134
+ ├── screens/
135
+ │ ├── scroll/ # Scroll journey screenshots
136
+ │ │ ├── scroll-000.png # Hero / above the fold
137
+ │ │ ├── scroll-017.png
138
+ │ │ ├── scroll-033.png
139
+ │ │ ├── scroll-050.png
140
+ │ │ ├── scroll-067.png
141
+ │ │ ├── scroll-083.png
142
+ │ │ └── scroll-100.png # Footer
143
+ │ ├── pages/ # Full-page screenshots (ultra)
144
+ │ └── sections/ # Section clip screenshots (ultra)
145
+ ├── tokens/
146
+ │ ├── colors.json
147
+ │ ├── spacing.json
148
+ │ └── typography.json
149
+ └── fonts/ # Bundled Google Fonts (woff2)
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Examples
155
+
156
+ ```bash
157
+ # Extract Nothing.tech design system with full ultra mode
158
+ skillui --url https://nothing.tech --mode ultra --screens 10
159
+
160
+ # Scan a local Next.js app
161
+ skillui --dir ./my-nextjs-app --name "MyApp"
162
+
163
+ # Clone and analyze a public repo
164
+ skillui --repo https://github.com/vercel/next.js --name "Next.js"
165
+
166
+ # Output only DESIGN.md, no .skill packaging
167
+ skillui --url https://stripe.com --format design-md
168
+
169
+ # Save output to a specific directory
170
+ skillui --url https://linear.app --out ./design-systems
171
+ ```
172
+
173
+ ---
174
+
175
+ ## How it works
176
+
177
+ skillui uses pure static analysis — no AI, no API keys, no cloud.
178
+
179
+ 1. **URL mode** — fetches HTML, crawls all linked CSS files, extracts computed styles via Playwright DOM inspection
180
+ 2. **Dir mode** — scans all `.css`, `.scss`, `.ts`, `.tsx`, `.js`, `.jsx` files for design tokens, Tailwind config, CSS variables, and component patterns
181
+ 3. **Repo mode** — clones the repo to a temp directory and runs dir mode
182
+ 4. **Ultra mode** — runs Playwright to capture scroll journey screenshots, detect animation libraries from `window.*` globals, extract `@keyframes` from `document.styleSheets`, capture hover/focus state diffs, and fingerprint DOM components
183
+
184
+ ---
185
+
186
+ ## Requirements
187
+
188
+ - Node.js 18+
189
+ - For `--mode ultra`: Playwright (`npm install playwright && npx playwright install chromium`)
190
+
191
+ ---
192
+
193
+ ## License
194
+
195
+ MIT
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.captureAnimations = captureAnimations;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
+ const playwright_loader_1 = require("../../playwright-loader");
39
40
  /**
40
41
  * Ultra mode — Full Animation Extractor
41
42
  *
@@ -67,13 +68,9 @@ async function captureAnimations(url, skillDir) {
67
68
  webglDetected: false,
68
69
  lottieCount: 0,
69
70
  };
70
- let playwright;
71
- try {
72
- playwright = require('playwright');
73
- }
74
- catch {
71
+ const playwright = (0, playwright_loader_1.loadPlaywright)();
72
+ if (!playwright)
75
73
  return empty;
76
- }
77
74
  const scrollDir = path.join(skillDir, 'screens', 'scroll');
78
75
  fs.mkdirSync(scrollDir, { recursive: true });
79
76
  const browser = await playwright.chromium.launch({ headless: true });
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.detectDOMComponents = detectDOMComponents;
4
+ const playwright_loader_1 = require("../../playwright-loader");
4
5
  /**
5
6
  * Ultra mode — DOM Component Detector
6
7
  *
@@ -12,13 +13,9 @@ exports.detectDOMComponents = detectDOMComponents;
12
13
  * Requires Playwright (optional peer dependency).
13
14
  */
14
15
  async function detectDOMComponents(url) {
15
- let playwright;
16
- try {
17
- playwright = require('playwright');
18
- }
19
- catch {
16
+ const playwright = (0, playwright_loader_1.loadPlaywright)();
17
+ if (!playwright)
20
18
  return [];
21
- }
22
19
  const browser = await playwright.chromium.launch({ headless: true });
23
20
  try {
24
21
  const context = await browser.newContext({
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.captureInteractions = captureInteractions;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
+ const playwright_loader_1 = require("../../playwright-loader");
39
40
  const TRACKED_PROPS = [
40
41
  'backgroundColor',
41
42
  'color',
@@ -67,13 +68,9 @@ const INTERACTIVE_SELECTORS = [
67
68
  * Returns InteractionRecord[] for INTERACTIONS.md generation.
68
69
  */
69
70
  async function captureInteractions(url, skillDir) {
70
- let playwright;
71
- try {
72
- playwright = require('playwright');
73
- }
74
- catch {
71
+ const playwright = (0, playwright_loader_1.loadPlaywright)();
72
+ if (!playwright)
75
73
  return [];
76
- }
77
74
  const statesDir = path.join(skillDir, 'screens', 'states');
78
75
  fs.mkdirSync(statesDir, { recursive: true });
79
76
  const records = [];
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.extractLayouts = extractLayouts;
4
+ const playwright_loader_1 = require("../../playwright-loader");
4
5
  /**
5
6
  * Ultra mode — DOM Layout Extractor
6
7
  *
@@ -13,13 +14,9 @@ exports.extractLayouts = extractLayouts;
13
14
  * Requires Playwright (optional peer dependency).
14
15
  */
15
16
  async function extractLayouts(url) {
16
- let playwright;
17
- try {
18
- playwright = require('playwright');
19
- }
20
- catch {
17
+ const playwright = (0, playwright_loader_1.loadPlaywright)();
18
+ if (!playwright)
21
19
  return [];
22
- }
23
20
  const browser = await playwright.chromium.launch({ headless: true });
24
21
  try {
25
22
  const context = await browser.newContext({
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.capturePageScreenshots = capturePageScreenshots;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
+ const playwright_loader_1 = require("../../playwright-loader");
39
40
  /**
40
41
  * Ultra mode — Page & Section Screenshots
41
42
  *
@@ -47,13 +48,9 @@ const path = __importStar(require("path"));
47
48
  * Requires Playwright (optional peer dependency).
48
49
  */
49
50
  async function capturePageScreenshots(originUrl, skillDir, maxPages) {
50
- let playwright;
51
- try {
52
- playwright = require('playwright');
53
- }
54
- catch {
51
+ const playwright = (0, playwright_loader_1.loadPlaywright)();
52
+ if (!playwright)
55
53
  return { pages: [], sections: [] };
56
- }
57
54
  const pagesDir = path.join(skillDir, 'screens', 'pages');
58
55
  const sectionsDir = path.join(skillDir, 'screens', 'sections');
59
56
  fs.mkdirSync(pagesDir, { recursive: true });
@@ -46,6 +46,7 @@ const interactions_md_1 = require("../writers/interactions-md");
46
46
  const components_md_1 = require("../writers/components-md");
47
47
  const animations_md_1 = require("../writers/animations-md");
48
48
  const tokens_json_1 = require("../writers/tokens-json");
49
+ const playwright_loader_1 = require("../playwright-loader");
49
50
  /**
50
51
  * Ultra mode orchestrator.
51
52
  *
@@ -72,15 +73,10 @@ async function runUltraMode(url, profile, skillDir, opts) {
72
73
  fs.mkdirSync(path.join(skillDir, 'screens', 'scroll'), { recursive: true });
73
74
  fs.mkdirSync(path.join(skillDir, 'references'), { recursive: true });
74
75
  fs.mkdirSync(path.join(skillDir, 'tokens'), { recursive: true });
75
- let hasPlaywright = false;
76
- try {
77
- require.resolve('playwright');
78
- hasPlaywright = true;
79
- }
80
- catch { /* not installed */ }
76
+ const hasPlaywright = (0, playwright_loader_1.loadPlaywright)() !== null;
81
77
  if (!hasPlaywright) {
82
- process.stdout.write('\n ⚠ Playwright not installed — ultra visual features skipped\n');
83
- process.stdout.write(' Run: npm install playwright && npx playwright install chromium\n\n');
78
+ process.stdout.write('\n ⚠ Playwright not found — ultra visual features skipped\n');
79
+ process.stdout.write(' Fix: npm install -g playwright && npx playwright install chromium\n\n');
84
80
  (0, tokens_json_1.writeTokensJson)(profile, skillDir);
85
81
  writeStubs(skillDir);
86
82
  const emptyAnim = emptyAnimResult();
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Loads playwright from any location it might be installed:
3
+ * 1. Bundled with the CLI (peer dep)
4
+ * 2. In the user's cwd node_modules (local project install)
5
+ * 3. In the global npm prefix (npm install -g playwright)
6
+ *
7
+ * Returns the playwright module or null if not found anywhere.
8
+ */
9
+ export declare function loadPlaywright(): any | null;
10
+ //# sourceMappingURL=playwright-loader.d.ts.map
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadPlaywright = loadPlaywright;
37
+ const path = __importStar(require("path"));
38
+ const child_process_1 = require("child_process");
39
+ /**
40
+ * Loads playwright from any location it might be installed:
41
+ * 1. Bundled with the CLI (peer dep)
42
+ * 2. In the user's cwd node_modules (local project install)
43
+ * 3. In the global npm prefix (npm install -g playwright)
44
+ *
45
+ * Returns the playwright module or null if not found anywhere.
46
+ */
47
+ function loadPlaywright() {
48
+ // 1. Try standard require (works when playwright is in same node_modules tree)
49
+ try {
50
+ return require('playwright');
51
+ }
52
+ catch { /* fall through */ }
53
+ // 2. Try from cwd (user ran: npm install playwright in their project)
54
+ try {
55
+ const cwdPath = path.join(process.cwd(), 'node_modules', 'playwright');
56
+ return require(cwdPath);
57
+ }
58
+ catch { /* fall through */ }
59
+ // 3. Try from global npm prefix (npm install -g playwright)
60
+ try {
61
+ const globalRoot = (0, child_process_1.execSync)('npm root -g', {
62
+ encoding: 'utf-8',
63
+ stdio: ['ignore', 'pipe', 'ignore'],
64
+ timeout: 5000,
65
+ }).trim();
66
+ return require(path.join(globalRoot, 'playwright'));
67
+ }
68
+ catch { /* fall through */ }
69
+ return null;
70
+ }
71
+ //# sourceMappingURL=playwright-loader.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillui",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Reverse-engineer design systems from any website, repo, or project. Extracts colors, fonts, spacing, animations, and components — packaged as a .skill file for Claude. Pure static analysis, zero AI, zero API keys.",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {
@@ -30,13 +30,13 @@
30
30
  ],
31
31
  "author": "Amaan",
32
32
  "license": "MIT",
33
- "homepage": "https://github.com/amaanbuilds/skillui#readme",
33
+ "homepage": "https://skillui.vercel.app/",
34
34
  "repository": {
35
35
  "type": "git",
36
- "url": "https://github.com/amaanbuilds/skillui.git"
36
+ "url": "https://github.com/amaancoderx/skillui.git"
37
37
  },
38
38
  "bugs": {
39
- "url": "https://github.com/amaanbuilds/skillui/issues"
39
+ "url": "https://github.com/amaancoderx/skillui/issues"
40
40
  },
41
41
  "dependencies": {
42
42
  "@babel/parser": "^7.24.0",
@@ -73,6 +73,7 @@
73
73
  },
74
74
  "files": [
75
75
  "dist/**/*.js",
76
- "dist/**/*.d.ts"
76
+ "dist/**/*.d.ts",
77
+ "README.md"
77
78
  ]
78
79
  }