@catchdrift/cli 0.1.18 → 0.1.19

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.
@@ -0,0 +1,506 @@
1
+ ---
2
+ description: "First-run wizard: installs Drift into any React project, discovers DS components from Storybook, generates AI rules files, adds GitHub Action CI, and measures baseline coverage."
3
+ allowed-tools: Read, Glob, Grep, Bash, Edit, Write
4
+ argument-hint: "[--check | --multi-team | <path-to-project>]"
5
+ disable-model-invocation: true
6
+ ---
7
+
8
+ # /drift-setup — First-run Drift installation wizard
9
+
10
+ Set up Drift in this project from scratch. Detect what already exists, ask targeted
11
+ questions, then do all the work — no manual steps.
12
+
13
+ Works with any React product team — SaaS, property management, fintech, consumer, B2B.
14
+ Supports Vite, Next.js, CRA, Remix, and any custom React + Storybook setup.
15
+
16
+ ## Arguments: `$ARGUMENTS`
17
+ - *(no args)* — full interactive setup inside the current project
18
+ - `--check` — audit existing setup, report what's missing without changing anything
19
+ - `--multi-team` — configure for shared DS across multiple product teams (npm package model)
20
+ - `<path>` — bootstrap Drift into another project, e.g. `/drift-setup ~/projects/my-app`
21
+
22
+ ---
23
+
24
+ ## Step 0 — Bootstrap into another project (if a path was given)
25
+
26
+ If `$ARGUMENTS` is a file path (starts with `/`, `./`, or `~`, or looks like a directory name):
27
+
28
+ 1. Treat it as `TARGET_DIR`. Resolve `~` if needed.
29
+ 2. Verify `TARGET_DIR` exists and has a `package.json`. If not, stop:
30
+ ```
31
+ No package.json found at <path>. Is this a React project?
32
+ ```
33
+ 3. Copy the Drift source files from this repo into the target:
34
+ ```bash
35
+ cp -r src/ds-coverage/ {TARGET_DIR}/src/ds-coverage/
36
+ cp -r .claude/ {TARGET_DIR}/.claude/
37
+ mkdir -p {TARGET_DIR}/scripts
38
+ cp scripts/drift-check.mjs {TARGET_DIR}/scripts/
39
+ cp scripts/drift-mcp.mjs {TARGET_DIR}/scripts/
40
+ cp scripts/figma-sync.mjs {TARGET_DIR}/scripts/
41
+ ```
42
+ 4. Check if `@modelcontextprotocol/sdk` is in `{TARGET_DIR}/package.json` devDependencies.
43
+ If not: `cd {TARGET_DIR} && npm install --save-dev @modelcontextprotocol/sdk`
44
+
45
+ 5. Report what was installed:
46
+ ```
47
+ ## Drift files copied to <TARGET_DIR>
48
+
49
+ ✅ src/ds-coverage/ — overlay + fiber scanner + token checker
50
+ ✅ .claude/commands/ — /drift, /drift-sync, /drift-push, /drift-prd, /drift-scaffold
51
+ ✅ scripts/ — drift-check, drift-mcp, figma-sync
52
+ ✅ @modelcontextprotocol/sdk installed
53
+
54
+ Now continuing setup inside <TARGET_DIR>…
55
+ ```
56
+
57
+ 6. Continue the rest of this setup (Steps 1–10) as if running inside `TARGET_DIR`.
58
+ All file reads/writes from this point forward target `TARGET_DIR`.
59
+
60
+ If no path argument: assume already running inside the target project and go straight to Step 1.
61
+
62
+ ---
63
+
64
+ ## Step 1 — Detect existing setup
65
+
66
+ Read these files if they exist and note what's already configured:
67
+ - `src/ds-coverage/config.ts` or `drift.config.ts`
68
+ - `package.json` — detect framework (Next.js, Vite, CRA, Remix), Storybook version, existing eslint plugins
69
+ - `.storybook/main.ts` or `.storybook/main.js`
70
+ - `.github/workflows/` — any existing drift workflow
71
+ - `CLAUDE.md`, `.cursorrules`, `.windsurfrules` — AI rules files
72
+ - `~/.claude.json` or `.claude/settings.json` — MCP servers
73
+
74
+ Print a brief audit:
75
+ ```
76
+ ## Drift setup audit
77
+
78
+ Framework: [Next.js 14 / Vite 5 / CRA / Remix / unknown]
79
+ Storybook: ✅ v8.x at http://localhost:6006 / ❌ not detected
80
+ drift.config: ✅ (37 components) / ❌ missing
81
+ CLAUDE.md: ✅ / ⚠️ stale (last updated: <date>) / ❌ missing
82
+ .cursorrules: ✅ / ❌ missing
83
+ .windsurfrules: ✅ / ❌ missing
84
+ GitHub Action: ✅ drift-check.yml / ❌ missing
85
+ MCP server: ✅ registered / ❌ missing
86
+ ESLint plugin: ✅ drift rules installed / ❌ not installed (optional)
87
+ Code Connect: ✅ / ❌ not configured (optional — improves Figma Dev Mode)
88
+ ```
89
+
90
+ If `--check` was passed, stop here and explain what each missing item would add.
91
+
92
+ ---
93
+
94
+ ## Step 2 — Gather configuration (ask all at once, don't ping-pong)
95
+
96
+ Ask these questions in a single message. Tell the user to answer what they know
97
+ and skip anything they don't have yet:
98
+
99
+ ```
100
+ To set up Drift I need a few details. Answer what you have — skip anything you don't:
101
+
102
+ 1. **Storybook URL (local)**
103
+ Default: http://localhost:6006 — press enter to accept
104
+
105
+ 2. **Deployed Storybook URL** (Chromatic, Netlify, Vercel, etc.)
106
+ e.g. https://main--abc123.chromatic.com
107
+ Skip if not deployed yet.
108
+
109
+ 3. **Figma file key**
110
+ Found in your Figma URL: figma.com/design/THIS_PART/your-file
111
+ Skip if no Figma file yet.
112
+
113
+ 4. **Figma MCP connected?** (yes/no)
114
+ Enables AI to read/write Figma directly. Required for /drift-push automation.
115
+
116
+ 5. **Jira base URL + project key** (optional)
117
+ e.g. https://yourcompany.atlassian.net project key: DS
118
+ Used by /drift promote to create Jira tickets for DS gap requests.
119
+
120
+ 6. **Coverage threshold** (default: 80)
121
+ CI fails if DS coverage drops below this %.
122
+ Recommended: start at your current baseline (we'll measure it), then raise quarterly.
123
+
124
+ 7. **Multi-team setup?** (yes/no)
125
+ If yes: are you the DS team setting up the source, or a product team consuming the DS?
126
+ (See --multi-team flag for full multi-team workflow.)
127
+
128
+ 8. **AI tools in use** (check all that apply)
129
+ - Claude Code (CLAUDE.md)
130
+ - Cursor (.cursorrules)
131
+ - Windsurf (.windsurfrules)
132
+ - Other: ___
133
+ ```
134
+
135
+ ---
136
+
137
+ ## Step 3 — Locate the overlay source
138
+
139
+ Check where the overlay lives:
140
+
141
+ **Option A — This is the design-drift source repo** (or the user copied `src/ds-coverage/` into their project):
142
+ - `src/ds-coverage/` exists with `DSCoverageOverlay.tsx`, `config.ts`, etc.
143
+ - No install needed. Note: "Overlay source found at `src/ds-coverage/`."
144
+
145
+ **Option B — Installing from npm** (once the package is published):
146
+ ```bash
147
+ npm install --save-dev design-drift
148
+ ```
149
+ Then imports use `from 'design-drift'` instead of `from './ds-coverage/DSCoverageOverlay'`.
150
+
151
+ If neither exists:
152
+ ```
153
+ The overlay source wasn't found in this project.
154
+ Clone the design-drift repo or copy src/ds-coverage/ into your project first.
155
+ git clone https://github.com/dyoon92/design-drift
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Step 4 — Discover DS components from Storybook
161
+
162
+ Try to fetch `{storybookUrl}/index.json`. If it succeeds:
163
+ - Parse the story index to get all component names and story paths
164
+ - Group by category (primitives, navigation, patterns, etc.)
165
+ - Present a grouped list and ask:
166
+ ```
167
+ Found N components in Storybook. Which are your official DS components?
168
+
169
+ Primitives (8): Button, Input, Badge, Modal, Toast, Dropdown, Tabs, Icon
170
+ Navigation (3): Navbar, Sidebar, Breadcrumb
171
+ Patterns (6): TenantsTable, UnitDetailsCard, PaymentBanner, ...
172
+ Other (12): ...
173
+
174
+ Options:
175
+ - "all" — treat everything in Storybook as DS
176
+ - "primitives, navigation" — only those categories
177
+ - Comma-separated names: "Button, Input, Badge, Modal"
178
+ ```
179
+ - Default to all discovered components if no response.
180
+
181
+ If Storybook isn't running or reachable:
182
+ - Ask the user to list their DS component names (comma or newline separated)
183
+ - Generate placeholder storyPaths they can fill in later via `/drift-sync`
184
+
185
+ ---
186
+
187
+ ## Step 5 — Create or update drift.config.ts
188
+
189
+ Write `drift.config.ts` at the project root (or `src/ds-coverage/config.ts` if
190
+ that's where the existing one is):
191
+
192
+ ```typescript
193
+ import type { DesignDriftConfig } from './src/ds-coverage/types' // or 'design-drift'
194
+
195
+ const config: DesignDriftConfig = {
196
+ storybookUrl: '<local-storybook-url>',
197
+ // chromaticUrl: '<deployed-url>', // uncomment when deployed
198
+ figmaFileKey: '<figma-file-key>', // omit if not provided
199
+ // jiraBaseUrl: '<jira-url>', // uncomment if using Jira
200
+ // jiraProjectKey: '<key>', // uncomment if using Jira
201
+ threshold: <threshold>,
202
+ components: {
203
+ // <ComponentName>: { storyPath: '<story-id>' },
204
+ // ...all discovered components...
205
+ },
206
+ // approvedGaps: {}, // components approved as intentional exceptions
207
+ }
208
+
209
+ export default config
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Step 6 — Add overlay to app entry point
215
+
216
+ Detect the framework automatically:
217
+
218
+ **Vite / CRA (`src/main.tsx` or `src/index.tsx`):**
219
+ ```tsx
220
+ // Add near the top — dev-only guard
221
+ if (import.meta.env.DEV) {
222
+ const { DSCoverageOverlay } = await import('./ds-coverage/DSCoverageOverlay')
223
+ // mounted as last child in root render
224
+ }
225
+
226
+ // Inside root render, as the last child:
227
+ {import.meta.env.DEV && <DSCoverageOverlay />}
228
+ ```
229
+
230
+ **Next.js (`pages/_app.tsx` or `app/layout.tsx`):**
231
+ ```tsx
232
+ {process.env.NODE_ENV === 'development' && <DSCoverageOverlay />}
233
+ ```
234
+
235
+ **Remix (`app/root.tsx`):**
236
+ ```tsx
237
+ {process.env.NODE_ENV === 'development' && <DSCoverageOverlay />}
238
+ ```
239
+
240
+ The overlay is always dev-only. It tree-shakes completely from production builds.
241
+
242
+ ---
243
+
244
+ ## Step 7 — Generate AI rules files
245
+
246
+ Create or update rules files for every AI tool the user selected.
247
+ All files get the same component table + constraints. Use these markers to delineate
248
+ the auto-generated section so future `/drift-sync` runs only regenerate this part:
249
+
250
+ ```markdown
251
+ <!-- drift:components-start -->
252
+ | Component | Story | Figma |
253
+ |-----------|-------|-------|
254
+ | Button | ✅ | ✅ |
255
+ ...
256
+ <!-- drift:components-end -->
257
+ ```
258
+
259
+ ### CLAUDE.md
260
+
261
+ ```markdown
262
+ # Design System Rules
263
+
264
+ ## Source of truth
265
+ - Figma: https://figma.com/design/<figmaFileKey>
266
+ - Storybook: <storybookUrl>
267
+ - Tokens: src/tokens/variables.css — use CSS variables only (var(--ds-color-*), var(--ds-spacing-*))
268
+
269
+ ## The #1 rule: never invent UI from scratch
270
+ If a component doesn't exist in the table below, output:
271
+ ⚠️ Missing component: [ComponentName]
272
+ This needs to be designed in Figma first. Use <Placeholder> in the meantime.
273
+ File a design request: run /drift-push request [ComponentName] "[description]"
274
+
275
+ ## Approved exceptions
276
+ To use a non-DS component intentionally, add this inline comment:
277
+ {/* drift:ignore reason="<why no DS component covers this>" */}
278
+ Exceptions are tracked in drift.config.ts approvedGaps and reported separately — they
279
+ do not count against coverage.
280
+
281
+ <!-- drift:components-start -->
282
+ ## Available DS components
283
+ | Component | Story | Figma |
284
+ |-----------|-------|-------|
285
+ ...
286
+ <!-- drift:components-end -->
287
+
288
+ ## Style rules
289
+ - Colors: var(--ds-color-*) — never hardcode hex
290
+ - Spacing: var(--ds-spacing-*) — never hardcode px
291
+ - No CSS files — inline styles only
292
+ - Font: Inter, system-ui, sans-serif
293
+
294
+ ## Drift commands
295
+ - /drift — analyze coverage + suggest fixes
296
+ - /drift-sync — re-pull components from Figma/Storybook
297
+ - /drift-push — push implemented components back to Figma
298
+ - /drift-prd — generate a component inventory for a PRD/spec
299
+ - /drift-scaffold — scaffold a new screen using only DS components
300
+ - /drift fix <X> — migrate custom component X to its DS equivalent
301
+ - /drift approve <X> "<reason>" — approve a gap with documented rationale
302
+ ```
303
+
304
+ Also create `.cursorrules` and `.windsurfrules` with the same content if those tools are in use.
305
+
306
+ ---
307
+
308
+ ## Step 8 — Add GitHub Actions workflow
309
+
310
+ Create `.github/workflows/drift-check.yml` if it doesn't exist.
311
+
312
+ Key configuration decisions to set correctly:
313
+ - `DRIFT_THRESHOLD`: set to current measured baseline (not a fixed 80 — let teams ramp up)
314
+ - `DRIFT_MAX_DROP`: start at `5` (allows 5% drop); suggest moving to `0` after 2 sprints of stability
315
+ - `DRIFT_STRICT`: `false` by default; only set `true` for new greenfield projects
316
+
317
+ ```yaml
318
+ name: Drift Check
319
+ on:
320
+ pull_request:
321
+ branches: [main, master]
322
+ push:
323
+ branches: [main, master]
324
+
325
+ env:
326
+ DRIFT_THRESHOLD: 80 # CI fails if coverage drops below this
327
+ DRIFT_MAX_DROP: 5 # Max allowed regression per PR (set to 0 for ratchet mode)
328
+ DRIFT_STRICT: false # Set true to fail on any non-DS component
329
+ DRIFT_ROUTES: / # Comma-separated routes to scan
330
+
331
+ jobs:
332
+ drift:
333
+ name: Design Drift Analysis
334
+ runs-on: ubuntu-latest
335
+ permissions:
336
+ contents: read
337
+ pull-requests: write
338
+ steps:
339
+ - uses: actions/checkout@v4
340
+ - uses: actions/setup-node@v4
341
+ with: { node-version: 20, cache: npm }
342
+ - run: npm ci
343
+ - run: npx playwright install chromium --with-deps
344
+ - name: Restore drift baseline
345
+ uses: actions/cache/restore@v4
346
+ with:
347
+ path: drift-baseline.json
348
+ key: drift-baseline-${{ github.base_ref || github.ref_name }}
349
+ - run: npm run build
350
+ - run: npx vite preview --port 4173 &
351
+ - run: npx wait-on http://localhost:4173 --timeout 30000
352
+ - name: Run drift check
353
+ run: |
354
+ node scripts/drift-check.mjs \
355
+ --url http://localhost:4173 \
356
+ --threshold ${{ env.DRIFT_THRESHOLD }} \
357
+ --routes "${{ env.DRIFT_ROUTES }}" \
358
+ --json > drift-report.json
359
+ continue-on-error: true
360
+ - name: Post PR comment
361
+ if: github.event_name == 'pull_request'
362
+ uses: actions/github-script@v7
363
+ with:
364
+ github-token: ${{ secrets.GITHUB_TOKEN }}
365
+ script: |
366
+ const report = JSON.parse(require('fs').readFileSync('drift-report.json', 'utf8'))
367
+ // full comment script in .github/workflows/drift-check.yml
368
+ - name: Save baseline
369
+ if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
370
+ uses: actions/cache/save@v4
371
+ with:
372
+ path: drift-report.json
373
+ key: drift-baseline-${{ github.ref_name }}-${{ github.run_id }}
374
+ - uses: actions/upload-artifact@v4
375
+ with:
376
+ name: drift-report
377
+ path: drift-report.json
378
+ retention-days: 90
379
+ ```
380
+
381
+ If a workflow already exists, diff the existing one and only update threshold/env vars.
382
+
383
+ **Multi-team note**: If `--multi-team` was requested and this is a product team (consumer) repo:
384
+ - Set `DRIFT_THRESHOLD` to the org-wide minimum published by the DS team
385
+ - Add a step to fetch the org's `drift-config.json` from a remote URL if the team uses remote config
386
+
387
+ ---
388
+
389
+ ## Step 9 — Register MCP server
390
+
391
+ Add the Drift MCP server to Claude Code settings. Check if `~/.claude.json` exists:
392
+
393
+ ```json
394
+ {
395
+ "mcpServers": {
396
+ "drift": {
397
+ "command": "node",
398
+ "args": ["scripts/drift-mcp.mjs"],
399
+ "cwd": "<absolute path to this project>"
400
+ }
401
+ }
402
+ }
403
+ ```
404
+
405
+ Use `pwd` to get the absolute path. If `~/.claude.json` already has mcpServers,
406
+ merge — don't overwrite existing entries.
407
+
408
+ If the user also has Figma MCP, show how to add it alongside:
409
+ ```json
410
+ "figma": {
411
+ "command": "npx",
412
+ "args": ["-y", "figma-developer-mcp", "--stdio"],
413
+ "env": { "FIGMA_ACCESS_TOKEN": "<token>" }
414
+ }
415
+ ```
416
+
417
+ ---
418
+
419
+ ## Step 10 — Measure baseline coverage
420
+
421
+ Before finishing, measure the current state so the team has a starting point:
422
+
423
+ ```bash
424
+ npm run build && npx vite preview --port 4173 &
425
+ npx wait-on http://localhost:4173
426
+ node scripts/drift-check.mjs --url http://localhost:4173 --json > drift-baseline.json
427
+ ```
428
+
429
+ Parse and report:
430
+ ```
431
+ ## Baseline coverage measured
432
+
433
+ Current DS coverage: XX%
434
+ Custom components found: N
435
+ Token violations: N
436
+
437
+ Recommended threshold setting: XX% (your current baseline, rounded down to nearest 5)
438
+ Suggested ramp: raise threshold by 5% each quarter as gaps are resolved.
439
+ ```
440
+
441
+ If coverage is below 40%, flag it prominently:
442
+ ```
443
+ ⚠️ Low baseline (XX%) — this is common for repos where the DS hasn't been enforced yet.
444
+ Start with threshold: <baseline - 5> to avoid immediate CI failures.
445
+ Use /drift audit to see the highest-impact gaps to fix first.
446
+ ```
447
+
448
+ ---
449
+
450
+ ## Step 11 — Final summary
451
+
452
+ Print:
453
+ ```
454
+ ## ✅ Drift is set up
455
+
456
+ Files created/updated:
457
+ drift.config.ts — <N> DS components registered
458
+ CLAUDE.md — AI coding rules with DS constraints
459
+ .cursorrules — Cursor rules (if selected)
460
+ .windsurfrules — Windsurf rules (if selected)
461
+ .github/workflows/drift-check.yml — CI drift check on every PR
462
+ ~/.claude.json — MCP server registered
463
+
464
+ Baseline coverage: XX% (threshold set to XX%)
465
+
466
+ Next steps:
467
+ 1. npm run dev — open your app, press D to see Drift overlay
468
+ 2. npm run storybook — verify Storybook component links work
469
+ 3. npm run figma-sync — pull latest design tokens (needs FIGMA_API_TOKEN)
470
+ 4. git push — first PR will show a drift delta comment
471
+
472
+ When you add a new DS component:
473
+ 1. Build it in src/stories/[Name].tsx
474
+ 2. Add to drift.config.ts
475
+ 3. Run /drift-sync to update all AI rules files automatically
476
+
477
+ When a PdM or designer wants to prototype:
478
+ 1. Run /drift-prd to generate a component inventory for their spec
479
+ 2. Run /drift-scaffold to generate a starter page using only DS components
480
+ 3. Run /drift check before submitting the PR to see coverage
481
+ ```
482
+
483
+ ---
484
+
485
+ ## Multi-team mode (`--multi-team`)
486
+
487
+ If `--multi-team` was passed, ask an additional question:
488
+
489
+ ```
490
+ Multi-team setup — which role are you?
491
+
492
+ A. DS Team (source): You maintain the component library that product teams consume.
493
+ B. Product Team (consumer): You build features using the DS team's components.
494
+ ```
495
+
496
+ ### DS Team setup
497
+ - Generate an additional `drift-org-config.json` file that can be hosted at a static URL
498
+ - This file contains the org's component registry, threshold, and token reference — product teams fetch it
499
+ - Add a GitHub Action step to publish `drift-org-config.json` to GitHub Pages or a CDN on every DS release
500
+ - Recommend Renovate or Dependabot for automated DS version upgrade PRs in product repos
501
+
502
+ ### Product Team setup
503
+ - Add a config fetch step: `remoteConfigUrl: 'https://ds.yourorg.com/drift-config.json'`
504
+ - The overlay and CI tool merge remote config (DS components) with local config (app-specific approvals)
505
+ - Local `drift.config.ts` only needs `approvedGaps` and local threshold overrides — all component definitions come from the remote URL
506
+ - This is the pattern used by Salesforce Lightning and Microsoft Fluent for multi-product DS governance