@fr0mpy/component-system 2.1.1 → 3.1.0

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.
Files changed (51) hide show
  1. package/README.md +86 -27
  2. package/bin/cli.js +155 -50
  3. package/bin/validate-compliance.js +447 -0
  4. package/bin/validate-config.js +175 -0
  5. package/bin/validate-harness.js +215 -0
  6. package/index.js +15 -0
  7. package/package.json +7 -4
  8. package/templates/agents/component-auditor.md +77 -0
  9. package/templates/agents/design-token-validator.md +72 -0
  10. package/templates/agents/harness-scaffolder.md +146 -0
  11. package/templates/agents/playwright-tester.md +437 -0
  12. package/templates/agents/style-inspector.md +81 -0
  13. package/templates/commands/component-harness.md +104 -10
  14. package/templates/commands/retheme.md +142 -0
  15. package/templates/commands/save-theme.md +50 -0
  16. package/templates/commands/setup-styling.md +386 -57
  17. package/templates/component-recipes/accordion.md +9 -9
  18. package/templates/component-recipes/alert.md +36 -23
  19. package/templates/component-recipes/avatar.md +14 -12
  20. package/templates/component-recipes/badge.md +9 -6
  21. package/templates/component-recipes/breadcrumb.md +4 -4
  22. package/templates/component-recipes/button.md +2 -2
  23. package/templates/component-recipes/checkbox.md +5 -5
  24. package/templates/component-recipes/collapsible.md +13 -13
  25. package/templates/component-recipes/combobox.md +2 -2
  26. package/templates/component-recipes/context-menu.md +11 -11
  27. package/templates/component-recipes/dialog.md +16 -16
  28. package/templates/component-recipes/drawer.md +18 -18
  29. package/templates/component-recipes/dropdown-menu.md +12 -12
  30. package/templates/component-recipes/hover-card.md +11 -11
  31. package/templates/component-recipes/label.md +4 -4
  32. package/templates/component-recipes/modal.md +9 -9
  33. package/templates/component-recipes/navigation-menu.md +19 -19
  34. package/templates/component-recipes/popover.md +10 -10
  35. package/templates/component-recipes/progress.md +10 -8
  36. package/templates/component-recipes/radio.md +6 -6
  37. package/templates/component-recipes/select.md +5 -5
  38. package/templates/component-recipes/separator.md +2 -2
  39. package/templates/component-recipes/slider.md +2 -2
  40. package/templates/component-recipes/switch.md +6 -6
  41. package/templates/component-recipes/table.md +1 -1
  42. package/templates/component-recipes/tabs.md +6 -6
  43. package/templates/component-recipes/toast.md +56 -42
  44. package/templates/component-recipes/toggle-group.md +4 -4
  45. package/templates/component-recipes/tooltip.md +5 -5
  46. package/templates/mcp/mcp.json +8 -0
  47. package/templates/playwright/playwright.config.ts +31 -0
  48. package/templates/playwright/tests/components.spec.ts +104 -0
  49. package/templates/skills/react-patterns.md +141 -0
  50. package/templates/skills/styling.md +141 -52
  51. package/templates/hooks/triggers.d/styling.json +0 -23
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @fr0mpy/component-system
2
2
 
3
- Claude Code UI styling system with design tokens, 36 component recipes, and visual preview harness.
3
+ Claude Code UI styling system with multi-theme support, design tokens, component agents, 40 Base UI recipes, and Playwright testing.
4
4
 
5
5
  ## Installation
6
6
 
@@ -10,36 +10,92 @@ npx @fr0mpy/component-system
10
10
 
11
11
  ## What's Included
12
12
 
13
- - **skills/** - Styling skill for consistent UI generation
14
- - **component-recipes/** - 36 pre-built component templates (button, card, modal, toast, etc.)
15
- - **commands/** - `/setup-styling` and `/component-harness`
13
+ | Directory | Purpose |
14
+ |-----------|---------|
15
+ | `skills/` | Styling + React patterns skills |
16
+ | `agents/` | 5 component system agents |
17
+ | `component-recipes/` | 40 Base UI component templates |
18
+ | `playwright-templates/` | Playwright test config + component specs |
19
+ | `commands/` | `/setup-styling`, `/component-harness`, `/save-theme`, `/retheme` |
20
+ | `.mcp.json` | Playwright MCP server configuration |
16
21
 
17
- ## Features
22
+ ## Multi-Theme System
18
23
 
19
- ### Design Tokens
24
+ Create and switch between multiple themes in real-time:
20
25
 
21
- Run `/setup-styling` to configure your design system interactively. Generates `styling-config.json` with:
26
+ ```
27
+ .claude/
28
+ ├── styling-config.json # Active theme config
29
+ ├── themes/ # Saved themes
30
+ │ ├── stripe-inspired.json
31
+ │ ├── matrix.json
32
+ │ └── vercel-dark.json
33
+ └── component-recipes/ # Component templates
34
+ ```
35
+
36
+ ### Workflow
37
+
38
+ 1. **Create themes** via `/setup-styling`:
39
+ - Extract from URL (analyzes any website's design system)
40
+ - Manual configuration (answer questions about colors, typography)
41
+ - Saves to both `styling-config.json` and `themes/{name}.json`
42
+
43
+ 2. **Switch themes** in the component harness:
44
+ - ThemeSwitcher dropdown loads all `.claude/themes/*.json`
45
+ - Live switching via CSS variable injection
46
+ - No page reload required
47
+
48
+ 3. **Quick commands**:
49
+ - `/save-theme [name]` - Save current config as a named theme
50
+ - `/retheme` - Regenerate CSS from current config
51
+
52
+ ## Commands
53
+
54
+ | Command | Purpose |
55
+ |---------|---------|
56
+ | `/setup-styling` | Configure design tokens, creates theme |
57
+ | `/component-harness` | Launch visual preview with theme switcher |
58
+ | `/save-theme` | Save current config as named theme |
59
+ | `/retheme` | Regenerate harness CSS from config |
60
+
61
+ ## Agents (5)
62
+
63
+ | Agent | Purpose |
64
+ |-------|---------|
65
+ | style-inspector | Reverse-engineers website design systems from URLs |
66
+ | design-token-validator | Audits components for token compliance |
67
+ | component-auditor | Validates recipe compliance, a11y, React patterns |
68
+ | harness-scaffolder | Scaffolds Vite preview gallery from recipes |
69
+ | playwright-tester | Tests components via Playwright MCP with Axe a11y |
70
+
71
+ ## Skills (2)
72
+
73
+ | Skill | Purpose |
74
+ |-------|---------|
75
+ | styling | Enforces design token usage, mobile-first patterns, recipe compliance |
76
+ | react-patterns | Enforces Rules of Hooks and correct state/effect patterns |
22
77
 
23
- - Colors (primary, secondary, destructive, muted, etc.)
24
- - Border radius
25
- - Shadows
26
- - Spacing
27
- - Typography
78
+ ## Component Recipes (40)
28
79
 
29
- ### Component Recipes
80
+ | Category | Components |
81
+ |----------|------------|
82
+ | **Form (10)** | button, input, textarea, select, combobox, checkbox, radio, switch, slider, label |
83
+ | **Layout (6)** | card, separator, collapsible, accordion, tabs, table |
84
+ | **Navigation (5)** | navigation-menu, breadcrumb, pagination, dropdown-menu, context-menu |
85
+ | **Overlay (6)** | modal, dialog, drawer, popover, hover-card, tooltip |
86
+ | **Feedback (5)** | alert, toast, progress, skeleton, spinner |
87
+ | **Display (4)** | badge, avatar, carousel, toggle-group |
30
88
 
31
- 36 component recipes organized by category:
89
+ All recipes use [Base UI](https://base-ui.com) headless primitives for accessibility with Tailwind CSS styling.
32
90
 
33
- - **Form** (10): button, input, textarea, select, combobox, checkbox, radio, switch, slider, label
34
- - **Layout** (6): card, separator, collapsible, accordion, tabs, table
35
- - **Navigation** (5): navigation-menu, breadcrumb, pagination, dropdown-menu, context-menu
36
- - **Overlay** (6): modal, dialog, drawer, popover, hover-card, tooltip
37
- - **Feedback** (5): alert, toast, progress, skeleton, spinner
38
- - **Display** (4): badge, avatar, carousel, toggle-group
91
+ ## Component Harness
39
92
 
40
- ### Component Harness
93
+ Run `/component-harness` to scaffold a Vite + React preview environment:
41
94
 
42
- Run `/component-harness` to scaffold a Vite + React development environment for visual component preview.
95
+ - **Theme Switcher** - Dropdown to switch between saved themes
96
+ - **Live Preview** - All 40 components with variants
97
+ - **Instant Updates** - CSS variable injection, no page reload
98
+ - **Playwright Testing** - Visual + accessibility testing via MCP
43
99
 
44
100
  ## Usage
45
101
 
@@ -47,13 +103,14 @@ Run `/component-harness` to scaffold a Vite + React development environment for
47
103
  # Initialize
48
104
  npx @fr0mpy/component-system
49
105
 
50
- # With options
106
+ # Options
51
107
  npx @fr0mpy/component-system --force # Overwrite existing
52
108
  npx @fr0mpy/component-system --merge # Add to existing .claude
53
109
  npx @fr0mpy/component-system --remove # Remove installation
54
110
 
55
111
  # Selective updates
56
112
  npx @fr0mpy/component-system --update-skills
113
+ npx @fr0mpy/component-system --update-agents
57
114
  npx @fr0mpy/component-system --update-recipes
58
115
  npx @fr0mpy/component-system --update-commands
59
116
  ```
@@ -61,18 +118,20 @@ npx @fr0mpy/component-system --update-commands
61
118
  ## Getting Started
62
119
 
63
120
  1. Install: `npx @fr0mpy/component-system`
64
- 2. Configure: Use `/setup-styling` to set up your design tokens
65
- 3. Preview: Use `/component-harness` to launch visual preview
121
+ 2. Configure: `/setup-styling` to create your first theme
122
+ 3. Preview: `/component-harness` to launch visual gallery
123
+ 4. Add themes: Run `/setup-styling` again to create more themes
124
+ 5. Switch: Use the ThemeSwitcher dropdown in the harness
66
125
 
67
126
  ## Integration with Prompt System
68
127
 
69
- For auto-triggering styling rules when you mention UI/styling keywords, also install:
128
+ For additional agents and context management:
70
129
 
71
130
  ```bash
72
131
  npx @fr0mpy/prompt-system
73
132
  ```
74
133
 
75
- When both packages are installed, the component system injects a `styling.json` trigger into the prompt system's `triggers.d/` directory.
134
+ Skills are automatically discovered via their `USE WHEN` descriptions in YAML frontmatter.
76
135
 
77
136
  ## License
78
137
 
package/bin/cli.js CHANGED
@@ -5,6 +5,7 @@ const path = require('path');
5
5
 
6
6
  const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
7
7
  const TARGET_DIR = path.join(process.cwd(), '.claude');
8
+ const PROJECT_ROOT = process.cwd();
8
9
  const args = process.argv.slice(2);
9
10
 
10
11
  // Parse flags
@@ -16,7 +17,8 @@ const helpMode = hasFlag('--help', '-h');
16
17
  const updateSkills = hasFlag('--update-skills');
17
18
  const updateRecipes = hasFlag('--update-recipes');
18
19
  const updateCommands = hasFlag('--update-commands');
19
- const updateMode = updateSkills || updateRecipes || updateCommands;
20
+ const updateAgents = hasFlag('--update-agents');
21
+ const updateMode = updateSkills || updateRecipes || updateCommands || updateAgents;
20
22
 
21
23
  function copyDir(src, dest) {
22
24
  fs.mkdirSync(dest, { recursive: true });
@@ -52,25 +54,20 @@ function copySubdir(subdir) {
52
54
  return true;
53
55
  }
54
56
 
55
- function injectStylingTrigger() {
56
- const triggersDDir = path.join(TARGET_DIR, 'hooks', 'triggers.d');
57
- const stylingTriggerSrc = path.join(TEMPLATES_DIR, 'hooks', 'triggers.d', 'styling.json');
58
- const stylingTriggerDest = path.join(triggersDDir, 'styling.json');
59
-
60
- if (fs.existsSync(triggersDDir) && fs.existsSync(stylingTriggerSrc)) {
61
- fs.copyFileSync(stylingTriggerSrc, stylingTriggerDest);
62
- return true;
57
+ function mergeJsonFile(src, dest) {
58
+ if (!fs.existsSync(src)) return false;
59
+ const srcData = JSON.parse(fs.readFileSync(src, 'utf8'));
60
+ let destData = {};
61
+ if (fs.existsSync(dest)) {
62
+ try { destData = JSON.parse(fs.readFileSync(dest, 'utf8')); } catch (e) { /* invalid JSON */ }
63
63
  }
64
- return false;
65
- }
66
-
67
- function removeStylingTrigger() {
68
- const stylingTrigger = path.join(TARGET_DIR, 'hooks', 'triggers.d', 'styling.json');
69
- if (fs.existsSync(stylingTrigger)) {
70
- fs.unlinkSync(stylingTrigger);
71
- return true;
64
+ const merged = { ...destData, ...srcData };
65
+ // Deep merge mcpServers if both exist
66
+ if (destData.mcpServers && srcData.mcpServers) {
67
+ merged.mcpServers = { ...destData.mcpServers, ...srcData.mcpServers };
72
68
  }
73
- return false;
69
+ fs.writeFileSync(dest, JSON.stringify(merged, null, 2) + '\n');
70
+ return true;
74
71
  }
75
72
 
76
73
  async function init() {
@@ -83,7 +80,7 @@ async function init() {
83
80
  if (componentSystemExists && !forceMode && !mergeMode) {
84
81
  console.log('⚠️ Component system already exists in .claude/');
85
82
  console.log(' Use --force to overwrite, --merge to update, or use selective updates:');
86
- console.log(' --update-skills, --update-recipes, --update-commands\n');
83
+ console.log(' --update-skills, --update-recipes, --update-commands, --update-agents\n');
87
84
  process.exit(1);
88
85
  }
89
86
 
@@ -96,14 +93,39 @@ async function init() {
96
93
  fs.mkdirSync(TARGET_DIR, { recursive: true });
97
94
 
98
95
  if (forceMode && componentSystemExists) {
99
- // Only remove component-system specific dirs
100
- const componentDirs = ['skills', 'component-recipes'];
101
- for (const dir of componentDirs) {
102
- const dirPath = path.join(TARGET_DIR, dir);
103
- if (fs.existsSync(dirPath)) {
104
- fs.rmSync(dirPath, { recursive: true });
96
+ // Remove component-system specific skill files (preserve prompt-system skills)
97
+ const componentSkills = ['styling.md', 'react-patterns.md', 'style-inspector.md'];
98
+ const skillsDir = path.join(TARGET_DIR, 'skills');
99
+ if (fs.existsSync(skillsDir)) {
100
+ for (const skill of componentSkills) {
101
+ const skillPath = path.join(skillsDir, skill);
102
+ if (fs.existsSync(skillPath)) {
103
+ fs.unlinkSync(skillPath);
104
+ }
105
105
  }
106
106
  }
107
+
108
+ // Remove component-system specific agent files
109
+ const componentAgents = [
110
+ 'style-inspector.md', 'design-token-validator.md',
111
+ 'component-auditor.md', 'harness-scaffolder.md', 'playwright-tester.md'
112
+ ];
113
+ const agentsDir = path.join(TARGET_DIR, 'agents');
114
+ if (fs.existsSync(agentsDir)) {
115
+ for (const agent of componentAgents) {
116
+ const agentPath = path.join(agentsDir, agent);
117
+ if (fs.existsSync(agentPath)) {
118
+ fs.unlinkSync(agentPath);
119
+ }
120
+ }
121
+ }
122
+
123
+ // Remove component-recipes entirely (owned by component-system)
124
+ const recipesDir = path.join(TARGET_DIR, 'component-recipes');
125
+ if (fs.existsSync(recipesDir)) {
126
+ fs.rmSync(recipesDir, { recursive: true });
127
+ }
128
+
107
129
  console.log('🗑️ Removed existing component system files.\n');
108
130
  }
109
131
 
@@ -111,6 +133,20 @@ async function init() {
111
133
  copyDir(path.join(TEMPLATES_DIR, 'skills'), path.join(TARGET_DIR, 'skills'));
112
134
  copyDir(path.join(TEMPLATES_DIR, 'component-recipes'), path.join(TARGET_DIR, 'component-recipes'));
113
135
 
136
+ // Copy agents (merge into existing agents dir if prompt-system is installed)
137
+ const agentsDir = path.join(TARGET_DIR, 'agents');
138
+ fs.mkdirSync(agentsDir, { recursive: true });
139
+ copyDir(path.join(TEMPLATES_DIR, 'agents'), agentsDir);
140
+
141
+ // Migrate: remove style-inspector from skills if it exists (now an agent)
142
+ const oldStyleInspector = path.join(TARGET_DIR, 'skills', 'style-inspector.md');
143
+ if (fs.existsSync(oldStyleInspector)) {
144
+ fs.unlinkSync(oldStyleInspector);
145
+ }
146
+
147
+ // Copy Playwright templates (staged for harness scaffolding)
148
+ copyDir(path.join(TEMPLATES_DIR, 'playwright'), path.join(TARGET_DIR, 'playwright-templates'));
149
+
114
150
  // Copy styling commands
115
151
  const commandsDir = path.join(TARGET_DIR, 'commands');
116
152
  fs.mkdirSync(commandsDir, { recursive: true });
@@ -123,21 +159,24 @@ async function init() {
123
159
  path.join(commandsDir, 'component-harness.md')
124
160
  );
125
161
 
162
+ // Merge MCP configuration into project .mcp.json
163
+ const mcpSrc = path.join(TEMPLATES_DIR, 'mcp', 'mcp.json');
164
+ const mcpDest = path.join(PROJECT_ROOT, '.mcp.json');
165
+ if (mergeJsonFile(mcpSrc, mcpDest)) {
166
+ console.log('✅ Configured Playwright MCP server in .mcp.json');
167
+ }
168
+
126
169
  console.log('✅ Created component system files:');
127
- console.log(' 📁 skills/ - Styling skill for UI generation');
128
- console.log(' 📁 component-recipes/ - 36 component templates');
170
+ console.log(' 📁 skills/ - Styling + React patterns skills');
171
+ console.log(' 📁 agents/ - 5 component system agents');
172
+ console.log(' 📁 component-recipes/ - 38 component templates');
173
+ console.log(' 📁 playwright-templates/ - Playwright test config + specs');
129
174
  console.log(' 📄 commands/setup-styling.md');
130
175
  console.log(' 📄 commands/component-harness.md\n');
131
176
 
132
- // Inject styling trigger if prompt-system is installed
133
- if (promptSystemExists) {
134
- if (injectStylingTrigger()) {
135
- console.log('✅ Injected styling trigger into prompt system.');
136
- console.log(' Styling-related prompts will now auto-trigger the styling skill.\n');
137
- }
138
- } else {
139
- console.log('ℹ️ Prompt system not detected.');
140
- console.log(' For auto-triggering styling rules, also install:');
177
+ // Suggest prompt-system if not installed
178
+ if (!promptSystemExists) {
179
+ console.log('💡 For agents and prompt management, also install:');
141
180
  console.log(' npx @fr0mpy/prompt-system\n');
142
181
  }
143
182
 
@@ -154,8 +193,21 @@ async function update() {
154
193
 
155
194
  const updates = [];
156
195
 
157
- if (updateSkills && copySubdir('skills')) updates.push('skills');
196
+ if (updateSkills && copySubdir('skills')) {
197
+ // Migrate: remove style-inspector from skills if it exists
198
+ const oldStyleInspector = path.join(TARGET_DIR, 'skills', 'style-inspector.md');
199
+ if (fs.existsSync(oldStyleInspector)) {
200
+ fs.unlinkSync(oldStyleInspector);
201
+ }
202
+ updates.push('skills');
203
+ }
158
204
  if (updateRecipes && copySubdir('component-recipes')) updates.push('component-recipes');
205
+ if (updateAgents) {
206
+ const agentsDir = path.join(TARGET_DIR, 'agents');
207
+ fs.mkdirSync(agentsDir, { recursive: true });
208
+ copyDir(path.join(TEMPLATES_DIR, 'agents'), agentsDir);
209
+ updates.push('agents');
210
+ }
159
211
  if (updateCommands) {
160
212
  const commandsDir = path.join(TARGET_DIR, 'commands');
161
213
  fs.mkdirSync(commandsDir, { recursive: true });
@@ -186,16 +238,47 @@ function remove() {
186
238
  // Check if prompt-system exists - if so, only remove component-system files
187
239
  const hasHooks = fs.existsSync(path.join(TARGET_DIR, 'hooks'));
188
240
 
189
- const componentDirs = ['skills', 'component-recipes'];
241
+ const componentSkills = ['styling.md', 'react-patterns.md', 'style-inspector.md'];
242
+ const componentAgents = [
243
+ 'style-inspector.md', 'design-token-validator.md',
244
+ 'component-auditor.md', 'harness-scaffolder.md', 'playwright-tester.md'
245
+ ];
190
246
  const componentCommands = ['setup-styling.md', 'component-harness.md'];
191
247
 
192
- for (const dir of componentDirs) {
193
- const dirPath = path.join(TARGET_DIR, dir);
194
- if (fs.existsSync(dirPath)) {
195
- fs.rmSync(dirPath, { recursive: true });
248
+ // Remove component-system specific skill files (preserve prompt-system skills)
249
+ const skillsDir = path.join(TARGET_DIR, 'skills');
250
+ if (fs.existsSync(skillsDir)) {
251
+ for (const skill of componentSkills) {
252
+ const skillPath = path.join(skillsDir, skill);
253
+ if (fs.existsSync(skillPath)) {
254
+ fs.unlinkSync(skillPath);
255
+ }
256
+ }
257
+ }
258
+
259
+ // Remove component-system specific agent files (preserve prompt-system agents)
260
+ const agentsDir = path.join(TARGET_DIR, 'agents');
261
+ if (fs.existsSync(agentsDir)) {
262
+ for (const agent of componentAgents) {
263
+ const agentPath = path.join(agentsDir, agent);
264
+ if (fs.existsSync(agentPath)) {
265
+ fs.unlinkSync(agentPath);
266
+ }
196
267
  }
197
268
  }
198
269
 
270
+ // Remove component-recipes entirely (owned by component-system)
271
+ const recipesDir = path.join(TARGET_DIR, 'component-recipes');
272
+ if (fs.existsSync(recipesDir)) {
273
+ fs.rmSync(recipesDir, { recursive: true });
274
+ }
275
+
276
+ // Remove playwright-templates (owned by component-system)
277
+ const playwrightDir = path.join(TARGET_DIR, 'playwright-templates');
278
+ if (fs.existsSync(playwrightDir)) {
279
+ fs.rmSync(playwrightDir, { recursive: true });
280
+ }
281
+
199
282
  // Remove styling commands
200
283
  const commandsDir = path.join(TARGET_DIR, 'commands');
201
284
  if (fs.existsSync(commandsDir)) {
@@ -207,15 +290,31 @@ function remove() {
207
290
  }
208
291
  }
209
292
 
210
- // Remove styling trigger
211
- removeStylingTrigger();
212
-
213
293
  // Remove styling-config.json if it exists
214
294
  const stylingConfig = path.join(TARGET_DIR, 'styling-config.json');
215
295
  if (fs.existsSync(stylingConfig)) {
216
296
  fs.unlinkSync(stylingConfig);
217
297
  }
218
298
 
299
+ // Clean up Playwright MCP config from .mcp.json
300
+ const mcpPath = path.join(PROJECT_ROOT, '.mcp.json');
301
+ if (fs.existsSync(mcpPath)) {
302
+ try {
303
+ const mcpConfig = JSON.parse(fs.readFileSync(mcpPath, 'utf8'));
304
+ if (mcpConfig.mcpServers?.playwright) {
305
+ delete mcpConfig.mcpServers.playwright;
306
+ if (Object.keys(mcpConfig.mcpServers).length === 0) {
307
+ delete mcpConfig.mcpServers;
308
+ }
309
+ if (Object.keys(mcpConfig).length === 0) {
310
+ fs.unlinkSync(mcpPath);
311
+ } else {
312
+ fs.writeFileSync(mcpPath, JSON.stringify(mcpConfig, null, 2) + '\n');
313
+ }
314
+ }
315
+ } catch (e) { /* .mcp.json may not be valid JSON */ }
316
+ }
317
+
219
318
  if (hasHooks) {
220
319
  console.log('✅ Removed component system files. Prompt system preserved.\n');
221
320
  } else {
@@ -244,6 +343,7 @@ Selective updates:
244
343
  --update-skills Update only skills/
245
344
  --update-recipes Update only component-recipes/
246
345
  --update-commands Update only styling commands
346
+ --update-agents Update only agents/
247
347
 
248
348
  Options:
249
349
  -h, --help Show this help message
@@ -252,16 +352,21 @@ Options:
252
352
  -r, --remove Remove component system (alias: --uninstall)
253
353
 
254
354
  What's included:
255
- • skills/ Styling skill for consistent UI generation
256
- component-recipes/ 36 pre-built component templates
257
- • commands/ /setup-styling, /component-harness
355
+ • skills/ Styling + React patterns skills
356
+ agents/ 5 component system agents (style-inspector,
357
+ design-token-validator, component-auditor,
358
+ harness-scaffolder, playwright-tester)
359
+ • component-recipes/ 38 pre-built component templates
360
+ • playwright-templates/ Playwright test config + component specs
361
+ • commands/ /setup-styling, /component-harness
362
+ • .mcp.json Playwright MCP server configuration
258
363
 
259
364
  Getting started:
260
365
  1. Run: npx @fr0mpy/component-system
261
366
  2. Use: /setup-styling to configure your design system
262
- 3. Use: /component-harness to preview components
367
+ 3. Use: /component-harness to preview and test components
263
368
 
264
- For prompt injection and agents:
369
+ For prompt injection and additional agents:
265
370
  npx @fr0mpy/prompt-system
266
371
 
267
372
  Learn more: https://github.com/fr0mpy/claude-base-setup