thachvd-kit 1.0.0 → 1.0.1

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.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -19
  3. package/agents/frontend-specialist.md +2 -2
  4. package/agents/mobile-developer.md +4 -4
  5. package/bin/cli.js +340 -118
  6. package/package.json +43 -19
  7. package/rules/GEMINI.md +5 -3
  8. package/scripts/init.py +317 -122
  9. package/skills/desktop-design/SKILL.md +25 -0
  10. package/skills/react-frontend/SKILL.md +25 -0
  11. package/.shared/ui-ux-pro-max/data/charts.csv +0 -26
  12. package/.shared/ui-ux-pro-max/data/colors.csv +0 -97
  13. package/.shared/ui-ux-pro-max/data/icons.csv +0 -101
  14. package/.shared/ui-ux-pro-max/data/landing.csv +0 -31
  15. package/.shared/ui-ux-pro-max/data/products.csv +0 -97
  16. package/.shared/ui-ux-pro-max/data/prompts.csv +0 -24
  17. package/.shared/ui-ux-pro-max/data/react-performance.csv +0 -45
  18. package/.shared/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
  19. package/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
  20. package/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
  21. package/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
  22. package/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
  23. package/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
  24. package/.shared/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
  25. package/.shared/ui-ux-pro-max/data/stacks/react.csv +0 -54
  26. package/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
  27. package/.shared/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
  28. package/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
  29. package/.shared/ui-ux-pro-max/data/stacks/vue.csv +0 -50
  30. package/.shared/ui-ux-pro-max/data/styles.csv +0 -59
  31. package/.shared/ui-ux-pro-max/data/typography.csv +0 -58
  32. package/.shared/ui-ux-pro-max/data/ui-reasoning.csv +0 -101
  33. package/.shared/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
  34. package/.shared/ui-ux-pro-max/data/web-interface.csv +0 -31
  35. package/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  36. package/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  37. package/.shared/ui-ux-pro-max/scripts/core.py +0 -258
  38. package/.shared/ui-ux-pro-max/scripts/design_system.py +0 -1067
  39. package/.shared/ui-ux-pro-max/scripts/search.py +0 -106
  40. package/ARCHITECTURE.md +0 -288
  41. package/CLAUDE.md +0 -90
  42. package/mcp_config.json +0 -24
package/scripts/init.py CHANGED
@@ -9,11 +9,12 @@ Usage:
9
9
  python scripts/init.py --platform claude # Only CLAUDE.md
10
10
  """
11
11
 
12
- import sys
13
- import os
14
- import argparse
15
- from pathlib import Path
16
- from datetime import datetime
12
+ import sys
13
+ import os
14
+ import argparse
15
+ import json
16
+ from pathlib import Path
17
+ from datetime import datetime
17
18
 
18
19
  # ─── Color helpers ──────────────────────────────────────────────────────────
19
20
 
@@ -53,13 +54,17 @@ def ask_multi(prompt, choices, default=None):
53
54
  selected.append(part) # allow free-text
54
55
  return selected
55
56
 
56
- def ask_bool(prompt, default=True):
57
+ def ask_bool(prompt, default=True):
57
58
  """Yes/no prompt."""
58
59
  default_str = "Y/n" if default else "y/N"
59
60
  val = input(f" {bold('→')} {prompt} [{dim(default_str)}]: ").strip().lower()
60
- if not val:
61
- return default
62
- return val.startswith("y")
61
+ if not val:
62
+ return default
63
+ return val.startswith("y")
64
+
65
+ def ask_select(prompt, choices, default=None):
66
+ default = default or choices[0]
67
+ return ask(prompt, default=default, choices=choices)
63
68
 
64
69
  def section(title):
65
70
  print(f"\n{bold(cyan('━━ ' + title + ' '))}")
@@ -79,10 +84,10 @@ LANG_SKILLS = {
79
84
  "csharp": ["api-design"],
80
85
  }
81
86
 
82
- FRAMEWORK_SKILLS = {
83
- "vue": ["frontend-design", "tailwind-patterns"],
84
- "react": ["nextjs-react-expert", "frontend-design"],
85
- "next": ["nextjs-react-expert", "frontend-design"],
87
+ FRAMEWORK_SKILLS = {
88
+ "vue": ["frontend-design", "tailwind-patterns"],
89
+ "react": ["react-frontend", "frontend-design"],
90
+ "next": ["nextjs-react-expert", "frontend-design"],
86
91
  "nuxt": ["frontend-design"],
87
92
  "svelte": ["frontend-design"],
88
93
  "laravel": ["laravel-patterns", "laravel-security", "laravel-tdd"],
@@ -91,12 +96,12 @@ FRAMEWORK_SKILLS = {
91
96
  "django": ["python-patterns", "api-design"],
92
97
  "gin": ["golang-patterns", "golang-testing"],
93
98
  "fiber": ["golang-patterns", "golang-testing"],
94
- "tauri": ["rust-pro", "mobile-design"],
95
- "flutter": ["mobile-design"],
96
- "react-native": ["mobile-design"],
97
- }
99
+ "tauri": ["rust-pro", "desktop-design"],
100
+ "flutter": ["mobile-design"],
101
+ "react-native": ["mobile-design"],
102
+ }
98
103
 
99
- INFRA_SKILLS = {
104
+ INFRA_SKILLS = {
100
105
  "docker": ["docker-patterns"],
101
106
  "aws": ["deployment-procedures", "docker-patterns"],
102
107
  "gcp": ["deployment-procedures", "docker-patterns"],
@@ -120,7 +125,157 @@ def resolve_skills(data):
120
125
  if key in infra_lower:
121
126
  skills.update(vals)
122
127
  skills.update(["clean-code", "systematic-debugging"])
123
- return sorted(skills)
128
+ return sorted(skills)
129
+
130
+ FRAMEWORKS_ALL = ["vue", "react", "next", "nuxt", "svelte", "angular",
131
+ "laravel", "express", "fastapi", "django", "gin", "fiber", "nestjs",
132
+ "tauri", "flutter", "react-native"]
133
+ LANGUAGES_ALL = ["typescript", "javascript", "python", "go", "php", "rust", "java", "swift", "kotlin", "csharp", "c", "cpp"]
134
+ PROJECT_TYPES_ALL = ["web-app", "api", "mobile", "desktop", "cli", "library", "fullstack"]
135
+ DATABASES_ALL = ["postgres", "mysql", "sqlite", "mongodb", "redis", "dynamodb", "supabase", "prisma", "none"]
136
+ PACKAGE_MANAGERS_ALL = ["npm", "pnpm", "yarn", "bun", "pip", "uv", "poetry", "go mod", "cargo", "composer", "auto-detect"]
137
+ TEST_FRAMEWORKS_ALL = ["jest", "vitest", "pytest", "go test", "phpunit", "pest", "rspec", "junit", "auto-detect"]
138
+ CLOUDS_ALL = ["aws", "gcp", "azure", "vercel", "fly", "railway", "digitalocean", "none"]
139
+
140
+ def read_text_if_exists(*parts):
141
+ path = Path.cwd().joinpath(*parts)
142
+ try:
143
+ return path.read_text(encoding="utf-8") if path.exists() else ""
144
+ except Exception:
145
+ return ""
146
+
147
+ def read_json_if_exists(*parts):
148
+ path = Path.cwd().joinpath(*parts)
149
+ try:
150
+ return json.loads(path.read_text(encoding="utf-8")) if path.exists() else None
151
+ except Exception:
152
+ return None
153
+
154
+ def detect_package_manager():
155
+ cwd = Path.cwd()
156
+ if (cwd / "pnpm-lock.yaml").exists(): return "pnpm"
157
+ if (cwd / "yarn.lock").exists(): return "yarn"
158
+ if (cwd / "bun.lockb").exists() or (cwd / "bun.lock").exists(): return "bun"
159
+ if (cwd / "package-lock.json").exists(): return "npm"
160
+ if (cwd / "uv.lock").exists(): return "uv"
161
+ if (cwd / "poetry.lock").exists(): return "poetry"
162
+ if (cwd / "requirements.txt").exists() or (cwd / "pyproject.toml").exists(): return "pip"
163
+ if (cwd / "go.mod").exists(): return "go mod"
164
+ if (cwd / "Cargo.toml").exists(): return "cargo"
165
+ if (cwd / "composer.json").exists(): return "composer"
166
+ return "auto-detect"
167
+
168
+ def uniq(values):
169
+ return list(dict.fromkeys(v for v in values if v))
170
+
171
+ def scan_project():
172
+ pkg = read_json_if_exists("package.json") or {}
173
+ deps = {}
174
+ for key in ("dependencies", "devDependencies", "peerDependencies"):
175
+ deps.update(pkg.get(key, {}) or {})
176
+ dep_names = set(deps.keys())
177
+ frameworks = []
178
+ infrastructure = []
179
+ primary_language = ""
180
+ project_type = ""
181
+ database = "none"
182
+ test_framework = "auto-detect"
183
+ cloud = "none"
184
+ ci_cd = "none"
185
+
186
+ def add_framework(name, condition):
187
+ if condition:
188
+ frameworks.append(name)
189
+
190
+ requirements = read_text_if_exists("requirements.txt")
191
+ go_mod = read_text_if_exists("go.mod")
192
+ pubspec = read_text_if_exists("pubspec.yaml")
193
+
194
+ add_framework("next", "next" in dep_names)
195
+ add_framework("react", "react" in dep_names)
196
+ add_framework("vue", "vue" in dep_names)
197
+ add_framework("nuxt", "nuxt" in dep_names)
198
+ add_framework("svelte", "svelte" in dep_names or "@sveltejs/kit" in dep_names)
199
+ add_framework("angular", "@angular/core" in dep_names)
200
+ add_framework("express", "express" in dep_names)
201
+ add_framework("nestjs", "@nestjs/core" in dep_names)
202
+ add_framework("fastapi", "fastapi" in requirements.lower())
203
+ add_framework("django", "django" in requirements.lower())
204
+ add_framework("tauri", "@tauri-apps/api" in dep_names or Path("src-tauri/tauri.conf.json").exists() or Path("src-tauri/tauri.conf.json5").exists())
205
+ add_framework("flutter", "flutter:" in pubspec.lower())
206
+ add_framework("react-native", "react-native" in dep_names or "expo" in dep_names)
207
+ add_framework("laravel", Path("artisan").exists())
208
+ add_framework("gin", "github.com/gin-gonic/gin" in go_mod.lower())
209
+ add_framework("fiber", "github.com/gofiber/fiber" in go_mod.lower())
210
+
211
+ if Path("tsconfig.json").exists() or "typescript" in dep_names: primary_language = "typescript"
212
+ elif Path("Cargo.toml").exists() or Path("src-tauri/Cargo.toml").exists(): primary_language = "rust"
213
+ elif Path("go.mod").exists(): primary_language = "go"
214
+ elif Path("requirements.txt").exists() or Path("pyproject.toml").exists(): primary_language = "python"
215
+ elif Path("composer.json").exists(): primary_language = "php"
216
+ elif dep_names or Path("package.json").exists(): primary_language = "javascript"
217
+
218
+ if "tauri" in frameworks: project_type = "desktop"
219
+ elif "flutter" in frameworks or "react-native" in frameworks: project_type = "mobile"
220
+ elif any(f in frameworks for f in ["express", "fastapi", "django", "laravel", "gin", "fiber", "nestjs"]):
221
+ project_type = "fullstack" if any(f in frameworks for f in ["react", "next", "vue", "nuxt", "svelte", "angular"]) else "api"
222
+ elif any(f in frameworks for f in ["react", "next", "vue", "nuxt", "svelte", "angular"]):
223
+ project_type = "web-app"
224
+ elif Path("package.json").exists() and pkg.get("bin"):
225
+ project_type = "cli"
226
+
227
+ if "pg" in dep_names or "postgres" in dep_names or "@prisma/client" in dep_names or "postgres" in json.dumps(pkg).lower(): database = "postgres"
228
+ elif "mysql" in dep_names or "mysql2" in dep_names: database = "mysql"
229
+ elif "sqlite3" in dep_names or "better-sqlite3" in dep_names or "rusqlite" in dep_names: database = "sqlite"
230
+ elif "mongodb" in dep_names or "mongoose" in dep_names: database = "mongodb"
231
+ elif "redis" in dep_names or "ioredis" in dep_names: database = "redis"
232
+ elif "@aws-sdk/client-dynamodb" in dep_names: database = "dynamodb"
233
+
234
+ if "vitest" in dep_names: test_framework = "vitest"
235
+ elif "jest" in dep_names: test_framework = "jest"
236
+ elif "pytest" in dep_names or "pytest" in requirements.lower(): test_framework = "pytest"
237
+ elif "phpunit" in dep_names: test_framework = "phpunit"
238
+ elif "pest" in dep_names: test_framework = "pest"
239
+ elif Path("go.mod").exists(): test_framework = "go test"
240
+
241
+ if Path("Dockerfile").exists() or Path("docker-compose.yml").exists() or Path("docker-compose.yaml").exists():
242
+ infrastructure.append("docker")
243
+
244
+ if Path("vercel.json").exists():
245
+ cloud = "vercel"
246
+ infrastructure.append("vercel")
247
+ elif Path("fly.toml").exists():
248
+ cloud = "fly"
249
+ infrastructure.append("fly")
250
+ elif Path("railway.json").exists() or Path("railway.toml").exists():
251
+ cloud = "railway"
252
+ infrastructure.append("railway")
253
+
254
+ if Path(".github/workflows").exists(): ci_cd = "github-actions"
255
+ elif Path(".gitlab-ci.yml").exists(): ci_cd = "gitlab-ci"
256
+ elif Path(".circleci/config.yml").exists(): ci_cd = "circleci"
257
+ elif Path("Jenkinsfile").exists(): ci_cd = "jenkins"
258
+
259
+ return {
260
+ "project_name": Path.cwd().name,
261
+ "description": pkg.get("description", "A software project"),
262
+ "project_type": project_type if project_type in PROJECT_TYPES_ALL else "web-app",
263
+ "primary_language": primary_language if primary_language in LANGUAGES_ALL else "typescript",
264
+ "frameworks": uniq(frameworks),
265
+ "database": database if database in DATABASES_ALL else "none",
266
+ "package_manager": detect_package_manager(),
267
+ "uses_docker": "docker" in infrastructure,
268
+ "cloud": cloud,
269
+ "infrastructure": uniq(infrastructure),
270
+ "ci_cd": ci_cd,
271
+ "test_framework": test_framework if test_framework in TEST_FRAMEWORKS_ALL else "auto-detect",
272
+ "max_file_lines": "300",
273
+ "code_style": "project-standard",
274
+ "architecture_notes": "<!-- Add notes -->",
275
+ "current_phase": "Initial setup",
276
+ "next_phase": "—",
277
+ "known_issues": "<!-- None yet -->",
278
+ }
124
279
 
125
280
  def resolve_agent_table(data):
126
281
  rows = []
@@ -252,11 +407,12 @@ def generate_claude_md(data):
252
407
  {data['description']}
253
408
  Stack: {data['primary_language']} | {', '.join(data.get('frameworks', []))}
254
409
 
255
- ## Rules
256
- - Read PROJECT_CONTEXT.md first for stack details and agent routing.
257
- - Follow skills in .claude/skills/ (or skills/ if using Antigravity).
258
- - Tests are mandatory. Verify before claiming done.
259
- - Max {data.get('max_file_lines', '300')} lines per file.
410
+ ## Rules
411
+ - Read PROJECT_CONTEXT.md first for stack details and agent routing.
412
+ - If PROJECT_CONTEXT.md is missing or stale, create/update it before major work.
413
+ - Follow skills in .claude/skills/ (or skills/ if using Antigravity).
414
+ - Tests are mandatory. Verify before claiming done.
415
+ - Max {data.get('max_file_lines', '300')} lines per file.
260
416
 
261
417
  ## Key Skills
262
418
  - Plan: `plan-writing` → `executing-plans`
@@ -275,19 +431,20 @@ See PROJECT_CONTEXT.md for full agent routing table.
275
431
 
276
432
  # ─── Main wizard ─────────────────────────────────────────────────────────────
277
433
 
278
- def main():
279
- parser = argparse.ArgumentParser(description="thachvd-kit project init wizard")
280
- parser.add_argument("--platform", choices=["antigravity", "claude", "all"], default="antigravity",
281
- help="Which platform config to generate (default: antigravity)")
282
- parser.add_argument("--yes", "-y", action="store_true", help="Use defaults without prompting")
283
- args = parser.parse_args()
434
+ def main():
435
+ parser = argparse.ArgumentParser(description="thachvd-kit project init wizard")
436
+ parser.add_argument("--platform", choices=["antigravity", "claude", "all"], default="antigravity",
437
+ help="Which platform config to generate (default: antigravity)")
438
+ parser.add_argument("--yes", "-y", action="store_true", help="Use defaults without prompting")
439
+ parser.add_argument("--scan", action="store_true", help="Scan the current project to prefill or auto-generate PROJECT_CONTEXT.md")
440
+ args = parser.parse_args()
284
441
 
285
442
  print(f"""
286
- {bold(cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))}
287
- {bold('thachvd-kit')} — Project Init Wizard
288
- Generates PROJECT_CONTEXT.md for smart agent routing
289
- {bold(cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))}
290
- """)
443
+ {bold(cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))}
444
+ {bold('thachvd-kit')} — Project Init Wizard
445
+ Generates PROJECT_CONTEXT.md for smart agent routing{' (scan-assisted)' if args.scan else ''}
446
+ {bold(cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'))}
447
+ """)
291
448
 
292
449
  # Check if PROJECT_CONTEXT.md already exists
293
450
  output_path = Path("PROJECT_CONTEXT.md")
@@ -297,85 +454,118 @@ def main():
297
454
  print(f"\n {yellow('Aborted.')} Existing PROJECT_CONTEXT.md unchanged.\n")
298
455
  sys.exit(0)
299
456
 
300
- data = {}
301
-
302
- # ── Project Info ──────────────────────────────────────────────────────
303
- section("Project Info")
304
- data["project_name"] = ask("Project name", default=Path.cwd().name)
305
- data["description"] = ask("Short description", default="A software project")
306
- data["project_type"] = ask("Project type",
307
- default="web-app",
308
- choices=["web-app", "api", "mobile", "desktop", "cli", "library", "fullstack"])
309
-
310
- # ── Tech Stack ────────────────────────────────────────────────────────
311
- section("Tech Stack")
312
-
313
- LANGUAGES = ["typescript", "javascript", "python", "go", "php", "rust", "java", "swift", "kotlin", "csharp", "c", "cpp"]
314
- data["primary_language"] = ask("Primary language",
315
- default="typescript",
316
- choices=LANGUAGES)
317
-
318
- FRAMEWORKS = ["vue", "react", "next", "nuxt", "svelte", "angular",
319
- "laravel", "express", "fastapi", "django", "gin", "fiber", "nestjs",
320
- "tauri", "flutter", "react-native",
321
- "none"]
322
- frameworks = ask_multi("Frameworks (select all that apply)", FRAMEWORKS, default=None)
323
- data["frameworks"] = frameworks or []
324
-
325
- DATABASES = ["postgres", "mysql", "sqlite", "mongodb", "redis", "dynamodb", "supabase", "prisma", "none"]
326
- data["database"] = ask("Database / ORM", default="postgres", choices=DATABASES)
327
-
328
- PACKAGE_MANAGERS = ["npm", "pnpm", "yarn", "bun", "pip", "uv", "poetry", "go mod", "cargo", "composer", "auto-detect"]
329
- data["package_manager"] = ask("Package manager", default="auto-detect", choices=PACKAGE_MANAGERS)
330
-
331
- # ── Infrastructure ────────────────────────────────────────────────────
332
- section("Infrastructure")
333
-
334
- data["uses_docker"] = ask_bool("Uses Docker / Docker Compose?", default=True)
335
- CLOUDS = ["aws", "gcp", "azure", "vercel", "fly", "railway", "digitalocean", "none"]
336
- cloud = ask("Cloud provider", default="none", choices=CLOUDS)
337
- data["cloud"] = cloud
338
-
339
- infrastructure = []
340
- if data["uses_docker"]: infrastructure.append("docker")
341
- if cloud != "none": infrastructure.append(cloud)
342
- data["infrastructure"] = infrastructure
343
-
344
- CI_CD = ["github-actions", "gitlab-ci", "circleci", "jenkins", "none"]
345
- data["ci_cd"] = ask("CI/CD", default="github-actions", choices=CI_CD)
346
-
347
- # ── Testing ───────────────────────────────────────────────────────────
348
- section("Testing")
349
-
350
- TEST_FRAMEWORKS = ["jest", "vitest", "pytest", "go test", "phpunit", "pest", "rspec", "junit", "auto-detect"]
351
- data["test_framework"] = ask("Test framework", default="auto-detect", choices=TEST_FRAMEWORKS)
352
-
353
- # ── Conventions ───────────────────────────────────────────────────────
354
- section("Coding Conventions")
355
-
356
- data["max_file_lines"] = ask("Max lines per file before splitting", default="300")
357
- data["code_style"] = ask("Code style / linter", default="project-standard",
358
- choices=["eslint", "prettier", "ruff", "gofmt", "pint", "standard", "project-standard"])
359
-
360
- # ── Optional fields ───────────────────────────────────────────────────
361
- section("Architecture (Optional — press Enter to skip)")
362
-
363
- data["architecture_notes"] = ask("Key architecture notes", default="<!-- Add notes -->")
364
- data["current_phase"] = ask("Current phase", default="Initial setup")
365
- data["next_phase"] = ask("Next planned phase", default="—")
366
- data["known_issues"] = ask("Known issues / tasks", default="<!-- None yet -->")
367
-
368
- # ── Generate files ────────────────────────────────────────────────────
369
- section("Generating Files")
457
+ use_scan = args.scan
458
+ if not args.scan and not args.yes:
459
+ section("Setup Mode")
460
+ project_setup = ask_select("Project already exists or are you starting fresh",
461
+ ["existing", "new"], default="existing")
462
+ if project_setup == "existing":
463
+ existing_mode = ask_select("How should thachvd-kit build PROJECT_CONTEXT.md",
464
+ ["scan", "manual"], default="scan")
465
+ use_scan = existing_mode == "scan"
466
+
467
+ scanned = scan_project() if use_scan else None
468
+ if use_scan:
469
+ print(f" {dim('Scan mode: detecting stack from current project files...')}")
470
+ print(f" {bold('Scan result:')} {scanned['primary_language']} | {', '.join(scanned['frameworks']) or 'no framework'}")
471
+ print(f" {bold('Detected infra:')} {', '.join(scanned['infrastructure']) or 'none'}\n")
472
+ elif not args.yes:
473
+ print(f" {dim('Manual mode: asking for project context explicitly.')}\n")
474
+
475
+ if args.yes and scanned:
476
+ data = dict(scanned)
477
+ else:
478
+ data = {}
479
+
480
+ if not args.yes:
481
+ # ── Project Info ──────────────────────────────────────────────────────
482
+ section("Project Info")
483
+ data["project_name"] = ask("Project name", default=(scanned or {}).get("project_name", Path.cwd().name))
484
+ data["description"] = ask("Short description", default=(scanned or {}).get("description", "A software project"))
485
+ data["project_type"] = ask("Project type",
486
+ default=(scanned or {}).get("project_type", "web-app"),
487
+ choices=PROJECT_TYPES_ALL)
488
+
489
+ # ── Tech Stack ────────────────────────────────────────────────────────
490
+ section("Tech Stack")
491
+
492
+ data["primary_language"] = ask("Primary language",
493
+ default=(scanned or {}).get("primary_language", "typescript"),
494
+ choices=LANGUAGES_ALL)
495
+
496
+ frameworks = ask_multi("Frameworks (select all that apply)", FRAMEWORKS_ALL, default=", ".join((scanned or {}).get("frameworks", [])) or None)
497
+ data["frameworks"] = frameworks or []
498
+
499
+ data["database"] = ask("Database / ORM", default=(scanned or {}).get("database", "postgres"), choices=DATABASES_ALL)
500
+
501
+ data["package_manager"] = ask("Package manager", default=(scanned or {}).get("package_manager", "auto-detect"), choices=PACKAGE_MANAGERS_ALL)
502
+
503
+ # ── Infrastructure ────────────────────────────────────────────────────
504
+ section("Infrastructure")
505
+
506
+ data["uses_docker"] = ask_bool("Uses Docker / Docker Compose?", default=(scanned or {}).get("uses_docker", True))
507
+ cloud = ask("Cloud provider", default=(scanned or {}).get("cloud", "none"), choices=CLOUDS_ALL)
508
+ data["cloud"] = cloud
509
+
510
+ infrastructure = []
511
+ if data["uses_docker"]: infrastructure.append("docker")
512
+ if cloud != "none": infrastructure.append(cloud)
513
+ data["infrastructure"] = infrastructure
514
+
515
+ CI_CD = ["github-actions", "gitlab-ci", "circleci", "jenkins", "none"]
516
+ data["ci_cd"] = ask("CI/CD", default=(scanned or {}).get("ci_cd", "github-actions"), choices=CI_CD)
517
+
518
+ # ── Testing ───────────────────────────────────────────────────────────
519
+ section("Testing")
520
+
521
+ data["test_framework"] = ask("Test framework", default=(scanned or {}).get("test_framework", "auto-detect"), choices=TEST_FRAMEWORKS_ALL)
522
+
523
+ # ── Conventions ───────────────────────────────────────────────────────
524
+ section("Coding Conventions")
525
+
526
+ data["max_file_lines"] = ask("Max lines per file before splitting", default=(scanned or {}).get("max_file_lines", "300"))
527
+ data["code_style"] = ask("Code style / linter", default=(scanned or {}).get("code_style", "project-standard"),
528
+ choices=["eslint", "prettier", "ruff", "gofmt", "pint", "standard", "project-standard"])
529
+
530
+ # ── Optional fields ───────────────────────────────────────────────────
531
+ section("Architecture (Optional — press Enter to skip)")
532
+
533
+ data["architecture_notes"] = ask("Key architecture notes", default=(scanned or {}).get("architecture_notes", "<!-- Add notes -->"))
534
+ data["current_phase"] = ask("Current phase", default=(scanned or {}).get("current_phase", "Initial setup"))
535
+ data["next_phase"] = ask("Next planned phase", default=(scanned or {}).get("next_phase", "—"))
536
+ data["known_issues"] = ask("Known issues / tasks", default=(scanned or {}).get("known_issues", "<!-- None yet -->"))
537
+
538
+ data["project_name"] = data.get("project_name", (scanned or {}).get("project_name", Path.cwd().name))
539
+ data["description"] = data.get("description", (scanned or {}).get("description", "A software project"))
540
+ data["project_type"] = data.get("project_type", (scanned or {}).get("project_type", "web-app"))
541
+ data["primary_language"] = data.get("primary_language", (scanned or {}).get("primary_language", "typescript"))
542
+ data["frameworks"] = data.get("frameworks", (scanned or {}).get("frameworks", []))
543
+ data["database"] = data.get("database", (scanned or {}).get("database", "none"))
544
+ data["package_manager"] = data.get("package_manager", (scanned or {}).get("package_manager", "auto-detect"))
545
+ data["uses_docker"] = data.get("uses_docker", (scanned or {}).get("uses_docker", True))
546
+ data["cloud"] = data.get("cloud", (scanned or {}).get("cloud", "none"))
547
+ data["test_framework"] = data.get("test_framework", (scanned or {}).get("test_framework", "auto-detect"))
548
+ data["max_file_lines"] = data.get("max_file_lines", (scanned or {}).get("max_file_lines", "300"))
549
+ data["code_style"] = data.get("code_style", (scanned or {}).get("code_style", "project-standard"))
550
+ data["architecture_notes"] = data.get("architecture_notes", (scanned or {}).get("architecture_notes", "<!-- Add notes -->"))
551
+ data["current_phase"] = data.get("current_phase", (scanned or {}).get("current_phase", "Initial setup"))
552
+ data["next_phase"] = data.get("next_phase", (scanned or {}).get("next_phase", "—"))
553
+ data["known_issues"] = data.get("known_issues", (scanned or {}).get("known_issues", "<!-- None yet -->"))
554
+ data["infrastructure"] = []
555
+ if data["uses_docker"]: data["infrastructure"].append("docker")
556
+ if data["cloud"] != "none": data["infrastructure"].append(data["cloud"])
557
+
558
+ # ── Generate files ────────────────────────────────────────────────────
559
+ section("Generating Files")
370
560
 
371
561
  # PROJECT_CONTEXT.md (always)
372
- context_content = generate_project_context(data)
373
- output_path.write_text(context_content, encoding="utf-8")
374
- print(f" {green('✓')} {bold('PROJECT_CONTEXT.md')} generated")
375
-
376
- # CLAUDE.md (for Claude Code / Codex)
377
- if args.platform in ("claude", "all"):
378
- claude_path = Path("CLAUDE.md")
562
+ context_content = generate_project_context(data)
563
+ output_path.write_text(context_content, encoding="utf-8")
564
+ print(f" {green('✓')} {bold('PROJECT_CONTEXT.md')} generated")
565
+
566
+ # CLAUDE.md (for Claude Code / Codex)
567
+ if args.platform in ("claude", "all"):
568
+ claude_path = Path("CLAUDE.md")
379
569
  claude_path.write_text(generate_claude_md(data), encoding="utf-8")
380
570
  print(f" {green('✓')} {bold('CLAUDE.md')} generated (Claude Code / Codex)")
381
571
 
@@ -388,16 +578,21 @@ def main():
388
578
  {bold('Stack:')} {data['primary_language']} | {', '.join(data['frameworks']) or 'no framework'}
389
579
  {bold('Infra:')} {', '.join(data['infrastructure']) or 'none'}
390
580
 
391
- {bold('Auto-resolved skills:')}
392
- {chr(10).join(f' · {s}' for s in auto_skills)}
393
-
394
- {bold('Next steps:')}
395
- 1. Review {bold('PROJECT_CONTEXT.md')} and add architecture notes
396
- 2. Open project in your AI editor (Antigravity / Claude Code / Codex)
397
- 3. The agent will read PROJECT_CONTEXT.md on session start
398
-
399
- {dim(' Tip: Run with --platform all to also generate CLAUDE.md')}
400
- """)
581
+ {bold('Auto-resolved skills:')}
582
+ {chr(10).join(f' · {s}' for s in auto_skills)}
583
+
584
+ {bold('Generated files:')}
585
+ · {bold(str(output_path.resolve()))}
586
+ · {bold(str(Path("CLAUDE.md").resolve())) if args.platform in ("claude", "all") else 'CLAUDE.md not generated for this platform'}
587
+
588
+ {bold('Next steps:')}
589
+ 1. Review {bold('PROJECT_CONTEXT.md')} first and add architecture notes
590
+ 2. Instruct the agent to read/update {bold('PROJECT_CONTEXT.md')} before major tasks
591
+ 3. Open project in your AI editor (Antigravity / Claude Code / Codex)
592
+ 4. The agent will read PROJECT_CONTEXT.md on session start
593
+
594
+ {dim(' Tip: Run with --platform all to also generate CLAUDE.md')}
595
+ """)
401
596
 
402
597
  if __name__ == "__main__":
403
598
  main()
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: desktop-design
3
+ description: Desktop and cross-platform app design guidance for Tauri and similar desktop shells. Use when building desktop-first interfaces, windowed workflows, keyboard-heavy UX, or cross-platform desktop UI behavior.
4
+ allowed-tools: Read, Write, Edit, Glob, Grep, Bash
5
+ ---
6
+
7
+ # Desktop Design
8
+
9
+ This skill covers desktop-first product thinking where `mobile-design` is the wrong default.
10
+
11
+ Use it for Tauri and other desktop-oriented apps with window management, keyboard shortcuts, dense layouts, or multi-panel workflows.
12
+
13
+ ## Guidance
14
+
15
+ - Design for pointer + keyboard, not touch-first.
16
+ - Use information density deliberately; desktop screens can support richer sidebars and multi-column layouts.
17
+ - Respect platform conventions for menus, shortcuts, dialogs, file pickers, and drag/drop.
18
+ - Assume resizing, multiple windows, and long-running sessions are normal.
19
+ - Pair with `rust-pro` for Tauri backend/native concerns and `frontend-design` for UI execution.
20
+
21
+ ## Related Skills
22
+
23
+ - `mobile-design` for touch-first mobile products
24
+ - `frontend-design` for visual and interaction design
25
+ - `rust-pro` for Rust and Tauri implementation details
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: react-frontend
3
+ description: React-focused frontend guidance for component architecture, state flow, rendering boundaries, and maintainable UI systems. Use for plain React apps that are not specifically Next.js-first.
4
+ allowed-tools: Read, Write, Edit, Glob, Grep, Bash
5
+ ---
6
+
7
+ # React Frontend
8
+
9
+ This skill is the React-first counterpart to `nextjs-react-expert`.
10
+
11
+ Use it when the project uses React without needing Next.js-specific assumptions such as SSR, App Router, or server components.
12
+
13
+ ## Guidance
14
+
15
+ - Prefer the existing project architecture over introducing a new pattern.
16
+ - Keep state ownership shallow and explicit.
17
+ - Separate presentational UI from data-fetching and side effects when it improves maintainability.
18
+ - Optimize rendering only after confirming an actual bottleneck.
19
+ - Pair with `frontend-design` for UI/UX decisions.
20
+
21
+ ## Related Skills
22
+
23
+ - `nextjs-react-expert` for Next.js-specific performance and routing concerns
24
+ - `frontend-design` for layout, visual hierarchy, and responsive design
25
+ - `clean-code` for naming, file boundaries, and readability
@@ -1,26 +0,0 @@
1
- No,Data Type,Keywords,Best Chart Type,Secondary Options,Color Guidance,Performance Impact,Accessibility Notes,Library Recommendation,Interactive Level
2
- 1,Trend Over Time,"trend, time-series, line, growth, timeline, progress",Line Chart,"Area Chart, Smooth Area",Primary: #0080FF. Multiple series: use distinct colors. Fill: 20% opacity,⚡ Excellent (optimized),✓ Clear line patterns for colorblind users. Add pattern overlays.,"Chart.js, Recharts, ApexCharts",Hover + Zoom
3
- 2,Compare Categories,"compare, categories, bar, comparison, ranking",Bar Chart (Horizontal or Vertical),"Column Chart, Grouped Bar",Each bar: distinct color. Category: grouped same color. Sorted: descending order,⚡ Excellent,✓ Easy to compare. Add value labels on bars for clarity.,"Chart.js, Recharts, D3.js",Hover + Sort
4
- 3,Part-to-Whole,"part-to-whole, pie, donut, percentage, proportion, share",Pie Chart or Donut,"Stacked Bar, Treemap",Colors: 5-6 max. Contrasting palette. Large slices first. Use labels.,⚡ Good (limit 6 slices),⚠ Hard for accessibility. Better: Stacked bar with legend. Avoid pie if >5 items.,"Chart.js, Recharts, D3.js",Hover + Drill
5
- 4,Correlation/Distribution,"correlation, distribution, scatter, relationship, pattern",Scatter Plot or Bubble Chart,"Heat Map, Matrix",Color axis: gradient (blue-red). Size: relative. Opacity: 0.6-0.8 to show density,⚠ Moderate (many points),⚠ Provide data table alternative. Use pattern + color distinction.,"D3.js, Plotly, Recharts",Hover + Brush
6
- 5,Heatmap/Intensity,"heatmap, heat-map, intensity, density, matrix",Heat Map or Choropleth,"Grid Heat Map, Bubble Heat",Gradient: Cool (blue) to Hot (red). Scale: clear legend. Divergent for ±data,⚡ Excellent (color CSS),⚠ Colorblind: Use pattern overlay. Provide numerical legend.,"D3.js, Plotly, ApexCharts",Hover + Zoom
7
- 6,Geographic Data,"geographic, map, location, region, geo, spatial","Choropleth Map, Bubble Map",Geographic Heat Map,Regional: single color gradient or categorized colors. Legend: clear scale,⚠ Moderate (rendering),⚠ Include text labels for regions. Provide data table alternative.,"D3.js, Mapbox, Leaflet",Pan + Zoom + Drill
8
- 7,Funnel/Flow,funnel/flow,"Funnel Chart, Sankey",Waterfall (for flows),Stages: gradient (starting color → ending color). Show conversion %,⚡ Good,✓ Clear stage labels + percentages. Good for accessibility if labeled.,"D3.js, Recharts, Custom SVG",Hover + Drill
9
- 8,Performance vs Target,performance-vs-target,Gauge Chart or Bullet Chart,"Dial, Thermometer",Performance: Red→Yellow→Green gradient. Target: marker line. Threshold colors,⚡ Good,✓ Add numerical value + percentage label beside gauge.,"D3.js, ApexCharts, Custom SVG",Hover
10
- 9,Time-Series Forecast,time-series-forecast,Line with Confidence Band,Ribbon Chart,Actual: solid line #0080FF. Forecast: dashed #FF9500. Band: light shading,⚡ Good,✓ Clearly distinguish actual vs forecast. Add legend.,"Chart.js, ApexCharts, Plotly",Hover + Toggle
11
- 10,Anomaly Detection,anomaly-detection,Line Chart with Highlights,Scatter with Alert,Normal: blue #0080FF. Anomaly: red #FF0000 circle/square marker + alert,⚡ Good,✓ Circle/marker for anomalies. Add text alert annotation.,"D3.js, Plotly, ApexCharts",Hover + Alert
12
- 11,Hierarchical/Nested Data,hierarchical/nested-data,Treemap,"Sunburst, Nested Donut, Icicle",Parent: distinct hues. Children: lighter shades. White borders 2-3px.,⚠ Moderate,⚠ Poor - provide table alternative. Label large areas.,"D3.js, Recharts, ApexCharts",Hover + Drilldown
13
- 12,Flow/Process Data,flow/process-data,Sankey Diagram,"Alluvial, Chord Diagram",Gradient from source to target. Opacity 0.4-0.6 for flows.,⚠ Moderate,⚠ Poor - provide flow table alternative.,"D3.js (d3-sankey), Plotly",Hover + Drilldown
14
- 13,Cumulative Changes,cumulative-changes,Waterfall Chart,"Stacked Bar, Cascade",Increases: #4CAF50. Decreases: #F44336. Start: #2196F3. End: #0D47A1.,⚡ Good,✓ Good - clear directional colors with labels.,"ApexCharts, Highcharts, Plotly",Hover
15
- 14,Multi-Variable Comparison,multi-variable-comparison,Radar/Spider Chart,"Parallel Coordinates, Grouped Bar",Single: #0080FF 20% fill. Multiple: distinct colors per dataset.,⚡ Good,⚠ Moderate - limit 5-8 axes. Add data table.,"Chart.js, Recharts, ApexCharts",Hover + Toggle
16
- 15,Stock/Trading OHLC,stock/trading-ohlc,Candlestick Chart,"OHLC Bar, Heikin-Ashi",Bullish: #26A69A. Bearish: #EF5350. Volume: 40% opacity below.,⚡ Good,⚠ Moderate - provide OHLC data table.,"Lightweight Charts (TradingView), ApexCharts",Real-time + Hover + Zoom
17
- 16,Relationship/Connection Data,relationship/connection-data,Network Graph,"Hierarchical Tree, Adjacency Matrix",Node types: categorical colors. Edges: #90A4AE 60% opacity.,❌ Poor (500+ nodes struggles),❌ Very Poor - provide adjacency list alternative.,"D3.js (d3-force), Vis.js, Cytoscape.js",Drilldown + Hover + Drag
18
- 17,Distribution/Statistical,distribution/statistical,Box Plot,"Violin Plot, Beeswarm",Box: #BBDEFB. Border: #1976D2. Median: #D32F2F. Outliers: #F44336.,⚡ Excellent,"✓ Good - include stats table (min, Q1, median, Q3, max).","Plotly, D3.js, Chart.js (plugin)",Hover
19
- 18,Performance vs Target (Compact),performance-vs-target-(compact),Bullet Chart,"Gauge, Progress Bar","Ranges: #FFCDD2, #FFF9C4, #C8E6C9. Performance: #1976D2. Target: black 3px.",⚡ Excellent,✓ Excellent - compact with clear values.,"D3.js, Plotly, Custom SVG",Hover
20
- 19,Proportional/Percentage,proportional/percentage,Waffle Chart,"Pictogram, Stacked Bar 100%",10x10 grid. 3-5 categories max. 2-3px spacing between squares.,⚡ Good,✓ Good - better than pie for accessibility.,"D3.js, React-Waffle, Custom CSS Grid",Hover
21
- 20,Hierarchical Proportional,hierarchical-proportional,Sunburst Chart,"Treemap, Icicle, Circle Packing",Center to outer: darker to lighter. 15-20% lighter per level.,⚠ Moderate,⚠ Poor - provide hierarchy table alternative.,"D3.js (d3-hierarchy), Recharts, ApexCharts",Drilldown + Hover
22
- 21,Root Cause Analysis,"root cause, decomposition, tree, hierarchy, drill-down, ai-split",Decomposition Tree,"Decision Tree, Flow Chart",Nodes: #2563EB (Primary) vs #EF4444 (Negative impact). Connectors: Neutral grey.,⚠ Moderate (calculation heavy),✓ clear hierarchy. Allow keyboard navigation for nodes.,"Power BI (native), React-Flow, Custom D3.js",Drill + Expand
23
- 22,3D Spatial Data,"3d, spatial, immersive, terrain, molecular, volumetric",3D Scatter/Surface Plot,"Volumetric Rendering, Point Cloud",Depth cues: lighting/shading. Z-axis: color gradient (cool to warm).,❌ Heavy (WebGL required),❌ Poor - requires alternative 2D view or data table.,"Three.js, Deck.gl, Plotly 3D",Rotate + Zoom + VR
24
- 23,Real-Time Streaming,"streaming, real-time, ticker, live, velocity, pulse",Streaming Area Chart,"Ticker Tape, Moving Gauge",Current: Bright Pulse (#00FF00). History: Fading opacity. Grid: Dark.,⚡ Optimized (canvas/webgl),⚠ Flashing elements - provide pause button. High contrast.,Smoothed D3.js, CanvasJS, SciChart,Real-time + Pause
25
- 24,Sentiment/Emotion,"sentiment, emotion, nlp, opinion, feeling",Word Cloud with Sentiment,"Sentiment Arc, Radar Chart",Positive: #22C55E. Negative: #EF4444. Neutral: #94A3B8. Size = Frequency.,⚡ Good,⚠ Word clouds poor for screen readers. Use list view.,"D3-cloud, Highcharts, Nivo",Hover + Filter
26
- 25,Process Mining,"process, mining, variants, path, bottleneck, log",Process Map / Graph,"Directed Acyclic Graph (DAG), Petri Net",Happy path: #10B981 (Thick). Deviations: #F59E0B (Thin). Bottlenecks: #EF4444.,⚠ Moderate to Heavy,⚠ Complex graphs hard to navigate. Provide path summary.,"React-Flow, Cytoscape.js, Recharts",Drag + Node-Click