@qazuor/claude-code-config 0.5.0 → 0.6.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/README.md +106 -41
- package/dist/bin.cjs +963 -84
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +963 -84
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +73 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +73 -56
- package/dist/index.js.map +1 -1
- package/package.json +23 -24
- package/templates/CLAUDE.md.template +60 -5
- package/templates/agents/README.md +58 -39
- package/templates/agents/_registry.json +43 -202
- package/templates/agents/engineering/{hono-engineer.md → api-engineer.md} +61 -70
- package/templates/agents/engineering/database-engineer.md +253 -0
- package/templates/agents/engineering/frontend-engineer.md +302 -0
- package/templates/hooks/on-notification.sh +0 -0
- package/templates/scripts/add-changelogs.sh +0 -0
- package/templates/scripts/generate-code-registry.ts +0 -0
- package/templates/scripts/health-check.sh +0 -0
- package/templates/scripts/sync-registry.sh +0 -0
- package/templates/scripts/telemetry-report.ts +0 -0
- package/templates/scripts/validate-docs.sh +0 -0
- package/templates/scripts/validate-registry.sh +0 -0
- package/templates/scripts/validate-structure.sh +0 -0
- package/templates/scripts/worktree-cleanup.sh +0 -0
- package/templates/scripts/worktree-create.sh +0 -0
- package/templates/skills/README.md +99 -90
- package/templates/skills/_registry.json +323 -16
- package/templates/skills/api-frameworks/express-patterns.md +411 -0
- package/templates/skills/api-frameworks/fastify-patterns.md +419 -0
- package/templates/skills/api-frameworks/hono-patterns.md +388 -0
- package/templates/skills/api-frameworks/nestjs-patterns.md +497 -0
- package/templates/skills/database/drizzle-patterns.md +449 -0
- package/templates/skills/database/mongoose-patterns.md +503 -0
- package/templates/skills/database/prisma-patterns.md +487 -0
- package/templates/skills/frontend-frameworks/astro-patterns.md +415 -0
- package/templates/skills/frontend-frameworks/nextjs-patterns.md +470 -0
- package/templates/skills/frontend-frameworks/react-patterns.md +516 -0
- package/templates/skills/frontend-frameworks/tanstack-start-patterns.md +469 -0
- package/templates/skills/patterns/atdd-methodology.md +364 -0
- package/templates/skills/patterns/bdd-methodology.md +281 -0
- package/templates/skills/patterns/clean-architecture.md +444 -0
- package/templates/skills/patterns/hexagonal-architecture.md +567 -0
- package/templates/skills/patterns/vertical-slice-architecture.md +502 -0
- package/templates/agents/engineering/astro-engineer.md +0 -293
- package/templates/agents/engineering/db-drizzle-engineer.md +0 -360
- package/templates/agents/engineering/express-engineer.md +0 -316
- package/templates/agents/engineering/fastify-engineer.md +0 -399
- package/templates/agents/engineering/mongoose-engineer.md +0 -473
- package/templates/agents/engineering/nestjs-engineer.md +0 -429
- package/templates/agents/engineering/nextjs-engineer.md +0 -451
- package/templates/agents/engineering/prisma-engineer.md +0 -432
- package/templates/agents/engineering/react-senior-dev.md +0 -394
- package/templates/agents/engineering/tanstack-start-engineer.md +0 -447
package/dist/bin.js
CHANGED
|
@@ -251,15 +251,10 @@ var BUNDLES = [
|
|
|
251
251
|
moduleDetails: {
|
|
252
252
|
agents: [
|
|
253
253
|
{
|
|
254
|
-
id: "
|
|
255
|
-
role: "
|
|
254
|
+
id: "frontend-engineer",
|
|
255
|
+
role: "Frontend Development",
|
|
256
256
|
responsibilities: ["Component design", "State management", "Performance optimization"]
|
|
257
257
|
},
|
|
258
|
-
{
|
|
259
|
-
id: "tanstack-start-engineer",
|
|
260
|
-
role: "TanStack Specialist",
|
|
261
|
-
responsibilities: ["Router setup", "Query patterns", "SSR configuration"]
|
|
262
|
-
},
|
|
263
258
|
{
|
|
264
259
|
id: "ux-ui-designer",
|
|
265
260
|
role: "UI/UX Design",
|
|
@@ -267,6 +262,8 @@ var BUNDLES = [
|
|
|
267
262
|
}
|
|
268
263
|
],
|
|
269
264
|
skills: [
|
|
265
|
+
{ id: "react-patterns", purpose: "React component patterns" },
|
|
266
|
+
{ id: "tanstack-start-patterns", purpose: "TanStack Router/Start patterns" },
|
|
270
267
|
{ id: "web-app-testing", purpose: "React Testing Library patterns" },
|
|
271
268
|
{ id: "shadcn-specialist", purpose: "Shadcn UI component usage" },
|
|
272
269
|
{ id: "accessibility-audit", purpose: "WCAG compliance" },
|
|
@@ -278,9 +275,10 @@ var BUNDLES = [
|
|
|
278
275
|
docs: [{ id: "design-standards", topic: "UI/UX design standards" }]
|
|
279
276
|
},
|
|
280
277
|
modules: [
|
|
281
|
-
{ id: "
|
|
282
|
-
{ id: "tanstack-start-engineer", category: "agents" },
|
|
278
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
283
279
|
{ id: "ux-ui-designer", category: "agents" },
|
|
280
|
+
{ id: "react-patterns", category: "skills" },
|
|
281
|
+
{ id: "tanstack-start-patterns", category: "skills" },
|
|
284
282
|
{ id: "web-app-testing", category: "skills" },
|
|
285
283
|
{ id: "shadcn-specialist", category: "skills" },
|
|
286
284
|
{ id: "accessibility-audit", category: "skills" },
|
|
@@ -316,15 +314,10 @@ var BUNDLES = [
|
|
|
316
314
|
moduleDetails: {
|
|
317
315
|
agents: [
|
|
318
316
|
{
|
|
319
|
-
id: "
|
|
320
|
-
role: "
|
|
317
|
+
id: "frontend-engineer",
|
|
318
|
+
role: "Frontend Development",
|
|
321
319
|
responsibilities: ["Routing", "Islands architecture", "Build optimization"]
|
|
322
320
|
},
|
|
323
|
-
{
|
|
324
|
-
id: "react-senior-dev",
|
|
325
|
-
role: "React Components",
|
|
326
|
-
responsibilities: ["Interactive components", "Client hydration"]
|
|
327
|
-
},
|
|
328
321
|
{
|
|
329
322
|
id: "seo-ai-specialist",
|
|
330
323
|
role: "SEO Optimization",
|
|
@@ -332,6 +325,8 @@ var BUNDLES = [
|
|
|
332
325
|
}
|
|
333
326
|
],
|
|
334
327
|
skills: [
|
|
328
|
+
{ id: "astro-patterns", purpose: "Astro-specific patterns" },
|
|
329
|
+
{ id: "react-patterns", purpose: "React island components" },
|
|
335
330
|
{ id: "web-app-testing", purpose: "Component testing" },
|
|
336
331
|
{ id: "vercel-specialist", purpose: "Deployment optimization" },
|
|
337
332
|
{ id: "performance-audit", purpose: "Core Web Vitals" }
|
|
@@ -340,9 +335,10 @@ var BUNDLES = [
|
|
|
340
335
|
docs: []
|
|
341
336
|
},
|
|
342
337
|
modules: [
|
|
343
|
-
{ id: "
|
|
344
|
-
{ id: "react-senior-dev", category: "agents" },
|
|
338
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
345
339
|
{ id: "seo-ai-specialist", category: "agents" },
|
|
340
|
+
{ id: "astro-patterns", category: "skills" },
|
|
341
|
+
{ id: "react-patterns", category: "skills" },
|
|
346
342
|
{ id: "web-app-testing", category: "skills" },
|
|
347
343
|
{ id: "vercel-specialist", category: "skills" },
|
|
348
344
|
{ id: "performance-audit", category: "skills" }
|
|
@@ -375,17 +371,12 @@ var BUNDLES = [
|
|
|
375
371
|
moduleDetails: {
|
|
376
372
|
agents: [
|
|
377
373
|
{
|
|
378
|
-
id: "
|
|
379
|
-
role: "
|
|
380
|
-
responsibilities: ["App Router", "Server Actions", "
|
|
381
|
-
},
|
|
382
|
-
{
|
|
383
|
-
id: "react-senior-dev",
|
|
384
|
-
role: "React Components",
|
|
385
|
-
responsibilities: ["Client components", "State management"]
|
|
374
|
+
id: "frontend-engineer",
|
|
375
|
+
role: "Frontend Development",
|
|
376
|
+
responsibilities: ["App Router", "Server Actions", "Client components"]
|
|
386
377
|
},
|
|
387
378
|
{
|
|
388
|
-
id: "
|
|
379
|
+
id: "database-engineer",
|
|
389
380
|
role: "Database",
|
|
390
381
|
responsibilities: ["Schema design", "Migrations", "Query optimization"]
|
|
391
382
|
},
|
|
@@ -396,6 +387,9 @@ var BUNDLES = [
|
|
|
396
387
|
}
|
|
397
388
|
],
|
|
398
389
|
skills: [
|
|
390
|
+
{ id: "nextjs-patterns", purpose: "Next.js App Router patterns" },
|
|
391
|
+
{ id: "react-patterns", purpose: "React component patterns" },
|
|
392
|
+
{ id: "prisma-patterns", purpose: "Prisma ORM patterns" },
|
|
399
393
|
{ id: "web-app-testing", purpose: "Next.js testing patterns" },
|
|
400
394
|
{ id: "shadcn-specialist", purpose: "UI components" },
|
|
401
395
|
{ id: "vercel-specialist", purpose: "Deployment" },
|
|
@@ -407,10 +401,12 @@ var BUNDLES = [
|
|
|
407
401
|
docs: []
|
|
408
402
|
},
|
|
409
403
|
modules: [
|
|
410
|
-
{ id: "
|
|
411
|
-
{ id: "
|
|
412
|
-
{ id: "prisma-engineer", category: "agents" },
|
|
404
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
405
|
+
{ id: "database-engineer", category: "agents" },
|
|
413
406
|
{ id: "ux-ui-designer", category: "agents" },
|
|
407
|
+
{ id: "nextjs-patterns", category: "skills" },
|
|
408
|
+
{ id: "react-patterns", category: "skills" },
|
|
409
|
+
{ id: "prisma-patterns", category: "skills" },
|
|
414
410
|
{ id: "web-app-testing", category: "skills" },
|
|
415
411
|
{ id: "shadcn-specialist", category: "skills" },
|
|
416
412
|
{ id: "vercel-specialist", category: "skills" },
|
|
@@ -446,12 +442,12 @@ var BUNDLES = [
|
|
|
446
442
|
moduleDetails: {
|
|
447
443
|
agents: [
|
|
448
444
|
{
|
|
449
|
-
id: "
|
|
450
|
-
role: "
|
|
445
|
+
id: "api-engineer",
|
|
446
|
+
role: "API Development",
|
|
451
447
|
responsibilities: ["Route design", "Middleware", "Error handling"]
|
|
452
448
|
},
|
|
453
449
|
{
|
|
454
|
-
id: "
|
|
450
|
+
id: "database-engineer",
|
|
455
451
|
role: "Database",
|
|
456
452
|
responsibilities: ["Schema", "Migrations", "Queries"]
|
|
457
453
|
},
|
|
@@ -462,6 +458,8 @@ var BUNDLES = [
|
|
|
462
458
|
}
|
|
463
459
|
],
|
|
464
460
|
skills: [
|
|
461
|
+
{ id: "express-patterns", purpose: "Express.js patterns" },
|
|
462
|
+
{ id: "prisma-patterns", purpose: "Prisma ORM patterns" },
|
|
465
463
|
{ id: "api-app-testing", purpose: "API testing with supertest" },
|
|
466
464
|
{ id: "error-handling-patterns", purpose: "Error middleware" },
|
|
467
465
|
{ id: "security-testing", purpose: "Security best practices" }
|
|
@@ -470,9 +468,11 @@ var BUNDLES = [
|
|
|
470
468
|
docs: [{ id: "architecture-patterns", topic: "API architecture patterns" }]
|
|
471
469
|
},
|
|
472
470
|
modules: [
|
|
473
|
-
{ id: "
|
|
474
|
-
{ id: "
|
|
471
|
+
{ id: "api-engineer", category: "agents" },
|
|
472
|
+
{ id: "database-engineer", category: "agents" },
|
|
475
473
|
{ id: "node-typescript-engineer", category: "agents" },
|
|
474
|
+
{ id: "express-patterns", category: "skills" },
|
|
475
|
+
{ id: "prisma-patterns", category: "skills" },
|
|
476
476
|
{ id: "api-app-testing", category: "skills" },
|
|
477
477
|
{ id: "error-handling-patterns", category: "skills" },
|
|
478
478
|
{ id: "security-testing", category: "skills" },
|
|
@@ -506,13 +506,13 @@ var BUNDLES = [
|
|
|
506
506
|
moduleDetails: {
|
|
507
507
|
agents: [
|
|
508
508
|
{
|
|
509
|
-
id: "
|
|
510
|
-
role: "
|
|
509
|
+
id: "api-engineer",
|
|
510
|
+
role: "API Development",
|
|
511
511
|
responsibilities: ["Route handlers", "Middleware", "OpenAPI integration"]
|
|
512
512
|
},
|
|
513
513
|
{
|
|
514
|
-
id: "
|
|
515
|
-
role: "
|
|
514
|
+
id: "database-engineer",
|
|
515
|
+
role: "Database",
|
|
516
516
|
responsibilities: ["Schema design", "Migrations", "Type-safe queries"]
|
|
517
517
|
},
|
|
518
518
|
{
|
|
@@ -522,6 +522,8 @@ var BUNDLES = [
|
|
|
522
522
|
}
|
|
523
523
|
],
|
|
524
524
|
skills: [
|
|
525
|
+
{ id: "hono-patterns", purpose: "Hono framework patterns" },
|
|
526
|
+
{ id: "drizzle-patterns", purpose: "Drizzle ORM patterns" },
|
|
525
527
|
{ id: "api-app-testing", purpose: "Hono testing patterns" },
|
|
526
528
|
{ id: "error-handling-patterns", purpose: "Error middleware" },
|
|
527
529
|
{ id: "security-testing", purpose: "Security validation" }
|
|
@@ -530,9 +532,11 @@ var BUNDLES = [
|
|
|
530
532
|
docs: [{ id: "architecture-patterns", topic: "API architecture patterns" }]
|
|
531
533
|
},
|
|
532
534
|
modules: [
|
|
533
|
-
{ id: "
|
|
534
|
-
{ id: "
|
|
535
|
+
{ id: "api-engineer", category: "agents" },
|
|
536
|
+
{ id: "database-engineer", category: "agents" },
|
|
535
537
|
{ id: "node-typescript-engineer", category: "agents" },
|
|
538
|
+
{ id: "hono-patterns", category: "skills" },
|
|
539
|
+
{ id: "drizzle-patterns", category: "skills" },
|
|
536
540
|
{ id: "api-app-testing", category: "skills" },
|
|
537
541
|
{ id: "error-handling-patterns", category: "skills" },
|
|
538
542
|
{ id: "security-testing", category: "skills" },
|
|
@@ -763,7 +767,8 @@ var BUNDLES = [
|
|
|
763
767
|
tags: ["database", "drizzle", "orm"],
|
|
764
768
|
alternativeTo: ["prisma-database", "mongoose-database"],
|
|
765
769
|
modules: [
|
|
766
|
-
{ id: "
|
|
770
|
+
{ id: "database-engineer", category: "agents" },
|
|
771
|
+
{ id: "drizzle-patterns", category: "skills" },
|
|
767
772
|
{ id: "json-data-auditor", category: "skills" }
|
|
768
773
|
]
|
|
769
774
|
},
|
|
@@ -777,7 +782,8 @@ var BUNDLES = [
|
|
|
777
782
|
tags: ["database", "prisma", "orm"],
|
|
778
783
|
alternativeTo: ["drizzle-database", "mongoose-database"],
|
|
779
784
|
modules: [
|
|
780
|
-
{ id: "
|
|
785
|
+
{ id: "database-engineer", category: "agents" },
|
|
786
|
+
{ id: "prisma-patterns", category: "skills" },
|
|
781
787
|
{ id: "json-data-auditor", category: "skills" }
|
|
782
788
|
]
|
|
783
789
|
},
|
|
@@ -791,7 +797,8 @@ var BUNDLES = [
|
|
|
791
797
|
tags: ["database", "mongodb", "mongoose", "nosql"],
|
|
792
798
|
alternativeTo: ["drizzle-database", "prisma-database"],
|
|
793
799
|
modules: [
|
|
794
|
-
{ id: "
|
|
800
|
+
{ id: "database-engineer", category: "agents" },
|
|
801
|
+
{ id: "mongoose-patterns", category: "skills" },
|
|
795
802
|
{ id: "json-data-auditor", category: "skills" }
|
|
796
803
|
]
|
|
797
804
|
},
|
|
@@ -808,7 +815,8 @@ var BUNDLES = [
|
|
|
808
815
|
tags: ["api", "hono", "backend"],
|
|
809
816
|
alternativeTo: ["express-api", "fastify-api", "nestjs-api"],
|
|
810
817
|
modules: [
|
|
811
|
-
{ id: "
|
|
818
|
+
{ id: "api-engineer", category: "agents" },
|
|
819
|
+
{ id: "hono-patterns", category: "skills" },
|
|
812
820
|
{ id: "api-app-testing", category: "skills" },
|
|
813
821
|
{ id: "error-handling-patterns", category: "skills" }
|
|
814
822
|
]
|
|
@@ -823,7 +831,8 @@ var BUNDLES = [
|
|
|
823
831
|
tags: ["api", "express", "backend"],
|
|
824
832
|
alternativeTo: ["hono-api", "fastify-api", "nestjs-api"],
|
|
825
833
|
modules: [
|
|
826
|
-
{ id: "
|
|
834
|
+
{ id: "api-engineer", category: "agents" },
|
|
835
|
+
{ id: "express-patterns", category: "skills" },
|
|
827
836
|
{ id: "api-app-testing", category: "skills" },
|
|
828
837
|
{ id: "error-handling-patterns", category: "skills" }
|
|
829
838
|
]
|
|
@@ -838,7 +847,8 @@ var BUNDLES = [
|
|
|
838
847
|
tags: ["api", "fastify", "backend", "performance"],
|
|
839
848
|
alternativeTo: ["hono-api", "express-api", "nestjs-api"],
|
|
840
849
|
modules: [
|
|
841
|
-
{ id: "
|
|
850
|
+
{ id: "api-engineer", category: "agents" },
|
|
851
|
+
{ id: "fastify-patterns", category: "skills" },
|
|
842
852
|
{ id: "api-app-testing", category: "skills" },
|
|
843
853
|
{ id: "error-handling-patterns", category: "skills" }
|
|
844
854
|
]
|
|
@@ -853,7 +863,8 @@ var BUNDLES = [
|
|
|
853
863
|
tags: ["api", "nestjs", "backend", "enterprise"],
|
|
854
864
|
alternativeTo: ["hono-api", "express-api", "fastify-api"],
|
|
855
865
|
modules: [
|
|
856
|
-
{ id: "
|
|
866
|
+
{ id: "api-engineer", category: "agents" },
|
|
867
|
+
{ id: "nestjs-patterns", category: "skills" },
|
|
857
868
|
{ id: "api-app-testing", category: "skills" },
|
|
858
869
|
{ id: "error-handling-patterns", category: "skills" }
|
|
859
870
|
]
|
|
@@ -870,8 +881,9 @@ var BUNDLES = [
|
|
|
870
881
|
techStack: ["React", "Shadcn UI", "Tailwind CSS", "Radix UI"],
|
|
871
882
|
tags: ["react", "ui", "components"],
|
|
872
883
|
modules: [
|
|
873
|
-
{ id: "
|
|
884
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
874
885
|
{ id: "ux-ui-designer", category: "agents" },
|
|
886
|
+
{ id: "react-patterns", category: "skills" },
|
|
875
887
|
{ id: "shadcn-specialist", category: "skills" },
|
|
876
888
|
{ id: "brand-guidelines", category: "skills" },
|
|
877
889
|
{ id: "accessibility-audit", category: "skills" }
|
|
@@ -886,7 +898,8 @@ var BUNDLES = [
|
|
|
886
898
|
techStack: ["React Hook Form", "Zod", "React", "TypeScript"],
|
|
887
899
|
tags: ["react", "forms", "validation"],
|
|
888
900
|
modules: [
|
|
889
|
-
{ id: "
|
|
901
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
902
|
+
{ id: "react-patterns", category: "skills" },
|
|
890
903
|
{ id: "react-hook-form-patterns", category: "skills" },
|
|
891
904
|
{ id: "shadcn-specialist", category: "skills" }
|
|
892
905
|
]
|
|
@@ -901,7 +914,8 @@ var BUNDLES = [
|
|
|
901
914
|
tags: ["react", "state", "zustand"],
|
|
902
915
|
alternativeTo: ["react-state-redux"],
|
|
903
916
|
modules: [
|
|
904
|
-
{ id: "
|
|
917
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
918
|
+
{ id: "react-patterns", category: "skills" },
|
|
905
919
|
{ id: "zustand-patterns", category: "skills" },
|
|
906
920
|
{ id: "tanstack-query-patterns", category: "skills" }
|
|
907
921
|
]
|
|
@@ -916,7 +930,8 @@ var BUNDLES = [
|
|
|
916
930
|
tags: ["react", "state", "redux"],
|
|
917
931
|
alternativeTo: ["react-state-zustand"],
|
|
918
932
|
modules: [
|
|
919
|
-
{ id: "
|
|
933
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
934
|
+
{ id: "react-patterns", category: "skills" },
|
|
920
935
|
{ id: "redux-toolkit-patterns", category: "skills" },
|
|
921
936
|
{ id: "tanstack-query-patterns", category: "skills", optional: true }
|
|
922
937
|
]
|
|
@@ -930,7 +945,8 @@ var BUNDLES = [
|
|
|
930
945
|
techStack: ["NextAuth.js", "Auth.js", "Next.js", "Prisma"],
|
|
931
946
|
tags: ["nextjs", "auth", "oauth"],
|
|
932
947
|
modules: [
|
|
933
|
-
{ id: "
|
|
948
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
949
|
+
{ id: "nextjs-patterns", category: "skills" },
|
|
934
950
|
{ id: "nextauth-patterns", category: "skills" },
|
|
935
951
|
{ id: "security-testing", category: "skills" }
|
|
936
952
|
]
|
|
@@ -944,8 +960,9 @@ var BUNDLES = [
|
|
|
944
960
|
techStack: ["next-intl", "Next.js", "React", "TypeScript"],
|
|
945
961
|
tags: ["nextjs", "i18n", "internationalization"],
|
|
946
962
|
modules: [
|
|
947
|
-
{ id: "
|
|
963
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
948
964
|
{ id: "i18n-specialist", category: "agents", optional: true },
|
|
965
|
+
{ id: "nextjs-patterns", category: "skills" },
|
|
949
966
|
{ id: "i18n-patterns", category: "skills" }
|
|
950
967
|
]
|
|
951
968
|
},
|
|
@@ -1065,7 +1082,7 @@ var BUNDLES = [
|
|
|
1065
1082
|
}
|
|
1066
1083
|
],
|
|
1067
1084
|
skills: [
|
|
1068
|
-
{ id: "
|
|
1085
|
+
{ id: "markdown-formatter", purpose: "Markdown formatting" },
|
|
1069
1086
|
{ id: "mermaid-diagram-specialist", purpose: "Diagram creation" }
|
|
1070
1087
|
],
|
|
1071
1088
|
commands: [
|
|
@@ -1080,7 +1097,7 @@ var BUNDLES = [
|
|
|
1080
1097
|
},
|
|
1081
1098
|
modules: [
|
|
1082
1099
|
{ id: "tech-writer", category: "agents" },
|
|
1083
|
-
{ id: "
|
|
1100
|
+
{ id: "markdown-formatter", category: "skills" },
|
|
1084
1101
|
{ id: "mermaid-diagram-specialist", category: "skills" },
|
|
1085
1102
|
{ id: "update-docs", category: "commands" },
|
|
1086
1103
|
{ id: "markdown-format", category: "commands" },
|
|
@@ -6101,11 +6118,13 @@ function processTemplate(template, projectInfo, options) {
|
|
|
6101
6118
|
const commands = options?.templateConfig?.commands;
|
|
6102
6119
|
const targets = options?.templateConfig?.targets;
|
|
6103
6120
|
const preferences = options?.claudeConfig?.preferences;
|
|
6121
|
+
const standards = options?.claudeConfig?.extras?.standards;
|
|
6104
6122
|
content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectInfo.name).replace(/\{\{PROJECT_DESCRIPTION\}\}/g, projectInfo.description).replace(/\{\{ORG\}\}/g, projectInfo.org).replace(/\{\{REPO\}\}/g, projectInfo.repo).replace(/\{\{ENTITY_TYPE\}\}/g, projectInfo.entityType).replace(/\{\{ENTITY_TYPE_PLURAL\}\}/g, projectInfo.entityTypePlural).replace(/\{\{LOCATION\}\}/g, projectInfo.location || "");
|
|
6105
6123
|
const packageManager = preferences?.packageManager || "pnpm";
|
|
6106
6124
|
content = content.replace(/\{\{PACKAGE_MANAGER\}\}/g, packageManager);
|
|
6107
|
-
const coverageTarget = targets && "coverage" in targets ? String(targets.coverage) : "90";
|
|
6125
|
+
const coverageTarget = standards?.testing?.coverageTarget ? String(standards.testing.coverageTarget) : targets && "coverage" in targets ? String(targets.coverage) : "90";
|
|
6108
6126
|
content = content.replace(/\{\{COVERAGE_TARGET\}\}/g, coverageTarget);
|
|
6127
|
+
content = processStandardsPlaceholders(content, standards, preferences);
|
|
6109
6128
|
if (projectInfo.domain) {
|
|
6110
6129
|
content = content.replace(/\{\{#if DOMAIN\}\}/g, "").replace(/\{\{\/if\}\}/g, "").replace(/\{\{DOMAIN\}\}/g, projectInfo.domain);
|
|
6111
6130
|
} else {
|
|
@@ -6202,6 +6221,55 @@ function generateCommandsSection(commands, packageManager) {
|
|
|
6202
6221
|
lines.push("```");
|
|
6203
6222
|
return lines.join("\n");
|
|
6204
6223
|
}
|
|
6224
|
+
function processStandardsPlaceholders(content, standards, preferences) {
|
|
6225
|
+
let result = content;
|
|
6226
|
+
const primaryLanguage = "TypeScript";
|
|
6227
|
+
result = result.replace(/\{\{PRIMARY_LANGUAGE\}\}/g, primaryLanguage);
|
|
6228
|
+
const maxFileLines = standards?.code?.maxFileLines?.toString() || "500";
|
|
6229
|
+
result = result.replace(/\{\{MAX_FILE_LINES\}\}/g, maxFileLines);
|
|
6230
|
+
const testPattern = standards?.testing?.testPattern === "gwt" ? "GWT (Given-When-Then)" : "AAA (Arrange, Act, Assert)";
|
|
6231
|
+
result = result.replace(/\{\{TEST_PATTERN\}\}/g, testPattern);
|
|
6232
|
+
const responseLanguage = preferences?.responseLanguage === "es" ? "Spanish" : preferences?.responseLanguage === "en" ? "English" : "Spanish";
|
|
6233
|
+
result = result.replace(/\{\{RESPONSE_LANGUAGE\}\}/g, responseLanguage);
|
|
6234
|
+
if (standards?.code?.namedExportsOnly) {
|
|
6235
|
+
result = result.replace(/\{\{#if NAMED_EXPORTS_ONLY\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6236
|
+
} else {
|
|
6237
|
+
result = result.replace(/\{\{#if NAMED_EXPORTS_ONLY\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6238
|
+
}
|
|
6239
|
+
if (standards?.code?.jsDocRequired) {
|
|
6240
|
+
result = result.replace(/\{\{#if JSDOC_REQUIRED\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6241
|
+
} else {
|
|
6242
|
+
result = result.replace(/\{\{#if JSDOC_REQUIRED\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6243
|
+
}
|
|
6244
|
+
if (standards?.code?.roroPattern) {
|
|
6245
|
+
result = result.replace(/\{\{#if RORO_PATTERN\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6246
|
+
} else {
|
|
6247
|
+
result = result.replace(/\{\{#if RORO_PATTERN\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6248
|
+
}
|
|
6249
|
+
if (standards?.testing?.tddRequired) {
|
|
6250
|
+
result = result.replace(/\{\{#if TDD_REQUIRED\}\}/g, "").replace(/\{\{else\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6251
|
+
} else {
|
|
6252
|
+
result = result.replace(/\{\{#if TDD_REQUIRED\}\}[\s\S]*?\{\{else\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6253
|
+
}
|
|
6254
|
+
const testLocation = standards?.testing?.testLocation;
|
|
6255
|
+
if (testLocation) {
|
|
6256
|
+
const testLocationText = testLocation === "colocated" ? "Co-located with source" : "Separate test directory";
|
|
6257
|
+
result = result.replace(/\{\{#if TEST_LOCATION\}\}/g, "").replace(/\{\{\/if\}\}/g, "").replace(/\{\{TEST_LOCATION\}\}/g, testLocationText);
|
|
6258
|
+
} else {
|
|
6259
|
+
result = result.replace(/\{\{#if TEST_LOCATION\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6260
|
+
}
|
|
6261
|
+
if (preferences?.includeCoAuthor) {
|
|
6262
|
+
result = result.replace(/\{\{#if INCLUDE_CO_AUTHOR\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6263
|
+
} else {
|
|
6264
|
+
result = result.replace(/\{\{#if INCLUDE_CO_AUTHOR\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6265
|
+
}
|
|
6266
|
+
if (preferences?.responseLanguage) {
|
|
6267
|
+
result = result.replace(/\{\{#if RESPONSE_LANGUAGE\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6268
|
+
} else {
|
|
6269
|
+
result = result.replace(/\{\{#if RESPONSE_LANGUAGE\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6270
|
+
}
|
|
6271
|
+
return result;
|
|
6272
|
+
}
|
|
6205
6273
|
function getMinimalTemplate() {
|
|
6206
6274
|
return `# CLAUDE.md
|
|
6207
6275
|
|
|
@@ -6747,6 +6815,242 @@ async function generateScaffoldWithProgress(projectPath, options) {
|
|
|
6747
6815
|
);
|
|
6748
6816
|
}
|
|
6749
6817
|
|
|
6818
|
+
// src/lib/scaffold/settings-generator.ts
|
|
6819
|
+
init_esm_shims();
|
|
6820
|
+
|
|
6821
|
+
// src/constants/claude-settings-defaults.ts
|
|
6822
|
+
init_esm_shims();
|
|
6823
|
+
var DEFAULT_CLAUDE_SETTINGS = {
|
|
6824
|
+
model: "sonnet",
|
|
6825
|
+
alwaysThinkingEnabled: false,
|
|
6826
|
+
sandbox: {
|
|
6827
|
+
enabled: false,
|
|
6828
|
+
autoAllowBashIfSandboxed: true
|
|
6829
|
+
},
|
|
6830
|
+
permissions: {
|
|
6831
|
+
allow: [],
|
|
6832
|
+
deny: [],
|
|
6833
|
+
ask: [],
|
|
6834
|
+
defaultMode: "acceptEdits"
|
|
6835
|
+
},
|
|
6836
|
+
attribution: {
|
|
6837
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)\n\n Co-Authored-By: Claude <noreply@anthropic.com>",
|
|
6838
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
6839
|
+
},
|
|
6840
|
+
cleanupPeriodDays: 30,
|
|
6841
|
+
stopNotification: "beep"
|
|
6842
|
+
};
|
|
6843
|
+
var ATTRIBUTION_NO_COAUTHOR = {
|
|
6844
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)",
|
|
6845
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
6846
|
+
};
|
|
6847
|
+
var ATTRIBUTION_WITH_COAUTHOR = {
|
|
6848
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)\n\n Co-Authored-By: Claude <noreply@anthropic.com>",
|
|
6849
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
6850
|
+
};
|
|
6851
|
+
var BEEP_COMMAND = "echo -ne '\\007'";
|
|
6852
|
+
var MODEL_DESCRIPTIONS = {
|
|
6853
|
+
sonnet: "Claude Sonnet - Balanced performance and speed (recommended)",
|
|
6854
|
+
opus: "Claude Opus - Most capable, best for complex tasks",
|
|
6855
|
+
haiku: "Claude Haiku - Fastest, best for simple tasks",
|
|
6856
|
+
default: "Default - Let Claude Code decide based on task"
|
|
6857
|
+
};
|
|
6858
|
+
var PERMISSION_MODE_DESCRIPTIONS = {
|
|
6859
|
+
acceptEdits: "Accept edits automatically, ask for other operations",
|
|
6860
|
+
askAlways: "Ask for confirmation on all operations",
|
|
6861
|
+
viewOnly: "Read-only mode, no modifications allowed"
|
|
6862
|
+
};
|
|
6863
|
+
var STOP_NOTIFICATION_DESCRIPTIONS = {
|
|
6864
|
+
beep: "Play a beep sound when task completes",
|
|
6865
|
+
custom: "Run a custom command when task completes",
|
|
6866
|
+
none: "No notification"
|
|
6867
|
+
};
|
|
6868
|
+
var CLAUDE_SETTINGS_PRESETS = {
|
|
6869
|
+
/** Default preset - balanced settings */
|
|
6870
|
+
default: {
|
|
6871
|
+
...DEFAULT_CLAUDE_SETTINGS
|
|
6872
|
+
},
|
|
6873
|
+
/** Performance preset - faster model, less confirmations */
|
|
6874
|
+
performance: {
|
|
6875
|
+
...DEFAULT_CLAUDE_SETTINGS,
|
|
6876
|
+
model: "haiku",
|
|
6877
|
+
permissions: {
|
|
6878
|
+
...DEFAULT_CLAUDE_SETTINGS.permissions,
|
|
6879
|
+
defaultMode: "acceptEdits"
|
|
6880
|
+
}
|
|
6881
|
+
},
|
|
6882
|
+
/** Quality preset - best model, extended thinking */
|
|
6883
|
+
quality: {
|
|
6884
|
+
...DEFAULT_CLAUDE_SETTINGS,
|
|
6885
|
+
model: "opus",
|
|
6886
|
+
alwaysThinkingEnabled: true
|
|
6887
|
+
},
|
|
6888
|
+
/** Secure preset - sandbox enabled, more confirmations */
|
|
6889
|
+
secure: {
|
|
6890
|
+
...DEFAULT_CLAUDE_SETTINGS,
|
|
6891
|
+
sandbox: {
|
|
6892
|
+
enabled: true,
|
|
6893
|
+
autoAllowBashIfSandboxed: true
|
|
6894
|
+
},
|
|
6895
|
+
permissions: {
|
|
6896
|
+
...DEFAULT_CLAUDE_SETTINGS.permissions,
|
|
6897
|
+
defaultMode: "askAlways"
|
|
6898
|
+
}
|
|
6899
|
+
}
|
|
6900
|
+
};
|
|
6901
|
+
var PRESET_DESCRIPTIONS2 = {
|
|
6902
|
+
default: "Balanced settings for most projects",
|
|
6903
|
+
performance: "Faster responses with Haiku model",
|
|
6904
|
+
quality: "Best quality with Opus model and extended thinking",
|
|
6905
|
+
secure: "Enhanced security with sandbox and confirmations"
|
|
6906
|
+
};
|
|
6907
|
+
|
|
6908
|
+
// src/lib/scaffold/settings-generator.ts
|
|
6909
|
+
init_fs();
|
|
6910
|
+
async function generateSettings(projectPath, options) {
|
|
6911
|
+
const settingsPath = joinPath(projectPath, ".claude", "settings.json");
|
|
6912
|
+
const exists = await pathExists(settingsPath);
|
|
6913
|
+
if (exists && !options?.overwrite) {
|
|
6914
|
+
return {
|
|
6915
|
+
created: false,
|
|
6916
|
+
skipped: true,
|
|
6917
|
+
path: settingsPath
|
|
6918
|
+
};
|
|
6919
|
+
}
|
|
6920
|
+
try {
|
|
6921
|
+
const settings = buildSettingsJson(options);
|
|
6922
|
+
await writeJson(settingsPath, settings, { spaces: 2 });
|
|
6923
|
+
return {
|
|
6924
|
+
created: true,
|
|
6925
|
+
skipped: false,
|
|
6926
|
+
path: settingsPath
|
|
6927
|
+
};
|
|
6928
|
+
} catch (error) {
|
|
6929
|
+
return {
|
|
6930
|
+
created: false,
|
|
6931
|
+
skipped: false,
|
|
6932
|
+
path: settingsPath,
|
|
6933
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6934
|
+
};
|
|
6935
|
+
}
|
|
6936
|
+
}
|
|
6937
|
+
async function generateSettingsWithSpinner(projectPath, options) {
|
|
6938
|
+
return withSpinner("Generating settings.json...", () => generateSettings(projectPath, options), {
|
|
6939
|
+
successText: "Created settings.json"
|
|
6940
|
+
});
|
|
6941
|
+
}
|
|
6942
|
+
async function generateSettingsLocal(projectPath, options) {
|
|
6943
|
+
const settingsPath = joinPath(projectPath, ".claude", "settings.local.json");
|
|
6944
|
+
const exists = await pathExists(settingsPath);
|
|
6945
|
+
if (exists && !options?.overwrite) {
|
|
6946
|
+
return {
|
|
6947
|
+
created: false,
|
|
6948
|
+
skipped: true,
|
|
6949
|
+
path: settingsPath
|
|
6950
|
+
};
|
|
6951
|
+
}
|
|
6952
|
+
try {
|
|
6953
|
+
const settings = buildSettingsLocalJson(options);
|
|
6954
|
+
await writeJson(settingsPath, settings, { spaces: 2 });
|
|
6955
|
+
return {
|
|
6956
|
+
created: true,
|
|
6957
|
+
skipped: false,
|
|
6958
|
+
path: settingsPath
|
|
6959
|
+
};
|
|
6960
|
+
} catch (error) {
|
|
6961
|
+
return {
|
|
6962
|
+
created: false,
|
|
6963
|
+
skipped: false,
|
|
6964
|
+
path: settingsPath,
|
|
6965
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6966
|
+
};
|
|
6967
|
+
}
|
|
6968
|
+
}
|
|
6969
|
+
async function generateSettingsLocalWithSpinner(projectPath, options) {
|
|
6970
|
+
return withSpinner(
|
|
6971
|
+
"Generating settings.local.json...",
|
|
6972
|
+
() => generateSettingsLocal(projectPath, options),
|
|
6973
|
+
{
|
|
6974
|
+
successText: "Created settings.local.json"
|
|
6975
|
+
}
|
|
6976
|
+
);
|
|
6977
|
+
}
|
|
6978
|
+
function buildSettingsJson(options) {
|
|
6979
|
+
const claudeSettings = options?.claudeSettings || DEFAULT_CLAUDE_SETTINGS;
|
|
6980
|
+
const includeCoAuthor = options?.includeCoAuthor ?? true;
|
|
6981
|
+
const settings = {
|
|
6982
|
+
$schema: "https://json.schemastore.org/claude-code-settings.json"
|
|
6983
|
+
};
|
|
6984
|
+
if (claudeSettings.model && claudeSettings.model !== "default") {
|
|
6985
|
+
settings.model = claudeSettings.model;
|
|
6986
|
+
}
|
|
6987
|
+
if (claudeSettings.alwaysThinkingEnabled) {
|
|
6988
|
+
settings.alwaysThinkingEnabled = true;
|
|
6989
|
+
}
|
|
6990
|
+
if (claudeSettings.cleanupPeriodDays !== 30) {
|
|
6991
|
+
settings.cleanupPeriodDays = claudeSettings.cleanupPeriodDays;
|
|
6992
|
+
}
|
|
6993
|
+
settings.attribution = includeCoAuthor ? ATTRIBUTION_WITH_COAUTHOR : ATTRIBUTION_NO_COAUTHOR;
|
|
6994
|
+
settings.permissions = {
|
|
6995
|
+
allow: [],
|
|
6996
|
+
deny: []
|
|
6997
|
+
};
|
|
6998
|
+
if (claudeSettings.sandbox?.enabled) {
|
|
6999
|
+
settings.sandbox = {
|
|
7000
|
+
enabled: true,
|
|
7001
|
+
autoAllowBashIfSandboxed: claudeSettings.sandbox.autoAllowBashIfSandboxed ?? true
|
|
7002
|
+
};
|
|
7003
|
+
}
|
|
7004
|
+
return settings;
|
|
7005
|
+
}
|
|
7006
|
+
function buildSettingsLocalJson(options) {
|
|
7007
|
+
const claudeSettings = options?.claudeSettings || DEFAULT_CLAUDE_SETTINGS;
|
|
7008
|
+
const settings = {};
|
|
7009
|
+
const allow = [...options?.additionalAllow || []];
|
|
7010
|
+
const deny = [...options?.additionalDeny || []];
|
|
7011
|
+
if (claudeSettings.permissions?.allow) {
|
|
7012
|
+
allow.push(...claudeSettings.permissions.allow);
|
|
7013
|
+
}
|
|
7014
|
+
if (claudeSettings.permissions?.deny) {
|
|
7015
|
+
deny.push(...claudeSettings.permissions.deny);
|
|
7016
|
+
}
|
|
7017
|
+
settings.permissions = {
|
|
7018
|
+
allow: [...new Set(allow)],
|
|
7019
|
+
// Deduplicate
|
|
7020
|
+
deny: [...new Set(deny)],
|
|
7021
|
+
ask: claudeSettings.permissions?.ask || [],
|
|
7022
|
+
defaultMode: claudeSettings.permissions?.defaultMode || "acceptEdits"
|
|
7023
|
+
};
|
|
7024
|
+
if (claudeSettings.stopNotification && claudeSettings.stopNotification !== "none") {
|
|
7025
|
+
const command = claudeSettings.stopNotification === "custom" && claudeSettings.customStopCommand ? claudeSettings.customStopCommand : BEEP_COMMAND;
|
|
7026
|
+
settings.hooks = {
|
|
7027
|
+
Stop: [
|
|
7028
|
+
{
|
|
7029
|
+
hooks: [
|
|
7030
|
+
{
|
|
7031
|
+
type: "command",
|
|
7032
|
+
command,
|
|
7033
|
+
timeout: 5
|
|
7034
|
+
}
|
|
7035
|
+
]
|
|
7036
|
+
}
|
|
7037
|
+
],
|
|
7038
|
+
SubagentStop: [
|
|
7039
|
+
{
|
|
7040
|
+
hooks: [
|
|
7041
|
+
{
|
|
7042
|
+
type: "command",
|
|
7043
|
+
command,
|
|
7044
|
+
timeout: 5
|
|
7045
|
+
}
|
|
7046
|
+
]
|
|
7047
|
+
}
|
|
7048
|
+
]
|
|
7049
|
+
};
|
|
7050
|
+
}
|
|
7051
|
+
return settings;
|
|
7052
|
+
}
|
|
7053
|
+
|
|
6750
7054
|
// src/lib/templates/config-replacer.ts
|
|
6751
7055
|
init_esm_shims();
|
|
6752
7056
|
import * as fs4 from "fs/promises";
|
|
@@ -8700,6 +9004,142 @@ async function promptCICDConfig(options) {
|
|
|
8700
9004
|
};
|
|
8701
9005
|
}
|
|
8702
9006
|
|
|
9007
|
+
// src/cli/prompts/claude-settings.ts
|
|
9008
|
+
init_esm_shims();
|
|
9009
|
+
async function promptClaudeSettings(options) {
|
|
9010
|
+
logger.section("Claude Code Settings", "\u{1F916}");
|
|
9011
|
+
const wantToConfigure = await confirm({
|
|
9012
|
+
message: "Would you like to configure Claude Code settings?",
|
|
9013
|
+
default: true
|
|
9014
|
+
});
|
|
9015
|
+
if (!wantToConfigure) {
|
|
9016
|
+
return {
|
|
9017
|
+
...DEFAULT_CLAUDE_SETTINGS,
|
|
9018
|
+
attribution: options?.includeCoAuthor ? DEFAULT_CLAUDE_SETTINGS.attribution : {
|
|
9019
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)",
|
|
9020
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
9021
|
+
}
|
|
9022
|
+
};
|
|
9023
|
+
}
|
|
9024
|
+
const setupMode = await select({
|
|
9025
|
+
message: "How would you like to configure?",
|
|
9026
|
+
choices: [
|
|
9027
|
+
{ name: "Use a preset", value: "preset" },
|
|
9028
|
+
{ name: "Customize settings", value: "custom" }
|
|
9029
|
+
],
|
|
9030
|
+
default: "preset"
|
|
9031
|
+
});
|
|
9032
|
+
if (setupMode === "preset") {
|
|
9033
|
+
return promptClaudeSettingsPreset(options);
|
|
9034
|
+
}
|
|
9035
|
+
return promptClaudeSettingsCustom(options);
|
|
9036
|
+
}
|
|
9037
|
+
async function promptClaudeSettingsPreset(options) {
|
|
9038
|
+
const preset = await select({
|
|
9039
|
+
message: "Choose a settings preset:",
|
|
9040
|
+
choices: Object.entries(PRESET_DESCRIPTIONS2).map(([key, description]) => ({
|
|
9041
|
+
name: `${key.charAt(0).toUpperCase() + key.slice(1)} - ${description}`,
|
|
9042
|
+
value: key
|
|
9043
|
+
})),
|
|
9044
|
+
default: "default"
|
|
9045
|
+
});
|
|
9046
|
+
const config = { ...CLAUDE_SETTINGS_PRESETS[preset] };
|
|
9047
|
+
if (options?.includeCoAuthor === false) {
|
|
9048
|
+
config.attribution = {
|
|
9049
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)",
|
|
9050
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
9051
|
+
};
|
|
9052
|
+
}
|
|
9053
|
+
return config;
|
|
9054
|
+
}
|
|
9055
|
+
async function promptClaudeSettingsCustom(options) {
|
|
9056
|
+
const defaults = options?.defaults || DEFAULT_CLAUDE_SETTINGS;
|
|
9057
|
+
const model = await select({
|
|
9058
|
+
message: "Default Claude model:",
|
|
9059
|
+
choices: Object.entries(MODEL_DESCRIPTIONS).map(([key, description]) => ({
|
|
9060
|
+
name: description,
|
|
9061
|
+
value: key
|
|
9062
|
+
})),
|
|
9063
|
+
default: defaults.model || "sonnet"
|
|
9064
|
+
});
|
|
9065
|
+
const alwaysThinkingEnabled = await confirm({
|
|
9066
|
+
message: "Enable extended thinking by default? (better for complex tasks)",
|
|
9067
|
+
default: defaults.alwaysThinkingEnabled ?? false
|
|
9068
|
+
});
|
|
9069
|
+
const sandboxEnabled = await confirm({
|
|
9070
|
+
message: "Enable bash sandboxing? (isolates shell commands for security)",
|
|
9071
|
+
default: defaults.sandbox?.enabled ?? false
|
|
9072
|
+
});
|
|
9073
|
+
const permissionMode = await select({
|
|
9074
|
+
message: "Default permission mode:",
|
|
9075
|
+
choices: Object.entries(PERMISSION_MODE_DESCRIPTIONS).map(([key, description]) => ({
|
|
9076
|
+
name: description,
|
|
9077
|
+
value: key
|
|
9078
|
+
})),
|
|
9079
|
+
default: defaults.permissions?.defaultMode || "acceptEdits"
|
|
9080
|
+
});
|
|
9081
|
+
const cleanupPeriodStr = await input({
|
|
9082
|
+
message: "Session cleanup period (days, 0 = delete all immediately):",
|
|
9083
|
+
default: String(defaults.cleanupPeriodDays ?? 30),
|
|
9084
|
+
validate: (value) => {
|
|
9085
|
+
const num = Number.parseInt(value, 10);
|
|
9086
|
+
if (Number.isNaN(num) || num < 0 || num > 365) {
|
|
9087
|
+
return "Please enter a number between 0 and 365";
|
|
9088
|
+
}
|
|
9089
|
+
return true;
|
|
9090
|
+
}
|
|
9091
|
+
});
|
|
9092
|
+
const cleanupPeriodDays = Number.parseInt(cleanupPeriodStr, 10);
|
|
9093
|
+
const stopNotification = await select({
|
|
9094
|
+
message: "Notification when task completes:",
|
|
9095
|
+
choices: Object.entries(STOP_NOTIFICATION_DESCRIPTIONS).map(([key, description]) => ({
|
|
9096
|
+
name: description,
|
|
9097
|
+
value: key
|
|
9098
|
+
})),
|
|
9099
|
+
default: defaults.stopNotification || "beep"
|
|
9100
|
+
});
|
|
9101
|
+
let customStopCommand;
|
|
9102
|
+
if (stopNotification === "custom") {
|
|
9103
|
+
customStopCommand = await input({
|
|
9104
|
+
message: "Custom command to run on task completion:",
|
|
9105
|
+
default: defaults.customStopCommand || ""
|
|
9106
|
+
});
|
|
9107
|
+
}
|
|
9108
|
+
const config = {
|
|
9109
|
+
model,
|
|
9110
|
+
alwaysThinkingEnabled,
|
|
9111
|
+
sandbox: {
|
|
9112
|
+
enabled: sandboxEnabled,
|
|
9113
|
+
autoAllowBashIfSandboxed: true
|
|
9114
|
+
},
|
|
9115
|
+
permissions: {
|
|
9116
|
+
allow: defaults.permissions?.allow || [],
|
|
9117
|
+
deny: defaults.permissions?.deny || [],
|
|
9118
|
+
ask: defaults.permissions?.ask || [],
|
|
9119
|
+
defaultMode: permissionMode
|
|
9120
|
+
},
|
|
9121
|
+
attribution: options?.includeCoAuthor === false ? {
|
|
9122
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)",
|
|
9123
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
9124
|
+
} : DEFAULT_CLAUDE_SETTINGS.attribution,
|
|
9125
|
+
cleanupPeriodDays,
|
|
9126
|
+
stopNotification,
|
|
9127
|
+
customStopCommand
|
|
9128
|
+
};
|
|
9129
|
+
if (stopNotification === "beep") {
|
|
9130
|
+
config.hooks = {
|
|
9131
|
+
Stop: [{ hooks: [{ type: "command", command: BEEP_COMMAND, timeout: 5 }] }],
|
|
9132
|
+
SubagentStop: [{ hooks: [{ type: "command", command: BEEP_COMMAND, timeout: 5 }] }]
|
|
9133
|
+
};
|
|
9134
|
+
} else if (stopNotification === "custom" && customStopCommand) {
|
|
9135
|
+
config.hooks = {
|
|
9136
|
+
Stop: [{ hooks: [{ type: "command", command: customStopCommand, timeout: 10 }] }],
|
|
9137
|
+
SubagentStop: [{ hooks: [{ type: "command", command: customStopCommand, timeout: 10 }] }]
|
|
9138
|
+
};
|
|
9139
|
+
}
|
|
9140
|
+
return config;
|
|
9141
|
+
}
|
|
9142
|
+
|
|
8703
9143
|
// src/cli/prompts/code-style.ts
|
|
8704
9144
|
init_esm_shims();
|
|
8705
9145
|
var CODE_STYLE_TOOLS = [
|
|
@@ -9837,7 +10277,95 @@ async function promptSubagentStopHook() {
|
|
|
9837
10277
|
|
|
9838
10278
|
// src/cli/prompts/item-select.ts
|
|
9839
10279
|
init_esm_shims();
|
|
9840
|
-
|
|
10280
|
+
|
|
10281
|
+
// src/cli/prompts/mutual-exclusivity.ts
|
|
10282
|
+
init_esm_shims();
|
|
10283
|
+
function getConflictingSelections(module, selectedIds) {
|
|
10284
|
+
if (!module.alternativeTo) {
|
|
10285
|
+
return [];
|
|
10286
|
+
}
|
|
10287
|
+
return module.alternativeTo.filter((altId) => selectedIds.includes(altId));
|
|
10288
|
+
}
|
|
10289
|
+
function createChoicesWithExclusivity(modules, selectedIds, options) {
|
|
10290
|
+
const choices = [];
|
|
10291
|
+
for (const module of modules) {
|
|
10292
|
+
const conflicts = getConflictingSelections(module, selectedIds);
|
|
10293
|
+
const isConflicting = conflicts.length > 0;
|
|
10294
|
+
const isPreselected = options?.preselected?.includes(module.id);
|
|
10295
|
+
const isSelected = selectedIds.includes(module.id);
|
|
10296
|
+
let name = module.name;
|
|
10297
|
+
let description = module.description;
|
|
10298
|
+
let disabled = false;
|
|
10299
|
+
if (isConflicting) {
|
|
10300
|
+
const conflictNames = conflicts.join(", ");
|
|
10301
|
+
disabled = options?.showConflictReason ? `Conflicts with: ${conflictNames}` : `Alternative to ${conflictNames} (already selected)`;
|
|
10302
|
+
name = colors.muted(`${module.name} (incompatible)`);
|
|
10303
|
+
description = `${colors.muted("\u26A0")} ${disabled}`;
|
|
10304
|
+
}
|
|
10305
|
+
choices.push({
|
|
10306
|
+
name,
|
|
10307
|
+
value: module.id,
|
|
10308
|
+
description,
|
|
10309
|
+
disabled: isConflicting ? disabled : false,
|
|
10310
|
+
checked: isSelected || isPreselected && !isConflicting
|
|
10311
|
+
});
|
|
10312
|
+
}
|
|
10313
|
+
return choices;
|
|
10314
|
+
}
|
|
10315
|
+
function validateNoConflicts(selectedIds, allModules) {
|
|
10316
|
+
const conflicts = [];
|
|
10317
|
+
for (const id of selectedIds) {
|
|
10318
|
+
const module = allModules.find((m) => m.id === id);
|
|
10319
|
+
if (!module?.alternativeTo) continue;
|
|
10320
|
+
for (const altId of module.alternativeTo) {
|
|
10321
|
+
if (selectedIds.includes(altId)) {
|
|
10322
|
+
const existingConflict = conflicts.find(
|
|
10323
|
+
(c) => c.selected === id && c.conflictsWith === altId || c.selected === altId && c.conflictsWith === id
|
|
10324
|
+
);
|
|
10325
|
+
if (!existingConflict) {
|
|
10326
|
+
conflicts.push({ selected: id, conflictsWith: altId });
|
|
10327
|
+
}
|
|
10328
|
+
}
|
|
10329
|
+
}
|
|
10330
|
+
}
|
|
10331
|
+
return conflicts;
|
|
10332
|
+
}
|
|
10333
|
+
function groupByExclusivity(modules) {
|
|
10334
|
+
const groups = /* @__PURE__ */ new Map();
|
|
10335
|
+
const processedIds = /* @__PURE__ */ new Set();
|
|
10336
|
+
for (const module of modules) {
|
|
10337
|
+
if (processedIds.has(module.id)) continue;
|
|
10338
|
+
const groupMembers = /* @__PURE__ */ new Set([module.id]);
|
|
10339
|
+
const toProcess = [...module.alternativeTo || []];
|
|
10340
|
+
while (toProcess.length > 0) {
|
|
10341
|
+
const altId = toProcess.pop();
|
|
10342
|
+
if (!altId || groupMembers.has(altId)) continue;
|
|
10343
|
+
const altModule = modules.find((m) => m.id === altId);
|
|
10344
|
+
if (altModule) {
|
|
10345
|
+
groupMembers.add(altId);
|
|
10346
|
+
for (const transitiveAlt of altModule.alternativeTo || []) {
|
|
10347
|
+
if (!groupMembers.has(transitiveAlt)) {
|
|
10348
|
+
toProcess.push(transitiveAlt);
|
|
10349
|
+
}
|
|
10350
|
+
}
|
|
10351
|
+
}
|
|
10352
|
+
}
|
|
10353
|
+
if (groupMembers.size > 1) {
|
|
10354
|
+
const sortedMembers = Array.from(groupMembers).sort();
|
|
10355
|
+
const groupId = `exclusivity-group-${sortedMembers[0]}`;
|
|
10356
|
+
groups.set(groupId, sortedMembers);
|
|
10357
|
+
for (const memberId of groupMembers) {
|
|
10358
|
+
processedIds.add(memberId);
|
|
10359
|
+
}
|
|
10360
|
+
} else {
|
|
10361
|
+
processedIds.add(module.id);
|
|
10362
|
+
}
|
|
10363
|
+
}
|
|
10364
|
+
return groups;
|
|
10365
|
+
}
|
|
10366
|
+
|
|
10367
|
+
// src/cli/prompts/item-select.ts
|
|
10368
|
+
async function promptBatchAction(category, totalItems, options) {
|
|
9841
10369
|
const choices = [
|
|
9842
10370
|
{
|
|
9843
10371
|
name: "Install all (recommended)",
|
|
@@ -9855,7 +10383,14 @@ async function promptBatchAction(category, totalItems, hasPreset) {
|
|
|
9855
10383
|
description: `Skip all ${category}`
|
|
9856
10384
|
}
|
|
9857
10385
|
];
|
|
9858
|
-
if (
|
|
10386
|
+
if (options?.hasExclusivityGroups && options.exclusivityGroupCount) {
|
|
10387
|
+
choices.splice(1, 0, {
|
|
10388
|
+
name: colors.primary("Smart selection (handles conflicts)"),
|
|
10389
|
+
value: "smart",
|
|
10390
|
+
description: `Intelligent selection with ${options.exclusivityGroupCount} mutually exclusive group(s)`
|
|
10391
|
+
});
|
|
10392
|
+
}
|
|
10393
|
+
if (options?.hasPreset) {
|
|
9859
10394
|
choices.splice(1, 0, {
|
|
9860
10395
|
name: "Use preset for this category",
|
|
9861
10396
|
value: "preset",
|
|
@@ -9865,27 +10400,43 @@ async function promptBatchAction(category, totalItems, hasPreset) {
|
|
|
9865
10400
|
return select({
|
|
9866
10401
|
message: `${capitalize(category)} selection (${totalItems} available):`,
|
|
9867
10402
|
choices,
|
|
9868
|
-
default: "all"
|
|
10403
|
+
default: options?.hasExclusivityGroups ? "smart" : "all"
|
|
9869
10404
|
});
|
|
9870
10405
|
}
|
|
9871
10406
|
async function selectItemsFromCategory(category, items, options) {
|
|
9872
|
-
const selectedItems = [];
|
|
9873
|
-
const skippedItems = [];
|
|
9874
10407
|
logger.newline();
|
|
9875
10408
|
logger.subtitle(`${capitalize(category)} Selection`);
|
|
9876
10409
|
logger.info(`${items.length} ${category} available`);
|
|
10410
|
+
const exclusivityGroups = groupByExclusivity(items);
|
|
10411
|
+
const hasExclusivityGroups = exclusivityGroups.size > 0;
|
|
10412
|
+
if (hasExclusivityGroups) {
|
|
10413
|
+
logger.info(
|
|
10414
|
+
colors.warning(
|
|
10415
|
+
`${exclusivityGroups.size} group(s) of mutually exclusive ${category} detected`
|
|
10416
|
+
)
|
|
10417
|
+
);
|
|
10418
|
+
}
|
|
9877
10419
|
logger.newline();
|
|
9878
|
-
const batchAction = await promptBatchAction(
|
|
9879
|
-
|
|
9880
|
-
|
|
9881
|
-
|
|
9882
|
-
);
|
|
10420
|
+
const batchAction = await promptBatchAction(category, items.length, {
|
|
10421
|
+
hasPreset: options?.preselected && options.preselected.length > 0,
|
|
10422
|
+
hasExclusivityGroups,
|
|
10423
|
+
exclusivityGroupCount: exclusivityGroups.size
|
|
10424
|
+
});
|
|
9883
10425
|
if (batchAction === "all") {
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
10426
|
+
const conflicts = validateNoConflicts(
|
|
10427
|
+
items.map((i) => i.id),
|
|
10428
|
+
items
|
|
10429
|
+
);
|
|
10430
|
+
if (conflicts.length > 0) {
|
|
10431
|
+
logger.warn("Cannot install all: some modules are mutually exclusive.");
|
|
10432
|
+
logger.info("Switching to smart selection mode...");
|
|
10433
|
+
} else {
|
|
10434
|
+
return {
|
|
10435
|
+
category,
|
|
10436
|
+
selectedItems: items.map((i) => i.id),
|
|
10437
|
+
skippedItems: []
|
|
10438
|
+
};
|
|
10439
|
+
}
|
|
9889
10440
|
}
|
|
9890
10441
|
if (batchAction === "none") {
|
|
9891
10442
|
return {
|
|
@@ -9896,24 +10447,106 @@ async function selectItemsFromCategory(category, items, options) {
|
|
|
9896
10447
|
}
|
|
9897
10448
|
if (batchAction === "preset" && options?.preselected) {
|
|
9898
10449
|
const preselectedSet = new Set(options.preselected);
|
|
9899
|
-
|
|
10450
|
+
const preselectedIds = items.filter((i) => preselectedSet.has(i.id)).map((i) => i.id);
|
|
10451
|
+
const conflicts = validateNoConflicts(preselectedIds, items);
|
|
10452
|
+
if (conflicts.length > 0) {
|
|
10453
|
+
logger.warn("Preset contains conflicting modules. Switching to smart selection...");
|
|
10454
|
+
} else {
|
|
10455
|
+
return {
|
|
10456
|
+
category,
|
|
10457
|
+
selectedItems: preselectedIds,
|
|
10458
|
+
skippedItems: items.filter((i) => !preselectedSet.has(i.id)).map((i) => i.id)
|
|
10459
|
+
};
|
|
10460
|
+
}
|
|
10461
|
+
}
|
|
10462
|
+
if (batchAction === "smart" || batchAction === "all" || batchAction === "preset") {
|
|
10463
|
+
return selectItemsWithExclusivity(category, items, options);
|
|
10464
|
+
}
|
|
10465
|
+
return selectItemsOneByOne(category, items, options);
|
|
10466
|
+
}
|
|
10467
|
+
async function selectItemsWithExclusivity(category, items, options) {
|
|
10468
|
+
let selectedIds = options?.preselected?.filter((id) => items.some((i) => i.id === id)) || [];
|
|
10469
|
+
let confirmed = false;
|
|
10470
|
+
while (!confirmed) {
|
|
10471
|
+
const choices = createChoicesWithExclusivity(items, selectedIds, {
|
|
10472
|
+
preselected: options?.preselected,
|
|
10473
|
+
showConflictReason: true
|
|
10474
|
+
});
|
|
10475
|
+
logger.newline();
|
|
10476
|
+
logger.info(
|
|
10477
|
+
colors.muted("Items marked as incompatible are disabled based on your selections.")
|
|
10478
|
+
);
|
|
10479
|
+
logger.info(colors.muted("Uncheck items to enable their alternatives."));
|
|
10480
|
+
logger.newline();
|
|
10481
|
+
const newSelection = await checkbox({
|
|
10482
|
+
message: `Select ${category} (Space to toggle, Enter to confirm):`,
|
|
10483
|
+
choices: choices.map((c) => ({
|
|
10484
|
+
name: c.name,
|
|
10485
|
+
value: c.value,
|
|
10486
|
+
description: c.description,
|
|
10487
|
+
disabled: c.disabled,
|
|
10488
|
+
checked: c.checked
|
|
10489
|
+
})),
|
|
10490
|
+
required: false
|
|
10491
|
+
});
|
|
10492
|
+
const conflicts = validateNoConflicts(newSelection, items);
|
|
10493
|
+
if (conflicts.length > 0) {
|
|
10494
|
+
logger.warn("Your selection contains conflicts:");
|
|
10495
|
+
for (const conflict of conflicts) {
|
|
10496
|
+
const module1 = items.find((i) => i.id === conflict.selected)?.name || conflict.selected;
|
|
10497
|
+
const module2 = items.find((i) => i.id === conflict.conflictsWith)?.name || conflict.conflictsWith;
|
|
10498
|
+
logger.info(` ${colors.error("\u2022")} ${module1} and ${module2} are mutually exclusive`);
|
|
10499
|
+
}
|
|
10500
|
+
logger.info("Please adjust your selection.");
|
|
10501
|
+
selectedIds = newSelection;
|
|
10502
|
+
continue;
|
|
10503
|
+
}
|
|
10504
|
+
selectedIds = newSelection;
|
|
10505
|
+
showCategorySelectionSummary({
|
|
9900
10506
|
category,
|
|
9901
|
-
selectedItems:
|
|
9902
|
-
skippedItems: items.filter((i) => !
|
|
9903
|
-
};
|
|
10507
|
+
selectedItems: selectedIds,
|
|
10508
|
+
skippedItems: items.filter((i) => !selectedIds.includes(i.id)).map((i) => i.id)
|
|
10509
|
+
});
|
|
10510
|
+
confirmed = await confirm({
|
|
10511
|
+
message: "Is this selection correct?",
|
|
10512
|
+
default: true
|
|
10513
|
+
});
|
|
9904
10514
|
}
|
|
10515
|
+
return {
|
|
10516
|
+
category,
|
|
10517
|
+
selectedItems: selectedIds,
|
|
10518
|
+
skippedItems: items.filter((i) => !selectedIds.includes(i.id)).map((i) => i.id)
|
|
10519
|
+
};
|
|
10520
|
+
}
|
|
10521
|
+
async function selectItemsOneByOne(category, items, options) {
|
|
10522
|
+
const selectedItems = [];
|
|
10523
|
+
const skippedItems = [];
|
|
9905
10524
|
const remainingItems = [...items];
|
|
9906
10525
|
let currentIndex = 0;
|
|
9907
10526
|
while (currentIndex < remainingItems.length) {
|
|
9908
10527
|
const item = remainingItems[currentIndex];
|
|
9909
10528
|
const remaining = remainingItems.length - currentIndex - 1;
|
|
9910
10529
|
const isPreselected = options?.preselected?.includes(item.id);
|
|
10530
|
+
const conflicts = item.alternativeTo?.filter((altId) => selectedItems.includes(altId)) || [];
|
|
10531
|
+
if (conflicts.length > 0) {
|
|
10532
|
+
const conflictNames = conflicts.map((id) => items.find((i) => i.id === id)?.name || id).join(", ");
|
|
10533
|
+
logger.info(
|
|
10534
|
+
colors.muted(`Skipping ${item.name} (conflicts with selected: ${conflictNames})`)
|
|
10535
|
+
);
|
|
10536
|
+
skippedItems.push(item.id);
|
|
10537
|
+
currentIndex++;
|
|
10538
|
+
continue;
|
|
10539
|
+
}
|
|
9911
10540
|
const progress = colors.muted(`[${currentIndex + 1}/${remainingItems.length}]`);
|
|
9912
10541
|
console.log(`
|
|
9913
10542
|
${progress} ${colors.bold(item.name)}`);
|
|
9914
10543
|
if (options?.showDescriptions && item.description) {
|
|
9915
10544
|
logger.note(item.description);
|
|
9916
10545
|
}
|
|
10546
|
+
if (item.alternativeTo && item.alternativeTo.length > 0) {
|
|
10547
|
+
const altNames = item.alternativeTo.map((id) => items.find((i) => i.id === id)?.name || id).join(", ");
|
|
10548
|
+
logger.info(colors.warning(`\u26A0 Selecting this will disable: ${altNames}`));
|
|
10549
|
+
}
|
|
9917
10550
|
const action = await promptItemWithShortcuts(item, {
|
|
9918
10551
|
defaultInstall: isPreselected,
|
|
9919
10552
|
remainingCount: remaining
|
|
@@ -9930,7 +10563,13 @@ ${progress} ${colors.bold(item.name)}`);
|
|
|
9930
10563
|
case "install-rest":
|
|
9931
10564
|
selectedItems.push(item.id);
|
|
9932
10565
|
for (let i = currentIndex + 1; i < remainingItems.length; i++) {
|
|
9933
|
-
|
|
10566
|
+
const nextItem = remainingItems[i];
|
|
10567
|
+
const nextConflicts = nextItem.alternativeTo?.filter((altId) => selectedItems.includes(altId)) || [];
|
|
10568
|
+
if (nextConflicts.length === 0) {
|
|
10569
|
+
selectedItems.push(nextItem.id);
|
|
10570
|
+
} else {
|
|
10571
|
+
skippedItems.push(nextItem.id);
|
|
10572
|
+
}
|
|
9934
10573
|
}
|
|
9935
10574
|
currentIndex = remainingItems.length;
|
|
9936
10575
|
break;
|
|
@@ -9972,6 +10611,17 @@ async function promptItemWithShortcuts(item, options) {
|
|
|
9972
10611
|
default: options.defaultInstall !== false ? "install" : "skip"
|
|
9973
10612
|
});
|
|
9974
10613
|
}
|
|
10614
|
+
function showCategorySelectionSummary(result) {
|
|
10615
|
+
const { category, selectedItems, skippedItems } = result;
|
|
10616
|
+
logger.newline();
|
|
10617
|
+
logger.subtitle(`${capitalize(category)} Summary`);
|
|
10618
|
+
if (selectedItems.length > 0) {
|
|
10619
|
+
logger.success(`Selected (${selectedItems.length}): ${selectedItems.join(", ")}`);
|
|
10620
|
+
}
|
|
10621
|
+
if (skippedItems.length > 0) {
|
|
10622
|
+
logger.info(`Skipped (${skippedItems.length}): ${colors.muted(skippedItems.join(", "))}`);
|
|
10623
|
+
}
|
|
10624
|
+
}
|
|
9975
10625
|
function capitalize(str) {
|
|
9976
10626
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
9977
10627
|
}
|
|
@@ -10735,6 +11385,122 @@ async function confirmProjectInfo(info) {
|
|
|
10735
11385
|
});
|
|
10736
11386
|
}
|
|
10737
11387
|
|
|
11388
|
+
// src/cli/prompts/related-skills.ts
|
|
11389
|
+
init_esm_shims();
|
|
11390
|
+
function getAllRelatedSkillIds(agentModules) {
|
|
11391
|
+
const relatedIds = /* @__PURE__ */ new Set();
|
|
11392
|
+
for (const agent of agentModules) {
|
|
11393
|
+
if (agent.relatedSkills) {
|
|
11394
|
+
for (const skillId of agent.relatedSkills) {
|
|
11395
|
+
relatedIds.add(skillId);
|
|
11396
|
+
}
|
|
11397
|
+
}
|
|
11398
|
+
}
|
|
11399
|
+
return Array.from(relatedIds);
|
|
11400
|
+
}
|
|
11401
|
+
function getAgentsWithRelatedSkills(selectedAgentIds, agentModules) {
|
|
11402
|
+
return agentModules.filter(
|
|
11403
|
+
(agent) => selectedAgentIds.includes(agent.id) && agent.relatedSkills && agent.relatedSkills.length > 0
|
|
11404
|
+
);
|
|
11405
|
+
}
|
|
11406
|
+
async function promptRelatedSkillsForAgent(agent, skillModules, options) {
|
|
11407
|
+
if (!agent.relatedSkills || agent.relatedSkills.length === 0) {
|
|
11408
|
+
return [];
|
|
11409
|
+
}
|
|
11410
|
+
const relatedSkillDefs = agent.relatedSkills.map((skillId) => skillModules.find((s) => s.id === skillId)).filter((s) => s !== void 0);
|
|
11411
|
+
if (relatedSkillDefs.length === 0) {
|
|
11412
|
+
return [];
|
|
11413
|
+
}
|
|
11414
|
+
if (relatedSkillDefs.length === 1) {
|
|
11415
|
+
const skill = relatedSkillDefs[0];
|
|
11416
|
+
const action = await select({
|
|
11417
|
+
message: `${colors.primary(agent.name)} has a related skill. Install it?`,
|
|
11418
|
+
choices: [
|
|
11419
|
+
{
|
|
11420
|
+
name: `Install ${skill.name}`,
|
|
11421
|
+
value: "install",
|
|
11422
|
+
description: skill.description
|
|
11423
|
+
},
|
|
11424
|
+
{
|
|
11425
|
+
name: "Skip",
|
|
11426
|
+
value: "skip",
|
|
11427
|
+
description: "Do not install this skill"
|
|
11428
|
+
}
|
|
11429
|
+
],
|
|
11430
|
+
default: "install"
|
|
11431
|
+
});
|
|
11432
|
+
return action === "install" ? [skill.id] : [];
|
|
11433
|
+
}
|
|
11434
|
+
const choices = relatedSkillDefs.map((skill) => ({
|
|
11435
|
+
name: skill.name,
|
|
11436
|
+
value: skill.id,
|
|
11437
|
+
description: skill.description,
|
|
11438
|
+
checked: options?.preselected?.includes(skill.id) ?? false
|
|
11439
|
+
}));
|
|
11440
|
+
if (options?.allowMultiple !== false) {
|
|
11441
|
+
const selected2 = await checkbox({
|
|
11442
|
+
message: `${colors.primary(agent.name)} supports multiple frameworks. Select which patterns to install:`,
|
|
11443
|
+
choices,
|
|
11444
|
+
required: false
|
|
11445
|
+
});
|
|
11446
|
+
return selected2;
|
|
11447
|
+
}
|
|
11448
|
+
const choicesWithSkip = [
|
|
11449
|
+
...choices.map((c) => ({ name: c.name, value: c.value, description: c.description })),
|
|
11450
|
+
{
|
|
11451
|
+
name: colors.muted("Skip (none)"),
|
|
11452
|
+
value: "__skip__",
|
|
11453
|
+
description: "Do not install any related skill for this agent"
|
|
11454
|
+
}
|
|
11455
|
+
];
|
|
11456
|
+
const selected = await select({
|
|
11457
|
+
message: `${colors.primary(agent.name)} supports multiple frameworks. Select which patterns to use:`,
|
|
11458
|
+
choices: choicesWithSkip,
|
|
11459
|
+
default: choicesWithSkip[0]?.value
|
|
11460
|
+
});
|
|
11461
|
+
return selected === "__skip__" ? [] : [selected];
|
|
11462
|
+
}
|
|
11463
|
+
async function promptAllRelatedSkills(selectedAgentIds, registry, options) {
|
|
11464
|
+
const agentsWithRelated = getAgentsWithRelatedSkills(selectedAgentIds, registry.agents);
|
|
11465
|
+
const allRelatedSkillIds = getAllRelatedSkillIds(registry.agents);
|
|
11466
|
+
if (agentsWithRelated.length === 0) {
|
|
11467
|
+
return {
|
|
11468
|
+
relatedSkillsSelected: [],
|
|
11469
|
+
relatedSkillsSkipped: [],
|
|
11470
|
+
allRelatedSkillIds
|
|
11471
|
+
};
|
|
11472
|
+
}
|
|
11473
|
+
logger.newline();
|
|
11474
|
+
logger.subtitle("Framework-Specific Skills");
|
|
11475
|
+
logger.info(
|
|
11476
|
+
"The selected agents support framework-specific patterns. Select which ones to install."
|
|
11477
|
+
);
|
|
11478
|
+
logger.newline();
|
|
11479
|
+
const selectedSkills = [];
|
|
11480
|
+
const skippedSkills = [];
|
|
11481
|
+
for (const agent of agentsWithRelated) {
|
|
11482
|
+
const selected = await promptRelatedSkillsForAgent(agent, registry.skills, {
|
|
11483
|
+
preselected: options?.preselectedSkills,
|
|
11484
|
+
allowMultiple: options?.allowMultiplePerAgent
|
|
11485
|
+
});
|
|
11486
|
+
selectedSkills.push(...selected);
|
|
11487
|
+
const agentRelatedIds = agent.relatedSkills || [];
|
|
11488
|
+
const skipped = agentRelatedIds.filter((id) => !selected.includes(id));
|
|
11489
|
+
skippedSkills.push(...skipped);
|
|
11490
|
+
}
|
|
11491
|
+
const uniqueSelected = [...new Set(selectedSkills)];
|
|
11492
|
+
const uniqueSkipped = [...new Set(skippedSkills)].filter((id) => !uniqueSelected.includes(id));
|
|
11493
|
+
return {
|
|
11494
|
+
relatedSkillsSelected: uniqueSelected,
|
|
11495
|
+
relatedSkillsSkipped: uniqueSkipped,
|
|
11496
|
+
allRelatedSkillIds
|
|
11497
|
+
};
|
|
11498
|
+
}
|
|
11499
|
+
function filterOutRelatedSkills(skillModules, relatedSkillIds) {
|
|
11500
|
+
const relatedSet = new Set(relatedSkillIds);
|
|
11501
|
+
return skillModules.filter((skill) => !relatedSet.has(skill.id));
|
|
11502
|
+
}
|
|
11503
|
+
|
|
10738
11504
|
// src/cli/prompts/scaffold.ts
|
|
10739
11505
|
init_esm_shims();
|
|
10740
11506
|
async function promptScaffoldType(options) {
|
|
@@ -11496,11 +12262,66 @@ function createBundleSelectionStep() {
|
|
|
11496
12262
|
}
|
|
11497
12263
|
if (mode === "individual" || mode === "both") {
|
|
11498
12264
|
const preselectedFromBundles = resolveBundles(result.selectedBundles);
|
|
11499
|
-
const categories = ["agents", "skills", "commands", "docs"];
|
|
11500
12265
|
if (ctx.registry) {
|
|
11501
12266
|
logger.newline();
|
|
11502
12267
|
logger.subtitle("Individual Module Selection");
|
|
11503
|
-
|
|
12268
|
+
const agentPreselected = mode === "both" ? preselectedFromBundles.agents : [];
|
|
12269
|
+
const agentResult = await selectItemsFromCategory("agents", ctx.registry.agents, {
|
|
12270
|
+
preselected: agentPreselected,
|
|
12271
|
+
showDescriptions: true
|
|
12272
|
+
});
|
|
12273
|
+
if (mode === "both") {
|
|
12274
|
+
result.additionalModules.agents = agentResult.selectedItems.filter(
|
|
12275
|
+
(id) => !agentPreselected.includes(id)
|
|
12276
|
+
);
|
|
12277
|
+
} else {
|
|
12278
|
+
result.additionalModules.agents = agentResult.selectedItems;
|
|
12279
|
+
}
|
|
12280
|
+
const allSelectedAgents = [
|
|
12281
|
+
...preselectedFromBundles.agents,
|
|
12282
|
+
...result.additionalModules.agents
|
|
12283
|
+
];
|
|
12284
|
+
const relatedSkillsResult = await promptAllRelatedSkills(
|
|
12285
|
+
allSelectedAgents,
|
|
12286
|
+
ctx.registry,
|
|
12287
|
+
{
|
|
12288
|
+
preselectedSkills: mode === "both" ? preselectedFromBundles.skills : [],
|
|
12289
|
+
allowMultiplePerAgent: true
|
|
12290
|
+
}
|
|
12291
|
+
);
|
|
12292
|
+
const skillPreselected = mode === "both" ? preselectedFromBundles.skills : [];
|
|
12293
|
+
const independentSkills = filterOutRelatedSkills(
|
|
12294
|
+
ctx.registry.skills,
|
|
12295
|
+
relatedSkillsResult.allRelatedSkillIds
|
|
12296
|
+
);
|
|
12297
|
+
const independentPreselected = skillPreselected.filter(
|
|
12298
|
+
(id) => !relatedSkillsResult.allRelatedSkillIds.includes(id)
|
|
12299
|
+
);
|
|
12300
|
+
let independentSkillsSelected = [];
|
|
12301
|
+
if (independentSkills.length > 0) {
|
|
12302
|
+
logger.newline();
|
|
12303
|
+
logger.info(
|
|
12304
|
+
colors.muted("Now selecting general-purpose skills (not framework-specific):")
|
|
12305
|
+
);
|
|
12306
|
+
const skillResult = await selectItemsFromCategory("skills", independentSkills, {
|
|
12307
|
+
preselected: independentPreselected,
|
|
12308
|
+
showDescriptions: true
|
|
12309
|
+
});
|
|
12310
|
+
independentSkillsSelected = skillResult.selectedItems;
|
|
12311
|
+
}
|
|
12312
|
+
const allSelectedSkills = [
|
|
12313
|
+
...relatedSkillsResult.relatedSkillsSelected,
|
|
12314
|
+
...independentSkillsSelected
|
|
12315
|
+
];
|
|
12316
|
+
if (mode === "both") {
|
|
12317
|
+
result.additionalModules.skills = allSelectedSkills.filter(
|
|
12318
|
+
(id) => !skillPreselected.includes(id)
|
|
12319
|
+
);
|
|
12320
|
+
} else {
|
|
12321
|
+
result.additionalModules.skills = allSelectedSkills;
|
|
12322
|
+
}
|
|
12323
|
+
const otherCategories = ["commands", "docs"];
|
|
12324
|
+
for (const category of otherCategories) {
|
|
11504
12325
|
const preselected = mode === "both" ? preselectedFromBundles[category] : [];
|
|
11505
12326
|
const categoryResult = await selectItemsFromCategory(category, ctx.registry[category], {
|
|
11506
12327
|
preselected,
|
|
@@ -11672,6 +12493,28 @@ function createTemplateConfigStep() {
|
|
|
11672
12493
|
}
|
|
11673
12494
|
};
|
|
11674
12495
|
}
|
|
12496
|
+
function createClaudeSettingsStep() {
|
|
12497
|
+
return {
|
|
12498
|
+
metadata: {
|
|
12499
|
+
id: "claudeSettings",
|
|
12500
|
+
name: "Claude Code Settings",
|
|
12501
|
+
description: "Configure Claude Code model, permissions, and behavior",
|
|
12502
|
+
required: false
|
|
12503
|
+
},
|
|
12504
|
+
computeDefaults: (ctx) => ctx.claudeSettings,
|
|
12505
|
+
execute: async (ctx, defaults) => {
|
|
12506
|
+
const goBack = await promptBackOption(11, "Configure Claude Code settings or go back?");
|
|
12507
|
+
if (goBack) {
|
|
12508
|
+
return createResult(defaults, "back");
|
|
12509
|
+
}
|
|
12510
|
+
const value = await promptClaudeSettings({
|
|
12511
|
+
defaults,
|
|
12512
|
+
includeCoAuthor: ctx.preferences?.includeCoAuthor
|
|
12513
|
+
});
|
|
12514
|
+
return createResult(value, "next");
|
|
12515
|
+
}
|
|
12516
|
+
};
|
|
12517
|
+
}
|
|
11675
12518
|
function createInitWizardConfig(projectPath, detection, registry) {
|
|
11676
12519
|
void projectPath;
|
|
11677
12520
|
void detection;
|
|
@@ -11720,6 +12563,10 @@ function createInitWizardConfig(projectPath, detection, registry) {
|
|
|
11720
12563
|
{
|
|
11721
12564
|
id: "templateConfig",
|
|
11722
12565
|
definition: createTemplateConfigStep()
|
|
12566
|
+
},
|
|
12567
|
+
{
|
|
12568
|
+
id: "claudeSettings",
|
|
12569
|
+
definition: createClaudeSettingsStep()
|
|
11723
12570
|
}
|
|
11724
12571
|
];
|
|
11725
12572
|
return {
|
|
@@ -12044,7 +12891,7 @@ async function runInit(path11, options) {
|
|
|
12044
12891
|
logger.warn("Configuration cancelled");
|
|
12045
12892
|
return;
|
|
12046
12893
|
}
|
|
12047
|
-
const { config, skippedMcpConfigs, templateConfig, cicdConfig } = buildResult;
|
|
12894
|
+
const { config, skippedMcpConfigs, templateConfig, cicdConfig, claudeSettings } = buildResult;
|
|
12048
12895
|
if (templateConfig) {
|
|
12049
12896
|
config.templateConfig = templateConfig;
|
|
12050
12897
|
}
|
|
@@ -12061,7 +12908,15 @@ async function runInit(path11, options) {
|
|
|
12061
12908
|
showConfigSummary(config);
|
|
12062
12909
|
return;
|
|
12063
12910
|
}
|
|
12064
|
-
await executeInstallation(
|
|
12911
|
+
await executeInstallation(
|
|
12912
|
+
projectPath,
|
|
12913
|
+
config,
|
|
12914
|
+
registry,
|
|
12915
|
+
templatesPath,
|
|
12916
|
+
options,
|
|
12917
|
+
cicdConfig,
|
|
12918
|
+
claudeSettings
|
|
12919
|
+
);
|
|
12065
12920
|
if (templateConfig && !options.noPlaceholders) {
|
|
12066
12921
|
const claudePath = joinPath(projectPath, ".claude");
|
|
12067
12922
|
await replaceTemplateConfigWithSpinner(claudePath, templateConfig);
|
|
@@ -12278,7 +13133,8 @@ async function buildInteractiveConfig(projectPath, detection, registry, options,
|
|
|
12278
13133
|
codeStyleConfig,
|
|
12279
13134
|
cicdConfig,
|
|
12280
13135
|
folderPreferences,
|
|
12281
|
-
templateConfig: templateConfigResult
|
|
13136
|
+
templateConfig: templateConfigResult,
|
|
13137
|
+
claudeSettings
|
|
12282
13138
|
} = wizardResult.values;
|
|
12283
13139
|
let mcpConfig = { level: "project", servers: [] };
|
|
12284
13140
|
let skippedMcpConfigs = [];
|
|
@@ -12336,10 +13192,11 @@ async function buildInteractiveConfig(projectPath, detection, registry, options,
|
|
|
12336
13192
|
config,
|
|
12337
13193
|
skippedMcpConfigs,
|
|
12338
13194
|
templateConfig: templateConfigResult,
|
|
12339
|
-
cicdConfig
|
|
13195
|
+
cicdConfig,
|
|
13196
|
+
claudeSettings
|
|
12340
13197
|
};
|
|
12341
13198
|
}
|
|
12342
|
-
async function executeInstallation(projectPath, config, registry, templatesPath, options, cicdConfig) {
|
|
13199
|
+
async function executeInstallation(projectPath, config, registry, templatesPath, options, cicdConfig, claudeSettings) {
|
|
12343
13200
|
logger.newline();
|
|
12344
13201
|
logger.title("Installing Configuration");
|
|
12345
13202
|
if (config.scaffold.type === "full-project") {
|
|
@@ -12361,6 +13218,28 @@ async function executeInstallation(projectPath, config, registry, templatesPath,
|
|
|
12361
13218
|
} else if (claudeMdResult.skipped) {
|
|
12362
13219
|
logger.info("CLAUDE.md already exists, skipped");
|
|
12363
13220
|
}
|
|
13221
|
+
if (claudeSettings) {
|
|
13222
|
+
const settingsResult = await generateSettingsWithSpinner(projectPath, {
|
|
13223
|
+
claudeSettings,
|
|
13224
|
+
includeCoAuthor: config.preferences.includeCoAuthor,
|
|
13225
|
+
overwrite: options.force
|
|
13226
|
+
});
|
|
13227
|
+
if (settingsResult.error) {
|
|
13228
|
+
logger.warn(`settings.json generation warning: ${settingsResult.error}`);
|
|
13229
|
+
} else if (settingsResult.skipped) {
|
|
13230
|
+
logger.info("settings.json already exists, skipped");
|
|
13231
|
+
}
|
|
13232
|
+
const settingsLocalResult = await generateSettingsLocalWithSpinner(projectPath, {
|
|
13233
|
+
claudeSettings,
|
|
13234
|
+
includeCoAuthor: config.preferences.includeCoAuthor,
|
|
13235
|
+
overwrite: options.force
|
|
13236
|
+
});
|
|
13237
|
+
if (settingsLocalResult.error) {
|
|
13238
|
+
logger.warn(`settings.local.json generation warning: ${settingsLocalResult.error}`);
|
|
13239
|
+
} else if (settingsLocalResult.skipped) {
|
|
13240
|
+
logger.info("settings.local.json already exists, skipped");
|
|
13241
|
+
}
|
|
13242
|
+
}
|
|
12364
13243
|
const modulesByCategory = {
|
|
12365
13244
|
agents: filterModules(registry, "agents", config.modules.agents.selected),
|
|
12366
13245
|
skills: filterModules(registry, "skills", config.modules.skills.selected),
|