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 CHANGED
@@ -1 +1 @@
1
- 3.77.0
1
+ 3.78.0
@@ -36,6 +36,8 @@ mental_models:
36
36
  - "StoryBrand SB7 (Miller)"
37
37
  - "Positioning (Ries/Trout)"
38
38
  - "Design Thinking (IDEO)"
39
+ - "KB-first (Obsidian canonical source)"
40
+ - "UI/UX validation gate (squad direction before implementation)"
39
41
 
40
42
  authority:
41
43
  orchestrate: true
@@ -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
- **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, not from trends.
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. Read project context (CLAUDE.md / PROJECT.md)
61
- 3. Read Gabriel's architecture design (component hierarchy, state management plan)
62
- 4. Find 2-3 similar existing components and match their patterns exactly
63
- 5. Implement: Composable/Hook Component Page Route
64
- 6. Handle ALL states: loading, error, empty, success
65
- 7. Test components with Vitest + Vue Test Utils or React Testing Library
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. Read Gabriel's component hierarchy and state management plan
206
- 2. Read the project's CLAUDE.md/PROJECT.md
207
- 3. Find 2-3 similar existing components and match their patterns
208
- 4. Use Context7 MCP if unsure about framework API
209
- 5. Never guess always verify
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() {
@@ -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
+ }
@@ -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() {
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkaos",
3
- "version": "3.77.0",
3
+ "version": "3.78.0",
4
4
  "description": "The Operating System for AI Agent Teams",
5
5
  "type": "module",
6
6
  "bin": {
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "arkaos-core"
3
- version = "3.77.0"
3
+ version = "3.78.0"
4
4
  description = "Core engine for ArkaOS — The Operating System for AI Agent Teams"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}