@worldresources/wri-design-systems 2.191.9 → 2.191.10-alpha-ds-cli

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 CHANGED
@@ -34,6 +34,40 @@ npm i @chakra-ui/react @emotion/react
34
34
 
35
35
  ## Usage
36
36
 
37
+ ### Set up AI tooling
38
+
39
+ Run the DS CLI to set up AI tooling for this design system in your project root (the directory where you run the command).
40
+
41
+ ```
42
+ ds setup-ai
43
+ ```
44
+
45
+ This will:
46
+
47
+ - Install / update AI instruction files (these may be overwritten):
48
+ - `AGENTS.md` content distributed as: `CLAUDE.md`, `GEMINI.md`, `.geminirules`
49
+ - Configure IDE integrations when detected:
50
+ - Cursor: writes `.cursor/rules` and creates `.cursor/mcp.json` (skips if it already exists)
51
+ - VS Code / GitHub Copilot: writes `copilot-instructions.md` and creates `.vscode/mcp.json` (skips if it already exists)
52
+ - Windsurf: writes `.windsurfrules`
53
+ - Cline: writes `.clinerules`
54
+ - Ensure a `.gitignore` block is present (creates `.gitignore` if missing; appends once and never duplicates):
55
+ - `CLAUDE.md`
56
+ - `.windsurfrules`
57
+ - `.clinerules`
58
+ - `copilot-instructions.md`
59
+ - `.cursor/rules`
60
+ - `.cursor/mcp.json`
61
+ - `.vscode/mcp.json`
62
+ - `GEMINI.md`
63
+ - `.geminirules`
64
+
65
+ Optional: run it against a specific path:
66
+
67
+ ```
68
+ ds setup-ai /path/to/your/project
69
+ ```
70
+
37
71
  ### Create the Project Theme
38
72
 
39
73
  With this custom theme you can change the color scheme according to your Project Theme
@@ -315,7 +349,7 @@ yarn lint-fix
315
349
  yarn build
316
350
  ```
317
351
 
318
- ## Publish new version
352
+ ## Publish new version (manual)
319
353
 
320
354
  ```
321
355
  npm login
@@ -0,0 +1,221 @@
1
+ # AI Agent Instructions — WRI Design System
2
+
3
+ This file provides context for AI coding agents working on WRI projects.
4
+ It is the **canonical source of truth** — do not edit the IDE-specific copies directly.
5
+ The setup script distributes this file to the correct location for each IDE.
6
+
7
+ ---
8
+
9
+ ## What is the WRI Design System?
10
+
11
+ `@worldresources/wri-design-systems` is the **standard component library for all World Resources Institute products**. It is built on top of Chakra UI v3 and provides WRI-branded, pre-styled components shared across multiple projects.
12
+
13
+ Because the library ships its own styles and design tokens, **do not override component styles with custom CSS**. Visual consistency across products depends on this.
14
+
15
+ | Resource | URL |
16
+ | ----------------- | ------------------------------------------------------------------------ |
17
+ | Storybook | https://wri.github.io/wri-design-systems/ |
18
+ | GitHub repo | https://github.com/wri/wri-design-systems |
19
+ | GitHub README | https://github.com/wri/wri-design-systems#readme |
20
+ | Component READMEs | `src/components/<Category>/<ComponentName>/README.md` in the GitHub repo |
21
+ | npm | https://www.npmjs.com/package/@worldresources/wri-design-systems |
22
+ | Style guide | https://zeroheight.com/4221801da |
23
+
24
+ ---
25
+
26
+ ## MCP Servers
27
+
28
+ Two MCP servers are configured for this project. **Query them before writing any component code** — never assume props or token names from memory.
29
+
30
+ ### Storybook MCP
31
+
32
+ Exposes WRI DS component stories, props, and usage patterns directly from the hosted Storybook.
33
+ Use it to verify: which WRI DS components exist, their props, and documented usage examples.
34
+
35
+ ```json
36
+ {
37
+ "mcpServers": {
38
+ "wri-storybook": {
39
+ "command": "npx",
40
+ "args": ["-y", "storybook-mcp@latest"],
41
+ "env": {
42
+ "STORYBOOK_URL": "https://wri.github.io/wri-design-systems/index.json"
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ### Chakra UI MCP
50
+
51
+ Exposes Chakra UI v3 component props, design tokens, and migration guidance.
52
+ Use it as fallback when a component is not in the WRI DS.
53
+
54
+ ```json
55
+ {
56
+ "mcpServers": {
57
+ "chakra-ui": {
58
+ "command": "npx",
59
+ "args": ["-y", "@chakra-ui/react-mcp"]
60
+ }
61
+ }
62
+ }
63
+ ```
64
+
65
+ > **Note:** The project setup script configures both MCP servers automatically.
66
+ > Run it once after cloning — see the README for instructions.
67
+
68
+ ---
69
+
70
+ ## Component Hierarchy — Never Skip a Level
71
+
72
+ ```
73
+ 1. @worldresources/wri-design-systems — always check first
74
+ 2. @chakra-ui/react — fallback only
75
+ 3. Custom code — last resort; add justification comment
76
+ ```
77
+
78
+ ### Level 1 — WRI Design System
79
+
80
+ Check the [Storybook](https://wri.github.io/wri-design-systems/) or query the Storybook MCP first. For detailed props and usage notes, also check the component's individual README in the [GitHub repo](https://github.com/wri/wri-design-systems) at `src/components/<Category>/<ComponentName>/README.md` — for example: [`Panel/README.md`](https://github.com/wri/wri-design-systems/blob/main/src/components/Containers/Panel/README.md).
81
+
82
+ ```tsx
83
+ // ✅ Correct
84
+ import { Button } from '@worldresources/wri-design-systems'
85
+ ;<Button variant='primary'>Save</Button>
86
+ ```
87
+
88
+ ### Level 2 — Chakra UI (fallback only)
89
+
90
+ Only use Chakra directly if there is **no WRI DS equivalent**. Use the Chakra MCP to verify props — do not rely on memory. Chakra v3 has breaking changes from v2.
91
+
92
+ ```tsx
93
+ // ✅ Acceptable — no WRI DS equivalent exists
94
+ import { Skeleton } from '@chakra-ui/react'
95
+ ```
96
+
97
+ ### Level 3 — Custom Code (last resort)
98
+
99
+ When neither the WRI DS nor Chakra covers the use case, you **must**:
100
+
101
+ 1. Add a `// [CUSTOM COMPONENT]` comment on the line above the definition.
102
+ This is a searchable marker — find all custom components with "Find in Files" → `[CUSTOM COMPONENT]`.
103
+ 2. Add a brief justification explaining why no DS or Chakra component was used.
104
+
105
+ ```tsx
106
+ // [CUSTOM COMPONENT] — No WRI DS or Chakra equivalent for map tooltip overlay
107
+ const MapTooltip = ({ lat, lng, children }: MapTooltipProps) => {
108
+ ...
109
+ }
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Design Tokens
115
+
116
+ WRI DS tokens are defined as Chakra semantic tokens. **Never hardcode values** that have a token equivalent.
117
+
118
+ ```tsx
119
+ // ❌ Wrong — hardcoded colour
120
+ <Box bg="#2C7D6E" />
121
+
122
+ // ✅ Correct — semantic token
123
+ <Box bg="brand.primary" />
124
+ ```
125
+
126
+ If unsure what tokens exist, use the Chakra MCP (`get_theme`) or check the [style guide](https://zeroheight.com/4221801da).
127
+
128
+ ### Color Palette — Authoritative Source
129
+
130
+ The project's `ChakraProvider` in `src/components/Providers/index.tsx` is the **single source of truth for all color overrides** in this project. Before suggesting or using any color token, read that file to see which palette scales are defined and what values they map to.
131
+
132
+ **Do not invent, assume, or guess color token names or values.** The provider only extends the following palette scales:
133
+
134
+ | Scale | Defined steps / tokens | Notes |
135
+ | ------------ | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
136
+ | `neutral` | 100, 200, 300, 400, 500, 600, 700, 800, 900 | Overrides Chakra defaults |
137
+ | `primary` | 100, 200, 300, 400, 500, 600, 700, 800, 900 | Overrides Chakra defaults |
138
+ | `secondary` | 100, 200, 300, 400, 500, 600, 700, 800, 900 | Overrides Chakra defaults |
139
+ | `success` | 100, 200, 300, 500, 900 | Falls back to WRI DS `designSystemStyles` |
140
+ | `warning` | 100, 200, 300, 500, 900 | Falls back to WRI DS `designSystemStyles` |
141
+ | `error` | 100, 200, 300, 500, 900 | Falls back to WRI DS `designSystemStyles` |
142
+ | `accessible` | 'text-on-primary-mids', 'text-on-secondary-mids', 'controls-on-neutral-lights', 'controls-on-neutral-darks' | Use repo-defined keys (for example `text-on-primary-mids`) from WRI DS `designSystemStyles` |
143
+
144
+ For scales not overridden, and for named token sets such as `accessible`, values come from the WRI DS `designSystemStyles` system context — **do not guess these values**. Query the Storybook MCP to verify what values are available. In particular, do not call `getThemedColor('accessible', 100)`; use the actual string token key defined by the design system.
145
+
146
+ ### How to Use Color Tokens — `getThemedColor`
147
+
148
+ Colors must always be accessed via `getThemedColor` exported from `@worldresources/wri-design-systems`. **Never use raw token strings as JSX prop values.**
149
+
150
+ ```tsx
151
+ import { getThemedColor } from "@worldresources/wri-design-systems";
152
+
153
+ // ❌ Wrong — raw token string
154
+ <Box bg="primary.500" />
155
+
156
+ // ✅ Correct — use getThemedColor
157
+ <Box bg={getThemedColor('primary', 500)} />
158
+ <Box color={getThemedColor('neutral', 300)} />
159
+ <Box borderColor={getThemedColor('success', 500)} />
160
+ ```
161
+
162
+ **Full function signature:**
163
+
164
+ ```typescript
165
+ getThemedColor(
166
+ variant: "neutral" | "primary" | "secondary" | "success" | "warning" | "error" | "accessible",
167
+ index:
168
+ | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
169
+ | "text-on-primary-mids"
170
+ | "text-on-secondary-mids"
171
+ | "controls-on-neutral-lights"
172
+ | "controls-on-neutral-darks"
173
+ ): string
174
+ ```
175
+
176
+ **Rules:**
177
+
178
+ - Only call `getThemedColor` with a `variant`/`index` combination that is confirmed to exist.
179
+ - For overridden scales (`neutral`, `primary`, `secondary`), valid steps are listed in the table above.
180
+ - For non-overridden scales (`success`, `warning`, `error`, `accessible`), query the Storybook MCP before using any step — do not assume which steps are defined.
181
+
182
+ ---
183
+
184
+ ## What NOT to Do
185
+
186
+ ```tsx
187
+ // ❌ Do not use a Chakra component that the WRI DS already wraps
188
+ import { Button } from "@chakra-ui/react" // → use WRI DS Button
189
+
190
+ // ❌ Do not override WRI DS styles
191
+ <Button sx={{ backgroundColor: "red" }}>Delete</Button>
192
+
193
+ // ❌ Do not hardcode design values
194
+ <Text fontSize="14px" color="#333333">Label</Text>
195
+
196
+ // ❌ Do not use raw token strings as color props — always use getThemedColor
197
+ <Box bg="primary.500" /> // → use getThemedColor('primary', 500)
198
+
199
+ // ❌ Do not create custom components without the searchable marker
200
+ const MyButton = () => <button style={{ background: "blue" }}>Click</button>
201
+
202
+ // ❌ Do not skip the hierarchy — always check WRI DS and Chakra before going custom
203
+
204
+ // ❌ Do not use Chakra v2 API — v3 has breaking changes (e.g. colorScheme is removed)
205
+ // Always verify props via the Chakra MCP
206
+ ```
207
+
208
+ ---
209
+
210
+ ## Quick Reference
211
+
212
+ | Question | Where to look |
213
+ | --------------------------------------------- | -------------------------------------------------------------------------- |
214
+ | Does a WRI DS component exist? | [Storybook](https://wri.github.io/wri-design-systems/) or Storybook MCP |
215
+ | Detailed props / usage for a WRI DS component | Component README in GitHub: `src/components/<Category>/<Name>/README.md` |
216
+ | What props does a Chakra component accept? | Chakra MCP → `get_component_props` |
217
+ | What design tokens are available? | Chakra MCP → `get_theme` or [Zeroheight](https://zeroheight.com/4221801da) |
218
+ | Which color scales/steps are overridden here? | Read `src/components/Providers/index.tsx` — that is the source of truth |
219
+ | Which steps exist for non-overridden scales? | Query Storybook MCP — do not guess |
220
+ | How do I use a color in JSX? | `getThemedColor('scale', step)` from `@worldresources/wri-design-systems` |
221
+ | Where are all custom components in this repo? | "Find in Files" → `[CUSTOM COMPONENT]` |
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env node
2
+ // scripts/setup-ai.js — WRI Design System AI Setup
3
+ // Distributes AGENTS.md to the correct location for each detected IDE.
4
+ // Usage: yarn setup:ai
5
+
6
+ import {
7
+ existsSync,
8
+ mkdirSync,
9
+ copyFileSync,
10
+ writeFileSync,
11
+ readFileSync,
12
+ readdirSync,
13
+ } from 'fs'
14
+ import { join, dirname, relative, resolve } from 'path'
15
+ import { execSync } from 'child_process'
16
+ import { homedir } from 'os'
17
+ import { fileURLToPath } from 'url'
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url))
20
+ const SOURCE = join(__dirname, 'AGENTS.md')
21
+ // Where we write the setup files.
22
+ // Default is the repo root you're currently in when you run the CLI.
23
+ // You can optionally pass a target directory as argv[2].
24
+ const ROOT = resolve(process.argv[2] ?? process.cwd())
25
+ const HOME = homedir()
26
+
27
+ const installed = []
28
+ const skipped = []
29
+
30
+ console.log('\nWRI Design System — AI Setup')
31
+ console.log('==============================')
32
+
33
+ if (!existsSync(SOURCE)) {
34
+ console.error('❌ AGENTS.md not found at', SOURCE)
35
+ process.exit(1)
36
+ }
37
+
38
+ // ── Helpers ──────────────────────────────────────────────────────
39
+
40
+ function installFile(dest, label) {
41
+ mkdirSync(dirname(dest), { recursive: true })
42
+ copyFileSync(SOURCE, dest)
43
+ installed.push(`${label} → ${relative(ROOT, dest)}`)
44
+ }
45
+
46
+ function commandExists(cmd) {
47
+ try {
48
+ execSync(`command -v ${cmd}`, { stdio: 'ignore' })
49
+ return true
50
+ } catch {
51
+ return false
52
+ }
53
+ }
54
+
55
+ function pathExists(...parts) {
56
+ return existsSync(join(...parts))
57
+ }
58
+
59
+ function dirContains(dir, substring) {
60
+ try {
61
+ return readdirSync(dir).some((f) => f.includes(substring))
62
+ } catch {
63
+ return false
64
+ }
65
+ }
66
+
67
+ function writeJSON(dest, label, content) {
68
+ if (existsSync(dest)) {
69
+ skipped.push(`${label} (already exists — skipped to avoid overwrite)`)
70
+ return
71
+ }
72
+ mkdirSync(dirname(dest), { recursive: true })
73
+ writeFileSync(dest, JSON.stringify(content, null, 2) + '\n')
74
+ installed.push(`${label} → ${relative(ROOT, dest)}`)
75
+ }
76
+
77
+ function ensureGitignoreBlock() {
78
+ const gitignorePath = join(ROOT, '.gitignore')
79
+ const marker =
80
+ '# AI setup — generated by agents/setup-ai.js (npx ds setup-ai)'
81
+ const blockLines = [
82
+ marker,
83
+ 'CLAUDE.md',
84
+ '.windsurfrules',
85
+ '.clinerules',
86
+ 'copilot-instructions.md',
87
+ '.cursor/rules',
88
+ '.cursor/mcp.json',
89
+ '.vscode/mcp.json',
90
+ 'GEMINI.md',
91
+ '.geminirules',
92
+ ]
93
+ const block = blockLines.join('\n') + '\n'
94
+
95
+ if (!existsSync(gitignorePath)) {
96
+ writeFileSync(gitignorePath, block)
97
+ installed.push('.gitignore → .gitignore')
98
+ return
99
+ }
100
+
101
+ const current = readFileSync(gitignorePath, 'utf8')
102
+ if (current.includes(marker)) {
103
+ skipped.push('.gitignore (block already present)')
104
+ return
105
+ }
106
+
107
+ const prefix = current.endsWith('\n') ? '\n' : '\n\n'
108
+ writeFileSync(gitignorePath, current + prefix + block)
109
+ installed.push('.gitignore → .gitignore (appended)')
110
+ }
111
+
112
+ // ── MCP config objects ────────────────────────────────────────────
113
+
114
+ const MCP_STORYBOOK_URL = 'https://wri.github.io/wri-design-systems/index.json'
115
+
116
+ const mcpCursor = {
117
+ mcpServers: {
118
+ 'wri-storybook': {
119
+ command: 'npx',
120
+ args: ['-y', 'storybook-mcp@latest'],
121
+ env: { STORYBOOK_URL: MCP_STORYBOOK_URL },
122
+ },
123
+ 'chakra-ui': {
124
+ command: 'npx',
125
+ args: ['-y', '@chakra-ui/react-mcp'],
126
+ },
127
+ },
128
+ }
129
+
130
+ const mcpVSCode = {
131
+ servers: {
132
+ 'wri-storybook': {
133
+ type: 'stdio',
134
+ command: 'npx',
135
+ args: ['-y', 'storybook-mcp@latest'],
136
+ env: { STORYBOOK_URL: MCP_STORYBOOK_URL },
137
+ },
138
+ 'chakra-ui': {
139
+ type: 'stdio',
140
+ command: 'npx',
141
+ args: ['-y', '@chakra-ui/react-mcp'],
142
+ },
143
+ },
144
+ }
145
+
146
+ // ── IDE detection & file installation ────────────────────────────
147
+
148
+ // Claude Code — always write CLAUDE.md (Claude Code reads both AGENTS.md and CLAUDE.md)
149
+ installFile(join(ROOT, 'CLAUDE.md'), 'Claude Code')
150
+
151
+ // Gemini — always write GEMINI.md and .geminirules for Gemini-based agents
152
+ installFile(join(ROOT, 'GEMINI.md'), 'Gemini')
153
+ installFile(join(ROOT, '.geminirules'), 'Gemini (rules)')
154
+
155
+ // Cursor
156
+ const hasCursor =
157
+ pathExists(HOME, '.cursor') ||
158
+ pathExists('/Applications/Cursor.app') ||
159
+ commandExists('cursor')
160
+
161
+ if (hasCursor) {
162
+ installFile(join(ROOT, '.cursor', 'rules'), 'Cursor (rules)')
163
+ writeJSON(join(ROOT, '.cursor', 'mcp.json'), 'Cursor MCP config', mcpCursor)
164
+ } else {
165
+ skipped.push('Cursor (not detected)')
166
+ }
167
+
168
+ // GitHub Copilot / VS Code
169
+ const hasVSCode =
170
+ commandExists('code') ||
171
+ pathExists(HOME, '.vscode') ||
172
+ pathExists('/Applications/Visual Studio Code.app')
173
+
174
+ if (hasVSCode) {
175
+ installFile(
176
+ join(ROOT, '.github', 'copilot-instructions.md'),
177
+ 'GitHub Copilot',
178
+ )
179
+ writeJSON(join(ROOT, '.vscode', 'mcp.json'), 'VS Code MCP config', mcpVSCode)
180
+ } else {
181
+ skipped.push('GitHub Copilot / VS Code (not detected)')
182
+ }
183
+
184
+ // Windsurf
185
+ const hasWindsurf =
186
+ pathExists(HOME, '.codeium') ||
187
+ pathExists('/Applications/Windsurf.app') ||
188
+ commandExists('windsurf')
189
+
190
+ if (hasWindsurf) {
191
+ installFile(join(ROOT, '.windsurfrules'), 'Windsurf')
192
+ } else {
193
+ skipped.push('Windsurf (not detected)')
194
+ }
195
+
196
+ // Cline (VS Code extension)
197
+ const hasCline = dirContains(join(HOME, '.vscode', 'extensions'), 'cline')
198
+
199
+ if (hasCline) {
200
+ installFile(join(ROOT, '.clinerules'), 'Cline')
201
+ } else {
202
+ skipped.push('Cline (not detected)')
203
+ }
204
+
205
+ ensureGitignoreBlock()
206
+
207
+ // ── Summary ───────────────────────────────────────────────────────
208
+
209
+ console.log('\n✅ Installed:')
210
+ installed.forEach((item) => console.log(' ', item))
211
+
212
+ if (skipped.length) {
213
+ console.log('\n⏭ Skipped:')
214
+ skipped.forEach((item) => console.log(' ', item))
215
+ }
216
+
217
+ console.log('\nDone. Your AI tools now have full WRI Design System context.')
218
+ console.log('Storybook: https://wri.github.io/wri-design-systems/\n')
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env bash
2
+ # setup-ai.sh — WRI Design System AI Setup
3
+ # Distributes AGENTS.md to the correct location for each detected IDE.
4
+ # Run once after cloning: bash setup-ai.sh
5
+
6
+ set -uo pipefail
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ SOURCE="$SCRIPT_DIR/AGENTS.md"
10
+ INSTALLED=()
11
+ SKIPPED=()
12
+
13
+ echo ""
14
+ echo "WRI Design System — AI Setup"
15
+ echo "=============================="
16
+
17
+ if [ ! -f "$SOURCE" ]; then
18
+ echo "❌ AGENTS.md not found at $SCRIPT_DIR"
19
+ exit 1
20
+ fi
21
+
22
+ install_file() {
23
+ local dest="$1"
24
+ local label="$2"
25
+ local dir
26
+ dir="$(dirname "$dest")"
27
+ mkdir -p "$dir"
28
+ cp "$SOURCE" "$dest"
29
+ INSTALLED+=("$label → $dest")
30
+ }
31
+
32
+ # ── Claude Code / Codex ────────────────────────────────────────
33
+ # AGENTS.md is already the source file in this directory — no copy needed.
34
+ # CLAUDE.md is a copy for Claude Code (reads both AGENTS.md and CLAUDE.md).
35
+ install_file "$SCRIPT_DIR/CLAUDE.md" "Claude Code (CLAUDE.md)"
36
+
37
+ # ── Gemini ─────────────────────────────────────────────────────
38
+ install_file "$SCRIPT_DIR/GEMINI.md" "Gemini"
39
+ install_file "$SCRIPT_DIR/.geminirules" "Gemini (rules)"
40
+
41
+
42
+ # ── Cursor ─────────────────────────────────────────────────────
43
+ if [ -d "$HOME/.cursor" ] || [ -d "/Applications/Cursor.app" ] || command -v cursor &>/dev/null; then
44
+ install_file "$SCRIPT_DIR/.cursor/rules" "Cursor"
45
+ else
46
+ SKIPPED+=("Cursor (not detected)")
47
+ fi
48
+
49
+ # ── GitHub Copilot (VS Code) ────────────────────────────────────
50
+ if command -v code &>/dev/null; then
51
+ install_file "$SCRIPT_DIR/.github/copilot-instructions.md" "GitHub Copilot / VS Code"
52
+ else
53
+ SKIPPED+=("GitHub Copilot (VS Code not detected)")
54
+ fi
55
+
56
+ # ── Windsurf ───────────────────────────────────────────────────
57
+ if [ -d "$HOME/.codeium" ] || [ -d "/Applications/Windsurf.app" ] || command -v windsurf &>/dev/null; then
58
+ install_file "$SCRIPT_DIR/.windsurfrules" "Windsurf"
59
+ else
60
+ SKIPPED+=("Windsurf (not detected)")
61
+ fi
62
+
63
+ # ── Cline (VS Code extension) ──────────────────────────────────
64
+ if [ -d "$HOME/.vscode/extensions" ] && ls "$HOME/.vscode/extensions" | grep -q "cline"; then
65
+ install_file "$SCRIPT_DIR/.clinerules" "Cline"
66
+ else
67
+ SKIPPED+=("Cline (not detected)")
68
+ fi
69
+
70
+ # ── MCP config — .vscode/mcp.json (Copilot) ───────────────────
71
+ if command -v code &>/dev/null; then
72
+ MCP_VSCODE="$SCRIPT_DIR/.vscode/mcp.json"
73
+ if [ ! -f "$MCP_VSCODE" ]; then
74
+ mkdir -p "$SCRIPT_DIR/.vscode"
75
+ cat > "$MCP_VSCODE" << 'EOF'
76
+ {
77
+ "servers": {
78
+ "wri-storybook": {
79
+ "type": "stdio",
80
+ "command": "npx",
81
+ "args": ["-y", "storybook-mcp@latest"],
82
+ "env": {
83
+ "STORYBOOK_URL": "https://wri.github.io/wri-design-systems/index.json"
84
+ }
85
+ },
86
+ "chakra-ui": {
87
+ "type": "stdio",
88
+ "command": "npx",
89
+ "args": ["-y", "@chakra-ui/react-mcp"]
90
+ }
91
+ }
92
+ }
93
+ EOF
94
+ INSTALLED+=("MCP config → .vscode/mcp.json")
95
+ else
96
+ SKIPPED+=("MCP .vscode/mcp.json (already exists — skipped to avoid overwrite)")
97
+ fi
98
+ fi
99
+
100
+ # ── MCP config — .cursor/mcp.json ─────────────────────────────
101
+ if [ -d "$HOME/.cursor" ] || [ -d "/Applications/Cursor.app" ] || command -v cursor &>/dev/null; then
102
+ MCP_CURSOR="$SCRIPT_DIR/.cursor/mcp.json"
103
+ if [ ! -f "$MCP_CURSOR" ]; then
104
+ mkdir -p "$SCRIPT_DIR/.cursor"
105
+ cat > "$MCP_CURSOR" << 'EOF'
106
+ {
107
+ "mcpServers": {
108
+ "wri-storybook": {
109
+ "command": "npx",
110
+ "args": ["-y", "storybook-mcp@latest"],
111
+ "env": {
112
+ "STORYBOOK_URL": "https://wri.github.io/wri-design-systems/index.json"
113
+ }
114
+ },
115
+ "chakra-ui": {
116
+ "command": "npx",
117
+ "args": ["-y", "@chakra-ui/react-mcp"]
118
+ }
119
+ }
120
+ }
121
+ EOF
122
+ INSTALLED+=("MCP config → .cursor/mcp.json")
123
+ else
124
+ SKIPPED+=("MCP .cursor/mcp.json (already exists — skipped to avoid overwrite)")
125
+ fi
126
+ fi
127
+
128
+ # ── Summary ────────────────────────────────────────────────────
129
+ echo ""
130
+ echo "✅ Installed:"
131
+ for item in "${INSTALLED[@]}"; do
132
+ echo " $item"
133
+ done
134
+
135
+ if [ ${#SKIPPED[@]} -gt 0 ]; then
136
+ echo ""
137
+ echo "⏭ Skipped:"
138
+ for item in "${SKIPPED[@]}"; do
139
+ echo " $item"
140
+ done
141
+ fi
142
+
143
+ echo ""
144
+ echo "Done. Your AI tools now have full WRI Design System context."
145
+ echo "Storybook: https://wri.github.io/wri-design-systems/"
146
+ echo ""
package/bin/ds.js ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawnSync } = require('child_process')
4
+ const path = require('path')
5
+
6
+ function printHelp() {
7
+ // Keep output minimal and CLI-friendly.
8
+ console.log(`WRI Design Systems CLI
9
+
10
+ Usage:
11
+ ds setup-ai
12
+ ds setup-ai <target-path>
13
+ `)
14
+ }
15
+
16
+ function runSetupAI(targetPath) {
17
+ const scriptPath = path.join(__dirname, '..', 'agents', 'setup-ai.mjs')
18
+
19
+ const result = spawnSync(
20
+ process.execPath,
21
+ targetPath ? [scriptPath, targetPath] : [scriptPath],
22
+ {
23
+ stdio: 'inherit',
24
+ cwd: process.cwd(),
25
+ env: process.env,
26
+ },
27
+ )
28
+
29
+ process.exit(result.status ?? 1)
30
+ }
31
+
32
+ const [, , command, ...rest] = process.argv
33
+
34
+ if (!command || command === '-h' || command === '--help') {
35
+ printHelp()
36
+ process.exit(0)
37
+ }
38
+
39
+ if (command === 'setup-ai') {
40
+ if (rest.includes('-h') || rest.includes('--help')) {
41
+ printHelp()
42
+ process.exit(0)
43
+ }
44
+
45
+ if (rest.length === 0) {
46
+ runSetupAI(null)
47
+ }
48
+
49
+ if (rest.length === 1) {
50
+ runSetupAI(rest[0])
51
+ }
52
+
53
+ console.error('Too many arguments for setup-ai')
54
+ printHelp()
55
+ process.exit(1)
56
+ }
57
+
58
+ console.error(`Unknown command: ${command}`)
59
+ printHelp()
60
+ process.exit(1)
package/package.json CHANGED
@@ -1,12 +1,17 @@
1
1
  {
2
2
  "name": "@worldresources/wri-design-systems",
3
- "version": "2.191.9",
3
+ "version": "2.191.10-alpha-ds-cli",
4
4
  "description": "WRI UI Library",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
7
7
  "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "ds": "bin/ds.js"
10
+ },
8
11
  "files": [
9
- "dist"
12
+ "dist",
13
+ "bin",
14
+ "agents"
10
15
  ],
11
16
  "scripts": {
12
17
  "start": "react-scripts start",