@superdesign/cli 0.1.5 → 0.1.7

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,264 @@
1
+ SuperDesign helps you (1) find design inspirations/styles and (2) generate/iterate design drafts on an infinite canvas.
2
+
3
+ ---
4
+
5
+ # Core scenarios (what this skill handles)
6
+
7
+ 1. **Help me design X** (feature/page/flow)
8
+ 2. **Set design system**
9
+ 3. **Help me improve design of X**
10
+
11
+ # Quickstart
12
+
13
+ Install CLI
14
+
15
+ ```
16
+ npm install -g @superdesign/cli@latest
17
+ ```
18
+
19
+ Install skills for any coding agent
20
+
21
+ ```
22
+ npx skills add superdesigndev/superdesign-skill
23
+ ```
24
+
25
+ Prompt in any agent
26
+
27
+ ```
28
+ /superdesign help me design X
29
+ ```
30
+
31
+ --
32
+
33
+ ## Tooling overview
34
+
35
+ ### A) Inspiration & Style Tools (generic, always available)
36
+
37
+ Use these to discover style direction, references, and brand context:
38
+
39
+ - **Search prompt library** (style/components/pages)
40
+
41
+ ```bash
42
+ superdesign search-prompts --keyword "<keyword>" --json
43
+ superdesign search-prompts --tags "style" --json
44
+ superdesign search-prompts --tags "style" --keyword "<style keyword>" --json
45
+ ```
46
+
47
+ - **Get full prompt details**
48
+
49
+ ```bash
50
+ superdesign get-prompts --slugs "<slug1,slug2,...>" --json
51
+ ```
52
+
53
+ - **Extract brand guide from a URL**
54
+ ```bash
55
+ superdesign extract-brand-guide --url https://example.com --json
56
+ ```
57
+
58
+ ### B) Canvas Design Tools
59
+
60
+ Use design agent to generate high quality design drafts:
61
+
62
+ - Create project (supports prompt / prompt file / HTML)
63
+ - Create design draft
64
+ - Iterate design draft (replace / branch)
65
+ - Plan flow pages → execute flow pages
66
+ - Fetch specific design draft
67
+
68
+ ---
69
+
70
+ ## Overall SOP for designing features on top of existing app:
71
+
72
+ 1. Investigate existing UI, workflow
73
+ 2. Setup design system file if not exist yet
74
+ 3. Requirements gathering: use askQuestion tool to clarify requirements with users (Optionally use Inspiration tool to find inspiration when needed)
75
+ 4. Ask user whether ready to design in superdesign OR implement UI directly
76
+ 5. If yes to superdesign
77
+ 5.1 Create/update a pixel perfect html replica of current UI of page that we will design on top of in `.superdesign/replica_html_template/<name>.html` (html should only contain & reflect how UI look now, the actual design should be handled by superdesign agent)
78
+ 5.2 Create project with this replica html + design system guide
79
+ 5.3 Start desigining by iterating & branching design draft based on designDraft ID returned from project
80
+
81
+ ## Always-on rules
82
+
83
+ - Design system should live at: `.superdesign/design-system.md`
84
+ - If `.superdesign/design-system.md` is missing, run **Design System Setup** first.
85
+ - Use `askQuestion` to ask high-signal questions (constraints, taste, tradeoffs).
86
+ - Always use `--json` for machine parsing.
87
+
88
+ ---
89
+
90
+ ## replica_html_template rules (Canvas only)
91
+
92
+ The purpose of replica html template is creating a lightweight version of existing UI so design agent can iterate on top of it (Since superdesign doesn't have access to your codebase directly, this is important context)
93
+
94
+ Overall process for designing features on top of existing app:
95
+
96
+ 1. Identify & understand existing UI of page related
97
+ 2. Create/update a pixel perfect replica html in `.superdesign/replica_html_template/<name>.html` (Only replicate how UI look now, do NOT design)
98
+
99
+ - If design task is redesign profile page, then replicate current profile page UI pixel perfectly
100
+ - If design task is add new button to side panel, identify which page side panel is using, then replicate that page UI pixel perfectly
101
+
102
+ **replica_html_template = BEFORE state (what exists now).** It provides context for SuperDesign agent.
103
+ Actual design will be done via superdesign agent, by passing the prompt
104
+
105
+ The replica_html_template must contain **ONLY UI that currently exists in the codebase**.
106
+
107
+ - **DO NOT** design or improve anything in the replica_html_template
108
+ - **DO NOT** add placeholder sections like `<!-- NEW FEATURE - DESIGN THIS -->`
109
+ - **DO** create pixel-perfect replica of current UI state
110
+ - Save to: `.superdesign/replica_html_template/<name>.html`
111
+
112
+ ### Naming & Reuse
113
+
114
+ **Naming convention**
115
+ Name replica_html_template for reusability: Use the page route (e.g., `home.html`, `settings-profile.html`, `dashboard.html`)
116
+ This makes it easy to identify if a page_template already exists.
117
+
118
+ **Before creating a replica_html_template:**
119
+
120
+ 1. Check if `.superdesign/replica_html_template/` already contains a matching file
121
+ 2. If exists: reuse it or update to reflect the latest existing UI
122
+ 3. If not exists: create the neww file
123
+
124
+ ### Example: Adding a "Book Demo" section to home page
125
+
126
+ **BAD approach:**
127
+
128
+ ```html
129
+ <!-- replica_html_template includes a sketched Book Demo section -->
130
+ <section class="book-demo">
131
+ <!-- DESIGN THIS - Add CTA here -->
132
+ <h3>Book a Demo</h3>
133
+ <button>Schedule</button>
134
+ </section>
135
+ ```
136
+
137
+ **GOOD approach:**
138
+
139
+ ```html
140
+ <!-- replica_html_template is pure replica of existing home page (hero + projects) -->
141
+ ```
142
+
143
+ Then in the iterate command:
144
+ 1/ create project passing this replica html
145
+ 2/ create design draft based on design draft id
146
+
147
+ ---
148
+
149
+ # 1) Design System Setup
150
+
151
+ ### Step 0 — Ask user (one question)
152
+
153
+ "Do you want to **create a new design system** or **extract from the current codebase**?"
154
+
155
+ ### A) Extract from codebase
156
+
157
+ 1. Investigate codebase:
158
+ - Product context: what is being built, target users, core value proposition, key user journeys and page structure
159
+ - design tokens, typography, colors, spacing, radius, shadows
160
+ - motion/animation patterns
161
+ - example components usage + implementation patterns
162
+ 2. Write standalone design system to:
163
+ - `.superdesign/design-system.md`
164
+ - Must be implementable without the codebase
165
+
166
+ ### B) Create a new design system (to improve current UI)
167
+
168
+ 1. Investigate codebase to understand:
169
+ - Product context: what is being built, target users, core value proposition, key user journeys and page structure
170
+ - needed pages/components
171
+ 2. Gather inspirations (generic tools):
172
+ - `superdesign search-prompts --tags "style" --json`
173
+ - `superdesign get-prompts --slugs ... --json`
174
+ - optional: `superdesign extract-brand-guide --url ... --json`
175
+ 3. Interview user (`askQuestion`) to choose direction
176
+ 4. Write:
177
+ - `.superdesign/design-system.md` (product context + UX flows + visual design, adapted to references)
178
+
179
+ ---
180
+
181
+ # 2) Designing X (feature/page/flow)
182
+
183
+ ### Example workflow - Add feature to existing page
184
+
185
+ 1. Investigate existing design and Ask targeted questions (`askQuestion`) about requirements + taste
186
+ 2. After clarifying, Ask user whether ready to design in superdesign OR implement UI directly
187
+ 3. If design in superdesign
188
+ 3.1 Ensure `.superdesign/design-system.md` exists (setup if missing)
189
+ 3.2 Identify page most relevant, and build a pixel-perfect replica in replica_html_template:
190
+ - `.superdesign/replica_html_template/<page>-<feature>.html`
191
+ 3.3 Create project with replica_html_template (returns `draftId`):
192
+ ```bash
193
+ superdesign create-project \
194
+ --title "<feature>" \
195
+ --html-file .superdesign/replica_html_template/<file>.html \
196
+ --set-project-prompt-file .superdesign/design-system.md \
197
+ --json
198
+ ```
199
+ → Note: `draftId` in response is the baseline draft
200
+ 3.4 Branch designs from baseline (use `draftId` from step 3.3)
201
+ ```bash
202
+ superdesign iterate-design-draft \
203
+ --draft-id <draftId> \
204
+ -p "Dark theme with neon accents" \
205
+ -p "Minimal with more whitespace" \
206
+ -p "Bold gradients and shadows" \
207
+ --mode branch \
208
+ --json
209
+ ```
210
+ 3.5 Share design title & preview URL → collect feedback → iterate
211
+
212
+ ### Advanced usage
213
+
214
+ #### Design multiple page OR a full user journey
215
+
216
+ Execute:
217
+
218
+ ```bash
219
+ superdesign execute-flow-pages \
220
+ --draft-id <draftId> \
221
+ --source-node-id <nodeId> \
222
+ --pages '[{"title":"Signup","prompt":"..."},{"title":"Payment","prompt":"..."}]' \
223
+ --json
224
+ ```
225
+
226
+ #### Get HTML reference from a draft
227
+
228
+ ```bash
229
+ superdesign get-design --draft-id <draftId> --output ./design.html
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Quick reference (key commands)
235
+
236
+ ```bash
237
+ # Inspirations
238
+ superdesign search-prompts --keyword "<keyword>" --json
239
+ superdesign search-prompts --tags "style" --json
240
+ superdesign get-prompts --slugs "<slug1,slug2>" --json
241
+ superdesign extract-brand-guide --url https://example.com --json
242
+
243
+ # Canvas - Create project
244
+ # Options: -s/--set-project-prompt (inline), --set-project-prompt-file (from file)
245
+ superdesign create-project --title "X" --set-project-prompt "..." --json
246
+ superdesign create-project --title "X" --set-project-prompt-file .superdesign/design-system.md --json
247
+ superdesign create-project --title "X" --html-file ./index.html --set-project-prompt-file .superdesign/design-system.md --json
248
+
249
+ # Iterate: replace mode (single variation, updates in place)
250
+ superdesign iterate-design-draft --draft-id <id> -p "..." --mode replace --json
251
+
252
+ # Iterate: Explore multiple versions & variations (each prompt = one variation, prompt should be just directional, do not specify color, style, let superdesign design expert fill in details, you just give direction)
253
+ superdesign iterate-design-draft --draft-id <id> -p "dark theme" -p "minimal" -p "bold" --mode branch --json
254
+
255
+ # Iterate: Auto explore (only give exploration direction, and let Superdesign fill in details, e.g. explore different styles; Default do not use this)
256
+ superdesign iterate-design-draft --draft-id <id> -p "..." --mode branch --count 3 --json
257
+
258
+ # Fetch & get designs
259
+ superdesign fetch-design-nodes --project-id <id> --json
260
+ superdesign get-design --draft-id <id> --json
261
+
262
+ # Create new design from scracth without any reference - ONLY use this for creating brand new design, default NEVER use this
263
+ superdesign create-design-draft --project-id <id> --title "X" -p "..." --json
264
+ ```
@@ -12,7 +12,10 @@ export declare const POLL_TIMEOUT_MS: number;
12
12
  export declare const AUTH_POLL_INTERVAL_MS = 2000;
13
13
  export declare const AUTH_POLL_TIMEOUT_MS: number;
14
14
  /** CLI version - should match package.json */
15
- export declare const CLI_VERSION = "0.1.5";
15
+ export declare const CLI_VERSION = "0.1.7";
16
+ /** PostHog analytics configuration */
17
+ export declare const POSTHOG_KEY: string;
18
+ export declare const POSTHOG_HOST: string;
16
19
  /** Config directory name */
17
20
  export declare const CONFIG_DIR_NAME = ".superdesign";
18
21
  /** Config file name */
package/dist/index.cjs CHANGED
@@ -91,8 +91,8 @@ var __webpack_exports__ = {};
91
91
  const external_url_namespaceObject = require("url");
92
92
  const external_path_namespaceObject = require("path");
93
93
  const external_commander_namespaceObject = require("commander");
94
- const external_fs_namespaceObject = require("fs");
95
- const external_os_namespaceObject = require("os");
94
+ const POSTHOG_KEY = process.env.POSTHOG_KEY || 'phc_oUcDklFBX3wy8eksSyEC0pataKCgSadur1sio5hBHg4';
95
+ const POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://eu.i.posthog.com';
96
96
  const CONFIG_DIR_NAME = '.superdesign';
97
97
  const CONFIG_FILE_NAME = 'config.json';
98
98
  const EXIT_CODES = {
@@ -106,6 +106,9 @@ var __webpack_exports__ = {};
106
106
  };
107
107
  const SKILLS_DIR = '.claude/skills/superdesign';
108
108
  const SKILL_FILE_NAME = 'SKILL.md';
109
+ const external_fs_namespaceObject = require("fs");
110
+ const external_os_namespaceObject = require("os");
111
+ var external_os_default = /*#__PURE__*/ __webpack_require__.n(external_os_namespaceObject);
109
112
  function getConfigDir() {
110
113
  return external_path_namespaceObject.join(external_os_namespaceObject.homedir(), CONFIG_DIR_NAME);
111
114
  }
@@ -313,7 +316,7 @@ var __webpack_exports__ = {};
313
316
  try {
314
317
  startSpinner('Creating auth session...');
315
318
  const session = await createSession({
316
- cliVersion: "0.1.5",
319
+ cliVersion: "0.1.7",
317
320
  os: `${external_os_namespaceObject.platform()} ${external_os_namespaceObject.release()}`,
318
321
  hostname: external_os_namespaceObject.hostname()
319
322
  });
@@ -512,269 +515,35 @@ var __webpack_exports__ = {};
512
515
  return `---
513
516
  name: superdesign
514
517
  description: Superdesign is a design agent, where it specialised in frontend UI/UX design; Use this skill before you implement any UI that require some design thinking
518
+ metadata:
519
+ author: superdesign
520
+ version: "0.0.1"
515
521
  ---
516
522
 
517
- SuperDesign helps you (1) find design inspirations/styles and (2) optionally generate/iterate design drafts on an infinite canvas.
518
-
519
- Each SuperDesign canvas run creates a new node and returns a \`previewUrl\`.
523
+ SuperDesign helps you (1) find design inspirations/styles and (2) generate/iterate design drafts on an infinite canvas.
520
524
 
521
525
  ---
522
526
 
523
- ## Core scenarios (what this skill handles)
527
+ # Core scenarios (what this skill handles)
524
528
 
525
529
  1. **Help me design X** (feature/page/flow)
526
530
  2. **Set design system**
527
531
  3. **Help me improve design of X**
528
532
 
529
- ---
530
-
531
- ## Tooling overview
532
-
533
- ### A) Inspiration & Style Tools (generic, always available)
534
- Use these to discover style direction, references, and brand context:
535
-
536
- - **Search prompt library** (style/components/pages)
537
- \`\`\`bash
538
- superdesign search-prompts --keyword "<keyword>" --json
539
- superdesign search-prompts --tags "style" --json
540
- superdesign search-prompts --tags "style" --keyword "<style keyword>" --json
541
- \`\`\`
542
-
543
- - **Get full prompt details**
544
- \`\`\`bash
545
- superdesign get-prompts --slugs "<slug1,slug2,...>" --json
546
- \`\`\`
547
-
548
- - **Extract brand guide from a URL**
549
- \`\`\`bash
550
- superdesign extract-brand-guide --url https://example.com --json
551
- \`\`\`
552
-
553
- ### B) Canvas Design Tools (specialised, optional)
554
-
555
- Use these when you want to explore multiple directions and show previews:
556
-
557
- - Create project (supports prompt / prompt file / HTML)
558
- - Create design draft
559
- - Iterate design draft (replace / branch)
560
- - Plan flow pages → execute flow pages
561
- - Fetch nodes, export HTML
562
-
563
- > Pixel-perfect HTML playground is ONLY required for Canvas workflows.
564
-
565
- ---
566
-
567
- ## Always-on rules
568
-
569
- - Design system should live at: \`.superdesign/design-system.md\`
570
- - If \`.superdesign/design-system.md\` is missing, run **Design System Setup** first.
571
- - Use \`askQuestion\` to ask high-signal questions (constraints, taste, tradeoffs).
572
- - For Canvas workflows: build a simplified/pixel-perfect prototype HTML in:
573
- - \`.superdesign/playgrounds/<name>.html\`
574
- - Always use \`--json\` for machine parsing.
575
-
576
- ---
577
-
578
- ## Playground rules (Canvas only)
579
-
580
- **Playground = BEFORE state (what exists now).** It provides context for SuperDesign agent.
581
- **Prompt = DESIRED CHANGE (what to add/modify).**
582
-
583
- The playground HTML must contain **ONLY UI that currently exists in the codebase**. For NEW features/sections, describe them entirely in the \`--prompt\` flag — do NOT add wireframes, placeholders, or sketches to the playground HTML.
584
-
585
- - **DO NOT** design or improve anything in the playground
586
- - **DO NOT** add placeholder sections like \`<!-- NEW FEATURE - DESIGN THIS -->\`
587
- - **DO** create pixel-perfect replica of current UI state
588
- - Valid formats:
589
- - **Component-only**: isolated component with enough markup to show core UX/states
590
- - **Full page**: replica of page where component operates (shows surrounding context)
591
- - Save to: \`.superdesign/playgrounds/<name>.html\`
592
-
593
- ### Example: Adding a "Book Demo" section to home page
594
-
595
- **BAD approach:**
596
- \`\`\`html
597
- <!-- playground includes a sketched Book Demo section -->
598
- <section class="book-demo">
599
- <!-- DESIGN THIS - Add CTA here -->
600
- <h3>Book a Demo</h3>
601
- <button>Schedule</button>
602
- </section>
603
- \`\`\`
604
-
605
- **GOOD approach:**
606
- \`\`\`html
607
- <!-- playground is pure replica of existing home page (hero + projects) -->
608
- <!-- NO book demo section in HTML -->
609
- \`\`\`
610
- Then in the iterate command:
611
- \`\`\`bash
612
- --prompt "Add a Book Demo section between the hero and projects sections. Requirements: minimal card style, horizontal layout..."
613
- \`\`\`
614
-
615
- ---
616
-
617
- # 1) Design System Setup
618
-
619
- ### Step 0 — Ask user (one question)
620
-
621
- "Do you want to **create a new design system** or **extract from the current codebase**?"
622
-
623
- ### A) Extract from codebase
624
-
625
- 1. Investigate codebase:
626
- - design tokens, typography, colors, spacing, radius, shadows
627
- - motion/animation patterns
628
- - example components usage + implementation patterns
629
- - core product functions + key pages
630
- 2. Write standalone design system to:
631
- - \`.superdesign/design-system.md\`
632
- - Must be implementable without the codebase
633
-
634
- ### B) Create a new design system (to improve current UI)
635
-
636
- 1. Investigate codebase to understand product + needed pages/components
637
- 2. Gather inspirations (generic tools):
638
- - \`superdesign search-prompts --tags "style" --json\`
639
- - \`superdesign get-prompts --slugs ... --json\`
640
- - optional: \`superdesign extract-brand-guide --url ... --json\`
641
- 3. Interview user (\`askQuestion\`) to choose direction
642
- 4. Write:
643
- - \`.superdesign/design-system.md\` (adapted to product + references)
644
-
645
- ---
646
-
647
- # 2) Designing X (feature/page/flow)
648
-
649
- ## A) If user wants references / direction only (no canvas)
650
-
651
- 1. Ensure \`.superdesign/design-system.md\` exists (setup if missing)
652
- 2. Use inspiration tools to collect references:
653
- - search prompts (style + component/page)
654
- - get prompts (full details)
655
- - extract brand guide if relevant
656
- 3. Provide a concrete design spec:
657
- - layout + hierarchy
658
- - component set + states
659
- - token guidance (typography/color/spacing/radius/motion)
660
- - interaction notes + edge cases
661
-
662
- ## B) If user wants visual exploration (canvas optional)
663
-
664
- Use canvas when direction is uncertain or multiple options are needed.
665
-
666
- ### Canvas workflow — Add feature to existing page
667
-
668
- 1. Ensure \`.superdesign/design-system.md\` exists (setup if missing)
669
- 2. Build prototype HTML playground (simplified + pixel-perfect enough):
670
- - \`.superdesign/playgrounds/<page>-<feature>.html\`
671
- 3. Ask targeted questions (\`askQuestion\`) about requirements + taste
672
- 4. Create project with playground HTML (returns \`draftId\`):
673
- \`\`\`bash
674
- superdesign create-project \\
675
- --title "<feature>" \\
676
- --html-file .superdesign/playgrounds/<file>.html \\
677
- --prompt-file .superdesign/design-system.md \\
678
- --json
679
- \`\`\`
680
- → Note: \`draftId\` in response is the baseline draft
681
- 5. Branch designs from baseline (use \`draftId\` from step 4):
682
- \`\`\`bash
683
- superdesign iterate-design-draft \\
684
- --draft-id <draftId> \\
685
- --prompt "<design requirements>" \\
686
- --mode branch \\
687
- --count 3 \\
688
- --json
689
- \`\`\`
690
- 6. Share \`previewUrl\` → collect feedback → iterate
691
-
692
- ### Canvas workflow — Add new page
693
-
694
- Same as above, but playground should include shared UI shell:
695
- - nav, layout container, spacing rhythm, shared components
696
-
697
- ### Canvas workflow — Improve current UI
698
-
699
- 1. Investigate product + current UI states
700
- 2. Ensure design system exists
701
- 3. Propose improvement options:
702
- - big restructure
703
- - style uplift
704
- - low-hanging polish
705
- 4. Pick one → build playground → create project (prompt-file design system) → branch drafts
706
- 5. Share \`previewUrl\` → iterate
707
-
708
- ### When to use create-design-draft
709
-
710
- Only use \`create-design-draft\` when creating from scratch (no HTML baseline).
711
-
712
- **Required in prompt:**
713
- - Full page structure (header, sidebar, main content areas)
714
- - Component environment/surroundings
715
- - Layout context (what's above/below/beside)
716
-
717
- \`\`\`bash
718
- superdesign create-design-draft \\
719
- --project-id <id> \\
720
- --title "Feature X" \\
721
- --prompt "Page has: fixed header 64px, left sidebar 240px, main content area. Design a settings panel in the main content area with..." \\
722
- --device desktop \\
723
- --json
533
+ # How it works
534
+ Fetch fresh guidelines below:
724
535
  \`\`\`
725
-
726
- ---
727
-
728
- # Advanced usage
729
-
730
- ### Plan + generate a full user journey
731
-
732
- Plan:
733
- \`\`\`bash
734
- superdesign plan-flow-pages \\
735
- --draft-id <draftId> \\
736
- --source-node-id <nodeId> \\
737
- --context "<flow context>" \\
738
- --json
536
+ https://raw.githubusercontent.com/superdesigndev/superdesign-skill/main/skills/superdesign/SUPERDESIGN.md
739
537
  \`\`\`
740
538
 
741
- Execute:
742
- \`\`\`bash
743
- superdesign execute-flow-pages \\
744
- --draft-id <draftId> \\
745
- --source-node-id <nodeId> \\
746
- --pages '[{"title":"Signup","prompt":"..."},{"title":"Payment","prompt":"..."}]' \\
747
- --json
748
- \`\`\`
539
+ Action accordingly based on instruction in the guidelines
749
540
 
750
- ### Get HTML reference from a draft
541
+ # Superdesign CLI
751
542
 
752
- \`\`\`bash
753
- superdesign get-design --draft-id <draftId> --output ./design.html
754
543
  \`\`\`
755
-
756
- ---
757
-
758
- ## Quick reference (key commands)
759
-
760
- \`\`\`bash
761
- # Inspirations
762
- superdesign search-prompts --keyword "<keyword>" --json
763
- superdesign search-prompts --tags "style" --json
764
- superdesign get-prompts --slugs "<slug1,slug2>" --json
765
- superdesign extract-brand-guide --url https://example.com --json
766
-
767
- # Canvas
768
- superdesign create-project --title "X" --prompt "..." --json
769
- superdesign create-project --title "X" --prompt-file .superdesign/design-system.md --json
770
- superdesign create-project --title "X" --html-file ./index.html --prompt-file .superdesign/design-system.md --json
771
-
772
- superdesign create-design-draft --project-id <id> --title "X" --prompt "..." --device desktop --json
773
- superdesign iterate-design-draft --draft-id <id> --prompt "..." --mode replace --json
774
- superdesign iterate-design-draft --draft-id <id> --prompt "..." --mode branch --count 3 --json
775
-
776
- superdesign fetch-design-nodes --project-id <id> --json
777
- superdesign get-design --draft-id <id> --json
544
+ npm install -g @superdesign/cli@latest
545
+ superdesign login
546
+ superdesign --help
778
547
  \`\`\`
779
548
  `;
780
549
  }
@@ -882,56 +651,45 @@ superdesign get-design --draft-id <id> --json
882
651
  }
883
652
  async function runJob(config) {
884
653
  const { startLabel, pollingLabel, successLabel, timeoutLabel, failureLabel, timeoutMs = 300000, startJob, transformResult, displayResult } = config;
885
- try {
886
- startSpinner(startLabel);
887
- const job = await startJob();
888
- updateSpinner(pollingLabel);
889
- const pollResult = await poll(()=>getJobStatus(job.jobId), isJobDone, {
890
- intervalMs: 2000,
891
- timeoutMs,
892
- onPoll: (attempt)=>{
893
- if (attempt % 5 === 0) updateSpinner(`${pollingLabel} (${Math.floor(2000 * attempt / 1000)}s)`);
894
- }
895
- });
896
- if (pollResult.timedOut) {
897
- failSpinner(timeoutLabel);
898
- output_error('Job timed out. The operation may still be processing in the background.');
899
- if (isJsonMode()) output({
900
- error: 'timeout',
901
- jobId: job.jobId
902
- });
903
- process.exit(EXIT_CODES.TIMEOUT);
904
- }
905
- if (!pollResult.success || !pollResult.data) {
906
- failSpinner(failureLabel);
907
- output_error(pollResult.error || 'Failed to get job status');
908
- process.exit(EXIT_CODES.API_ERROR);
909
- }
910
- const jobResult = pollResult.data;
911
- if (isJobFailed(jobResult)) {
912
- failSpinner(failureLabel);
913
- output_error(`${jobResult.error.code}: ${jobResult.error.message}`);
914
- process.exit(EXIT_CODES.API_ERROR);
915
- }
916
- if (!isJobCompleted(jobResult)) {
917
- failSpinner('Unexpected job status');
918
- output_error('Job ended in unexpected state');
919
- process.exit(EXIT_CODES.API_ERROR);
654
+ startSpinner(startLabel);
655
+ const job = await startJob();
656
+ updateSpinner(pollingLabel);
657
+ const pollResult = await poll(()=>getJobStatus(job.jobId), isJobDone, {
658
+ intervalMs: 2000,
659
+ timeoutMs,
660
+ onPoll: (attempt)=>{
661
+ if (attempt % 5 === 0) updateSpinner(`${pollingLabel} (${Math.floor(2000 * attempt / 1000)}s)`);
920
662
  }
921
- succeedSpinner(successLabel);
922
- if (isJsonMode()) output(transformResult(jobResult));
923
- else displayResult(jobResult);
924
- process.exit(EXIT_CODES.SUCCESS);
925
- } catch (err) {
663
+ });
664
+ if (pollResult.timedOut) {
665
+ failSpinner(timeoutLabel);
666
+ if (isJsonMode()) output({
667
+ error: 'timeout',
668
+ jobId: job.jobId
669
+ });
670
+ else output_error('Job timed out. The operation may still be processing in the background.');
671
+ throw new ApiClientError('Job timed out', 'timeout');
672
+ }
673
+ if (!pollResult.success || !pollResult.data) {
926
674
  failSpinner(failureLabel);
927
- if (err instanceof ApiClientError) {
928
- output_error(`API Error: ${err.message}`);
929
- process.exit(EXIT_CODES.API_ERROR);
930
- }
931
- const message = err instanceof Error ? err.message : 'Unknown error';
932
- output_error(message);
933
- process.exit(EXIT_CODES.GENERAL_ERROR);
675
+ const errMsg = pollResult.error || 'Failed to get job status';
676
+ if (!isJsonMode()) output_error(errMsg);
677
+ throw new ApiClientError(errMsg, 'api_error');
678
+ }
679
+ const jobResult = pollResult.data;
680
+ if (isJobFailed(jobResult)) {
681
+ failSpinner(failureLabel);
682
+ if (!isJsonMode()) output_error(`${jobResult.error.code}: ${jobResult.error.message}`);
683
+ throw new ApiClientError(jobResult.error.message, jobResult.error.code);
934
684
  }
685
+ if (!isJobCompleted(jobResult)) {
686
+ failSpinner('Unexpected job status');
687
+ if (!isJsonMode()) output_error('Job ended in unexpected state');
688
+ throw new ApiClientError('Job ended in unexpected state', 'unexpected_status');
689
+ }
690
+ succeedSpinner(successLabel);
691
+ if (isJsonMode()) output(transformResult(jobResult));
692
+ else displayResult(jobResult);
935
693
  }
936
694
  function job_runner_requireAuth(isAuthenticated) {
937
695
  if (!isAuthenticated()) {
@@ -1509,6 +1267,72 @@ superdesign get-design --draft-id <id> --json
1509
1267
  });
1510
1268
  return command;
1511
1269
  }
1270
+ const external_posthog_node_namespaceObject = require("posthog-node");
1271
+ let posthogClient = null;
1272
+ function getPostHog() {
1273
+ if (!posthogClient && POSTHOG_KEY) posthogClient = new external_posthog_node_namespaceObject.PostHog(POSTHOG_KEY, {
1274
+ host: POSTHOG_HOST
1275
+ });
1276
+ return posthogClient;
1277
+ }
1278
+ const SENSITIVE_KEYS = [
1279
+ 'token',
1280
+ 'key',
1281
+ 'secret',
1282
+ 'password',
1283
+ 'apikey',
1284
+ 'auth',
1285
+ 'authorization',
1286
+ 'credential'
1287
+ ];
1288
+ function sanitizeOptions(options) {
1289
+ const sanitized = {};
1290
+ for (const [key, value] of Object.entries(options)){
1291
+ if ('function' == typeof value || key.startsWith('_')) continue;
1292
+ const lowerKey = key.toLowerCase();
1293
+ if (!SENSITIVE_KEYS.some((sensitive)=>lowerKey.includes(sensitive))) {
1294
+ if ('string' != typeof value || !(value.length > 100)) sanitized[key] = value;
1295
+ }
1296
+ }
1297
+ return sanitized;
1298
+ }
1299
+ async function trackCommand(opts) {
1300
+ const { teamId } = loadConfig();
1301
+ const metadata = {
1302
+ command: opts.command,
1303
+ success: opts.success,
1304
+ durationMs: opts.durationMs,
1305
+ errorCode: opts.errorCode,
1306
+ options: opts.options,
1307
+ cliVersion: "0.1.7",
1308
+ os: `${external_os_default().platform()} ${external_os_default().release()}`
1309
+ };
1310
+ const posthog = getPostHog();
1311
+ if (posthog) {
1312
+ const distinctId = teamId || `anon_${external_os_default().hostname()}`;
1313
+ posthog.capture({
1314
+ distinctId,
1315
+ event: 'cli_command',
1316
+ properties: {
1317
+ team_id: teamId,
1318
+ ...metadata
1319
+ }
1320
+ });
1321
+ }
1322
+ if (manager_isAuthenticated() && teamId) try {
1323
+ const client = getApiClient();
1324
+ await client.post('/external/track', {
1325
+ activityType: 'cli_command',
1326
+ metadata
1327
+ });
1328
+ } catch {}
1329
+ }
1330
+ async function shutdownAnalytics() {
1331
+ if (posthogClient) {
1332
+ await posthogClient.shutdown();
1333
+ posthogClient = null;
1334
+ }
1335
+ }
1512
1336
  const src_filename = (0, external_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__);
1513
1337
  const src_dirname = (0, external_path_namespaceObject.dirname)(src_filename);
1514
1338
  (0, external_dotenv_namespaceObject.config)({
@@ -1517,7 +1341,20 @@ superdesign get-design --draft-id <id> --json
1517
1341
  (0, external_dotenv_namespaceObject.config)();
1518
1342
  function createProgram() {
1519
1343
  const program = new external_commander_namespaceObject.Command();
1520
- program.name('superdesign').description('SuperDesign CLI - AI product designer for coding agents').version("0.1.5");
1344
+ program.name('superdesign').description('SuperDesign CLI - AI product designer for coding agents').version("0.1.7");
1345
+ let startTime = 0;
1346
+ program.hook('preAction', ()=>{
1347
+ startTime = Date.now();
1348
+ });
1349
+ program.hook('postAction', async (_thisCommand, actionCommand)=>{
1350
+ await trackCommand({
1351
+ command: actionCommand.name(),
1352
+ success: true,
1353
+ durationMs: Date.now() - startTime,
1354
+ options: sanitizeOptions(actionCommand.opts())
1355
+ });
1356
+ await shutdownAnalytics();
1357
+ });
1521
1358
  program.addCommand(createLoginCommand());
1522
1359
  program.addCommand(createLogoutCommand());
1523
1360
  program.addCommand(createInitCommand());
package/dist/index.js CHANGED
@@ -3,10 +3,13 @@ import { fileURLToPath } from "url";
3
3
  import { dirname, join, resolve as external_path_resolve } from "path";
4
4
  import { Command } from "commander";
5
5
  import { appendFileSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
6
- import { homedir, hostname, platform, release } from "os";
6
+ import os, { homedir, hostname, platform, release } from "os";
7
7
  import axios from "axios";
8
8
  import ora from "ora";
9
9
  import { writeFile } from "fs/promises";
10
+ import { PostHog } from "posthog-node";
11
+ const POSTHOG_KEY = process.env.POSTHOG_KEY || 'phc_oUcDklFBX3wy8eksSyEC0pataKCgSadur1sio5hBHg4';
12
+ const POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://eu.i.posthog.com';
10
13
  const CONFIG_DIR_NAME = '.superdesign';
11
14
  const CONFIG_FILE_NAME = 'config.json';
12
15
  const EXIT_CODES = {
@@ -223,7 +226,7 @@ async function runAuthFlow(options = {}) {
223
226
  try {
224
227
  startSpinner('Creating auth session...');
225
228
  const session = await createSession({
226
- cliVersion: "0.1.5",
229
+ cliVersion: "0.1.7",
227
230
  os: `${platform()} ${release()}`,
228
231
  hostname: hostname()
229
232
  });
@@ -422,269 +425,35 @@ function getSkillTemplate() {
422
425
  return `---
423
426
  name: superdesign
424
427
  description: Superdesign is a design agent, where it specialised in frontend UI/UX design; Use this skill before you implement any UI that require some design thinking
428
+ metadata:
429
+ author: superdesign
430
+ version: "0.0.1"
425
431
  ---
426
432
 
427
- SuperDesign helps you (1) find design inspirations/styles and (2) optionally generate/iterate design drafts on an infinite canvas.
428
-
429
- Each SuperDesign canvas run creates a new node and returns a \`previewUrl\`.
433
+ SuperDesign helps you (1) find design inspirations/styles and (2) generate/iterate design drafts on an infinite canvas.
430
434
 
431
435
  ---
432
436
 
433
- ## Core scenarios (what this skill handles)
437
+ # Core scenarios (what this skill handles)
434
438
 
435
439
  1. **Help me design X** (feature/page/flow)
436
440
  2. **Set design system**
437
441
  3. **Help me improve design of X**
438
442
 
439
- ---
440
-
441
- ## Tooling overview
442
-
443
- ### A) Inspiration & Style Tools (generic, always available)
444
- Use these to discover style direction, references, and brand context:
445
-
446
- - **Search prompt library** (style/components/pages)
447
- \`\`\`bash
448
- superdesign search-prompts --keyword "<keyword>" --json
449
- superdesign search-prompts --tags "style" --json
450
- superdesign search-prompts --tags "style" --keyword "<style keyword>" --json
451
- \`\`\`
452
-
453
- - **Get full prompt details**
454
- \`\`\`bash
455
- superdesign get-prompts --slugs "<slug1,slug2,...>" --json
456
- \`\`\`
457
-
458
- - **Extract brand guide from a URL**
459
- \`\`\`bash
460
- superdesign extract-brand-guide --url https://example.com --json
461
- \`\`\`
462
-
463
- ### B) Canvas Design Tools (specialised, optional)
464
-
465
- Use these when you want to explore multiple directions and show previews:
466
-
467
- - Create project (supports prompt / prompt file / HTML)
468
- - Create design draft
469
- - Iterate design draft (replace / branch)
470
- - Plan flow pages → execute flow pages
471
- - Fetch nodes, export HTML
472
-
473
- > Pixel-perfect HTML playground is ONLY required for Canvas workflows.
474
-
475
- ---
476
-
477
- ## Always-on rules
478
-
479
- - Design system should live at: \`.superdesign/design-system.md\`
480
- - If \`.superdesign/design-system.md\` is missing, run **Design System Setup** first.
481
- - Use \`askQuestion\` to ask high-signal questions (constraints, taste, tradeoffs).
482
- - For Canvas workflows: build a simplified/pixel-perfect prototype HTML in:
483
- - \`.superdesign/playgrounds/<name>.html\`
484
- - Always use \`--json\` for machine parsing.
485
-
486
- ---
487
-
488
- ## Playground rules (Canvas only)
489
-
490
- **Playground = BEFORE state (what exists now).** It provides context for SuperDesign agent.
491
- **Prompt = DESIRED CHANGE (what to add/modify).**
492
-
493
- The playground HTML must contain **ONLY UI that currently exists in the codebase**. For NEW features/sections, describe them entirely in the \`--prompt\` flag — do NOT add wireframes, placeholders, or sketches to the playground HTML.
494
-
495
- - **DO NOT** design or improve anything in the playground
496
- - **DO NOT** add placeholder sections like \`<!-- NEW FEATURE - DESIGN THIS -->\`
497
- - **DO** create pixel-perfect replica of current UI state
498
- - Valid formats:
499
- - **Component-only**: isolated component with enough markup to show core UX/states
500
- - **Full page**: replica of page where component operates (shows surrounding context)
501
- - Save to: \`.superdesign/playgrounds/<name>.html\`
502
-
503
- ### Example: Adding a "Book Demo" section to home page
504
-
505
- **BAD approach:**
506
- \`\`\`html
507
- <!-- playground includes a sketched Book Demo section -->
508
- <section class="book-demo">
509
- <!-- DESIGN THIS - Add CTA here -->
510
- <h3>Book a Demo</h3>
511
- <button>Schedule</button>
512
- </section>
513
- \`\`\`
514
-
515
- **GOOD approach:**
516
- \`\`\`html
517
- <!-- playground is pure replica of existing home page (hero + projects) -->
518
- <!-- NO book demo section in HTML -->
443
+ # How it works
444
+ Fetch fresh guidelines below:
519
445
  \`\`\`
520
- Then in the iterate command:
521
- \`\`\`bash
522
- --prompt "Add a Book Demo section between the hero and projects sections. Requirements: minimal card style, horizontal layout..."
523
- \`\`\`
524
-
525
- ---
526
-
527
- # 1) Design System Setup
528
-
529
- ### Step 0 — Ask user (one question)
530
-
531
- "Do you want to **create a new design system** or **extract from the current codebase**?"
532
-
533
- ### A) Extract from codebase
534
-
535
- 1. Investigate codebase:
536
- - design tokens, typography, colors, spacing, radius, shadows
537
- - motion/animation patterns
538
- - example components usage + implementation patterns
539
- - core product functions + key pages
540
- 2. Write standalone design system to:
541
- - \`.superdesign/design-system.md\`
542
- - Must be implementable without the codebase
543
-
544
- ### B) Create a new design system (to improve current UI)
545
-
546
- 1. Investigate codebase to understand product + needed pages/components
547
- 2. Gather inspirations (generic tools):
548
- - \`superdesign search-prompts --tags "style" --json\`
549
- - \`superdesign get-prompts --slugs ... --json\`
550
- - optional: \`superdesign extract-brand-guide --url ... --json\`
551
- 3. Interview user (\`askQuestion\`) to choose direction
552
- 4. Write:
553
- - \`.superdesign/design-system.md\` (adapted to product + references)
554
-
555
- ---
556
-
557
- # 2) Designing X (feature/page/flow)
558
-
559
- ## A) If user wants references / direction only (no canvas)
560
-
561
- 1. Ensure \`.superdesign/design-system.md\` exists (setup if missing)
562
- 2. Use inspiration tools to collect references:
563
- - search prompts (style + component/page)
564
- - get prompts (full details)
565
- - extract brand guide if relevant
566
- 3. Provide a concrete design spec:
567
- - layout + hierarchy
568
- - component set + states
569
- - token guidance (typography/color/spacing/radius/motion)
570
- - interaction notes + edge cases
571
-
572
- ## B) If user wants visual exploration (canvas optional)
573
-
574
- Use canvas when direction is uncertain or multiple options are needed.
575
-
576
- ### Canvas workflow — Add feature to existing page
577
-
578
- 1. Ensure \`.superdesign/design-system.md\` exists (setup if missing)
579
- 2. Build prototype HTML playground (simplified + pixel-perfect enough):
580
- - \`.superdesign/playgrounds/<page>-<feature>.html\`
581
- 3. Ask targeted questions (\`askQuestion\`) about requirements + taste
582
- 4. Create project with playground HTML (returns \`draftId\`):
583
- \`\`\`bash
584
- superdesign create-project \\
585
- --title "<feature>" \\
586
- --html-file .superdesign/playgrounds/<file>.html \\
587
- --prompt-file .superdesign/design-system.md \\
588
- --json
589
- \`\`\`
590
- → Note: \`draftId\` in response is the baseline draft
591
- 5. Branch designs from baseline (use \`draftId\` from step 4):
592
- \`\`\`bash
593
- superdesign iterate-design-draft \\
594
- --draft-id <draftId> \\
595
- --prompt "<design requirements>" \\
596
- --mode branch \\
597
- --count 3 \\
598
- --json
599
- \`\`\`
600
- 6. Share \`previewUrl\` → collect feedback → iterate
601
-
602
- ### Canvas workflow — Add new page
603
-
604
- Same as above, but playground should include shared UI shell:
605
- - nav, layout container, spacing rhythm, shared components
606
-
607
- ### Canvas workflow — Improve current UI
608
-
609
- 1. Investigate product + current UI states
610
- 2. Ensure design system exists
611
- 3. Propose improvement options:
612
- - big restructure
613
- - style uplift
614
- - low-hanging polish
615
- 4. Pick one → build playground → create project (prompt-file design system) → branch drafts
616
- 5. Share \`previewUrl\` → iterate
617
-
618
- ### When to use create-design-draft
619
-
620
- Only use \`create-design-draft\` when creating from scratch (no HTML baseline).
621
-
622
- **Required in prompt:**
623
- - Full page structure (header, sidebar, main content areas)
624
- - Component environment/surroundings
625
- - Layout context (what's above/below/beside)
626
-
627
- \`\`\`bash
628
- superdesign create-design-draft \\
629
- --project-id <id> \\
630
- --title "Feature X" \\
631
- --prompt "Page has: fixed header 64px, left sidebar 240px, main content area. Design a settings panel in the main content area with..." \\
632
- --device desktop \\
633
- --json
634
- \`\`\`
635
-
636
- ---
637
-
638
- # Advanced usage
639
-
640
- ### Plan + generate a full user journey
641
-
642
- Plan:
643
- \`\`\`bash
644
- superdesign plan-flow-pages \\
645
- --draft-id <draftId> \\
646
- --source-node-id <nodeId> \\
647
- --context "<flow context>" \\
648
- --json
446
+ https://raw.githubusercontent.com/superdesigndev/superdesign-skill/main/skills/superdesign/SUPERDESIGN.md
649
447
  \`\`\`
650
448
 
651
- Execute:
652
- \`\`\`bash
653
- superdesign execute-flow-pages \\
654
- --draft-id <draftId> \\
655
- --source-node-id <nodeId> \\
656
- --pages '[{"title":"Signup","prompt":"..."},{"title":"Payment","prompt":"..."}]' \\
657
- --json
658
- \`\`\`
449
+ Action accordingly based on instruction in the guidelines
659
450
 
660
- ### Get HTML reference from a draft
451
+ # Superdesign CLI
661
452
 
662
- \`\`\`bash
663
- superdesign get-design --draft-id <draftId> --output ./design.html
664
453
  \`\`\`
665
-
666
- ---
667
-
668
- ## Quick reference (key commands)
669
-
670
- \`\`\`bash
671
- # Inspirations
672
- superdesign search-prompts --keyword "<keyword>" --json
673
- superdesign search-prompts --tags "style" --json
674
- superdesign get-prompts --slugs "<slug1,slug2>" --json
675
- superdesign extract-brand-guide --url https://example.com --json
676
-
677
- # Canvas
678
- superdesign create-project --title "X" --prompt "..." --json
679
- superdesign create-project --title "X" --prompt-file .superdesign/design-system.md --json
680
- superdesign create-project --title "X" --html-file ./index.html --prompt-file .superdesign/design-system.md --json
681
-
682
- superdesign create-design-draft --project-id <id> --title "X" --prompt "..." --device desktop --json
683
- superdesign iterate-design-draft --draft-id <id> --prompt "..." --mode replace --json
684
- superdesign iterate-design-draft --draft-id <id> --prompt "..." --mode branch --count 3 --json
685
-
686
- superdesign fetch-design-nodes --project-id <id> --json
687
- superdesign get-design --draft-id <id> --json
454
+ npm install -g @superdesign/cli@latest
455
+ superdesign login
456
+ superdesign --help
688
457
  \`\`\`
689
458
  `;
690
459
  }
@@ -792,56 +561,45 @@ function isJobFailed(response) {
792
561
  }
793
562
  async function runJob(config) {
794
563
  const { startLabel, pollingLabel, successLabel, timeoutLabel, failureLabel, timeoutMs = 300000, startJob, transformResult, displayResult } = config;
795
- try {
796
- startSpinner(startLabel);
797
- const job = await startJob();
798
- updateSpinner(pollingLabel);
799
- const pollResult = await poll(()=>getJobStatus(job.jobId), isJobDone, {
800
- intervalMs: 2000,
801
- timeoutMs,
802
- onPoll: (attempt)=>{
803
- if (attempt % 5 === 0) updateSpinner(`${pollingLabel} (${Math.floor(2000 * attempt / 1000)}s)`);
804
- }
805
- });
806
- if (pollResult.timedOut) {
807
- failSpinner(timeoutLabel);
808
- output_error('Job timed out. The operation may still be processing in the background.');
809
- if (isJsonMode()) output({
810
- error: 'timeout',
811
- jobId: job.jobId
812
- });
813
- process.exit(EXIT_CODES.TIMEOUT);
814
- }
815
- if (!pollResult.success || !pollResult.data) {
816
- failSpinner(failureLabel);
817
- output_error(pollResult.error || 'Failed to get job status');
818
- process.exit(EXIT_CODES.API_ERROR);
819
- }
820
- const jobResult = pollResult.data;
821
- if (isJobFailed(jobResult)) {
822
- failSpinner(failureLabel);
823
- output_error(`${jobResult.error.code}: ${jobResult.error.message}`);
824
- process.exit(EXIT_CODES.API_ERROR);
564
+ startSpinner(startLabel);
565
+ const job = await startJob();
566
+ updateSpinner(pollingLabel);
567
+ const pollResult = await poll(()=>getJobStatus(job.jobId), isJobDone, {
568
+ intervalMs: 2000,
569
+ timeoutMs,
570
+ onPoll: (attempt)=>{
571
+ if (attempt % 5 === 0) updateSpinner(`${pollingLabel} (${Math.floor(2000 * attempt / 1000)}s)`);
825
572
  }
826
- if (!isJobCompleted(jobResult)) {
827
- failSpinner('Unexpected job status');
828
- output_error('Job ended in unexpected state');
829
- process.exit(EXIT_CODES.API_ERROR);
830
- }
831
- succeedSpinner(successLabel);
832
- if (isJsonMode()) output(transformResult(jobResult));
833
- else displayResult(jobResult);
834
- process.exit(EXIT_CODES.SUCCESS);
835
- } catch (err) {
573
+ });
574
+ if (pollResult.timedOut) {
575
+ failSpinner(timeoutLabel);
576
+ if (isJsonMode()) output({
577
+ error: 'timeout',
578
+ jobId: job.jobId
579
+ });
580
+ else output_error('Job timed out. The operation may still be processing in the background.');
581
+ throw new ApiClientError('Job timed out', 'timeout');
582
+ }
583
+ if (!pollResult.success || !pollResult.data) {
836
584
  failSpinner(failureLabel);
837
- if (err instanceof ApiClientError) {
838
- output_error(`API Error: ${err.message}`);
839
- process.exit(EXIT_CODES.API_ERROR);
840
- }
841
- const message = err instanceof Error ? err.message : 'Unknown error';
842
- output_error(message);
843
- process.exit(EXIT_CODES.GENERAL_ERROR);
585
+ const errMsg = pollResult.error || 'Failed to get job status';
586
+ if (!isJsonMode()) output_error(errMsg);
587
+ throw new ApiClientError(errMsg, 'api_error');
588
+ }
589
+ const jobResult = pollResult.data;
590
+ if (isJobFailed(jobResult)) {
591
+ failSpinner(failureLabel);
592
+ if (!isJsonMode()) output_error(`${jobResult.error.code}: ${jobResult.error.message}`);
593
+ throw new ApiClientError(jobResult.error.message, jobResult.error.code);
594
+ }
595
+ if (!isJobCompleted(jobResult)) {
596
+ failSpinner('Unexpected job status');
597
+ if (!isJsonMode()) output_error('Job ended in unexpected state');
598
+ throw new ApiClientError('Job ended in unexpected state', 'unexpected_status');
844
599
  }
600
+ succeedSpinner(successLabel);
601
+ if (isJsonMode()) output(transformResult(jobResult));
602
+ else displayResult(jobResult);
845
603
  }
846
604
  function job_runner_requireAuth(isAuthenticated) {
847
605
  if (!isAuthenticated()) {
@@ -1418,6 +1176,71 @@ function createGetDesignCommand() {
1418
1176
  });
1419
1177
  return command;
1420
1178
  }
1179
+ let posthogClient = null;
1180
+ function getPostHog() {
1181
+ if (!posthogClient && POSTHOG_KEY) posthogClient = new PostHog(POSTHOG_KEY, {
1182
+ host: POSTHOG_HOST
1183
+ });
1184
+ return posthogClient;
1185
+ }
1186
+ const SENSITIVE_KEYS = [
1187
+ 'token',
1188
+ 'key',
1189
+ 'secret',
1190
+ 'password',
1191
+ 'apikey',
1192
+ 'auth',
1193
+ 'authorization',
1194
+ 'credential'
1195
+ ];
1196
+ function sanitizeOptions(options) {
1197
+ const sanitized = {};
1198
+ for (const [key, value] of Object.entries(options)){
1199
+ if ('function' == typeof value || key.startsWith('_')) continue;
1200
+ const lowerKey = key.toLowerCase();
1201
+ if (!SENSITIVE_KEYS.some((sensitive)=>lowerKey.includes(sensitive))) {
1202
+ if ('string' != typeof value || !(value.length > 100)) sanitized[key] = value;
1203
+ }
1204
+ }
1205
+ return sanitized;
1206
+ }
1207
+ async function trackCommand(opts) {
1208
+ const { teamId } = loadConfig();
1209
+ const metadata = {
1210
+ command: opts.command,
1211
+ success: opts.success,
1212
+ durationMs: opts.durationMs,
1213
+ errorCode: opts.errorCode,
1214
+ options: opts.options,
1215
+ cliVersion: "0.1.7",
1216
+ os: `${os.platform()} ${os.release()}`
1217
+ };
1218
+ const posthog = getPostHog();
1219
+ if (posthog) {
1220
+ const distinctId = teamId || `anon_${os.hostname()}`;
1221
+ posthog.capture({
1222
+ distinctId,
1223
+ event: 'cli_command',
1224
+ properties: {
1225
+ team_id: teamId,
1226
+ ...metadata
1227
+ }
1228
+ });
1229
+ }
1230
+ if (manager_isAuthenticated() && teamId) try {
1231
+ const client = getApiClient();
1232
+ await client.post('/external/track', {
1233
+ activityType: 'cli_command',
1234
+ metadata
1235
+ });
1236
+ } catch {}
1237
+ }
1238
+ async function shutdownAnalytics() {
1239
+ if (posthogClient) {
1240
+ await posthogClient.shutdown();
1241
+ posthogClient = null;
1242
+ }
1243
+ }
1421
1244
  const src_filename = fileURLToPath(import.meta.url);
1422
1245
  const src_dirname = dirname(src_filename);
1423
1246
  external_dotenv_config({
@@ -1426,7 +1249,20 @@ external_dotenv_config({
1426
1249
  external_dotenv_config();
1427
1250
  function createProgram() {
1428
1251
  const program = new Command();
1429
- program.name('superdesign').description('SuperDesign CLI - AI product designer for coding agents').version("0.1.5");
1252
+ program.name('superdesign').description('SuperDesign CLI - AI product designer for coding agents').version("0.1.7");
1253
+ let startTime = 0;
1254
+ program.hook('preAction', ()=>{
1255
+ startTime = Date.now();
1256
+ });
1257
+ program.hook('postAction', async (_thisCommand, actionCommand)=>{
1258
+ await trackCommand({
1259
+ command: actionCommand.name(),
1260
+ success: true,
1261
+ durationMs: Date.now() - startTime,
1262
+ options: sanitizeOptions(actionCommand.opts())
1263
+ });
1264
+ await shutdownAnalytics();
1265
+ });
1430
1266
  program.addCommand(createLoginCommand());
1431
1267
  program.addCommand(createLogoutCommand());
1432
1268
  program.addCommand(createInitCommand());
@@ -0,0 +1,24 @@
1
+ /**
2
+ * CLI Analytics - Dual tracking with PostHog (real-time) and Backend (long-term storage)
3
+ */
4
+ export interface TrackCommandOptions {
5
+ command: string;
6
+ success: boolean;
7
+ durationMs: number;
8
+ errorCode?: string;
9
+ options?: Record<string, unknown>;
10
+ }
11
+ /**
12
+ * Sanitize command options by removing sensitive values, functions, and internal properties
13
+ */
14
+ export declare function sanitizeOptions(options: Record<string, unknown>): Record<string, unknown>;
15
+ /**
16
+ * Track a CLI command execution
17
+ * Sends to both PostHog (real-time dashboards) and backend (long-term storage)
18
+ */
19
+ export declare function trackCommand(opts: TrackCommandOptions): Promise<void>;
20
+ /**
21
+ * Shutdown analytics and flush any pending events
22
+ * Should be called before CLI exits
23
+ */
24
+ export declare function shutdownAnalytics(): Promise<void>;
@@ -33,8 +33,9 @@ export interface JobRunnerResult<TResult> {
33
33
  /**
34
34
  * Run a job with polling and standard error handling
35
35
  * Handles spinner updates, timeout, failure states, and output formatting
36
+ * Returns normally on success, throws on failure (to allow postAction hooks to run)
36
37
  */
37
- export declare function runJob<TResult>(config: JobRunnerConfig<TResult>): Promise<never>;
38
+ export declare function runJob<TResult>(config: JobRunnerConfig<TResult>): Promise<void>;
38
39
  /**
39
40
  * Check authentication and exit with appropriate error if not authenticated
40
41
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superdesign/cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "CLI for SuperDesign Platform - agent skills for Claude Code",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -29,7 +29,8 @@
29
29
  "commander": "^11.1.0",
30
30
  "dotenv": "^16.3.0",
31
31
  "open": "^10.0.0",
32
- "ora": "^8.0.0"
32
+ "ora": "^8.0.0",
33
+ "posthog-node": "^5.24.1"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@rslib/core": "0.15.1",