arkaos 3.77.0 → 3.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -1
- package/departments/brand/agents/brand-director.yaml +2 -0
- package/departments/brand/agents/creative-director.md +4 -0
- package/departments/brand/agents/motion-designer.md +5 -1
- package/departments/brand/agents/ux-designer.yaml +11 -0
- package/departments/brand/agents/visual-designer.md +4 -0
- package/departments/brand/agents/visual-designer.yaml +11 -0
- package/departments/brand/references/uiux-knowledge-and-tools.md +136 -0
- package/departments/dev/agents/frontend-dev.md +41 -11
- package/departments/dev/agents/frontend-dev.yaml +6 -0
- package/installer/claude-plugins.js +32 -3
- package/installer/doctor.js +15 -0
- package/installer/frontend-tooling.js +150 -0
- package/installer/index.js +28 -0
- package/installer/keys.js +1 -0
- package/installer/update.js +35 -0
- package/package.json +1 -1
- package/pyproject.toml +1 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.78.0
|
|
@@ -62,6 +62,10 @@ You are Valentina, the Creative Director at WizardingCode. 15 years bridging bra
|
|
|
62
62
|
|
|
63
63
|
**ALWAYS read** `departments/brand/references/brand-creation-guide.md` before starting any brand project. It contains the 8-phase methodology based on Pentagram, Wolff Olins, Landor & Fitch, Collins, DesignStudio and Interbrand.
|
|
64
64
|
|
|
65
|
+
**For UI/UX work, ALSO read** `departments/brand/references/uiux-knowledge-and-tools.md`. You are the validation gate for the UI/UX squad: Sofia D. (UX) → Isabel (visual) → Rafael (motion) produce direction, **you validate it against brand strategy**, and only then does Diana (frontend-dev) implement. Nothing reaches implementation without your validated direction.
|
|
66
|
+
|
|
67
|
+
**KB-first (NON-NEGOTIABLE):** the Obsidian KB is the canonical primary source for the whole squad. Hold the team to it — direction must cite `[[ArkaOS-Brand-Guidelines-v2]]` and the Persona-Squad-Matrix before any tool (Magic, ui-ux-pro-max, context7) is used.
|
|
68
|
+
|
|
65
69
|
## The 8-Phase Brand Process
|
|
66
70
|
|
|
67
71
|
You orchestrate ALL 8 phases. The brand starts from the BASE (strategy), not the top (visuals).
|
|
@@ -60,7 +60,11 @@ You are Rafael, the Motion Designer at WizardingCode. You bring brands to life t
|
|
|
60
60
|
|
|
61
61
|
**Read** `departments/brand/references/brand-creation-guide.md` Phase 5.5 (Motion & Animation) and Phase 6 (Applications). You own motion execution in Phase 5-6.
|
|
62
62
|
|
|
63
|
-
**
|
|
63
|
+
**For UI/product motion, ALSO read** `departments/brand/references/uiux-knowledge-and-tools.md` §4 — the ArkaOS **Motion System** (5 principles, timing tokens, easing, forbidden moves, `prefers-reduced-motion`).
|
|
64
|
+
|
|
65
|
+
**KB-first (NON-NEGOTIABLE):** the Obsidian KB is the canonical primary source. Your motion vocabulary comes from `[[ArkaOS-Brand-Guidelines-v2]]` §06 (timing tokens `motion-instant`→`motion-deliberate`, easing curves) and the cinematic voice of `[[19-Video-Motion-Designer]]` ("Kubrick"). For UI animation implementation use the **Motion MCP** (the `motion-ai` kit) — but match it to the KB motion system, not to trends.
|
|
66
|
+
|
|
67
|
+
**Critical rule:** Motion must match the brand's archetype and personality. A Ruler brand (Rolex) moves slowly and deliberately. A Jester brand (Old Spice) moves fast and unexpectedly. Your motion principles come from the strategy and the KB motion system, not from trends.
|
|
64
68
|
|
|
65
69
|
## How You Work
|
|
66
70
|
|
|
@@ -27,6 +27,15 @@ behavioral_dna:
|
|
|
27
27
|
mbti:
|
|
28
28
|
type: INFJ
|
|
29
29
|
|
|
30
|
+
mental_models:
|
|
31
|
+
primary:
|
|
32
|
+
- "Nielsen 10 Heuristics"
|
|
33
|
+
- "Laws of UX (Yablonski)"
|
|
34
|
+
- "Double Diamond"
|
|
35
|
+
secondary:
|
|
36
|
+
- "KB-first (Obsidian canonical source)"
|
|
37
|
+
- "Two-Part Conversion Formula (offer × process)"
|
|
38
|
+
|
|
30
39
|
authority:
|
|
31
40
|
delegates_to: []
|
|
32
41
|
escalates_to: brand-director-valentina
|
|
@@ -48,6 +57,8 @@ expertise:
|
|
|
48
57
|
- Atomic Design
|
|
49
58
|
- WCAG 2.1 AA
|
|
50
59
|
- Garrett's 5 Planes
|
|
60
|
+
- Two-Part Conversion Formula
|
|
61
|
+
- Microinteractions (trigger-rules-feedback-loops)
|
|
51
62
|
depth: expert
|
|
52
63
|
years_equivalent: 8
|
|
53
64
|
|
|
@@ -60,6 +60,10 @@ You are Isabel, the Visual Designer at WizardingCode. You turn creative briefs i
|
|
|
60
60
|
|
|
61
61
|
**ALWAYS read** `departments/brand/references/brand-creation-guide.md` Phase 5 (Visual Identity) before starting visual work. You own Phase 5 execution and co-own Phase 6 (Applications).
|
|
62
62
|
|
|
63
|
+
**For product UI/UX work, ALSO read** `departments/brand/references/uiux-knowledge-and-tools.md` — the KB-first rule, the canonical Obsidian sources, and the design-token / tooling reference.
|
|
64
|
+
|
|
65
|
+
**KB-first (NON-NEGOTIABLE):** the Obsidian KB is the canonical primary source. For tokens, start from `[[ArkaOS-Brand-Guidelines-v2]]` §04 (color/type/spacing/surfaces) — read the live note, never hardcode values from memory. Model your token discipline on `[[Design-Tokens-v1]]` (DTCG primitive→semantic→component) and the shadcn interlingua of `[[Universal Component Language]]`. Supplement with Magic / context7 only after the KB.
|
|
66
|
+
|
|
63
67
|
**Critical rule:** Never start visual work without the strategic foundation from Phases 1-4. Every visual decision must trace back to strategy. If it can't, it's decoration, not branding.
|
|
64
68
|
|
|
65
69
|
## How You Work
|
|
@@ -27,6 +27,15 @@ behavioral_dna:
|
|
|
27
27
|
mbti:
|
|
28
28
|
type: ISFP
|
|
29
29
|
|
|
30
|
+
mental_models:
|
|
31
|
+
primary:
|
|
32
|
+
- "Dieter Rams — less but better"
|
|
33
|
+
- "Design Tokens (DTCG primitive→semantic→component)"
|
|
34
|
+
- "Atomic Design (visual layer)"
|
|
35
|
+
secondary:
|
|
36
|
+
- "KB-first (Obsidian canonical source)"
|
|
37
|
+
- "Universal Component Language (shadcn interlingua)"
|
|
38
|
+
|
|
30
39
|
authority:
|
|
31
40
|
delegates_to: []
|
|
32
41
|
escalates_to: brand-director-valentina
|
|
@@ -46,6 +55,8 @@ expertise:
|
|
|
46
55
|
- Color Theory
|
|
47
56
|
- Typography Hierarchy
|
|
48
57
|
- Brand Identity Process (Wheeler)
|
|
58
|
+
- ArkaOS Design Tokens
|
|
59
|
+
- WCAG AA contrast
|
|
49
60
|
depth: expert
|
|
50
61
|
years_equivalent: 8
|
|
51
62
|
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# UI/UX Knowledge & Tools — Squad Reference
|
|
2
|
+
|
|
3
|
+
> Shared reference for the frontend UI/UX squad: **Diana** (frontend-dev),
|
|
4
|
+
> **Sofia D.** (ux-designer), **Isabel** (visual-designer), **Rafael**
|
|
5
|
+
> (motion-designer) and **Valentina** (creative-director).
|
|
6
|
+
>
|
|
7
|
+
> Read this BEFORE any UI/UX work. It defines the non-negotiable KB-first
|
|
8
|
+
> rule, the canonical knowledge sources, the concrete design tokens, the
|
|
9
|
+
> motion system, the new tooling, and the squad validation order.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. KB-First (NON-NEGOTIABLE)
|
|
14
|
+
|
|
15
|
+
**The Obsidian knowledge base is the canonical, primary source for every
|
|
16
|
+
agent and every team.** New tools (Magic, Motion, ui-ux-pro-max, context7,
|
|
17
|
+
nuxt-ui) are **supplements** — they never replace the vault.
|
|
18
|
+
|
|
19
|
+
Order of operations on ANY UI/UX task:
|
|
20
|
+
|
|
21
|
+
1. **Search the Obsidian KB first** (`mcp__obsidian__search_notes` /
|
|
22
|
+
`read_note`). Start from the canonical sources in §2.
|
|
23
|
+
2. **Cite what you found** with `[[wikilinks]]`, or explicitly declare a
|
|
24
|
+
KB gap if nothing relevant exists.
|
|
25
|
+
3. **Only then** supplement with the tools in §5 for theory the vault
|
|
26
|
+
lacks (see §7).
|
|
27
|
+
4. When external research produces something material, **write it back to
|
|
28
|
+
the KB** so the vault gets richer over time.
|
|
29
|
+
|
|
30
|
+
This mirrors the Synapse L2.5 pre-injection and the `kb-first` constitution
|
|
31
|
+
rule. Operator directive (2026-05-30): *"a prioridade é sempre a base de
|
|
32
|
+
conhecimento que temos no Obsidian — para qualquer agent ou equipa."*
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 2. Canonical KB Sources
|
|
37
|
+
|
|
38
|
+
| Source (Obsidian) | What it gives you |
|
|
39
|
+
|---|---|
|
|
40
|
+
| `[[ArkaOS-Brand-Guidelines-v2]]` | **Primary.** Color tokens, typography, logo, iconography, layout (§04); the full **Motion System** (§06); **WCAG / accessibility** (Appendix B). Concrete, ready-to-code values. |
|
|
41
|
+
| `[[Area 02 - Design]]` | Framework index: Nielsen, Laws of UX (Yablonski), Krug, Garrett's 5 Planes, Cooper, Norman, Double Diamond, Design Sprint. Names the bodies of theory (see §7 for depth gaps). |
|
|
42
|
+
| `[[ArkaOS-Persona-Squad-Matrix]]` | Persona × framework × squad mapping (NN/g for Francisca; Two-Part Conversion Formula; archetypes for Valentina). |
|
|
43
|
+
| `[[Universal Component Language]]` | Alani Nicolas: 39 design systems → shadcn interlingua; token-extraction pipeline (OKLCH normalization → WCAG audit → Atomic Design). |
|
|
44
|
+
| `[[Design-Tokens-v1]]` (Hringr) | DTCG token architecture: primitive → semantic → component. Reference model for token discipline. |
|
|
45
|
+
| `[[19-Video-Motion-Designer]]` ("Kubrick") | Cinematic motion/video persona — base voice for Rafael's video work. |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 3. Design Tokens — Quick Reference
|
|
50
|
+
|
|
51
|
+
From `[[ArkaOS-Brand-Guidelines-v2]]` §04 (verify against the note before use):
|
|
52
|
+
|
|
53
|
+
- **Composition ratio 60 / 25 / 15** — canvas / content / signal (accent
|
|
54
|
+
green 10–15% max).
|
|
55
|
+
- **Spacing** base 4px scale: `space-1`=4px … `space-24`=96px.
|
|
56
|
+
- **Type**: never body < 16px; line-height 1.5–1.6× body, 1.1–1.2× display;
|
|
57
|
+
max line length ~75 chars; max 2 families + mono for code.
|
|
58
|
+
- **Surface hierarchy**: 5 layers (0→4), 1px edge border mandatory.
|
|
59
|
+
- **Radius** scale 4px → full; **grid** 12-column, max content 1280px.
|
|
60
|
+
- **Icons**: stroke 1.5px, 24×24 grid, optical alignment.
|
|
61
|
+
|
|
62
|
+
> Always read the live note for the exact HEX/token names — do not
|
|
63
|
+
> hardcode values from memory.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 4. Motion System
|
|
68
|
+
|
|
69
|
+
From `[[ArkaOS-Brand-Guidelines-v2]]` §06. **5 principles** (inject verbatim):
|
|
70
|
+
|
|
71
|
+
1. **Purposeful** — every animation answers "what does it communicate?"; if nothing, remove it.
|
|
72
|
+
2. **Subtle** — felt subconsciously; if the user watches the animation instead of the content, it's too much.
|
|
73
|
+
3. **Precise** — intentional easing, exact timing.
|
|
74
|
+
4. **Fast** — CLI-first product; default to the fastest option.
|
|
75
|
+
5. **Consistent** — same action → same animation everywhere.
|
|
76
|
+
|
|
77
|
+
**Timing tokens**: `motion-instant` 100ms · `motion-fast` 150ms (default) ·
|
|
78
|
+
`motion-normal` 300ms · `motion-slow` 500ms · `motion-deliberate` 800ms.
|
|
79
|
+
**Easing**: `--ease-out` cubic-bezier(0.25,0,0,1); `--ease-spring`
|
|
80
|
+
cubic-bezier(0.16,1,0.3,1).
|
|
81
|
+
|
|
82
|
+
**Forbidden**: rotation/spin, bounce/elastic on the logo, 3D/perspective,
|
|
83
|
+
particles, morphing, color-cycling.
|
|
84
|
+
|
|
85
|
+
**Accessibility**: always honour `prefers-reduced-motion`.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 5. Tools (supplement only — after KB)
|
|
90
|
+
|
|
91
|
+
| Tool | Type | Use for | Notes |
|
|
92
|
+
|---|---|---|---|
|
|
93
|
+
| **Magic** (`@21st-dev/magic`) | MCP (user scope) | Generate production UI components from natural language, framework-aware (Nuxt UI, Tailwind, shadcn) | Preferred path for frontend UI/UX — mandatory when configured. Wired into nuxt/vue/react/nextjs/full-stack MCP profiles. Needs `MAGIC_API_KEY` (falls back gracefully when absent). |
|
|
94
|
+
| **Motion** (`motion-ai` kit) | MCP + skills | Animation/motion implementation (Motion library) | Auto-installed on install/update. Pair with the §4 motion system. |
|
|
95
|
+
| **ui-ux-pro-max** | Claude plugin | UI/UX methodology + patterns, conjugated with whatever framework is in use | Marketplace `nextlevelbuilder/ui-ux-pro-max-skill`. Use to fill the §7 theory gaps. |
|
|
96
|
+
| **nuxt-ui** / **context7** | MCP | Up-to-date framework + component docs | Use for current API/usage instead of memory. |
|
|
97
|
+
| **playwright** | MCP | Verify the UI in a real browser before claiming done | Constitution: test before claim. |
|
|
98
|
+
|
|
99
|
+
Framework-agnostic rule: detect the project's framework first (Nuxt UI,
|
|
100
|
+
Tailwind, shadcn, …) and conjugate Magic + ui-ux-pro-max to THAT framework.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 6. Squad Validation Order (NON-NEGOTIABLE)
|
|
105
|
+
|
|
106
|
+
**Diana (frontend-dev) implements UI ONLY after the UI/UX design agents
|
|
107
|
+
have analysed and their output is validated.** No interface freelancing.
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
1. Sofia D. (ux-designer) → UX analysis: flows, IA, heuristics, accessibility
|
|
111
|
+
2. Isabel (visual-designer) → visual direction: tokens, hierarchy, components
|
|
112
|
+
3. Rafael (motion-designer) → motion/interaction direction (where relevant)
|
|
113
|
+
4. Valentina (creative-director) → validates direction against brand strategy
|
|
114
|
+
───────────────────────────────────────────────────────────────────────
|
|
115
|
+
5. Diana (frontend-dev) → implements the VALIDATED design with Magic +
|
|
116
|
+
the project framework, then QA + Quality Gate
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Operator directive (2026-05-30): *"o frontend developer só faz alguma coisa
|
|
120
|
+
com validação e sempre depois da análise dos outros agentes de UI/UX."*
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 7. Theory Gaps (KB-thin → supplement, then write back)
|
|
125
|
+
|
|
126
|
+
The KB is rich in **applied** knowledge (tokens, motion, WCAG application)
|
|
127
|
+
but thin on **theory**. For these, consult ui-ux-pro-max + context7, then
|
|
128
|
+
write material findings back to `[[Area 02 - Design]]`:
|
|
129
|
+
|
|
130
|
+
- Nielsen's 10 heuristics in detail
|
|
131
|
+
- Laws of UX (each law)
|
|
132
|
+
- Dieter Rams' 10 principles
|
|
133
|
+
- Atomic Design (full atoms→pages)
|
|
134
|
+
- Microinteractions (trigger→rules→feedback→loops/modes)
|
|
135
|
+
- Color theory & typography science (OKLCH, harmony, modular scale)
|
|
136
|
+
- Gestalt & visual hierarchy (F/Z scanning, proximity, contrast)
|
|
@@ -54,15 +54,43 @@ You are Diana, the Senior Frontend Developer at WizardingCode. 8 years building
|
|
|
54
54
|
- **With higher-tier (Marco, Paulo, Gabriel):** Advocates for UX within architectural constraints. Adapts creatively.
|
|
55
55
|
- **With same/lower-tier:** Collaborative. Proposes creative solutions that satisfy both aesthetics and functionality.
|
|
56
56
|
|
|
57
|
+
## Core Reference — UI/UX Knowledge, Tools & Validation Gate
|
|
58
|
+
|
|
59
|
+
**ALWAYS read** `departments/brand/references/uiux-knowledge-and-tools.md`
|
|
60
|
+
before any UI work. It defines the KB-first rule, the canonical Obsidian
|
|
61
|
+
sources, the design tokens, the motion system, and the tooling.
|
|
62
|
+
|
|
63
|
+
**KB-first (NON-NEGOTIABLE):** the Obsidian KB is the canonical primary
|
|
64
|
+
source. Search it first (`[[ArkaOS-Brand-Guidelines-v2]]` for tokens/motion/
|
|
65
|
+
WCAG), cite, then supplement with Magic / Motion / ui-ux-pro-max / context7.
|
|
66
|
+
|
|
67
|
+
**Validation Gate (NON-NEGOTIABLE):** you implement UI **only after** the
|
|
68
|
+
UI/UX design agents have analysed AND their direction is validated. No
|
|
69
|
+
interface freelancing. The order is:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
Sofia D. (UX analysis) → Isabel (visual) → Rafael (motion)
|
|
73
|
+
→ Valentina (validates vs brand strategy) → THEN Diana implements
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If you are handed a UI task without that validated design input, stop and
|
|
77
|
+
request it from the UI/UX squad before writing code.
|
|
78
|
+
|
|
79
|
+
**Magic MCP:** for new components, generate framework-aware scaffolds with
|
|
80
|
+
the Magic MCP (21st.dev), conjugated to the project's framework (Nuxt UI /
|
|
81
|
+
Tailwind / shadcn), then refine to the validated design and the KB tokens.
|
|
82
|
+
|
|
57
83
|
## How You Work
|
|
58
84
|
|
|
59
85
|
1. ALWAYS verify you are on a feature branch before writing code. If on main/master/dev, create a feature branch first.
|
|
60
|
-
2.
|
|
61
|
-
3. Read
|
|
62
|
-
4.
|
|
63
|
-
5.
|
|
64
|
-
6.
|
|
65
|
-
7.
|
|
86
|
+
2. **Confirm the validated UI/UX design exists** (Sofia D. + Isabel + Rafael, approved by Valentina). No validated design → request it, do not freelance.
|
|
87
|
+
3. Read project context (CLAUDE.md / PROJECT.md)
|
|
88
|
+
4. Read the architecture design (component hierarchy, state management plan)
|
|
89
|
+
5. Search the Obsidian KB for the relevant tokens/patterns; cite them
|
|
90
|
+
6. Find 2-3 similar existing components and match their patterns exactly
|
|
91
|
+
7. Implement with Magic MCP + the project framework: Composable/Hook → Component → Page → Route
|
|
92
|
+
8. Handle ALL states: loading, error, empty, success
|
|
93
|
+
9. Test components with Vitest + Vue Test Utils or React Testing Library; verify in-browser with Playwright
|
|
66
94
|
|
|
67
95
|
## Vue 3 / Nuxt 3 Patterns
|
|
68
96
|
|
|
@@ -202,11 +230,13 @@ Every component must have:
|
|
|
202
230
|
|
|
203
231
|
## Before Writing ANY Code
|
|
204
232
|
|
|
205
|
-
1.
|
|
206
|
-
2. Read
|
|
207
|
-
3.
|
|
208
|
-
4.
|
|
209
|
-
5.
|
|
233
|
+
1. Confirm the validated UI/UX design (Sofia D. + Isabel + Rafael, approved by Valentina). No validated design → request it, do not freelance.
|
|
234
|
+
2. Read Gabriel's component hierarchy and state management plan
|
|
235
|
+
3. Read the project's CLAUDE.md/PROJECT.md
|
|
236
|
+
4. Search the Obsidian KB first for tokens/patterns; cite them
|
|
237
|
+
5. Find 2-3 similar existing components and match their patterns
|
|
238
|
+
6. Use the Magic MCP for scaffolds and Context7/nuxt-ui MCP if unsure about framework API
|
|
239
|
+
7. Never guess — always verify
|
|
210
240
|
|
|
211
241
|
## Memory
|
|
212
242
|
|
|
@@ -36,6 +36,8 @@ mental_models:
|
|
|
36
36
|
- "Laws of UX (Yablonski)"
|
|
37
37
|
- "WCAG Accessibility"
|
|
38
38
|
- "Component-Driven Development"
|
|
39
|
+
- "Design-system-as-context (Universal Component Language)"
|
|
40
|
+
- "KB-first (Obsidian canonical source)"
|
|
39
41
|
|
|
40
42
|
authority:
|
|
41
43
|
push_code: true
|
|
@@ -52,12 +54,16 @@ expertise:
|
|
|
52
54
|
- Design system implementation
|
|
53
55
|
- Accessibility (WCAG 2.1 AA)
|
|
54
56
|
- Core Web Vitals
|
|
57
|
+
- Magic MCP (21st.dev) component generation
|
|
58
|
+
- Motion (animation implementation)
|
|
55
59
|
frameworks:
|
|
56
60
|
- Atomic Design
|
|
57
61
|
- Component-Driven Development
|
|
58
62
|
- Laws of UX
|
|
59
63
|
- Nielsen Heuristics
|
|
60
64
|
- CWV Optimization
|
|
65
|
+
- ArkaOS Motion System
|
|
66
|
+
- Design Tokens (DTCG)
|
|
61
67
|
depth: expert
|
|
62
68
|
years_equivalent: 9
|
|
63
69
|
|
|
@@ -16,10 +16,18 @@ import { execSync, spawnSync } from "node:child_process";
|
|
|
16
16
|
import { homedir } from "node:os";
|
|
17
17
|
import { join } from "node:path";
|
|
18
18
|
|
|
19
|
+
// Third-party marketplaces that must be registered (via
|
|
20
|
+
// `claude plugin marketplace add <repo>`) before their plugins can be
|
|
21
|
+
// installed. Each entry is a GitHub `owner/repo` shorthand.
|
|
22
|
+
export const DEFAULT_CLAUDE_MARKETPLACES = [
|
|
23
|
+
"nextlevelbuilder/ui-ux-pro-max-skill",
|
|
24
|
+
];
|
|
25
|
+
|
|
19
26
|
// Each entry is "name@marketplace" matching the `claude plugin install`
|
|
20
27
|
// CLI argument format.
|
|
21
28
|
export const DEFAULT_CLAUDE_PLUGINS = [
|
|
22
29
|
"frontend-design@claude-plugins-official",
|
|
30
|
+
"ui-ux-pro-max@ui-ux-pro-max-skill",
|
|
23
31
|
];
|
|
24
32
|
|
|
25
33
|
const _INSTALLED_REGISTRY = join(
|
|
@@ -29,19 +37,40 @@ const _INSTALLED_REGISTRY = join(
|
|
|
29
37
|
export function installDefaultClaudePlugins({
|
|
30
38
|
runtime = "claude-code",
|
|
31
39
|
plugins = DEFAULT_CLAUDE_PLUGINS,
|
|
40
|
+
marketplaces = DEFAULT_CLAUDE_MARKETPLACES,
|
|
32
41
|
home = homedir(),
|
|
33
42
|
} = {}) {
|
|
34
43
|
if (runtime !== "claude-code") {
|
|
35
|
-
return { skipped: "runtime-not-claude-code", results: [] };
|
|
44
|
+
return { skipped: "runtime-not-claude-code", results: [], marketplaces: [] };
|
|
36
45
|
}
|
|
37
46
|
if (!isClaudeCliAvailable()) {
|
|
38
|
-
return { skipped: "claude-cli-not-found", results: [] };
|
|
47
|
+
return { skipped: "claude-cli-not-found", results: [], marketplaces: [] };
|
|
39
48
|
}
|
|
49
|
+
// Marketplaces must be registered before their plugins can resolve.
|
|
50
|
+
const marketplaceResults = marketplaces.map((m) => addMarketplace(m));
|
|
40
51
|
const alreadyInstalled = readInstalledRegistry(home);
|
|
41
52
|
const results = plugins.map((p) =>
|
|
42
53
|
installOne(p, alreadyInstalled),
|
|
43
54
|
);
|
|
44
|
-
return { skipped: null, results };
|
|
55
|
+
return { skipped: null, results, marketplaces: marketplaceResults };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Register a third-party plugin marketplace. Idempotent and never-throws:
|
|
59
|
+
// a marketplace that is already known is reported as already-present.
|
|
60
|
+
function addMarketplace(marketplace) {
|
|
61
|
+
const out = spawnSync("claude", ["plugin", "marketplace", "add", marketplace], {
|
|
62
|
+
timeout: 60_000,
|
|
63
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
64
|
+
encoding: "utf-8",
|
|
65
|
+
});
|
|
66
|
+
if (out.status === 0) {
|
|
67
|
+
return { marketplace, action: "added" };
|
|
68
|
+
}
|
|
69
|
+
const msg = (out.stderr || out.error?.message || "").toLowerCase();
|
|
70
|
+
if (msg.includes("already") || msg.includes("exists")) {
|
|
71
|
+
return { marketplace, action: "already-present" };
|
|
72
|
+
}
|
|
73
|
+
return { marketplace, action: "failed", reason: msg.trim().slice(0, 200) };
|
|
45
74
|
}
|
|
46
75
|
|
|
47
76
|
function isClaudeCliAvailable() {
|
package/installer/doctor.js
CHANGED
|
@@ -195,6 +195,21 @@ const checks = [
|
|
|
195
195
|
},
|
|
196
196
|
fix: () => "Upgrade Claude Code: npm install -g @anthropic-ai/claude-code@latest",
|
|
197
197
|
},
|
|
198
|
+
{
|
|
199
|
+
name: "magic-api-key",
|
|
200
|
+
description: "Magic API key configured (frontend UI/UX — Magic MCP)",
|
|
201
|
+
severity: "warn",
|
|
202
|
+
check: () => {
|
|
203
|
+
if (process.env.MAGIC_API_KEY) return true;
|
|
204
|
+
const keysPath = join(INSTALL_DIR, "keys.json");
|
|
205
|
+
if (!existsSync(keysPath)) return false;
|
|
206
|
+
try {
|
|
207
|
+
const keys = JSON.parse(readFileSync(keysPath, "utf-8"));
|
|
208
|
+
return !!keys.MAGIC_API_KEY;
|
|
209
|
+
} catch { return false; }
|
|
210
|
+
},
|
|
211
|
+
fix: () => "Run: npx arkaos keys set MAGIC_API_KEY <your-21st-dev-key> (or re-run npx arkaos@latest update)",
|
|
212
|
+
},
|
|
198
213
|
];
|
|
199
214
|
|
|
200
215
|
// ─── Windows-only checks ───────────────────────────────────────────────
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Frontend UI/UX tooling setup for `npx arkaos install` and
|
|
2
|
+
// `npx arkaos@latest update`.
|
|
3
|
+
//
|
|
4
|
+
// Wires three operator-mandated tools into the install/update flow:
|
|
5
|
+
// 1. Magic MCP (@21st-dev/magic) — user-scope, API-key gated. The key is
|
|
6
|
+
// prompted interactively when missing and never stored in the repo;
|
|
7
|
+
// it lives only in ~/.arkaos/keys.json (chmod 600) + Claude user config.
|
|
8
|
+
// 2. Motion AI Kit (npx motion-ai) — auto-run on every install/update.
|
|
9
|
+
// 3. (ui-ux-pro-max plugin + marketplace is handled in claude-plugins.js.)
|
|
10
|
+
//
|
|
11
|
+
// Invariants (.claude/rules/node-installer.md):
|
|
12
|
+
// - ESM, os.homedir()/path.join only, never hardcoded paths.
|
|
13
|
+
// - No interactive prompts during headless/CI runs (guarded by isTTY).
|
|
14
|
+
// - Never throws — every failure is logged and swallowed so the installer
|
|
15
|
+
// never breaks on optional tooling.
|
|
16
|
+
|
|
17
|
+
import { existsSync, readFileSync, writeFileSync, chmodSync } from "node:fs";
|
|
18
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
19
|
+
import { createInterface } from "node:readline";
|
|
20
|
+
import { homedir } from "node:os";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
|
|
23
|
+
const MAGIC_ENV = "MAGIC_API_KEY";
|
|
24
|
+
|
|
25
|
+
function keysPath(home) {
|
|
26
|
+
return join(home, ".arkaos", "keys.json");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function loadKeys(home) {
|
|
30
|
+
const path = keysPath(home);
|
|
31
|
+
if (!existsSync(path)) return {};
|
|
32
|
+
try { return JSON.parse(readFileSync(path, "utf-8")); } catch { return {}; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function saveKey(home, name, value) {
|
|
36
|
+
const path = keysPath(home);
|
|
37
|
+
const keys = loadKeys(home);
|
|
38
|
+
keys[name] = value;
|
|
39
|
+
writeFileSync(path, JSON.stringify(keys, null, 2));
|
|
40
|
+
try { chmodSync(path, 0o600); } catch {}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Resolve the Magic API key from (in order) keys.json, then the environment.
|
|
44
|
+
function resolveMagicKey(home) {
|
|
45
|
+
const keys = loadKeys(home);
|
|
46
|
+
return keys[MAGIC_ENV] || process.env[MAGIC_ENV] || "";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Prompt once for the key. Resolves to "" in headless contexts so the
|
|
50
|
+
// installer never blocks on a closed stdin (node-installer rule).
|
|
51
|
+
function promptMagicKey() {
|
|
52
|
+
if (!process.stdin.isTTY) return Promise.resolve("");
|
|
53
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
54
|
+
const q = " 21st.dev Magic API key (frontend UI/UX, leave empty to skip): ";
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
rl.question(q, (answer) => { rl.close(); resolve((answer || "").trim()); });
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Ensure MAGIC_API_KEY exists, prompting interactively when missing.
|
|
61
|
+
// Returns the resolved key (possibly "").
|
|
62
|
+
export async function ensureMagicApiKey({ home = homedir() } = {}) {
|
|
63
|
+
const existing = resolveMagicKey(home);
|
|
64
|
+
if (existing) return existing;
|
|
65
|
+
const entered = await promptMagicKey();
|
|
66
|
+
if (entered) {
|
|
67
|
+
saveKey(home, MAGIC_ENV, entered);
|
|
68
|
+
console.log(" Magic API key saved to ~/.arkaos/keys.json (chmod 600).");
|
|
69
|
+
}
|
|
70
|
+
return entered;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function isClaudeCliAvailable() {
|
|
74
|
+
try {
|
|
75
|
+
execSync("claude --version", { stdio: "pipe", timeout: 5000 });
|
|
76
|
+
return true;
|
|
77
|
+
} catch { return false; }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isMagicMcpRegistered() {
|
|
81
|
+
const out = spawnSync("claude", ["mcp", "list"], {
|
|
82
|
+
timeout: 10_000, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8",
|
|
83
|
+
});
|
|
84
|
+
return out.status === 0 && /(^|\s)magic(\s|:)/.test(out.stdout || "");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Register the Magic MCP at Claude Code user scope. Idempotent and
|
|
88
|
+
// never-throws. Skips on non-Claude runtimes, missing CLI, or missing key.
|
|
89
|
+
export function registerMagicMcp({ runtime = "claude-code", apiKey = "" } = {}) {
|
|
90
|
+
if (runtime !== "claude-code") return { action: "skipped", reason: "runtime-not-claude-code" };
|
|
91
|
+
if (!isClaudeCliAvailable()) return { action: "skipped", reason: "claude-cli-not-found" };
|
|
92
|
+
if (!apiKey) return { action: "skipped", reason: "no-api-key" };
|
|
93
|
+
if (isMagicMcpRegistered()) return { action: "already-present" };
|
|
94
|
+
// NOTE (known limitation): the key is passed as a CLI argument because
|
|
95
|
+
// `claude mcp add` offers no stdin/file alternative. It is briefly
|
|
96
|
+
// visible to `ps`/proc while the child runs. It is NEVER written to the
|
|
97
|
+
// repo or to any log (only stderr is captured into `reason`).
|
|
98
|
+
const out = spawnSync("claude", [
|
|
99
|
+
"mcp", "add", "magic", "--scope", "user",
|
|
100
|
+
"--env", `API_KEY=${apiKey}`,
|
|
101
|
+
"--", "npx", "-y", "@21st-dev/magic@latest",
|
|
102
|
+
], { timeout: 60_000, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" });
|
|
103
|
+
if (out.error || out.status !== 0) {
|
|
104
|
+
const reason = (out.stderr || out.error?.message || "unknown").trim().slice(0, 200);
|
|
105
|
+
return { action: "failed", reason };
|
|
106
|
+
}
|
|
107
|
+
return { action: "registered" };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function motionMarkerPath(home) {
|
|
111
|
+
return join(home, ".arkaos", ".motion-kit-installed");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Run the Motion AI Kit. Auto-runs (no prompt) per operator decision
|
|
115
|
+
// (2026-05-30), but idempotently: a one-time marker in ~/.arkaos/ means
|
|
116
|
+
// re-runs (e.g. every `npx arkaos update`) skip the 180s kit instead of
|
|
117
|
+
// re-downloading it. Claude-runtime only, requires the claude CLI (the
|
|
118
|
+
// kit installs Motion skills into the Claude agent), never-throws.
|
|
119
|
+
export function installMotionKit({ runtime = "claude-code", home = homedir() } = {}) {
|
|
120
|
+
if (runtime !== "claude-code") return { action: "skipped", reason: "runtime-not-claude-code" };
|
|
121
|
+
if (!isClaudeCliAvailable()) return { action: "skipped", reason: "claude-cli-not-found" };
|
|
122
|
+
if (existsSync(motionMarkerPath(home))) return { action: "already-present" };
|
|
123
|
+
const out = spawnSync("npx", ["-y", "motion-ai"], {
|
|
124
|
+
timeout: 180_000, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8",
|
|
125
|
+
});
|
|
126
|
+
if (out.error || out.status !== 0) {
|
|
127
|
+
const reason = (out.stderr || out.error?.message || "unknown").trim().slice(0, 200);
|
|
128
|
+
return { action: "failed", reason };
|
|
129
|
+
}
|
|
130
|
+
try { writeFileSync(motionMarkerPath(home), new Date().toISOString()); } catch {}
|
|
131
|
+
return { action: "installed" };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Orchestrate the full frontend tooling setup. Single entry point wired
|
|
135
|
+
// into both installer/index.js and installer/update.js.
|
|
136
|
+
export async function setupFrontendTooling({ runtime = "claude-code", home = homedir() } = {}) {
|
|
137
|
+
const results = {};
|
|
138
|
+
try {
|
|
139
|
+
const apiKey = await ensureMagicApiKey({ home });
|
|
140
|
+
results.magicMcp = registerMagicMcp({ runtime, apiKey });
|
|
141
|
+
} catch (err) {
|
|
142
|
+
results.magicMcp = { action: "failed", reason: err.message };
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
results.motionKit = installMotionKit({ runtime, home });
|
|
146
|
+
} catch (err) {
|
|
147
|
+
results.motionKit = { action: "failed", reason: err.message };
|
|
148
|
+
}
|
|
149
|
+
return results;
|
|
150
|
+
}
|
package/installer/index.js
CHANGED
|
@@ -352,6 +352,13 @@ export async function install({ runtime, path, force, skipSystem, withOllama })
|
|
|
352
352
|
const { installDefaultClaudePlugins } = await import("./claude-plugins.js");
|
|
353
353
|
const pluginResult = installDefaultClaudePlugins({ runtime });
|
|
354
354
|
if (!pluginResult.skipped) {
|
|
355
|
+
for (const m of pluginResult.marketplaces || []) {
|
|
356
|
+
if (m.action === "added") {
|
|
357
|
+
console.log(` marketplace ${m.marketplace} added.`);
|
|
358
|
+
} else if (m.action === "failed") {
|
|
359
|
+
console.log(` marketplace ${m.marketplace} failed (${m.reason}).`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
355
362
|
for (const r of pluginResult.results) {
|
|
356
363
|
if (r.action === "installed") {
|
|
357
364
|
console.log(` ${r.plugin} installed.`);
|
|
@@ -366,6 +373,27 @@ export async function install({ runtime, path, force, skipSystem, withOllama })
|
|
|
366
373
|
console.log(` Warning: could not install default Claude plugins (${err.message})`);
|
|
367
374
|
}
|
|
368
375
|
|
|
376
|
+
// Frontend UI/UX tooling — Magic MCP (user scope, API-key gated) + Motion
|
|
377
|
+
// AI Kit. Key is prompted when missing (interactive only). Never blocks.
|
|
378
|
+
try {
|
|
379
|
+
const { setupFrontendTooling } = await import("./frontend-tooling.js");
|
|
380
|
+
const ft = await setupFrontendTooling({ runtime });
|
|
381
|
+
if (ft.magicMcp?.action === "registered") {
|
|
382
|
+
console.log(" Magic MCP registered (user scope).");
|
|
383
|
+
} else if (ft.magicMcp?.action === "already-present") {
|
|
384
|
+
console.log(" Magic MCP already registered (skipped).");
|
|
385
|
+
} else if (ft.magicMcp?.action === "failed") {
|
|
386
|
+
console.log(` Magic MCP registration failed (${ft.magicMcp.reason}).`);
|
|
387
|
+
}
|
|
388
|
+
if (ft.motionKit?.action === "installed") {
|
|
389
|
+
console.log(" Motion AI Kit installed.");
|
|
390
|
+
} else if (ft.motionKit?.action === "failed") {
|
|
391
|
+
console.log(` Motion AI Kit install failed (${ft.motionKit.reason}).`);
|
|
392
|
+
}
|
|
393
|
+
} catch (err) {
|
|
394
|
+
console.log(` Warning: could not set up frontend tooling (${err.message})`);
|
|
395
|
+
}
|
|
396
|
+
|
|
369
397
|
const manifest = {
|
|
370
398
|
version: VERSION,
|
|
371
399
|
runtime,
|
package/installer/keys.js
CHANGED
|
@@ -8,6 +8,7 @@ const PROVIDERS = {
|
|
|
8
8
|
OPENAI_API_KEY: { name: "OpenAI", used_for: "Whisper transcription, embeddings, GPT" },
|
|
9
9
|
GOOGLE_API_KEY: { name: "Google", used_for: "Gemini API, Nano Banana, Google Cloud AI" },
|
|
10
10
|
FAL_API_KEY: { name: "fal.ai", used_for: "Image generation, video generation" },
|
|
11
|
+
MAGIC_API_KEY: { name: "21st.dev Magic", used_for: "Frontend UI/UX component generation (Magic MCP)" },
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
function loadKeys() {
|
package/installer/update.js
CHANGED
|
@@ -439,6 +439,41 @@ export async function update() {
|
|
|
439
439
|
console.log(" ✓ Repo path updated (skills alias not present)");
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
+
// ── 7b. Frontend UI/UX tooling + Claude plugins ──
|
|
443
|
+
// Mirrors installer/index.js: marketplaces + plugins (ui-ux-pro-max,
|
|
444
|
+
// frontend-design) and Magic MCP + Motion AI Kit. The operator wants
|
|
445
|
+
// these provisioned on update too, not just fresh install. All steps
|
|
446
|
+
// are idempotent and never throw; interactive key prompt is skipped
|
|
447
|
+
// in headless runs.
|
|
448
|
+
const toolingRuntime = manifest.runtime || "claude-code";
|
|
449
|
+
try {
|
|
450
|
+
const { installDefaultClaudePlugins } = await import("./claude-plugins.js");
|
|
451
|
+
const pluginResult = installDefaultClaudePlugins({ runtime: toolingRuntime });
|
|
452
|
+
if (!pluginResult.skipped) {
|
|
453
|
+
for (const m of pluginResult.marketplaces || []) {
|
|
454
|
+
if (m.action === "added") console.log(` ✓ marketplace ${m.marketplace} added`);
|
|
455
|
+
else if (m.action === "failed") console.log(` ⚠ marketplace ${m.marketplace} failed (${m.reason})`);
|
|
456
|
+
}
|
|
457
|
+
for (const r of pluginResult.results) {
|
|
458
|
+
if (r.action === "installed") console.log(` ✓ ${r.plugin} installed`);
|
|
459
|
+
else if (r.action === "failed") console.log(` ⚠ ${r.plugin} failed (${r.reason})`);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
} catch (err) {
|
|
463
|
+
console.log(` ⚠ Could not update Claude plugins (${err.message})`);
|
|
464
|
+
}
|
|
465
|
+
try {
|
|
466
|
+
const { setupFrontendTooling } = await import("./frontend-tooling.js");
|
|
467
|
+
const ft = await setupFrontendTooling({ runtime: toolingRuntime });
|
|
468
|
+
if (ft.magicMcp?.action === "registered") console.log(" ✓ Magic MCP registered (user scope)");
|
|
469
|
+
else if (ft.magicMcp?.action === "already-present") console.log(" ✓ Magic MCP already registered");
|
|
470
|
+
else if (ft.magicMcp?.action === "failed") console.log(` ⚠ Magic MCP failed (${ft.magicMcp.reason})`);
|
|
471
|
+
if (ft.motionKit?.action === "installed") console.log(" ✓ Motion AI Kit installed");
|
|
472
|
+
else if (ft.motionKit?.action === "failed") console.log(` ⚠ Motion AI Kit failed (${ft.motionKit.reason})`);
|
|
473
|
+
} catch (err) {
|
|
474
|
+
console.log(` ⚠ Could not set up frontend tooling (${err.message})`);
|
|
475
|
+
}
|
|
476
|
+
|
|
442
477
|
// ── 8. Update manifest ──
|
|
443
478
|
console.log(" [8/8] Finalizing...");
|
|
444
479
|
manifest.version = VERSION;
|
package/package.json
CHANGED