@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.cjs
CHANGED
|
@@ -274,15 +274,10 @@ var BUNDLES = [
|
|
|
274
274
|
moduleDetails: {
|
|
275
275
|
agents: [
|
|
276
276
|
{
|
|
277
|
-
id: "
|
|
278
|
-
role: "
|
|
277
|
+
id: "frontend-engineer",
|
|
278
|
+
role: "Frontend Development",
|
|
279
279
|
responsibilities: ["Component design", "State management", "Performance optimization"]
|
|
280
280
|
},
|
|
281
|
-
{
|
|
282
|
-
id: "tanstack-start-engineer",
|
|
283
|
-
role: "TanStack Specialist",
|
|
284
|
-
responsibilities: ["Router setup", "Query patterns", "SSR configuration"]
|
|
285
|
-
},
|
|
286
281
|
{
|
|
287
282
|
id: "ux-ui-designer",
|
|
288
283
|
role: "UI/UX Design",
|
|
@@ -290,6 +285,8 @@ var BUNDLES = [
|
|
|
290
285
|
}
|
|
291
286
|
],
|
|
292
287
|
skills: [
|
|
288
|
+
{ id: "react-patterns", purpose: "React component patterns" },
|
|
289
|
+
{ id: "tanstack-start-patterns", purpose: "TanStack Router/Start patterns" },
|
|
293
290
|
{ id: "web-app-testing", purpose: "React Testing Library patterns" },
|
|
294
291
|
{ id: "shadcn-specialist", purpose: "Shadcn UI component usage" },
|
|
295
292
|
{ id: "accessibility-audit", purpose: "WCAG compliance" },
|
|
@@ -301,9 +298,10 @@ var BUNDLES = [
|
|
|
301
298
|
docs: [{ id: "design-standards", topic: "UI/UX design standards" }]
|
|
302
299
|
},
|
|
303
300
|
modules: [
|
|
304
|
-
{ id: "
|
|
305
|
-
{ id: "tanstack-start-engineer", category: "agents" },
|
|
301
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
306
302
|
{ id: "ux-ui-designer", category: "agents" },
|
|
303
|
+
{ id: "react-patterns", category: "skills" },
|
|
304
|
+
{ id: "tanstack-start-patterns", category: "skills" },
|
|
307
305
|
{ id: "web-app-testing", category: "skills" },
|
|
308
306
|
{ id: "shadcn-specialist", category: "skills" },
|
|
309
307
|
{ id: "accessibility-audit", category: "skills" },
|
|
@@ -339,15 +337,10 @@ var BUNDLES = [
|
|
|
339
337
|
moduleDetails: {
|
|
340
338
|
agents: [
|
|
341
339
|
{
|
|
342
|
-
id: "
|
|
343
|
-
role: "
|
|
340
|
+
id: "frontend-engineer",
|
|
341
|
+
role: "Frontend Development",
|
|
344
342
|
responsibilities: ["Routing", "Islands architecture", "Build optimization"]
|
|
345
343
|
},
|
|
346
|
-
{
|
|
347
|
-
id: "react-senior-dev",
|
|
348
|
-
role: "React Components",
|
|
349
|
-
responsibilities: ["Interactive components", "Client hydration"]
|
|
350
|
-
},
|
|
351
344
|
{
|
|
352
345
|
id: "seo-ai-specialist",
|
|
353
346
|
role: "SEO Optimization",
|
|
@@ -355,6 +348,8 @@ var BUNDLES = [
|
|
|
355
348
|
}
|
|
356
349
|
],
|
|
357
350
|
skills: [
|
|
351
|
+
{ id: "astro-patterns", purpose: "Astro-specific patterns" },
|
|
352
|
+
{ id: "react-patterns", purpose: "React island components" },
|
|
358
353
|
{ id: "web-app-testing", purpose: "Component testing" },
|
|
359
354
|
{ id: "vercel-specialist", purpose: "Deployment optimization" },
|
|
360
355
|
{ id: "performance-audit", purpose: "Core Web Vitals" }
|
|
@@ -363,9 +358,10 @@ var BUNDLES = [
|
|
|
363
358
|
docs: []
|
|
364
359
|
},
|
|
365
360
|
modules: [
|
|
366
|
-
{ id: "
|
|
367
|
-
{ id: "react-senior-dev", category: "agents" },
|
|
361
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
368
362
|
{ id: "seo-ai-specialist", category: "agents" },
|
|
363
|
+
{ id: "astro-patterns", category: "skills" },
|
|
364
|
+
{ id: "react-patterns", category: "skills" },
|
|
369
365
|
{ id: "web-app-testing", category: "skills" },
|
|
370
366
|
{ id: "vercel-specialist", category: "skills" },
|
|
371
367
|
{ id: "performance-audit", category: "skills" }
|
|
@@ -398,17 +394,12 @@ var BUNDLES = [
|
|
|
398
394
|
moduleDetails: {
|
|
399
395
|
agents: [
|
|
400
396
|
{
|
|
401
|
-
id: "
|
|
402
|
-
role: "
|
|
403
|
-
responsibilities: ["App Router", "Server Actions", "
|
|
404
|
-
},
|
|
405
|
-
{
|
|
406
|
-
id: "react-senior-dev",
|
|
407
|
-
role: "React Components",
|
|
408
|
-
responsibilities: ["Client components", "State management"]
|
|
397
|
+
id: "frontend-engineer",
|
|
398
|
+
role: "Frontend Development",
|
|
399
|
+
responsibilities: ["App Router", "Server Actions", "Client components"]
|
|
409
400
|
},
|
|
410
401
|
{
|
|
411
|
-
id: "
|
|
402
|
+
id: "database-engineer",
|
|
412
403
|
role: "Database",
|
|
413
404
|
responsibilities: ["Schema design", "Migrations", "Query optimization"]
|
|
414
405
|
},
|
|
@@ -419,6 +410,9 @@ var BUNDLES = [
|
|
|
419
410
|
}
|
|
420
411
|
],
|
|
421
412
|
skills: [
|
|
413
|
+
{ id: "nextjs-patterns", purpose: "Next.js App Router patterns" },
|
|
414
|
+
{ id: "react-patterns", purpose: "React component patterns" },
|
|
415
|
+
{ id: "prisma-patterns", purpose: "Prisma ORM patterns" },
|
|
422
416
|
{ id: "web-app-testing", purpose: "Next.js testing patterns" },
|
|
423
417
|
{ id: "shadcn-specialist", purpose: "UI components" },
|
|
424
418
|
{ id: "vercel-specialist", purpose: "Deployment" },
|
|
@@ -430,10 +424,12 @@ var BUNDLES = [
|
|
|
430
424
|
docs: []
|
|
431
425
|
},
|
|
432
426
|
modules: [
|
|
433
|
-
{ id: "
|
|
434
|
-
{ id: "
|
|
435
|
-
{ id: "prisma-engineer", category: "agents" },
|
|
427
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
428
|
+
{ id: "database-engineer", category: "agents" },
|
|
436
429
|
{ id: "ux-ui-designer", category: "agents" },
|
|
430
|
+
{ id: "nextjs-patterns", category: "skills" },
|
|
431
|
+
{ id: "react-patterns", category: "skills" },
|
|
432
|
+
{ id: "prisma-patterns", category: "skills" },
|
|
437
433
|
{ id: "web-app-testing", category: "skills" },
|
|
438
434
|
{ id: "shadcn-specialist", category: "skills" },
|
|
439
435
|
{ id: "vercel-specialist", category: "skills" },
|
|
@@ -469,12 +465,12 @@ var BUNDLES = [
|
|
|
469
465
|
moduleDetails: {
|
|
470
466
|
agents: [
|
|
471
467
|
{
|
|
472
|
-
id: "
|
|
473
|
-
role: "
|
|
468
|
+
id: "api-engineer",
|
|
469
|
+
role: "API Development",
|
|
474
470
|
responsibilities: ["Route design", "Middleware", "Error handling"]
|
|
475
471
|
},
|
|
476
472
|
{
|
|
477
|
-
id: "
|
|
473
|
+
id: "database-engineer",
|
|
478
474
|
role: "Database",
|
|
479
475
|
responsibilities: ["Schema", "Migrations", "Queries"]
|
|
480
476
|
},
|
|
@@ -485,6 +481,8 @@ var BUNDLES = [
|
|
|
485
481
|
}
|
|
486
482
|
],
|
|
487
483
|
skills: [
|
|
484
|
+
{ id: "express-patterns", purpose: "Express.js patterns" },
|
|
485
|
+
{ id: "prisma-patterns", purpose: "Prisma ORM patterns" },
|
|
488
486
|
{ id: "api-app-testing", purpose: "API testing with supertest" },
|
|
489
487
|
{ id: "error-handling-patterns", purpose: "Error middleware" },
|
|
490
488
|
{ id: "security-testing", purpose: "Security best practices" }
|
|
@@ -493,9 +491,11 @@ var BUNDLES = [
|
|
|
493
491
|
docs: [{ id: "architecture-patterns", topic: "API architecture patterns" }]
|
|
494
492
|
},
|
|
495
493
|
modules: [
|
|
496
|
-
{ id: "
|
|
497
|
-
{ id: "
|
|
494
|
+
{ id: "api-engineer", category: "agents" },
|
|
495
|
+
{ id: "database-engineer", category: "agents" },
|
|
498
496
|
{ id: "node-typescript-engineer", category: "agents" },
|
|
497
|
+
{ id: "express-patterns", category: "skills" },
|
|
498
|
+
{ id: "prisma-patterns", category: "skills" },
|
|
499
499
|
{ id: "api-app-testing", category: "skills" },
|
|
500
500
|
{ id: "error-handling-patterns", category: "skills" },
|
|
501
501
|
{ id: "security-testing", category: "skills" },
|
|
@@ -529,13 +529,13 @@ var BUNDLES = [
|
|
|
529
529
|
moduleDetails: {
|
|
530
530
|
agents: [
|
|
531
531
|
{
|
|
532
|
-
id: "
|
|
533
|
-
role: "
|
|
532
|
+
id: "api-engineer",
|
|
533
|
+
role: "API Development",
|
|
534
534
|
responsibilities: ["Route handlers", "Middleware", "OpenAPI integration"]
|
|
535
535
|
},
|
|
536
536
|
{
|
|
537
|
-
id: "
|
|
538
|
-
role: "
|
|
537
|
+
id: "database-engineer",
|
|
538
|
+
role: "Database",
|
|
539
539
|
responsibilities: ["Schema design", "Migrations", "Type-safe queries"]
|
|
540
540
|
},
|
|
541
541
|
{
|
|
@@ -545,6 +545,8 @@ var BUNDLES = [
|
|
|
545
545
|
}
|
|
546
546
|
],
|
|
547
547
|
skills: [
|
|
548
|
+
{ id: "hono-patterns", purpose: "Hono framework patterns" },
|
|
549
|
+
{ id: "drizzle-patterns", purpose: "Drizzle ORM patterns" },
|
|
548
550
|
{ id: "api-app-testing", purpose: "Hono testing patterns" },
|
|
549
551
|
{ id: "error-handling-patterns", purpose: "Error middleware" },
|
|
550
552
|
{ id: "security-testing", purpose: "Security validation" }
|
|
@@ -553,9 +555,11 @@ var BUNDLES = [
|
|
|
553
555
|
docs: [{ id: "architecture-patterns", topic: "API architecture patterns" }]
|
|
554
556
|
},
|
|
555
557
|
modules: [
|
|
556
|
-
{ id: "
|
|
557
|
-
{ id: "
|
|
558
|
+
{ id: "api-engineer", category: "agents" },
|
|
559
|
+
{ id: "database-engineer", category: "agents" },
|
|
558
560
|
{ id: "node-typescript-engineer", category: "agents" },
|
|
561
|
+
{ id: "hono-patterns", category: "skills" },
|
|
562
|
+
{ id: "drizzle-patterns", category: "skills" },
|
|
559
563
|
{ id: "api-app-testing", category: "skills" },
|
|
560
564
|
{ id: "error-handling-patterns", category: "skills" },
|
|
561
565
|
{ id: "security-testing", category: "skills" },
|
|
@@ -786,7 +790,8 @@ var BUNDLES = [
|
|
|
786
790
|
tags: ["database", "drizzle", "orm"],
|
|
787
791
|
alternativeTo: ["prisma-database", "mongoose-database"],
|
|
788
792
|
modules: [
|
|
789
|
-
{ id: "
|
|
793
|
+
{ id: "database-engineer", category: "agents" },
|
|
794
|
+
{ id: "drizzle-patterns", category: "skills" },
|
|
790
795
|
{ id: "json-data-auditor", category: "skills" }
|
|
791
796
|
]
|
|
792
797
|
},
|
|
@@ -800,7 +805,8 @@ var BUNDLES = [
|
|
|
800
805
|
tags: ["database", "prisma", "orm"],
|
|
801
806
|
alternativeTo: ["drizzle-database", "mongoose-database"],
|
|
802
807
|
modules: [
|
|
803
|
-
{ id: "
|
|
808
|
+
{ id: "database-engineer", category: "agents" },
|
|
809
|
+
{ id: "prisma-patterns", category: "skills" },
|
|
804
810
|
{ id: "json-data-auditor", category: "skills" }
|
|
805
811
|
]
|
|
806
812
|
},
|
|
@@ -814,7 +820,8 @@ var BUNDLES = [
|
|
|
814
820
|
tags: ["database", "mongodb", "mongoose", "nosql"],
|
|
815
821
|
alternativeTo: ["drizzle-database", "prisma-database"],
|
|
816
822
|
modules: [
|
|
817
|
-
{ id: "
|
|
823
|
+
{ id: "database-engineer", category: "agents" },
|
|
824
|
+
{ id: "mongoose-patterns", category: "skills" },
|
|
818
825
|
{ id: "json-data-auditor", category: "skills" }
|
|
819
826
|
]
|
|
820
827
|
},
|
|
@@ -831,7 +838,8 @@ var BUNDLES = [
|
|
|
831
838
|
tags: ["api", "hono", "backend"],
|
|
832
839
|
alternativeTo: ["express-api", "fastify-api", "nestjs-api"],
|
|
833
840
|
modules: [
|
|
834
|
-
{ id: "
|
|
841
|
+
{ id: "api-engineer", category: "agents" },
|
|
842
|
+
{ id: "hono-patterns", category: "skills" },
|
|
835
843
|
{ id: "api-app-testing", category: "skills" },
|
|
836
844
|
{ id: "error-handling-patterns", category: "skills" }
|
|
837
845
|
]
|
|
@@ -846,7 +854,8 @@ var BUNDLES = [
|
|
|
846
854
|
tags: ["api", "express", "backend"],
|
|
847
855
|
alternativeTo: ["hono-api", "fastify-api", "nestjs-api"],
|
|
848
856
|
modules: [
|
|
849
|
-
{ id: "
|
|
857
|
+
{ id: "api-engineer", category: "agents" },
|
|
858
|
+
{ id: "express-patterns", category: "skills" },
|
|
850
859
|
{ id: "api-app-testing", category: "skills" },
|
|
851
860
|
{ id: "error-handling-patterns", category: "skills" }
|
|
852
861
|
]
|
|
@@ -861,7 +870,8 @@ var BUNDLES = [
|
|
|
861
870
|
tags: ["api", "fastify", "backend", "performance"],
|
|
862
871
|
alternativeTo: ["hono-api", "express-api", "nestjs-api"],
|
|
863
872
|
modules: [
|
|
864
|
-
{ id: "
|
|
873
|
+
{ id: "api-engineer", category: "agents" },
|
|
874
|
+
{ id: "fastify-patterns", category: "skills" },
|
|
865
875
|
{ id: "api-app-testing", category: "skills" },
|
|
866
876
|
{ id: "error-handling-patterns", category: "skills" }
|
|
867
877
|
]
|
|
@@ -876,7 +886,8 @@ var BUNDLES = [
|
|
|
876
886
|
tags: ["api", "nestjs", "backend", "enterprise"],
|
|
877
887
|
alternativeTo: ["hono-api", "express-api", "fastify-api"],
|
|
878
888
|
modules: [
|
|
879
|
-
{ id: "
|
|
889
|
+
{ id: "api-engineer", category: "agents" },
|
|
890
|
+
{ id: "nestjs-patterns", category: "skills" },
|
|
880
891
|
{ id: "api-app-testing", category: "skills" },
|
|
881
892
|
{ id: "error-handling-patterns", category: "skills" }
|
|
882
893
|
]
|
|
@@ -893,8 +904,9 @@ var BUNDLES = [
|
|
|
893
904
|
techStack: ["React", "Shadcn UI", "Tailwind CSS", "Radix UI"],
|
|
894
905
|
tags: ["react", "ui", "components"],
|
|
895
906
|
modules: [
|
|
896
|
-
{ id: "
|
|
907
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
897
908
|
{ id: "ux-ui-designer", category: "agents" },
|
|
909
|
+
{ id: "react-patterns", category: "skills" },
|
|
898
910
|
{ id: "shadcn-specialist", category: "skills" },
|
|
899
911
|
{ id: "brand-guidelines", category: "skills" },
|
|
900
912
|
{ id: "accessibility-audit", category: "skills" }
|
|
@@ -909,7 +921,8 @@ var BUNDLES = [
|
|
|
909
921
|
techStack: ["React Hook Form", "Zod", "React", "TypeScript"],
|
|
910
922
|
tags: ["react", "forms", "validation"],
|
|
911
923
|
modules: [
|
|
912
|
-
{ id: "
|
|
924
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
925
|
+
{ id: "react-patterns", category: "skills" },
|
|
913
926
|
{ id: "react-hook-form-patterns", category: "skills" },
|
|
914
927
|
{ id: "shadcn-specialist", category: "skills" }
|
|
915
928
|
]
|
|
@@ -924,7 +937,8 @@ var BUNDLES = [
|
|
|
924
937
|
tags: ["react", "state", "zustand"],
|
|
925
938
|
alternativeTo: ["react-state-redux"],
|
|
926
939
|
modules: [
|
|
927
|
-
{ id: "
|
|
940
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
941
|
+
{ id: "react-patterns", category: "skills" },
|
|
928
942
|
{ id: "zustand-patterns", category: "skills" },
|
|
929
943
|
{ id: "tanstack-query-patterns", category: "skills" }
|
|
930
944
|
]
|
|
@@ -939,7 +953,8 @@ var BUNDLES = [
|
|
|
939
953
|
tags: ["react", "state", "redux"],
|
|
940
954
|
alternativeTo: ["react-state-zustand"],
|
|
941
955
|
modules: [
|
|
942
|
-
{ id: "
|
|
956
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
957
|
+
{ id: "react-patterns", category: "skills" },
|
|
943
958
|
{ id: "redux-toolkit-patterns", category: "skills" },
|
|
944
959
|
{ id: "tanstack-query-patterns", category: "skills", optional: true }
|
|
945
960
|
]
|
|
@@ -953,7 +968,8 @@ var BUNDLES = [
|
|
|
953
968
|
techStack: ["NextAuth.js", "Auth.js", "Next.js", "Prisma"],
|
|
954
969
|
tags: ["nextjs", "auth", "oauth"],
|
|
955
970
|
modules: [
|
|
956
|
-
{ id: "
|
|
971
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
972
|
+
{ id: "nextjs-patterns", category: "skills" },
|
|
957
973
|
{ id: "nextauth-patterns", category: "skills" },
|
|
958
974
|
{ id: "security-testing", category: "skills" }
|
|
959
975
|
]
|
|
@@ -967,8 +983,9 @@ var BUNDLES = [
|
|
|
967
983
|
techStack: ["next-intl", "Next.js", "React", "TypeScript"],
|
|
968
984
|
tags: ["nextjs", "i18n", "internationalization"],
|
|
969
985
|
modules: [
|
|
970
|
-
{ id: "
|
|
986
|
+
{ id: "frontend-engineer", category: "agents" },
|
|
971
987
|
{ id: "i18n-specialist", category: "agents", optional: true },
|
|
988
|
+
{ id: "nextjs-patterns", category: "skills" },
|
|
972
989
|
{ id: "i18n-patterns", category: "skills" }
|
|
973
990
|
]
|
|
974
991
|
},
|
|
@@ -1088,7 +1105,7 @@ var BUNDLES = [
|
|
|
1088
1105
|
}
|
|
1089
1106
|
],
|
|
1090
1107
|
skills: [
|
|
1091
|
-
{ id: "
|
|
1108
|
+
{ id: "markdown-formatter", purpose: "Markdown formatting" },
|
|
1092
1109
|
{ id: "mermaid-diagram-specialist", purpose: "Diagram creation" }
|
|
1093
1110
|
],
|
|
1094
1111
|
commands: [
|
|
@@ -1103,7 +1120,7 @@ var BUNDLES = [
|
|
|
1103
1120
|
},
|
|
1104
1121
|
modules: [
|
|
1105
1122
|
{ id: "tech-writer", category: "agents" },
|
|
1106
|
-
{ id: "
|
|
1123
|
+
{ id: "markdown-formatter", category: "skills" },
|
|
1107
1124
|
{ id: "mermaid-diagram-specialist", category: "skills" },
|
|
1108
1125
|
{ id: "update-docs", category: "commands" },
|
|
1109
1126
|
{ id: "markdown-format", category: "commands" },
|
|
@@ -6124,11 +6141,13 @@ function processTemplate(template, projectInfo, options) {
|
|
|
6124
6141
|
const commands = options?.templateConfig?.commands;
|
|
6125
6142
|
const targets = options?.templateConfig?.targets;
|
|
6126
6143
|
const preferences = options?.claudeConfig?.preferences;
|
|
6144
|
+
const standards = options?.claudeConfig?.extras?.standards;
|
|
6127
6145
|
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 || "");
|
|
6128
6146
|
const packageManager = preferences?.packageManager || "pnpm";
|
|
6129
6147
|
content = content.replace(/\{\{PACKAGE_MANAGER\}\}/g, packageManager);
|
|
6130
|
-
const coverageTarget = targets && "coverage" in targets ? String(targets.coverage) : "90";
|
|
6148
|
+
const coverageTarget = standards?.testing?.coverageTarget ? String(standards.testing.coverageTarget) : targets && "coverage" in targets ? String(targets.coverage) : "90";
|
|
6131
6149
|
content = content.replace(/\{\{COVERAGE_TARGET\}\}/g, coverageTarget);
|
|
6150
|
+
content = processStandardsPlaceholders(content, standards, preferences);
|
|
6132
6151
|
if (projectInfo.domain) {
|
|
6133
6152
|
content = content.replace(/\{\{#if DOMAIN\}\}/g, "").replace(/\{\{\/if\}\}/g, "").replace(/\{\{DOMAIN\}\}/g, projectInfo.domain);
|
|
6134
6153
|
} else {
|
|
@@ -6225,6 +6244,55 @@ function generateCommandsSection(commands, packageManager) {
|
|
|
6225
6244
|
lines.push("```");
|
|
6226
6245
|
return lines.join("\n");
|
|
6227
6246
|
}
|
|
6247
|
+
function processStandardsPlaceholders(content, standards, preferences) {
|
|
6248
|
+
let result = content;
|
|
6249
|
+
const primaryLanguage = "TypeScript";
|
|
6250
|
+
result = result.replace(/\{\{PRIMARY_LANGUAGE\}\}/g, primaryLanguage);
|
|
6251
|
+
const maxFileLines = standards?.code?.maxFileLines?.toString() || "500";
|
|
6252
|
+
result = result.replace(/\{\{MAX_FILE_LINES\}\}/g, maxFileLines);
|
|
6253
|
+
const testPattern = standards?.testing?.testPattern === "gwt" ? "GWT (Given-When-Then)" : "AAA (Arrange, Act, Assert)";
|
|
6254
|
+
result = result.replace(/\{\{TEST_PATTERN\}\}/g, testPattern);
|
|
6255
|
+
const responseLanguage = preferences?.responseLanguage === "es" ? "Spanish" : preferences?.responseLanguage === "en" ? "English" : "Spanish";
|
|
6256
|
+
result = result.replace(/\{\{RESPONSE_LANGUAGE\}\}/g, responseLanguage);
|
|
6257
|
+
if (standards?.code?.namedExportsOnly) {
|
|
6258
|
+
result = result.replace(/\{\{#if NAMED_EXPORTS_ONLY\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6259
|
+
} else {
|
|
6260
|
+
result = result.replace(/\{\{#if NAMED_EXPORTS_ONLY\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6261
|
+
}
|
|
6262
|
+
if (standards?.code?.jsDocRequired) {
|
|
6263
|
+
result = result.replace(/\{\{#if JSDOC_REQUIRED\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6264
|
+
} else {
|
|
6265
|
+
result = result.replace(/\{\{#if JSDOC_REQUIRED\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6266
|
+
}
|
|
6267
|
+
if (standards?.code?.roroPattern) {
|
|
6268
|
+
result = result.replace(/\{\{#if RORO_PATTERN\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6269
|
+
} else {
|
|
6270
|
+
result = result.replace(/\{\{#if RORO_PATTERN\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6271
|
+
}
|
|
6272
|
+
if (standards?.testing?.tddRequired) {
|
|
6273
|
+
result = result.replace(/\{\{#if TDD_REQUIRED\}\}/g, "").replace(/\{\{else\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6274
|
+
} else {
|
|
6275
|
+
result = result.replace(/\{\{#if TDD_REQUIRED\}\}[\s\S]*?\{\{else\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6276
|
+
}
|
|
6277
|
+
const testLocation = standards?.testing?.testLocation;
|
|
6278
|
+
if (testLocation) {
|
|
6279
|
+
const testLocationText = testLocation === "colocated" ? "Co-located with source" : "Separate test directory";
|
|
6280
|
+
result = result.replace(/\{\{#if TEST_LOCATION\}\}/g, "").replace(/\{\{\/if\}\}/g, "").replace(/\{\{TEST_LOCATION\}\}/g, testLocationText);
|
|
6281
|
+
} else {
|
|
6282
|
+
result = result.replace(/\{\{#if TEST_LOCATION\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6283
|
+
}
|
|
6284
|
+
if (preferences?.includeCoAuthor) {
|
|
6285
|
+
result = result.replace(/\{\{#if INCLUDE_CO_AUTHOR\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6286
|
+
} else {
|
|
6287
|
+
result = result.replace(/\{\{#if INCLUDE_CO_AUTHOR\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6288
|
+
}
|
|
6289
|
+
if (preferences?.responseLanguage) {
|
|
6290
|
+
result = result.replace(/\{\{#if RESPONSE_LANGUAGE\}\}/g, "").replace(/\{\{\/if\}\}/g, "");
|
|
6291
|
+
} else {
|
|
6292
|
+
result = result.replace(/\{\{#if RESPONSE_LANGUAGE\}\}[\s\S]*?\{\{\/if\}\}/g, "");
|
|
6293
|
+
}
|
|
6294
|
+
return result;
|
|
6295
|
+
}
|
|
6228
6296
|
function getMinimalTemplate() {
|
|
6229
6297
|
return `# CLAUDE.md
|
|
6230
6298
|
|
|
@@ -6770,6 +6838,242 @@ async function generateScaffoldWithProgress(projectPath, options) {
|
|
|
6770
6838
|
);
|
|
6771
6839
|
}
|
|
6772
6840
|
|
|
6841
|
+
// src/lib/scaffold/settings-generator.ts
|
|
6842
|
+
init_cjs_shims();
|
|
6843
|
+
|
|
6844
|
+
// src/constants/claude-settings-defaults.ts
|
|
6845
|
+
init_cjs_shims();
|
|
6846
|
+
var DEFAULT_CLAUDE_SETTINGS = {
|
|
6847
|
+
model: "sonnet",
|
|
6848
|
+
alwaysThinkingEnabled: false,
|
|
6849
|
+
sandbox: {
|
|
6850
|
+
enabled: false,
|
|
6851
|
+
autoAllowBashIfSandboxed: true
|
|
6852
|
+
},
|
|
6853
|
+
permissions: {
|
|
6854
|
+
allow: [],
|
|
6855
|
+
deny: [],
|
|
6856
|
+
ask: [],
|
|
6857
|
+
defaultMode: "acceptEdits"
|
|
6858
|
+
},
|
|
6859
|
+
attribution: {
|
|
6860
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)\n\n Co-Authored-By: Claude <noreply@anthropic.com>",
|
|
6861
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
6862
|
+
},
|
|
6863
|
+
cleanupPeriodDays: 30,
|
|
6864
|
+
stopNotification: "beep"
|
|
6865
|
+
};
|
|
6866
|
+
var ATTRIBUTION_NO_COAUTHOR = {
|
|
6867
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)",
|
|
6868
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
6869
|
+
};
|
|
6870
|
+
var ATTRIBUTION_WITH_COAUTHOR = {
|
|
6871
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)\n\n Co-Authored-By: Claude <noreply@anthropic.com>",
|
|
6872
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
6873
|
+
};
|
|
6874
|
+
var BEEP_COMMAND = "echo -ne '\\007'";
|
|
6875
|
+
var MODEL_DESCRIPTIONS = {
|
|
6876
|
+
sonnet: "Claude Sonnet - Balanced performance and speed (recommended)",
|
|
6877
|
+
opus: "Claude Opus - Most capable, best for complex tasks",
|
|
6878
|
+
haiku: "Claude Haiku - Fastest, best for simple tasks",
|
|
6879
|
+
default: "Default - Let Claude Code decide based on task"
|
|
6880
|
+
};
|
|
6881
|
+
var PERMISSION_MODE_DESCRIPTIONS = {
|
|
6882
|
+
acceptEdits: "Accept edits automatically, ask for other operations",
|
|
6883
|
+
askAlways: "Ask for confirmation on all operations",
|
|
6884
|
+
viewOnly: "Read-only mode, no modifications allowed"
|
|
6885
|
+
};
|
|
6886
|
+
var STOP_NOTIFICATION_DESCRIPTIONS = {
|
|
6887
|
+
beep: "Play a beep sound when task completes",
|
|
6888
|
+
custom: "Run a custom command when task completes",
|
|
6889
|
+
none: "No notification"
|
|
6890
|
+
};
|
|
6891
|
+
var CLAUDE_SETTINGS_PRESETS = {
|
|
6892
|
+
/** Default preset - balanced settings */
|
|
6893
|
+
default: {
|
|
6894
|
+
...DEFAULT_CLAUDE_SETTINGS
|
|
6895
|
+
},
|
|
6896
|
+
/** Performance preset - faster model, less confirmations */
|
|
6897
|
+
performance: {
|
|
6898
|
+
...DEFAULT_CLAUDE_SETTINGS,
|
|
6899
|
+
model: "haiku",
|
|
6900
|
+
permissions: {
|
|
6901
|
+
...DEFAULT_CLAUDE_SETTINGS.permissions,
|
|
6902
|
+
defaultMode: "acceptEdits"
|
|
6903
|
+
}
|
|
6904
|
+
},
|
|
6905
|
+
/** Quality preset - best model, extended thinking */
|
|
6906
|
+
quality: {
|
|
6907
|
+
...DEFAULT_CLAUDE_SETTINGS,
|
|
6908
|
+
model: "opus",
|
|
6909
|
+
alwaysThinkingEnabled: true
|
|
6910
|
+
},
|
|
6911
|
+
/** Secure preset - sandbox enabled, more confirmations */
|
|
6912
|
+
secure: {
|
|
6913
|
+
...DEFAULT_CLAUDE_SETTINGS,
|
|
6914
|
+
sandbox: {
|
|
6915
|
+
enabled: true,
|
|
6916
|
+
autoAllowBashIfSandboxed: true
|
|
6917
|
+
},
|
|
6918
|
+
permissions: {
|
|
6919
|
+
...DEFAULT_CLAUDE_SETTINGS.permissions,
|
|
6920
|
+
defaultMode: "askAlways"
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6923
|
+
};
|
|
6924
|
+
var PRESET_DESCRIPTIONS2 = {
|
|
6925
|
+
default: "Balanced settings for most projects",
|
|
6926
|
+
performance: "Faster responses with Haiku model",
|
|
6927
|
+
quality: "Best quality with Opus model and extended thinking",
|
|
6928
|
+
secure: "Enhanced security with sandbox and confirmations"
|
|
6929
|
+
};
|
|
6930
|
+
|
|
6931
|
+
// src/lib/scaffold/settings-generator.ts
|
|
6932
|
+
init_fs();
|
|
6933
|
+
async function generateSettings(projectPath, options) {
|
|
6934
|
+
const settingsPath = joinPath(projectPath, ".claude", "settings.json");
|
|
6935
|
+
const exists = await pathExists(settingsPath);
|
|
6936
|
+
if (exists && !options?.overwrite) {
|
|
6937
|
+
return {
|
|
6938
|
+
created: false,
|
|
6939
|
+
skipped: true,
|
|
6940
|
+
path: settingsPath
|
|
6941
|
+
};
|
|
6942
|
+
}
|
|
6943
|
+
try {
|
|
6944
|
+
const settings = buildSettingsJson(options);
|
|
6945
|
+
await writeJson(settingsPath, settings, { spaces: 2 });
|
|
6946
|
+
return {
|
|
6947
|
+
created: true,
|
|
6948
|
+
skipped: false,
|
|
6949
|
+
path: settingsPath
|
|
6950
|
+
};
|
|
6951
|
+
} catch (error) {
|
|
6952
|
+
return {
|
|
6953
|
+
created: false,
|
|
6954
|
+
skipped: false,
|
|
6955
|
+
path: settingsPath,
|
|
6956
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6957
|
+
};
|
|
6958
|
+
}
|
|
6959
|
+
}
|
|
6960
|
+
async function generateSettingsWithSpinner(projectPath, options) {
|
|
6961
|
+
return withSpinner("Generating settings.json...", () => generateSettings(projectPath, options), {
|
|
6962
|
+
successText: "Created settings.json"
|
|
6963
|
+
});
|
|
6964
|
+
}
|
|
6965
|
+
async function generateSettingsLocal(projectPath, options) {
|
|
6966
|
+
const settingsPath = joinPath(projectPath, ".claude", "settings.local.json");
|
|
6967
|
+
const exists = await pathExists(settingsPath);
|
|
6968
|
+
if (exists && !options?.overwrite) {
|
|
6969
|
+
return {
|
|
6970
|
+
created: false,
|
|
6971
|
+
skipped: true,
|
|
6972
|
+
path: settingsPath
|
|
6973
|
+
};
|
|
6974
|
+
}
|
|
6975
|
+
try {
|
|
6976
|
+
const settings = buildSettingsLocalJson(options);
|
|
6977
|
+
await writeJson(settingsPath, settings, { spaces: 2 });
|
|
6978
|
+
return {
|
|
6979
|
+
created: true,
|
|
6980
|
+
skipped: false,
|
|
6981
|
+
path: settingsPath
|
|
6982
|
+
};
|
|
6983
|
+
} catch (error) {
|
|
6984
|
+
return {
|
|
6985
|
+
created: false,
|
|
6986
|
+
skipped: false,
|
|
6987
|
+
path: settingsPath,
|
|
6988
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6989
|
+
};
|
|
6990
|
+
}
|
|
6991
|
+
}
|
|
6992
|
+
async function generateSettingsLocalWithSpinner(projectPath, options) {
|
|
6993
|
+
return withSpinner(
|
|
6994
|
+
"Generating settings.local.json...",
|
|
6995
|
+
() => generateSettingsLocal(projectPath, options),
|
|
6996
|
+
{
|
|
6997
|
+
successText: "Created settings.local.json"
|
|
6998
|
+
}
|
|
6999
|
+
);
|
|
7000
|
+
}
|
|
7001
|
+
function buildSettingsJson(options) {
|
|
7002
|
+
const claudeSettings = options?.claudeSettings || DEFAULT_CLAUDE_SETTINGS;
|
|
7003
|
+
const includeCoAuthor = options?.includeCoAuthor ?? true;
|
|
7004
|
+
const settings = {
|
|
7005
|
+
$schema: "https://json.schemastore.org/claude-code-settings.json"
|
|
7006
|
+
};
|
|
7007
|
+
if (claudeSettings.model && claudeSettings.model !== "default") {
|
|
7008
|
+
settings.model = claudeSettings.model;
|
|
7009
|
+
}
|
|
7010
|
+
if (claudeSettings.alwaysThinkingEnabled) {
|
|
7011
|
+
settings.alwaysThinkingEnabled = true;
|
|
7012
|
+
}
|
|
7013
|
+
if (claudeSettings.cleanupPeriodDays !== 30) {
|
|
7014
|
+
settings.cleanupPeriodDays = claudeSettings.cleanupPeriodDays;
|
|
7015
|
+
}
|
|
7016
|
+
settings.attribution = includeCoAuthor ? ATTRIBUTION_WITH_COAUTHOR : ATTRIBUTION_NO_COAUTHOR;
|
|
7017
|
+
settings.permissions = {
|
|
7018
|
+
allow: [],
|
|
7019
|
+
deny: []
|
|
7020
|
+
};
|
|
7021
|
+
if (claudeSettings.sandbox?.enabled) {
|
|
7022
|
+
settings.sandbox = {
|
|
7023
|
+
enabled: true,
|
|
7024
|
+
autoAllowBashIfSandboxed: claudeSettings.sandbox.autoAllowBashIfSandboxed ?? true
|
|
7025
|
+
};
|
|
7026
|
+
}
|
|
7027
|
+
return settings;
|
|
7028
|
+
}
|
|
7029
|
+
function buildSettingsLocalJson(options) {
|
|
7030
|
+
const claudeSettings = options?.claudeSettings || DEFAULT_CLAUDE_SETTINGS;
|
|
7031
|
+
const settings = {};
|
|
7032
|
+
const allow = [...options?.additionalAllow || []];
|
|
7033
|
+
const deny = [...options?.additionalDeny || []];
|
|
7034
|
+
if (claudeSettings.permissions?.allow) {
|
|
7035
|
+
allow.push(...claudeSettings.permissions.allow);
|
|
7036
|
+
}
|
|
7037
|
+
if (claudeSettings.permissions?.deny) {
|
|
7038
|
+
deny.push(...claudeSettings.permissions.deny);
|
|
7039
|
+
}
|
|
7040
|
+
settings.permissions = {
|
|
7041
|
+
allow: [...new Set(allow)],
|
|
7042
|
+
// Deduplicate
|
|
7043
|
+
deny: [...new Set(deny)],
|
|
7044
|
+
ask: claudeSettings.permissions?.ask || [],
|
|
7045
|
+
defaultMode: claudeSettings.permissions?.defaultMode || "acceptEdits"
|
|
7046
|
+
};
|
|
7047
|
+
if (claudeSettings.stopNotification && claudeSettings.stopNotification !== "none") {
|
|
7048
|
+
const command = claudeSettings.stopNotification === "custom" && claudeSettings.customStopCommand ? claudeSettings.customStopCommand : BEEP_COMMAND;
|
|
7049
|
+
settings.hooks = {
|
|
7050
|
+
Stop: [
|
|
7051
|
+
{
|
|
7052
|
+
hooks: [
|
|
7053
|
+
{
|
|
7054
|
+
type: "command",
|
|
7055
|
+
command,
|
|
7056
|
+
timeout: 5
|
|
7057
|
+
}
|
|
7058
|
+
]
|
|
7059
|
+
}
|
|
7060
|
+
],
|
|
7061
|
+
SubagentStop: [
|
|
7062
|
+
{
|
|
7063
|
+
hooks: [
|
|
7064
|
+
{
|
|
7065
|
+
type: "command",
|
|
7066
|
+
command,
|
|
7067
|
+
timeout: 5
|
|
7068
|
+
}
|
|
7069
|
+
]
|
|
7070
|
+
}
|
|
7071
|
+
]
|
|
7072
|
+
};
|
|
7073
|
+
}
|
|
7074
|
+
return settings;
|
|
7075
|
+
}
|
|
7076
|
+
|
|
6773
7077
|
// src/lib/templates/config-replacer.ts
|
|
6774
7078
|
init_cjs_shims();
|
|
6775
7079
|
var fs4 = __toESM(require("fs/promises"), 1);
|
|
@@ -8717,6 +9021,142 @@ async function promptCICDConfig(options) {
|
|
|
8717
9021
|
};
|
|
8718
9022
|
}
|
|
8719
9023
|
|
|
9024
|
+
// src/cli/prompts/claude-settings.ts
|
|
9025
|
+
init_cjs_shims();
|
|
9026
|
+
async function promptClaudeSettings(options) {
|
|
9027
|
+
logger.section("Claude Code Settings", "\u{1F916}");
|
|
9028
|
+
const wantToConfigure = await confirm({
|
|
9029
|
+
message: "Would you like to configure Claude Code settings?",
|
|
9030
|
+
default: true
|
|
9031
|
+
});
|
|
9032
|
+
if (!wantToConfigure) {
|
|
9033
|
+
return {
|
|
9034
|
+
...DEFAULT_CLAUDE_SETTINGS,
|
|
9035
|
+
attribution: options?.includeCoAuthor ? DEFAULT_CLAUDE_SETTINGS.attribution : {
|
|
9036
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)",
|
|
9037
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
9038
|
+
}
|
|
9039
|
+
};
|
|
9040
|
+
}
|
|
9041
|
+
const setupMode = await select({
|
|
9042
|
+
message: "How would you like to configure?",
|
|
9043
|
+
choices: [
|
|
9044
|
+
{ name: "Use a preset", value: "preset" },
|
|
9045
|
+
{ name: "Customize settings", value: "custom" }
|
|
9046
|
+
],
|
|
9047
|
+
default: "preset"
|
|
9048
|
+
});
|
|
9049
|
+
if (setupMode === "preset") {
|
|
9050
|
+
return promptClaudeSettingsPreset(options);
|
|
9051
|
+
}
|
|
9052
|
+
return promptClaudeSettingsCustom(options);
|
|
9053
|
+
}
|
|
9054
|
+
async function promptClaudeSettingsPreset(options) {
|
|
9055
|
+
const preset = await select({
|
|
9056
|
+
message: "Choose a settings preset:",
|
|
9057
|
+
choices: Object.entries(PRESET_DESCRIPTIONS2).map(([key, description]) => ({
|
|
9058
|
+
name: `${key.charAt(0).toUpperCase() + key.slice(1)} - ${description}`,
|
|
9059
|
+
value: key
|
|
9060
|
+
})),
|
|
9061
|
+
default: "default"
|
|
9062
|
+
});
|
|
9063
|
+
const config = { ...CLAUDE_SETTINGS_PRESETS[preset] };
|
|
9064
|
+
if (options?.includeCoAuthor === false) {
|
|
9065
|
+
config.attribution = {
|
|
9066
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)",
|
|
9067
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
9068
|
+
};
|
|
9069
|
+
}
|
|
9070
|
+
return config;
|
|
9071
|
+
}
|
|
9072
|
+
async function promptClaudeSettingsCustom(options) {
|
|
9073
|
+
const defaults = options?.defaults || DEFAULT_CLAUDE_SETTINGS;
|
|
9074
|
+
const model = await select({
|
|
9075
|
+
message: "Default Claude model:",
|
|
9076
|
+
choices: Object.entries(MODEL_DESCRIPTIONS).map(([key, description]) => ({
|
|
9077
|
+
name: description,
|
|
9078
|
+
value: key
|
|
9079
|
+
})),
|
|
9080
|
+
default: defaults.model || "sonnet"
|
|
9081
|
+
});
|
|
9082
|
+
const alwaysThinkingEnabled = await confirm({
|
|
9083
|
+
message: "Enable extended thinking by default? (better for complex tasks)",
|
|
9084
|
+
default: defaults.alwaysThinkingEnabled ?? false
|
|
9085
|
+
});
|
|
9086
|
+
const sandboxEnabled = await confirm({
|
|
9087
|
+
message: "Enable bash sandboxing? (isolates shell commands for security)",
|
|
9088
|
+
default: defaults.sandbox?.enabled ?? false
|
|
9089
|
+
});
|
|
9090
|
+
const permissionMode = await select({
|
|
9091
|
+
message: "Default permission mode:",
|
|
9092
|
+
choices: Object.entries(PERMISSION_MODE_DESCRIPTIONS).map(([key, description]) => ({
|
|
9093
|
+
name: description,
|
|
9094
|
+
value: key
|
|
9095
|
+
})),
|
|
9096
|
+
default: defaults.permissions?.defaultMode || "acceptEdits"
|
|
9097
|
+
});
|
|
9098
|
+
const cleanupPeriodStr = await input({
|
|
9099
|
+
message: "Session cleanup period (days, 0 = delete all immediately):",
|
|
9100
|
+
default: String(defaults.cleanupPeriodDays ?? 30),
|
|
9101
|
+
validate: (value) => {
|
|
9102
|
+
const num = Number.parseInt(value, 10);
|
|
9103
|
+
if (Number.isNaN(num) || num < 0 || num > 365) {
|
|
9104
|
+
return "Please enter a number between 0 and 365";
|
|
9105
|
+
}
|
|
9106
|
+
return true;
|
|
9107
|
+
}
|
|
9108
|
+
});
|
|
9109
|
+
const cleanupPeriodDays = Number.parseInt(cleanupPeriodStr, 10);
|
|
9110
|
+
const stopNotification = await select({
|
|
9111
|
+
message: "Notification when task completes:",
|
|
9112
|
+
choices: Object.entries(STOP_NOTIFICATION_DESCRIPTIONS).map(([key, description]) => ({
|
|
9113
|
+
name: description,
|
|
9114
|
+
value: key
|
|
9115
|
+
})),
|
|
9116
|
+
default: defaults.stopNotification || "beep"
|
|
9117
|
+
});
|
|
9118
|
+
let customStopCommand;
|
|
9119
|
+
if (stopNotification === "custom") {
|
|
9120
|
+
customStopCommand = await input({
|
|
9121
|
+
message: "Custom command to run on task completion:",
|
|
9122
|
+
default: defaults.customStopCommand || ""
|
|
9123
|
+
});
|
|
9124
|
+
}
|
|
9125
|
+
const config = {
|
|
9126
|
+
model,
|
|
9127
|
+
alwaysThinkingEnabled,
|
|
9128
|
+
sandbox: {
|
|
9129
|
+
enabled: sandboxEnabled,
|
|
9130
|
+
autoAllowBashIfSandboxed: true
|
|
9131
|
+
},
|
|
9132
|
+
permissions: {
|
|
9133
|
+
allow: defaults.permissions?.allow || [],
|
|
9134
|
+
deny: defaults.permissions?.deny || [],
|
|
9135
|
+
ask: defaults.permissions?.ask || [],
|
|
9136
|
+
defaultMode: permissionMode
|
|
9137
|
+
},
|
|
9138
|
+
attribution: options?.includeCoAuthor === false ? {
|
|
9139
|
+
commit: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)",
|
|
9140
|
+
pr: "\u{1F916} Generated with [Claude Code](https://claude.com/claude-code)"
|
|
9141
|
+
} : DEFAULT_CLAUDE_SETTINGS.attribution,
|
|
9142
|
+
cleanupPeriodDays,
|
|
9143
|
+
stopNotification,
|
|
9144
|
+
customStopCommand
|
|
9145
|
+
};
|
|
9146
|
+
if (stopNotification === "beep") {
|
|
9147
|
+
config.hooks = {
|
|
9148
|
+
Stop: [{ hooks: [{ type: "command", command: BEEP_COMMAND, timeout: 5 }] }],
|
|
9149
|
+
SubagentStop: [{ hooks: [{ type: "command", command: BEEP_COMMAND, timeout: 5 }] }]
|
|
9150
|
+
};
|
|
9151
|
+
} else if (stopNotification === "custom" && customStopCommand) {
|
|
9152
|
+
config.hooks = {
|
|
9153
|
+
Stop: [{ hooks: [{ type: "command", command: customStopCommand, timeout: 10 }] }],
|
|
9154
|
+
SubagentStop: [{ hooks: [{ type: "command", command: customStopCommand, timeout: 10 }] }]
|
|
9155
|
+
};
|
|
9156
|
+
}
|
|
9157
|
+
return config;
|
|
9158
|
+
}
|
|
9159
|
+
|
|
8720
9160
|
// src/cli/prompts/code-style.ts
|
|
8721
9161
|
init_cjs_shims();
|
|
8722
9162
|
var CODE_STYLE_TOOLS = [
|
|
@@ -9854,7 +10294,95 @@ async function promptSubagentStopHook() {
|
|
|
9854
10294
|
|
|
9855
10295
|
// src/cli/prompts/item-select.ts
|
|
9856
10296
|
init_cjs_shims();
|
|
9857
|
-
|
|
10297
|
+
|
|
10298
|
+
// src/cli/prompts/mutual-exclusivity.ts
|
|
10299
|
+
init_cjs_shims();
|
|
10300
|
+
function getConflictingSelections(module2, selectedIds) {
|
|
10301
|
+
if (!module2.alternativeTo) {
|
|
10302
|
+
return [];
|
|
10303
|
+
}
|
|
10304
|
+
return module2.alternativeTo.filter((altId) => selectedIds.includes(altId));
|
|
10305
|
+
}
|
|
10306
|
+
function createChoicesWithExclusivity(modules, selectedIds, options) {
|
|
10307
|
+
const choices = [];
|
|
10308
|
+
for (const module2 of modules) {
|
|
10309
|
+
const conflicts = getConflictingSelections(module2, selectedIds);
|
|
10310
|
+
const isConflicting = conflicts.length > 0;
|
|
10311
|
+
const isPreselected = options?.preselected?.includes(module2.id);
|
|
10312
|
+
const isSelected = selectedIds.includes(module2.id);
|
|
10313
|
+
let name = module2.name;
|
|
10314
|
+
let description = module2.description;
|
|
10315
|
+
let disabled = false;
|
|
10316
|
+
if (isConflicting) {
|
|
10317
|
+
const conflictNames = conflicts.join(", ");
|
|
10318
|
+
disabled = options?.showConflictReason ? `Conflicts with: ${conflictNames}` : `Alternative to ${conflictNames} (already selected)`;
|
|
10319
|
+
name = colors.muted(`${module2.name} (incompatible)`);
|
|
10320
|
+
description = `${colors.muted("\u26A0")} ${disabled}`;
|
|
10321
|
+
}
|
|
10322
|
+
choices.push({
|
|
10323
|
+
name,
|
|
10324
|
+
value: module2.id,
|
|
10325
|
+
description,
|
|
10326
|
+
disabled: isConflicting ? disabled : false,
|
|
10327
|
+
checked: isSelected || isPreselected && !isConflicting
|
|
10328
|
+
});
|
|
10329
|
+
}
|
|
10330
|
+
return choices;
|
|
10331
|
+
}
|
|
10332
|
+
function validateNoConflicts(selectedIds, allModules) {
|
|
10333
|
+
const conflicts = [];
|
|
10334
|
+
for (const id of selectedIds) {
|
|
10335
|
+
const module2 = allModules.find((m) => m.id === id);
|
|
10336
|
+
if (!module2?.alternativeTo) continue;
|
|
10337
|
+
for (const altId of module2.alternativeTo) {
|
|
10338
|
+
if (selectedIds.includes(altId)) {
|
|
10339
|
+
const existingConflict = conflicts.find(
|
|
10340
|
+
(c) => c.selected === id && c.conflictsWith === altId || c.selected === altId && c.conflictsWith === id
|
|
10341
|
+
);
|
|
10342
|
+
if (!existingConflict) {
|
|
10343
|
+
conflicts.push({ selected: id, conflictsWith: altId });
|
|
10344
|
+
}
|
|
10345
|
+
}
|
|
10346
|
+
}
|
|
10347
|
+
}
|
|
10348
|
+
return conflicts;
|
|
10349
|
+
}
|
|
10350
|
+
function groupByExclusivity(modules) {
|
|
10351
|
+
const groups = /* @__PURE__ */ new Map();
|
|
10352
|
+
const processedIds = /* @__PURE__ */ new Set();
|
|
10353
|
+
for (const module2 of modules) {
|
|
10354
|
+
if (processedIds.has(module2.id)) continue;
|
|
10355
|
+
const groupMembers = /* @__PURE__ */ new Set([module2.id]);
|
|
10356
|
+
const toProcess = [...module2.alternativeTo || []];
|
|
10357
|
+
while (toProcess.length > 0) {
|
|
10358
|
+
const altId = toProcess.pop();
|
|
10359
|
+
if (!altId || groupMembers.has(altId)) continue;
|
|
10360
|
+
const altModule = modules.find((m) => m.id === altId);
|
|
10361
|
+
if (altModule) {
|
|
10362
|
+
groupMembers.add(altId);
|
|
10363
|
+
for (const transitiveAlt of altModule.alternativeTo || []) {
|
|
10364
|
+
if (!groupMembers.has(transitiveAlt)) {
|
|
10365
|
+
toProcess.push(transitiveAlt);
|
|
10366
|
+
}
|
|
10367
|
+
}
|
|
10368
|
+
}
|
|
10369
|
+
}
|
|
10370
|
+
if (groupMembers.size > 1) {
|
|
10371
|
+
const sortedMembers = Array.from(groupMembers).sort();
|
|
10372
|
+
const groupId = `exclusivity-group-${sortedMembers[0]}`;
|
|
10373
|
+
groups.set(groupId, sortedMembers);
|
|
10374
|
+
for (const memberId of groupMembers) {
|
|
10375
|
+
processedIds.add(memberId);
|
|
10376
|
+
}
|
|
10377
|
+
} else {
|
|
10378
|
+
processedIds.add(module2.id);
|
|
10379
|
+
}
|
|
10380
|
+
}
|
|
10381
|
+
return groups;
|
|
10382
|
+
}
|
|
10383
|
+
|
|
10384
|
+
// src/cli/prompts/item-select.ts
|
|
10385
|
+
async function promptBatchAction(category, totalItems, options) {
|
|
9858
10386
|
const choices = [
|
|
9859
10387
|
{
|
|
9860
10388
|
name: "Install all (recommended)",
|
|
@@ -9872,7 +10400,14 @@ async function promptBatchAction(category, totalItems, hasPreset) {
|
|
|
9872
10400
|
description: `Skip all ${category}`
|
|
9873
10401
|
}
|
|
9874
10402
|
];
|
|
9875
|
-
if (
|
|
10403
|
+
if (options?.hasExclusivityGroups && options.exclusivityGroupCount) {
|
|
10404
|
+
choices.splice(1, 0, {
|
|
10405
|
+
name: colors.primary("Smart selection (handles conflicts)"),
|
|
10406
|
+
value: "smart",
|
|
10407
|
+
description: `Intelligent selection with ${options.exclusivityGroupCount} mutually exclusive group(s)`
|
|
10408
|
+
});
|
|
10409
|
+
}
|
|
10410
|
+
if (options?.hasPreset) {
|
|
9876
10411
|
choices.splice(1, 0, {
|
|
9877
10412
|
name: "Use preset for this category",
|
|
9878
10413
|
value: "preset",
|
|
@@ -9882,27 +10417,43 @@ async function promptBatchAction(category, totalItems, hasPreset) {
|
|
|
9882
10417
|
return select({
|
|
9883
10418
|
message: `${capitalize(category)} selection (${totalItems} available):`,
|
|
9884
10419
|
choices,
|
|
9885
|
-
default: "all"
|
|
10420
|
+
default: options?.hasExclusivityGroups ? "smart" : "all"
|
|
9886
10421
|
});
|
|
9887
10422
|
}
|
|
9888
10423
|
async function selectItemsFromCategory(category, items, options) {
|
|
9889
|
-
const selectedItems = [];
|
|
9890
|
-
const skippedItems = [];
|
|
9891
10424
|
logger.newline();
|
|
9892
10425
|
logger.subtitle(`${capitalize(category)} Selection`);
|
|
9893
10426
|
logger.info(`${items.length} ${category} available`);
|
|
10427
|
+
const exclusivityGroups = groupByExclusivity(items);
|
|
10428
|
+
const hasExclusivityGroups = exclusivityGroups.size > 0;
|
|
10429
|
+
if (hasExclusivityGroups) {
|
|
10430
|
+
logger.info(
|
|
10431
|
+
colors.warning(
|
|
10432
|
+
`${exclusivityGroups.size} group(s) of mutually exclusive ${category} detected`
|
|
10433
|
+
)
|
|
10434
|
+
);
|
|
10435
|
+
}
|
|
9894
10436
|
logger.newline();
|
|
9895
|
-
const batchAction = await promptBatchAction(
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
);
|
|
10437
|
+
const batchAction = await promptBatchAction(category, items.length, {
|
|
10438
|
+
hasPreset: options?.preselected && options.preselected.length > 0,
|
|
10439
|
+
hasExclusivityGroups,
|
|
10440
|
+
exclusivityGroupCount: exclusivityGroups.size
|
|
10441
|
+
});
|
|
9900
10442
|
if (batchAction === "all") {
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
10443
|
+
const conflicts = validateNoConflicts(
|
|
10444
|
+
items.map((i) => i.id),
|
|
10445
|
+
items
|
|
10446
|
+
);
|
|
10447
|
+
if (conflicts.length > 0) {
|
|
10448
|
+
logger.warn("Cannot install all: some modules are mutually exclusive.");
|
|
10449
|
+
logger.info("Switching to smart selection mode...");
|
|
10450
|
+
} else {
|
|
10451
|
+
return {
|
|
10452
|
+
category,
|
|
10453
|
+
selectedItems: items.map((i) => i.id),
|
|
10454
|
+
skippedItems: []
|
|
10455
|
+
};
|
|
10456
|
+
}
|
|
9906
10457
|
}
|
|
9907
10458
|
if (batchAction === "none") {
|
|
9908
10459
|
return {
|
|
@@ -9913,24 +10464,106 @@ async function selectItemsFromCategory(category, items, options) {
|
|
|
9913
10464
|
}
|
|
9914
10465
|
if (batchAction === "preset" && options?.preselected) {
|
|
9915
10466
|
const preselectedSet = new Set(options.preselected);
|
|
9916
|
-
|
|
10467
|
+
const preselectedIds = items.filter((i) => preselectedSet.has(i.id)).map((i) => i.id);
|
|
10468
|
+
const conflicts = validateNoConflicts(preselectedIds, items);
|
|
10469
|
+
if (conflicts.length > 0) {
|
|
10470
|
+
logger.warn("Preset contains conflicting modules. Switching to smart selection...");
|
|
10471
|
+
} else {
|
|
10472
|
+
return {
|
|
10473
|
+
category,
|
|
10474
|
+
selectedItems: preselectedIds,
|
|
10475
|
+
skippedItems: items.filter((i) => !preselectedSet.has(i.id)).map((i) => i.id)
|
|
10476
|
+
};
|
|
10477
|
+
}
|
|
10478
|
+
}
|
|
10479
|
+
if (batchAction === "smart" || batchAction === "all" || batchAction === "preset") {
|
|
10480
|
+
return selectItemsWithExclusivity(category, items, options);
|
|
10481
|
+
}
|
|
10482
|
+
return selectItemsOneByOne(category, items, options);
|
|
10483
|
+
}
|
|
10484
|
+
async function selectItemsWithExclusivity(category, items, options) {
|
|
10485
|
+
let selectedIds = options?.preselected?.filter((id) => items.some((i) => i.id === id)) || [];
|
|
10486
|
+
let confirmed = false;
|
|
10487
|
+
while (!confirmed) {
|
|
10488
|
+
const choices = createChoicesWithExclusivity(items, selectedIds, {
|
|
10489
|
+
preselected: options?.preselected,
|
|
10490
|
+
showConflictReason: true
|
|
10491
|
+
});
|
|
10492
|
+
logger.newline();
|
|
10493
|
+
logger.info(
|
|
10494
|
+
colors.muted("Items marked as incompatible are disabled based on your selections.")
|
|
10495
|
+
);
|
|
10496
|
+
logger.info(colors.muted("Uncheck items to enable their alternatives."));
|
|
10497
|
+
logger.newline();
|
|
10498
|
+
const newSelection = await checkbox({
|
|
10499
|
+
message: `Select ${category} (Space to toggle, Enter to confirm):`,
|
|
10500
|
+
choices: choices.map((c) => ({
|
|
10501
|
+
name: c.name,
|
|
10502
|
+
value: c.value,
|
|
10503
|
+
description: c.description,
|
|
10504
|
+
disabled: c.disabled,
|
|
10505
|
+
checked: c.checked
|
|
10506
|
+
})),
|
|
10507
|
+
required: false
|
|
10508
|
+
});
|
|
10509
|
+
const conflicts = validateNoConflicts(newSelection, items);
|
|
10510
|
+
if (conflicts.length > 0) {
|
|
10511
|
+
logger.warn("Your selection contains conflicts:");
|
|
10512
|
+
for (const conflict of conflicts) {
|
|
10513
|
+
const module1 = items.find((i) => i.id === conflict.selected)?.name || conflict.selected;
|
|
10514
|
+
const module2 = items.find((i) => i.id === conflict.conflictsWith)?.name || conflict.conflictsWith;
|
|
10515
|
+
logger.info(` ${colors.error("\u2022")} ${module1} and ${module2} are mutually exclusive`);
|
|
10516
|
+
}
|
|
10517
|
+
logger.info("Please adjust your selection.");
|
|
10518
|
+
selectedIds = newSelection;
|
|
10519
|
+
continue;
|
|
10520
|
+
}
|
|
10521
|
+
selectedIds = newSelection;
|
|
10522
|
+
showCategorySelectionSummary({
|
|
9917
10523
|
category,
|
|
9918
|
-
selectedItems:
|
|
9919
|
-
skippedItems: items.filter((i) => !
|
|
9920
|
-
};
|
|
10524
|
+
selectedItems: selectedIds,
|
|
10525
|
+
skippedItems: items.filter((i) => !selectedIds.includes(i.id)).map((i) => i.id)
|
|
10526
|
+
});
|
|
10527
|
+
confirmed = await confirm({
|
|
10528
|
+
message: "Is this selection correct?",
|
|
10529
|
+
default: true
|
|
10530
|
+
});
|
|
9921
10531
|
}
|
|
10532
|
+
return {
|
|
10533
|
+
category,
|
|
10534
|
+
selectedItems: selectedIds,
|
|
10535
|
+
skippedItems: items.filter((i) => !selectedIds.includes(i.id)).map((i) => i.id)
|
|
10536
|
+
};
|
|
10537
|
+
}
|
|
10538
|
+
async function selectItemsOneByOne(category, items, options) {
|
|
10539
|
+
const selectedItems = [];
|
|
10540
|
+
const skippedItems = [];
|
|
9922
10541
|
const remainingItems = [...items];
|
|
9923
10542
|
let currentIndex = 0;
|
|
9924
10543
|
while (currentIndex < remainingItems.length) {
|
|
9925
10544
|
const item = remainingItems[currentIndex];
|
|
9926
10545
|
const remaining = remainingItems.length - currentIndex - 1;
|
|
9927
10546
|
const isPreselected = options?.preselected?.includes(item.id);
|
|
10547
|
+
const conflicts = item.alternativeTo?.filter((altId) => selectedItems.includes(altId)) || [];
|
|
10548
|
+
if (conflicts.length > 0) {
|
|
10549
|
+
const conflictNames = conflicts.map((id) => items.find((i) => i.id === id)?.name || id).join(", ");
|
|
10550
|
+
logger.info(
|
|
10551
|
+
colors.muted(`Skipping ${item.name} (conflicts with selected: ${conflictNames})`)
|
|
10552
|
+
);
|
|
10553
|
+
skippedItems.push(item.id);
|
|
10554
|
+
currentIndex++;
|
|
10555
|
+
continue;
|
|
10556
|
+
}
|
|
9928
10557
|
const progress = colors.muted(`[${currentIndex + 1}/${remainingItems.length}]`);
|
|
9929
10558
|
console.log(`
|
|
9930
10559
|
${progress} ${colors.bold(item.name)}`);
|
|
9931
10560
|
if (options?.showDescriptions && item.description) {
|
|
9932
10561
|
logger.note(item.description);
|
|
9933
10562
|
}
|
|
10563
|
+
if (item.alternativeTo && item.alternativeTo.length > 0) {
|
|
10564
|
+
const altNames = item.alternativeTo.map((id) => items.find((i) => i.id === id)?.name || id).join(", ");
|
|
10565
|
+
logger.info(colors.warning(`\u26A0 Selecting this will disable: ${altNames}`));
|
|
10566
|
+
}
|
|
9934
10567
|
const action = await promptItemWithShortcuts(item, {
|
|
9935
10568
|
defaultInstall: isPreselected,
|
|
9936
10569
|
remainingCount: remaining
|
|
@@ -9947,7 +10580,13 @@ ${progress} ${colors.bold(item.name)}`);
|
|
|
9947
10580
|
case "install-rest":
|
|
9948
10581
|
selectedItems.push(item.id);
|
|
9949
10582
|
for (let i = currentIndex + 1; i < remainingItems.length; i++) {
|
|
9950
|
-
|
|
10583
|
+
const nextItem = remainingItems[i];
|
|
10584
|
+
const nextConflicts = nextItem.alternativeTo?.filter((altId) => selectedItems.includes(altId)) || [];
|
|
10585
|
+
if (nextConflicts.length === 0) {
|
|
10586
|
+
selectedItems.push(nextItem.id);
|
|
10587
|
+
} else {
|
|
10588
|
+
skippedItems.push(nextItem.id);
|
|
10589
|
+
}
|
|
9951
10590
|
}
|
|
9952
10591
|
currentIndex = remainingItems.length;
|
|
9953
10592
|
break;
|
|
@@ -9989,6 +10628,17 @@ async function promptItemWithShortcuts(item, options) {
|
|
|
9989
10628
|
default: options.defaultInstall !== false ? "install" : "skip"
|
|
9990
10629
|
});
|
|
9991
10630
|
}
|
|
10631
|
+
function showCategorySelectionSummary(result) {
|
|
10632
|
+
const { category, selectedItems, skippedItems } = result;
|
|
10633
|
+
logger.newline();
|
|
10634
|
+
logger.subtitle(`${capitalize(category)} Summary`);
|
|
10635
|
+
if (selectedItems.length > 0) {
|
|
10636
|
+
logger.success(`Selected (${selectedItems.length}): ${selectedItems.join(", ")}`);
|
|
10637
|
+
}
|
|
10638
|
+
if (skippedItems.length > 0) {
|
|
10639
|
+
logger.info(`Skipped (${skippedItems.length}): ${colors.muted(skippedItems.join(", "))}`);
|
|
10640
|
+
}
|
|
10641
|
+
}
|
|
9992
10642
|
function capitalize(str) {
|
|
9993
10643
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
9994
10644
|
}
|
|
@@ -10752,6 +11402,122 @@ async function confirmProjectInfo(info) {
|
|
|
10752
11402
|
});
|
|
10753
11403
|
}
|
|
10754
11404
|
|
|
11405
|
+
// src/cli/prompts/related-skills.ts
|
|
11406
|
+
init_cjs_shims();
|
|
11407
|
+
function getAllRelatedSkillIds(agentModules) {
|
|
11408
|
+
const relatedIds = /* @__PURE__ */ new Set();
|
|
11409
|
+
for (const agent of agentModules) {
|
|
11410
|
+
if (agent.relatedSkills) {
|
|
11411
|
+
for (const skillId of agent.relatedSkills) {
|
|
11412
|
+
relatedIds.add(skillId);
|
|
11413
|
+
}
|
|
11414
|
+
}
|
|
11415
|
+
}
|
|
11416
|
+
return Array.from(relatedIds);
|
|
11417
|
+
}
|
|
11418
|
+
function getAgentsWithRelatedSkills(selectedAgentIds, agentModules) {
|
|
11419
|
+
return agentModules.filter(
|
|
11420
|
+
(agent) => selectedAgentIds.includes(agent.id) && agent.relatedSkills && agent.relatedSkills.length > 0
|
|
11421
|
+
);
|
|
11422
|
+
}
|
|
11423
|
+
async function promptRelatedSkillsForAgent(agent, skillModules, options) {
|
|
11424
|
+
if (!agent.relatedSkills || agent.relatedSkills.length === 0) {
|
|
11425
|
+
return [];
|
|
11426
|
+
}
|
|
11427
|
+
const relatedSkillDefs = agent.relatedSkills.map((skillId) => skillModules.find((s) => s.id === skillId)).filter((s) => s !== void 0);
|
|
11428
|
+
if (relatedSkillDefs.length === 0) {
|
|
11429
|
+
return [];
|
|
11430
|
+
}
|
|
11431
|
+
if (relatedSkillDefs.length === 1) {
|
|
11432
|
+
const skill = relatedSkillDefs[0];
|
|
11433
|
+
const action = await select({
|
|
11434
|
+
message: `${colors.primary(agent.name)} has a related skill. Install it?`,
|
|
11435
|
+
choices: [
|
|
11436
|
+
{
|
|
11437
|
+
name: `Install ${skill.name}`,
|
|
11438
|
+
value: "install",
|
|
11439
|
+
description: skill.description
|
|
11440
|
+
},
|
|
11441
|
+
{
|
|
11442
|
+
name: "Skip",
|
|
11443
|
+
value: "skip",
|
|
11444
|
+
description: "Do not install this skill"
|
|
11445
|
+
}
|
|
11446
|
+
],
|
|
11447
|
+
default: "install"
|
|
11448
|
+
});
|
|
11449
|
+
return action === "install" ? [skill.id] : [];
|
|
11450
|
+
}
|
|
11451
|
+
const choices = relatedSkillDefs.map((skill) => ({
|
|
11452
|
+
name: skill.name,
|
|
11453
|
+
value: skill.id,
|
|
11454
|
+
description: skill.description,
|
|
11455
|
+
checked: options?.preselected?.includes(skill.id) ?? false
|
|
11456
|
+
}));
|
|
11457
|
+
if (options?.allowMultiple !== false) {
|
|
11458
|
+
const selected2 = await checkbox({
|
|
11459
|
+
message: `${colors.primary(agent.name)} supports multiple frameworks. Select which patterns to install:`,
|
|
11460
|
+
choices,
|
|
11461
|
+
required: false
|
|
11462
|
+
});
|
|
11463
|
+
return selected2;
|
|
11464
|
+
}
|
|
11465
|
+
const choicesWithSkip = [
|
|
11466
|
+
...choices.map((c) => ({ name: c.name, value: c.value, description: c.description })),
|
|
11467
|
+
{
|
|
11468
|
+
name: colors.muted("Skip (none)"),
|
|
11469
|
+
value: "__skip__",
|
|
11470
|
+
description: "Do not install any related skill for this agent"
|
|
11471
|
+
}
|
|
11472
|
+
];
|
|
11473
|
+
const selected = await select({
|
|
11474
|
+
message: `${colors.primary(agent.name)} supports multiple frameworks. Select which patterns to use:`,
|
|
11475
|
+
choices: choicesWithSkip,
|
|
11476
|
+
default: choicesWithSkip[0]?.value
|
|
11477
|
+
});
|
|
11478
|
+
return selected === "__skip__" ? [] : [selected];
|
|
11479
|
+
}
|
|
11480
|
+
async function promptAllRelatedSkills(selectedAgentIds, registry, options) {
|
|
11481
|
+
const agentsWithRelated = getAgentsWithRelatedSkills(selectedAgentIds, registry.agents);
|
|
11482
|
+
const allRelatedSkillIds = getAllRelatedSkillIds(registry.agents);
|
|
11483
|
+
if (agentsWithRelated.length === 0) {
|
|
11484
|
+
return {
|
|
11485
|
+
relatedSkillsSelected: [],
|
|
11486
|
+
relatedSkillsSkipped: [],
|
|
11487
|
+
allRelatedSkillIds
|
|
11488
|
+
};
|
|
11489
|
+
}
|
|
11490
|
+
logger.newline();
|
|
11491
|
+
logger.subtitle("Framework-Specific Skills");
|
|
11492
|
+
logger.info(
|
|
11493
|
+
"The selected agents support framework-specific patterns. Select which ones to install."
|
|
11494
|
+
);
|
|
11495
|
+
logger.newline();
|
|
11496
|
+
const selectedSkills = [];
|
|
11497
|
+
const skippedSkills = [];
|
|
11498
|
+
for (const agent of agentsWithRelated) {
|
|
11499
|
+
const selected = await promptRelatedSkillsForAgent(agent, registry.skills, {
|
|
11500
|
+
preselected: options?.preselectedSkills,
|
|
11501
|
+
allowMultiple: options?.allowMultiplePerAgent
|
|
11502
|
+
});
|
|
11503
|
+
selectedSkills.push(...selected);
|
|
11504
|
+
const agentRelatedIds = agent.relatedSkills || [];
|
|
11505
|
+
const skipped = agentRelatedIds.filter((id) => !selected.includes(id));
|
|
11506
|
+
skippedSkills.push(...skipped);
|
|
11507
|
+
}
|
|
11508
|
+
const uniqueSelected = [...new Set(selectedSkills)];
|
|
11509
|
+
const uniqueSkipped = [...new Set(skippedSkills)].filter((id) => !uniqueSelected.includes(id));
|
|
11510
|
+
return {
|
|
11511
|
+
relatedSkillsSelected: uniqueSelected,
|
|
11512
|
+
relatedSkillsSkipped: uniqueSkipped,
|
|
11513
|
+
allRelatedSkillIds
|
|
11514
|
+
};
|
|
11515
|
+
}
|
|
11516
|
+
function filterOutRelatedSkills(skillModules, relatedSkillIds) {
|
|
11517
|
+
const relatedSet = new Set(relatedSkillIds);
|
|
11518
|
+
return skillModules.filter((skill) => !relatedSet.has(skill.id));
|
|
11519
|
+
}
|
|
11520
|
+
|
|
10755
11521
|
// src/cli/prompts/scaffold.ts
|
|
10756
11522
|
init_cjs_shims();
|
|
10757
11523
|
async function promptScaffoldType(options) {
|
|
@@ -11513,11 +12279,66 @@ function createBundleSelectionStep() {
|
|
|
11513
12279
|
}
|
|
11514
12280
|
if (mode === "individual" || mode === "both") {
|
|
11515
12281
|
const preselectedFromBundles = resolveBundles(result.selectedBundles);
|
|
11516
|
-
const categories = ["agents", "skills", "commands", "docs"];
|
|
11517
12282
|
if (ctx.registry) {
|
|
11518
12283
|
logger.newline();
|
|
11519
12284
|
logger.subtitle("Individual Module Selection");
|
|
11520
|
-
|
|
12285
|
+
const agentPreselected = mode === "both" ? preselectedFromBundles.agents : [];
|
|
12286
|
+
const agentResult = await selectItemsFromCategory("agents", ctx.registry.agents, {
|
|
12287
|
+
preselected: agentPreselected,
|
|
12288
|
+
showDescriptions: true
|
|
12289
|
+
});
|
|
12290
|
+
if (mode === "both") {
|
|
12291
|
+
result.additionalModules.agents = agentResult.selectedItems.filter(
|
|
12292
|
+
(id) => !agentPreselected.includes(id)
|
|
12293
|
+
);
|
|
12294
|
+
} else {
|
|
12295
|
+
result.additionalModules.agents = agentResult.selectedItems;
|
|
12296
|
+
}
|
|
12297
|
+
const allSelectedAgents = [
|
|
12298
|
+
...preselectedFromBundles.agents,
|
|
12299
|
+
...result.additionalModules.agents
|
|
12300
|
+
];
|
|
12301
|
+
const relatedSkillsResult = await promptAllRelatedSkills(
|
|
12302
|
+
allSelectedAgents,
|
|
12303
|
+
ctx.registry,
|
|
12304
|
+
{
|
|
12305
|
+
preselectedSkills: mode === "both" ? preselectedFromBundles.skills : [],
|
|
12306
|
+
allowMultiplePerAgent: true
|
|
12307
|
+
}
|
|
12308
|
+
);
|
|
12309
|
+
const skillPreselected = mode === "both" ? preselectedFromBundles.skills : [];
|
|
12310
|
+
const independentSkills = filterOutRelatedSkills(
|
|
12311
|
+
ctx.registry.skills,
|
|
12312
|
+
relatedSkillsResult.allRelatedSkillIds
|
|
12313
|
+
);
|
|
12314
|
+
const independentPreselected = skillPreselected.filter(
|
|
12315
|
+
(id) => !relatedSkillsResult.allRelatedSkillIds.includes(id)
|
|
12316
|
+
);
|
|
12317
|
+
let independentSkillsSelected = [];
|
|
12318
|
+
if (independentSkills.length > 0) {
|
|
12319
|
+
logger.newline();
|
|
12320
|
+
logger.info(
|
|
12321
|
+
colors.muted("Now selecting general-purpose skills (not framework-specific):")
|
|
12322
|
+
);
|
|
12323
|
+
const skillResult = await selectItemsFromCategory("skills", independentSkills, {
|
|
12324
|
+
preselected: independentPreselected,
|
|
12325
|
+
showDescriptions: true
|
|
12326
|
+
});
|
|
12327
|
+
independentSkillsSelected = skillResult.selectedItems;
|
|
12328
|
+
}
|
|
12329
|
+
const allSelectedSkills = [
|
|
12330
|
+
...relatedSkillsResult.relatedSkillsSelected,
|
|
12331
|
+
...independentSkillsSelected
|
|
12332
|
+
];
|
|
12333
|
+
if (mode === "both") {
|
|
12334
|
+
result.additionalModules.skills = allSelectedSkills.filter(
|
|
12335
|
+
(id) => !skillPreselected.includes(id)
|
|
12336
|
+
);
|
|
12337
|
+
} else {
|
|
12338
|
+
result.additionalModules.skills = allSelectedSkills;
|
|
12339
|
+
}
|
|
12340
|
+
const otherCategories = ["commands", "docs"];
|
|
12341
|
+
for (const category of otherCategories) {
|
|
11521
12342
|
const preselected = mode === "both" ? preselectedFromBundles[category] : [];
|
|
11522
12343
|
const categoryResult = await selectItemsFromCategory(category, ctx.registry[category], {
|
|
11523
12344
|
preselected,
|
|
@@ -11689,6 +12510,28 @@ function createTemplateConfigStep() {
|
|
|
11689
12510
|
}
|
|
11690
12511
|
};
|
|
11691
12512
|
}
|
|
12513
|
+
function createClaudeSettingsStep() {
|
|
12514
|
+
return {
|
|
12515
|
+
metadata: {
|
|
12516
|
+
id: "claudeSettings",
|
|
12517
|
+
name: "Claude Code Settings",
|
|
12518
|
+
description: "Configure Claude Code model, permissions, and behavior",
|
|
12519
|
+
required: false
|
|
12520
|
+
},
|
|
12521
|
+
computeDefaults: (ctx) => ctx.claudeSettings,
|
|
12522
|
+
execute: async (ctx, defaults) => {
|
|
12523
|
+
const goBack = await promptBackOption(11, "Configure Claude Code settings or go back?");
|
|
12524
|
+
if (goBack) {
|
|
12525
|
+
return createResult(defaults, "back");
|
|
12526
|
+
}
|
|
12527
|
+
const value = await promptClaudeSettings({
|
|
12528
|
+
defaults,
|
|
12529
|
+
includeCoAuthor: ctx.preferences?.includeCoAuthor
|
|
12530
|
+
});
|
|
12531
|
+
return createResult(value, "next");
|
|
12532
|
+
}
|
|
12533
|
+
};
|
|
12534
|
+
}
|
|
11692
12535
|
function createInitWizardConfig(projectPath, detection, registry) {
|
|
11693
12536
|
void projectPath;
|
|
11694
12537
|
void detection;
|
|
@@ -11737,6 +12580,10 @@ function createInitWizardConfig(projectPath, detection, registry) {
|
|
|
11737
12580
|
{
|
|
11738
12581
|
id: "templateConfig",
|
|
11739
12582
|
definition: createTemplateConfigStep()
|
|
12583
|
+
},
|
|
12584
|
+
{
|
|
12585
|
+
id: "claudeSettings",
|
|
12586
|
+
definition: createClaudeSettingsStep()
|
|
11740
12587
|
}
|
|
11741
12588
|
];
|
|
11742
12589
|
return {
|
|
@@ -12061,7 +12908,7 @@ async function runInit(path10, options) {
|
|
|
12061
12908
|
logger.warn("Configuration cancelled");
|
|
12062
12909
|
return;
|
|
12063
12910
|
}
|
|
12064
|
-
const { config, skippedMcpConfigs, templateConfig, cicdConfig } = buildResult;
|
|
12911
|
+
const { config, skippedMcpConfigs, templateConfig, cicdConfig, claudeSettings } = buildResult;
|
|
12065
12912
|
if (templateConfig) {
|
|
12066
12913
|
config.templateConfig = templateConfig;
|
|
12067
12914
|
}
|
|
@@ -12078,7 +12925,15 @@ async function runInit(path10, options) {
|
|
|
12078
12925
|
showConfigSummary(config);
|
|
12079
12926
|
return;
|
|
12080
12927
|
}
|
|
12081
|
-
await executeInstallation(
|
|
12928
|
+
await executeInstallation(
|
|
12929
|
+
projectPath,
|
|
12930
|
+
config,
|
|
12931
|
+
registry,
|
|
12932
|
+
templatesPath,
|
|
12933
|
+
options,
|
|
12934
|
+
cicdConfig,
|
|
12935
|
+
claudeSettings
|
|
12936
|
+
);
|
|
12082
12937
|
if (templateConfig && !options.noPlaceholders) {
|
|
12083
12938
|
const claudePath = joinPath(projectPath, ".claude");
|
|
12084
12939
|
await replaceTemplateConfigWithSpinner(claudePath, templateConfig);
|
|
@@ -12295,7 +13150,8 @@ async function buildInteractiveConfig(projectPath, detection, registry, options,
|
|
|
12295
13150
|
codeStyleConfig,
|
|
12296
13151
|
cicdConfig,
|
|
12297
13152
|
folderPreferences,
|
|
12298
|
-
templateConfig: templateConfigResult
|
|
13153
|
+
templateConfig: templateConfigResult,
|
|
13154
|
+
claudeSettings
|
|
12299
13155
|
} = wizardResult.values;
|
|
12300
13156
|
let mcpConfig = { level: "project", servers: [] };
|
|
12301
13157
|
let skippedMcpConfigs = [];
|
|
@@ -12353,10 +13209,11 @@ async function buildInteractiveConfig(projectPath, detection, registry, options,
|
|
|
12353
13209
|
config,
|
|
12354
13210
|
skippedMcpConfigs,
|
|
12355
13211
|
templateConfig: templateConfigResult,
|
|
12356
|
-
cicdConfig
|
|
13212
|
+
cicdConfig,
|
|
13213
|
+
claudeSettings
|
|
12357
13214
|
};
|
|
12358
13215
|
}
|
|
12359
|
-
async function executeInstallation(projectPath, config, registry, templatesPath, options, cicdConfig) {
|
|
13216
|
+
async function executeInstallation(projectPath, config, registry, templatesPath, options, cicdConfig, claudeSettings) {
|
|
12360
13217
|
logger.newline();
|
|
12361
13218
|
logger.title("Installing Configuration");
|
|
12362
13219
|
if (config.scaffold.type === "full-project") {
|
|
@@ -12378,6 +13235,28 @@ async function executeInstallation(projectPath, config, registry, templatesPath,
|
|
|
12378
13235
|
} else if (claudeMdResult.skipped) {
|
|
12379
13236
|
logger.info("CLAUDE.md already exists, skipped");
|
|
12380
13237
|
}
|
|
13238
|
+
if (claudeSettings) {
|
|
13239
|
+
const settingsResult = await generateSettingsWithSpinner(projectPath, {
|
|
13240
|
+
claudeSettings,
|
|
13241
|
+
includeCoAuthor: config.preferences.includeCoAuthor,
|
|
13242
|
+
overwrite: options.force
|
|
13243
|
+
});
|
|
13244
|
+
if (settingsResult.error) {
|
|
13245
|
+
logger.warn(`settings.json generation warning: ${settingsResult.error}`);
|
|
13246
|
+
} else if (settingsResult.skipped) {
|
|
13247
|
+
logger.info("settings.json already exists, skipped");
|
|
13248
|
+
}
|
|
13249
|
+
const settingsLocalResult = await generateSettingsLocalWithSpinner(projectPath, {
|
|
13250
|
+
claudeSettings,
|
|
13251
|
+
includeCoAuthor: config.preferences.includeCoAuthor,
|
|
13252
|
+
overwrite: options.force
|
|
13253
|
+
});
|
|
13254
|
+
if (settingsLocalResult.error) {
|
|
13255
|
+
logger.warn(`settings.local.json generation warning: ${settingsLocalResult.error}`);
|
|
13256
|
+
} else if (settingsLocalResult.skipped) {
|
|
13257
|
+
logger.info("settings.local.json already exists, skipped");
|
|
13258
|
+
}
|
|
13259
|
+
}
|
|
12381
13260
|
const modulesByCategory = {
|
|
12382
13261
|
agents: filterModules(registry, "agents", config.modules.agents.selected),
|
|
12383
13262
|
skills: filterModules(registry, "skills", config.modules.skills.selected),
|