@cometchat/skills 4.0.0 → 4.2.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.
Files changed (258) hide show
  1. package/README.md +42 -2
  2. package/bin/install.js +448 -57
  3. package/package.json +1 -1
  4. package/skills/cometchat/SKILL.md +337 -80
  5. package/skills/cometchat-a11y/SKILL.md +476 -0
  6. package/skills/cometchat-android-v5/SKILL.md +1 -1
  7. package/skills/cometchat-android-v5-calls/SKILL.md +413 -0
  8. package/skills/cometchat-android-v5-calls/references/README.md +53 -0
  9. package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +195 -0
  10. package/skills/cometchat-android-v5-calls/references/audio-controls.md +91 -0
  11. package/skills/cometchat-android-v5-calls/references/background-handling.md +168 -0
  12. package/skills/cometchat-android-v5-calls/references/call-layouts.md +123 -0
  13. package/skills/cometchat-android-v5-calls/references/call-logs.md +113 -0
  14. package/skills/cometchat-android-v5-calls/references/call-session.md +274 -0
  15. package/skills/cometchat-android-v5-calls/references/custom-ui.md +150 -0
  16. package/skills/cometchat-android-v5-calls/references/event-listeners.md +123 -0
  17. package/skills/cometchat-android-v5-calls/references/group-calls.md +205 -0
  18. package/skills/cometchat-android-v5-calls/references/idle-timeout.md +111 -0
  19. package/skills/cometchat-android-v5-calls/references/in-call-chat.md +134 -0
  20. package/skills/cometchat-android-v5-calls/references/join-session.md +120 -0
  21. package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +206 -0
  22. package/skills/cometchat-android-v5-calls/references/participant-management.md +110 -0
  23. package/skills/cometchat-android-v5-calls/references/picture-in-picture.md +106 -0
  24. package/skills/cometchat-android-v5-calls/references/raise-hand.md +242 -0
  25. package/skills/cometchat-android-v5-calls/references/recording.md +101 -0
  26. package/skills/cometchat-android-v5-calls/references/ringing-integration.md +152 -0
  27. package/skills/cometchat-android-v5-calls/references/screen-sharing.md +82 -0
  28. package/skills/cometchat-android-v5-calls/references/server-fcm-voip.md +215 -0
  29. package/skills/cometchat-android-v5-calls/references/session-settings.md +121 -0
  30. package/skills/cometchat-android-v5-calls/references/setup.md +137 -0
  31. package/skills/cometchat-android-v5-calls/references/share-invite.md +151 -0
  32. package/skills/cometchat-android-v5-calls/references/video-controls.md +87 -0
  33. package/skills/cometchat-android-v5-calls/references/voip-calling.md +526 -0
  34. package/skills/cometchat-android-v5-components/SKILL.md +1 -1
  35. package/skills/cometchat-android-v5-core/SKILL.md +1 -1
  36. package/skills/cometchat-android-v5-customization/SKILL.md +1 -1
  37. package/skills/cometchat-android-v5-extensions/SKILL.md +1 -1
  38. package/skills/cometchat-android-v5-features/SKILL.md +1 -1
  39. package/skills/cometchat-android-v5-placement/SKILL.md +1 -1
  40. package/skills/cometchat-android-v5-production/SKILL.md +1 -1
  41. package/skills/cometchat-android-v5-push/SKILL.md +1 -1
  42. package/skills/cometchat-android-v5-testing/SKILL.md +1 -1
  43. package/skills/cometchat-android-v5-theming/SKILL.md +1 -1
  44. package/skills/cometchat-android-v5-troubleshooting/SKILL.md +1 -1
  45. package/skills/cometchat-android-v6/SKILL.md +1 -1
  46. package/skills/cometchat-android-v6-builder-settings/SKILL.md +1 -1
  47. package/skills/cometchat-android-v6-calls/SKILL.md +375 -0
  48. package/skills/cometchat-android-v6-calls/references/add-calls-to-existing-chat.md +97 -0
  49. package/skills/cometchat-android-v6-calls/references/call-layouts.md +91 -0
  50. package/skills/cometchat-android-v6-calls/references/call-session.md +163 -0
  51. package/skills/cometchat-android-v6-calls/references/device-management.md +171 -0
  52. package/skills/cometchat-android-v6-calls/references/group-calls.md +191 -0
  53. package/skills/cometchat-android-v6-calls/references/idle-timeout.md +107 -0
  54. package/skills/cometchat-android-v6-calls/references/in-call-chat.md +136 -0
  55. package/skills/cometchat-android-v6-calls/references/raise-hand.md +186 -0
  56. package/skills/cometchat-android-v6-calls/references/ringing-integration.md +176 -0
  57. package/skills/cometchat-android-v6-calls/references/server-fcm-voip.md +127 -0
  58. package/skills/cometchat-android-v6-calls/references/share-invite.md +105 -0
  59. package/skills/cometchat-android-v6-compose-components/SKILL.md +2 -2
  60. package/skills/cometchat-android-v6-compose-customization/SKILL.md +1 -1
  61. package/skills/cometchat-android-v6-compose-placement/SKILL.md +1 -1
  62. package/skills/cometchat-android-v6-compose-theming/SKILL.md +1 -1
  63. package/skills/cometchat-android-v6-core/SKILL.md +1 -1
  64. package/skills/cometchat-android-v6-events/SKILL.md +1 -1
  65. package/skills/cometchat-android-v6-extensions/SKILL.md +1 -1
  66. package/skills/cometchat-android-v6-features/SKILL.md +1 -1
  67. package/skills/cometchat-android-v6-kotlin-components/SKILL.md +1 -1
  68. package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +1 -1
  69. package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +1 -1
  70. package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +1 -1
  71. package/skills/cometchat-android-v6-migration/SKILL.md +398 -0
  72. package/skills/cometchat-android-v6-production/SKILL.md +1 -1
  73. package/skills/cometchat-android-v6-push/SKILL.md +1 -1
  74. package/skills/cometchat-android-v6-testing/SKILL.md +1 -1
  75. package/skills/cometchat-android-v6-troubleshooting/SKILL.md +1 -1
  76. package/skills/cometchat-angular-calls/SKILL.md +511 -0
  77. package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +95 -0
  78. package/skills/cometchat-angular-calls/references/call-layouts.md +106 -0
  79. package/skills/cometchat-angular-calls/references/call-session.md +167 -0
  80. package/skills/cometchat-angular-calls/references/custom-ui.md +231 -0
  81. package/skills/cometchat-angular-calls/references/device-management.md +135 -0
  82. package/skills/cometchat-angular-calls/references/group-calls.md +412 -0
  83. package/skills/cometchat-angular-calls/references/idle-timeout.md +145 -0
  84. package/skills/cometchat-angular-calls/references/in-call-chat.md +148 -0
  85. package/skills/cometchat-angular-calls/references/lazy-loading-pitfalls.md +205 -0
  86. package/skills/cometchat-angular-calls/references/migration-v4-to-v5.md +53 -0
  87. package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +183 -0
  88. package/skills/cometchat-angular-calls/references/picture-in-picture.md +285 -0
  89. package/skills/cometchat-angular-calls/references/raise-hand.md +167 -0
  90. package/skills/cometchat-angular-calls/references/recording-screen-share.md +267 -0
  91. package/skills/cometchat-angular-calls/references/ringing-integration.md +131 -0
  92. package/skills/cometchat-angular-calls/references/server-web-push-vapid.md +100 -0
  93. package/skills/cometchat-angular-calls/references/share-invite.md +116 -0
  94. package/skills/cometchat-angular-components/SKILL.md +1 -1
  95. package/skills/cometchat-angular-core/SKILL.md +1 -1
  96. package/skills/cometchat-angular-customization/SKILL.md +1 -1
  97. package/skills/cometchat-angular-features/SKILL.md +1 -1
  98. package/skills/cometchat-angular-patterns/SKILL.md +1 -1
  99. package/skills/cometchat-angular-placement/SKILL.md +1 -1
  100. package/skills/cometchat-angular-production/SKILL.md +1 -1
  101. package/skills/cometchat-angular-push/SKILL.md +403 -0
  102. package/skills/cometchat-angular-testing/SKILL.md +333 -0
  103. package/skills/cometchat-angular-theming/SKILL.md +1 -1
  104. package/skills/cometchat-angular-troubleshooting/SKILL.md +1 -1
  105. package/skills/cometchat-astro-patterns/SKILL.md +1 -1
  106. package/skills/cometchat-calls/SKILL.md +358 -0
  107. package/skills/cometchat-calls/references/use-case-broadcast.md +194 -0
  108. package/skills/cometchat-calls/references/use-case-marketplace.md +158 -0
  109. package/skills/cometchat-calls/references/use-case-support.md +190 -0
  110. package/skills/cometchat-calls/references/use-case-team.md +169 -0
  111. package/skills/cometchat-calls/references/use-case-telehealth.md +154 -0
  112. package/skills/cometchat-components/SKILL.md +1 -1
  113. package/skills/cometchat-core/SKILL.md +1 -1
  114. package/skills/cometchat-customization/SKILL.md +2 -2
  115. package/skills/cometchat-features/SKILL.md +2 -2
  116. package/skills/cometchat-flutter-v5/SKILL.md +1 -1
  117. package/skills/cometchat-flutter-v5-calls/SKILL.md +325 -94
  118. package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +169 -0
  119. package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +98 -0
  120. package/skills/cometchat-flutter-v5-calls/references/call-session.md +330 -0
  121. package/skills/cometchat-flutter-v5-calls/references/device-management.md +120 -0
  122. package/skills/cometchat-flutter-v5-calls/references/group-calls.md +187 -0
  123. package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +97 -0
  124. package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +132 -0
  125. package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +160 -0
  126. package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +244 -0
  127. package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +193 -0
  128. package/skills/cometchat-flutter-v5-calls/references/server-push-bridge.md +101 -0
  129. package/skills/cometchat-flutter-v5-calls/references/share-invite.md +142 -0
  130. package/skills/cometchat-flutter-v5-conversations/SKILL.md +1 -1
  131. package/skills/cometchat-flutter-v5-core/SKILL.md +1 -1
  132. package/skills/cometchat-flutter-v5-customization/SKILL.md +1 -1
  133. package/skills/cometchat-flutter-v5-events/SKILL.md +1 -1
  134. package/skills/cometchat-flutter-v5-messages/SKILL.md +1 -1
  135. package/skills/cometchat-flutter-v5-production/SKILL.md +1 -1
  136. package/skills/cometchat-flutter-v5-push/SKILL.md +1 -1
  137. package/skills/cometchat-flutter-v5-testing/SKILL.md +390 -0
  138. package/skills/cometchat-flutter-v5-theming/SKILL.md +1 -1
  139. package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +1 -1
  140. package/skills/cometchat-flutter-v5-users-groups/SKILL.md +1 -1
  141. package/skills/cometchat-flutter-v6/SKILL.md +1 -1
  142. package/skills/cometchat-flutter-v6-calls/SKILL.md +308 -243
  143. package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +134 -0
  144. package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +102 -0
  145. package/skills/cometchat-flutter-v6-calls/references/call-session.md +229 -0
  146. package/skills/cometchat-flutter-v6-calls/references/device-management.md +99 -0
  147. package/skills/cometchat-flutter-v6-calls/references/group-calls.md +190 -0
  148. package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +80 -0
  149. package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +122 -0
  150. package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +268 -0
  151. package/skills/cometchat-flutter-v6-calls/references/ringing-integration.md +171 -0
  152. package/skills/cometchat-flutter-v6-calls/references/server-push-bridge.md +93 -0
  153. package/skills/cometchat-flutter-v6-calls/references/share-invite.md +102 -0
  154. package/skills/cometchat-flutter-v6-components/SKILL.md +1 -1
  155. package/skills/cometchat-flutter-v6-conversations/SKILL.md +1 -1
  156. package/skills/cometchat-flutter-v6-core/SKILL.md +1 -1
  157. package/skills/cometchat-flutter-v6-customization/SKILL.md +1 -1
  158. package/skills/cometchat-flutter-v6-events/SKILL.md +1 -1
  159. package/skills/cometchat-flutter-v6-features/SKILL.md +1 -1
  160. package/skills/cometchat-flutter-v6-messages/SKILL.md +1 -1
  161. package/skills/cometchat-flutter-v6-migration/SKILL.md +1 -1
  162. package/skills/cometchat-flutter-v6-placement/SKILL.md +1 -1
  163. package/skills/cometchat-flutter-v6-production/SKILL.md +1 -1
  164. package/skills/cometchat-flutter-v6-push/SKILL.md +452 -0
  165. package/skills/cometchat-flutter-v6-testing/SKILL.md +319 -0
  166. package/skills/cometchat-flutter-v6-theming/SKILL.md +1 -1
  167. package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +1 -1
  168. package/skills/cometchat-flutter-v6-users-groups/SKILL.md +1 -1
  169. package/skills/cometchat-i18n/SKILL.md +358 -0
  170. package/skills/cometchat-ios/SKILL.md +5 -5
  171. package/skills/cometchat-ios-calls/SKILL.md +409 -0
  172. package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +172 -0
  173. package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +189 -0
  174. package/skills/cometchat-ios-calls/references/call-layouts.md +136 -0
  175. package/skills/cometchat-ios-calls/references/call-session.md +221 -0
  176. package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +353 -0
  177. package/skills/cometchat-ios-calls/references/custom-ui.md +322 -0
  178. package/skills/cometchat-ios-calls/references/device-management.md +171 -0
  179. package/skills/cometchat-ios-calls/references/group-calls.md +396 -0
  180. package/skills/cometchat-ios-calls/references/idle-timeout.md +185 -0
  181. package/skills/cometchat-ios-calls/references/in-call-chat.md +183 -0
  182. package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +138 -0
  183. package/skills/cometchat-ios-calls/references/picture-in-picture.md +246 -0
  184. package/skills/cometchat-ios-calls/references/raise-hand.md +239 -0
  185. package/skills/cometchat-ios-calls/references/recording-screen-share.md +339 -0
  186. package/skills/cometchat-ios-calls/references/ringing-integration.md +142 -0
  187. package/skills/cometchat-ios-calls/references/server-apns-pushkit.md +267 -0
  188. package/skills/cometchat-ios-calls/references/share-invite.md +152 -0
  189. package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +246 -0
  190. package/skills/cometchat-ios-calls/references/voip-cert-setup.md +166 -0
  191. package/skills/cometchat-ios-components/SKILL.md +1 -1
  192. package/skills/cometchat-ios-core/SKILL.md +1 -1
  193. package/skills/cometchat-ios-customization/SKILL.md +1 -1
  194. package/skills/cometchat-ios-features/SKILL.md +1 -1
  195. package/skills/cometchat-ios-placement/SKILL.md +1 -1
  196. package/skills/cometchat-ios-production/SKILL.md +1 -1
  197. package/skills/cometchat-ios-push/SKILL.md +1 -1
  198. package/skills/cometchat-ios-testing/SKILL.md +371 -0
  199. package/skills/cometchat-ios-theming/SKILL.md +1 -1
  200. package/skills/cometchat-ios-troubleshooting/SKILL.md +1 -1
  201. package/skills/cometchat-native-bare-patterns/SKILL.md +45 -3
  202. package/skills/cometchat-native-calls/SKILL.md +599 -0
  203. package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +203 -0
  204. package/skills/cometchat-native-calls/references/call-layouts.md +124 -0
  205. package/skills/cometchat-native-calls/references/call-session.md +182 -0
  206. package/skills/cometchat-native-calls/references/custom-ui.md +250 -0
  207. package/skills/cometchat-native-calls/references/device-management.md +135 -0
  208. package/skills/cometchat-native-calls/references/expo-vs-bare.md +179 -0
  209. package/skills/cometchat-native-calls/references/group-calls.md +291 -0
  210. package/skills/cometchat-native-calls/references/idle-timeout.md +128 -0
  211. package/skills/cometchat-native-calls/references/in-call-chat.md +143 -0
  212. package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +72 -0
  213. package/skills/cometchat-native-calls/references/picture-in-picture.md +276 -0
  214. package/skills/cometchat-native-calls/references/raise-hand.md +203 -0
  215. package/skills/cometchat-native-calls/references/recording-screen-share.md +290 -0
  216. package/skills/cometchat-native-calls/references/ringing-integration.md +118 -0
  217. package/skills/cometchat-native-calls/references/server-push-bridge.md +135 -0
  218. package/skills/cometchat-native-calls/references/server-push-payloads.md +193 -0
  219. package/skills/cometchat-native-calls/references/share-invite.md +144 -0
  220. package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +317 -0
  221. package/skills/cometchat-native-components/SKILL.md +1 -1
  222. package/skills/cometchat-native-core/SKILL.md +1 -1
  223. package/skills/cometchat-native-customization/SKILL.md +1 -1
  224. package/skills/cometchat-native-expo-patterns/SKILL.md +18 -1
  225. package/skills/cometchat-native-features/SKILL.md +1 -1
  226. package/skills/cometchat-native-placement/SKILL.md +1 -1
  227. package/skills/cometchat-native-production/SKILL.md +1 -1
  228. package/skills/cometchat-native-push/SKILL.md +1 -1
  229. package/skills/cometchat-native-testing/SKILL.md +1 -1
  230. package/skills/cometchat-native-theming/SKILL.md +1 -1
  231. package/skills/cometchat-native-troubleshooting/SKILL.md +1 -1
  232. package/skills/cometchat-nextjs-patterns/SKILL.md +1 -1
  233. package/skills/cometchat-placement/SKILL.md +29 -1
  234. package/skills/cometchat-production/SKILL.md +1 -1
  235. package/skills/cometchat-react-calls/SKILL.md +539 -0
  236. package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +145 -0
  237. package/skills/cometchat-react-calls/references/call-layouts.md +161 -0
  238. package/skills/cometchat-react-calls/references/call-session.md +235 -0
  239. package/skills/cometchat-react-calls/references/custom-ui.md +201 -0
  240. package/skills/cometchat-react-calls/references/device-management.md +206 -0
  241. package/skills/cometchat-react-calls/references/group-calls.md +262 -0
  242. package/skills/cometchat-react-calls/references/idle-timeout.md +175 -0
  243. package/skills/cometchat-react-calls/references/in-call-chat.md +212 -0
  244. package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +172 -0
  245. package/skills/cometchat-react-calls/references/picture-in-picture.md +245 -0
  246. package/skills/cometchat-react-calls/references/raise-hand.md +238 -0
  247. package/skills/cometchat-react-calls/references/recording-screen-share.md +143 -0
  248. package/skills/cometchat-react-calls/references/ringing-integration.md +255 -0
  249. package/skills/cometchat-react-calls/references/server-web-push-vapid.md +241 -0
  250. package/skills/cometchat-react-calls/references/share-invite.md +176 -0
  251. package/skills/cometchat-react-calls/references/testing-calls-on-web.md +198 -0
  252. package/skills/cometchat-react-calls/references/voip-and-web-push.md +165 -0
  253. package/skills/cometchat-react-patterns/SKILL.md +56 -8
  254. package/skills/cometchat-react-push/SKILL.md +448 -0
  255. package/skills/cometchat-react-router-patterns/SKILL.md +1 -1
  256. package/skills/cometchat-react-testing/SKILL.md +404 -0
  257. package/skills/cometchat-theming/SKILL.md +3 -3
  258. package/skills/cometchat-troubleshooting/SKILL.md +2 -2
package/bin/install.js CHANGED
@@ -6,6 +6,7 @@ const fs = require("fs");
6
6
  const path = require("path");
7
7
  const os = require("os");
8
8
  const readline = require("readline");
9
+ const { spawn } = require("child_process");
9
10
 
10
11
  // ── Lazy-load optional deps ───────────────────────────────────────────────────
11
12
  function tryRequire(name) {
@@ -36,6 +37,13 @@ const SKILLS = [
36
37
  // Dispatcher — shared across every family
37
38
  { name: "cometchat", families: ["web", "native", "flutter", "angular", "android", "ios"], description: "Entry point — detects framework, handles onboarding, guides integration" },
38
39
 
40
+ // Calls dispatcher — shared across every family (v4.1)
41
+ { name: "cometchat-calls", families: ["web", "native", "flutter", "angular", "android", "ios"], description: "Calls entry point — routes to per-family -calls skill, picks standalone vs additive mode" },
42
+
43
+ // Cross-family polish (v4.1) — i18n + accessibility apply to every family
44
+ { name: "cometchat-i18n", families: ["web", "native", "flutter", "angular", "android", "ios"], description: "Localization across all kits — CometChatLocalize.init/setLocale signature differences, RTL, fallback language, custom resources" },
45
+ { name: "cometchat-a11y", families: ["web", "native", "flutter", "angular", "android", "ios"], description: "Accessibility (WCAG 2.1 AA) — contrast, keyboard nav, live regions for new messages, focus management on chat entry, prefers-reduced-motion, calls a11y" },
46
+
39
47
  // Web (React / Next.js / React Router / Astro)
40
48
  { name: "cometchat-core", families: ["web"], description: "Foundational rules — init, login, CSS, env vars, SSR safety, provider" },
41
49
  { name: "cometchat-components", families: ["web"], description: "Component catalog — names, props, composition patterns" },
@@ -49,6 +57,9 @@ const SKILLS = [
49
57
  { name: "cometchat-customization", families: ["web"], description: "Component customization — custom views, builders, events" },
50
58
  { name: "cometchat-production", families: ["web"], description: "Production auth — token endpoints, user management, security" },
51
59
  { name: "cometchat-troubleshooting", families: ["web"], description: "Diagnostics — verify, drift, doctor, symptom lookup" },
60
+ { name: "cometchat-react-calls", families: ["web"], description: "Web calls (v4.1) — Calls SDK install, dual-SDK init, Incoming/Outgoing/Ongoing, framework SSR safety" },
61
+ { name: "cometchat-react-testing", families: ["web"], description: "Web testing (v4.1) — Vitest + RTL setup, mocking the SDK, Playwright e2e, init-resolves-before-render assertion, no-Auth-Key-in-source meta-test, CI" },
62
+ { name: "cometchat-react-push", families: ["web"], description: "Web push (v4.1) — Service Worker + VAPID + Push API for new-message notifications, server-side webhook send, click-through routing, iOS PWA-only caveat" },
52
63
 
53
64
  // React Native (Expo + bare RN)
54
65
  { name: "cometchat-native-core", families: ["native"], description: "RN: init, login, provider chain, env vars, anti-patterns" },
@@ -63,6 +74,7 @@ const SKILLS = [
63
74
  { name: "cometchat-native-push", families: ["native"], description: "RN push: APNs + FCM, dashboard providers, client registration, deep-link" },
64
75
  { name: "cometchat-native-testing", families: ["native"], description: "RN testing: Jest + RNTL, mocking the kit/SDK, Detox vs Maestro, CI" },
65
76
  { name: "cometchat-native-troubleshooting", families: ["native"], description: "RN troubleshooting: Metro cache, pod install, native module linking" },
77
+ { name: "cometchat-native-calls", families: ["native"], description: "RN calls (v4.1) — Calls SDK + callkeep + voip-push + FCM, CallKit/ConnectionService, dev-client requirement" },
66
78
 
67
79
  // Angular (12-15)
68
80
  { name: "cometchat-angular-core", families: ["angular"], description: "Angular: UIKitSettingsBuilder init, login order, environment config, provider" },
@@ -74,6 +86,9 @@ const SKILLS = [
74
86
  { name: "cometchat-angular-customization", families: ["angular"], description: "Angular: content projection, ng-template slots, custom views" },
75
87
  { name: "cometchat-angular-production", families: ["angular"], description: "Angular: server-minted auth tokens, user management, external-backend recipes" },
76
88
  { name: "cometchat-angular-troubleshooting", families: ["angular"], description: "Angular troubleshooting: build errors, module imports, Zone.js issues" },
89
+ { name: "cometchat-angular-calls", families: ["angular"], description: "Angular calls (v4.1) — Calls SDK in APP_INITIALIZER, NgZone correctness, <cometchat-call-buttons> + <cometchat-incoming-call>" },
90
+ { name: "cometchat-angular-testing", families: ["angular"], description: "Angular testing (v4.1) — Karma OR Jest, TestBed with CUSTOM_ELEMENTS_SCHEMA, NgZone-aware fakeAsync, Cypress e2e" },
91
+ { name: "cometchat-angular-push", families: ["angular"], description: "Angular push (v4.1) — @angular/service-worker + ngsw-config, SwPush subscription, click-through via Router.navigateByUrl, Universal SSR guards" },
77
92
 
78
93
  // Android native — both V5 (live, Java + Kotlin Views) and V6 (beta,
79
94
  // Compose + Kotlin Views) ship together. The V5 + V6 dispatcher entries
@@ -91,6 +106,7 @@ const SKILLS = [
91
106
  { name: "cometchat-android-v5-extensions", families: ["android"], description: "V5 extensions — moderation, smart replies, message translation" },
92
107
  { name: "cometchat-android-v5-testing", families: ["android"], description: "V5 testing: Espresso, Robolectric, mocking the kit/SDK" },
93
108
  { name: "cometchat-android-v5-troubleshooting", families: ["android"], description: "V5 troubleshooting: gradle conflicts, manifest, lifecycle, ProGuard" },
109
+ { name: "cometchat-android-v5-calls", families: ["android"], description: "V5 calls (v4.1) — calls-sdk-android Cloudsmith install, ConnectionService + FCM VoIP, foreground service, 16 deep references/" },
94
110
 
95
111
  { name: "cometchat-android-v6", families: ["android"], description: "V6 dispatcher — Compose + Kotlin Views (chatuikit-{compose,kotlin}-android:6.x)" },
96
112
  { name: "cometchat-android-v6-core", families: ["android"], description: "V6: gradle deps, init, login, message sending" },
@@ -110,6 +126,8 @@ const SKILLS = [
110
126
  { name: "cometchat-android-v6-push", families: ["android"], description: "V6 push: FCM, dashboard providers, deep-link" },
111
127
  { name: "cometchat-android-v6-testing", families: ["android"], description: "V6 testing: Espresso, Robolectric, Compose UI tests, mocking" },
112
128
  { name: "cometchat-android-v6-troubleshooting", families: ["android"], description: "V6 troubleshooting: gradle, Compose runtime, R8, BuildConfig" },
129
+ { name: "cometchat-android-v6-calls", families: ["android"], description: "V6 calls (v4.1, beta) — calls bundled into chatuikit-{compose,kotlin}, .enableCalling(), surface-aware Compose+Views routing" },
130
+ { name: "cometchat-android-v6-migration", families: ["android"], description: "V5→V6 migration recipes — gradle deps rewrite, UIKitSettings.Builder API, theme parent (CometChatTheme.DayNight), calls bundled, Compose vs Views cohort selection" },
113
131
 
114
132
  // Flutter — V5 stable (`cometchat_chat_uikit:^5.2`) + V6 beta
115
133
  // (`cometchat_chat_uikit:^6.0.0-beta`) ship together. Routed by the
@@ -126,6 +144,7 @@ const SKILLS = [
126
144
  { name: "cometchat-flutter-v5-production", families: ["flutter"], description: "V5: server-minted auth tokens, user management, external-backend recipes" },
127
145
  { name: "cometchat-flutter-v5-push", families: ["flutter"], description: "V5: FCM/APNs push, token lifecycle, deep-link" },
128
146
  { name: "cometchat-flutter-v5-troubleshooting", families: ["flutter"], description: "V5 troubleshooting: pubspec, GetX, Pod errors, runtime crashes" },
147
+ { name: "cometchat-flutter-v5-testing", families: ["flutter"], description: "V5 testing (v4.1) — flutter_test + mocktail, GetX-aware widget tests, integration_test, golden tests, CI" },
129
148
 
130
149
  { name: "cometchat-flutter-v6", families: ["flutter"], description: "V6 dispatcher — cometchat_chat_uikit ^6.0.0-beta (Bloc-based)" },
131
150
  { name: "cometchat-flutter-v6-core", families: ["flutter"], description: "V6: pubspec deps, UIKitSettings, init/login, app entry" },
@@ -142,6 +161,8 @@ const SKILLS = [
142
161
  { name: "cometchat-flutter-v6-production", families: ["flutter"], description: "V6: server-minted auth tokens, user management, external-backend recipes" },
143
162
  { name: "cometchat-flutter-v6-troubleshooting", families: ["flutter"], description: "V6 troubleshooting: pubspec, Bloc, theme cache, build errors" },
144
163
  { name: "cometchat-flutter-v6-migration", families: ["flutter"], description: "V5→V6 migration recipes — GetX → Bloc, theme API rewrite, breaking changes" },
164
+ { name: "cometchat-flutter-v6-testing", families: ["flutter"], description: "V6 testing (v4.1) — flutter_test + bloc_test, BlocProvider.value patterns, integration_test, calls init-order assertion" },
165
+ { name: "cometchat-flutter-v6-push", families: ["flutter"], description: "V6 push (v4.1) — firebase_messaging FCM/APNs, background isolate handler with @pragma vm:entry-point, Bloc-driven foreground UI, deep-link to chat threads" },
145
166
 
146
167
  // iOS — V5 stable (`CometChatUIKitSwift:^5`). No V6 beta yet; when
147
168
  // it ships, add per-cohort namespacing as Android/Flutter do today.
@@ -155,8 +176,30 @@ const SKILLS = [
155
176
  { name: "cometchat-ios-production", families: ["ios"], description: "iOS: server-minted auth tokens, user management, external-backend recipes" },
156
177
  { name: "cometchat-ios-push", families: ["ios"], description: "iOS push: APNs + VoIP, CallKit, token lifecycle, deep-link" },
157
178
  { name: "cometchat-ios-troubleshooting", families: ["ios"], description: "iOS troubleshooting: SPM, CocoaPods, Xcode build errors, Info.plist, runtime crashes" },
179
+ { name: "cometchat-ios-calls", families: ["ios"], description: "iOS calls (v4.1) — CometChatCallsSDK install, CallKit + PushKit VoIP, AVAudioSession routing, mixed SwiftUI/UIKit hosting" },
180
+ { name: "cometchat-ios-testing", families: ["ios"], description: "iOS testing (v4.1) — XCTest + protocol-wrapped SDK mocks, async/await tests, SnapshotTesting, XCUITest, Xcode Cloud / GitHub Actions CI" },
158
181
  ];
159
182
 
183
+ // ── Base skills (cross-family) ────────────────────────────────────────────────
184
+ //
185
+ // Skills registered for ALL six families. These are the baseline a dispatcher
186
+ // needs to detect framework and route — they're installed in the default
187
+ // interactive flow, before any family is resolved. The dispatcher (read at
188
+ // runtime in the user's IDE) detects the framework and asks the agent to
189
+ // install the relevant family skills via:
190
+ //
191
+ // npx @cometchat/skills add --family <X> --ide <Y>
192
+ //
193
+ // (Logic already in `skills/cometchat/SKILL.md` Step 1 — "If `framework` is
194
+ // X AND `cometchat-{X}-core` is NOT loaded: <install command>".)
195
+ //
196
+ // This list grows automatically as more cross-family skills are registered
197
+ // (e.g. when the calls work merges, cometchat-calls/i18n/a11y join).
198
+ const ALL_FAMILIES_SET = ["web", "native", "flutter", "angular", "android", "ios"];
199
+ const BASE_SKILLS = SKILLS.filter(s =>
200
+ ALL_FAMILIES_SET.every(f => s.families.includes(f))
201
+ );
202
+
160
203
  // ── Framework → family routing ────────────────────────────────────────────────
161
204
  const FRAMEWORK_TO_FAMILY = {
162
205
  reactjs: "web",
@@ -186,15 +229,50 @@ function ensureDir(dir) {
186
229
  }
187
230
 
188
231
  // ── IDE target directories ────────────────────────────────────────────────────
232
+ //
233
+ // Three install modes:
234
+ //
235
+ // - "multi" → one SKILL.md per skill in a directory tree. Anthropic-spec
236
+ // native. Used by Claude Code, Replit Agent, Kiro.
237
+ //
238
+ // - "single" → all skills concatenated into one markdown file at a
239
+ // specific path. Used by GitHub Copilot Chat
240
+ // (.github/copilot-instructions.md), Cursor + Continue.dev
241
+ // (AGENTS.md at project root), Cline (.clinerules/cometchat.md),
242
+ // Aider (CONVENTIONS.md). The single file is markdown with
243
+ // `---` separators between skills — works with any agent that
244
+ // reads markdown context.
245
+ //
246
+ // - "cli-only" → no file written. The agent uses the `cometchat` CLI
247
+ // directly. For agents without a skill/rules format
248
+ // (Codex CLI, Gemini CLI, Aider when not using
249
+ // CONVENTIONS.md). Installer prints CLI usage hints.
250
+ //
251
+ // File-path notes:
252
+ // - Cursor's docs (cursor.com/docs/rules) say rules live at `.cursor/rules/`,
253
+ // NOT `.cursor/skills/`. AGENTS.md at project root is the simpler
254
+ // alternative Cursor also supports.
255
+ // - GitHub Copilot reads `.github/copilot-instructions.md` automatically.
256
+ // - Cline reads `.clinerules/*.md`.
257
+ // - Aider reads any markdown file passed via `--read CONVENTIONS.md` (or via
258
+ // `read: CONVENTIONS.md` in `.aider.conf.yml`).
189
259
  const IDE_TARGETS = {
190
- claude: { local: ".claude/skills", global: path.join(os.homedir(), ".claude", "skills"), skillFile: "SKILL.md" },
191
- // Cursor loads agent "skills" from `.cursor/skills/` (not `.cursor/rules/`).
192
- cursor: { local: ".cursor/skills", global: path.join(os.homedir(), ".cursor", "skills"), skillFile: "SKILL.md" },
193
- kiro: { local: ".kiro/skills", global: path.join(os.homedir(), ".kiro", "skills"), skillFile: "SKILL.md" },
194
- copilot: { local: ".github", global: null, skillFile: null }, // single-file mode
260
+ // Multi-file (Anthropic-spec compatible)
261
+ claude: { mode: "multi", local: ".claude/skills", global: path.join(os.homedir(), ".claude", "skills"), skillFile: "SKILL.md" },
262
+ kiro: { mode: "multi", local: ".kiro/skills", global: path.join(os.homedir(), ".kiro", "skills"), skillFile: "SKILL.md" },
195
263
  // Replit Agent reads `.agents/skills/` per docs.replit.com/core-concepts/agent/skills.
196
- // Global path matches the convention published by vercel-labs/skills.
197
- replit: { local: ".agents/skills", global: path.join(os.homedir(), ".config", "agents", "skills"), skillFile: "SKILL.md" },
264
+ replit: { mode: "multi", local: ".agents/skills", global: path.join(os.homedir(), ".config", "agents", "skills"), skillFile: "SKILL.md" },
265
+
266
+ // Single-file (concatenated markdown)
267
+ copilot: { mode: "single", local: ".github", global: null, fileName: "copilot-instructions.md" },
268
+ cursor: { mode: "single", local: ".", global: null, fileName: "AGENTS.md" },
269
+ continue: { mode: "single", local: ".", global: null, fileName: "AGENTS.md" },
270
+ cline: { mode: "single", local: ".clinerules", global: null, fileName: "cometchat.md" },
271
+ aider: { mode: "single", local: ".", global: null, fileName: "CONVENTIONS.md" },
272
+
273
+ // CLI-only (no skill/rules format on the agent side)
274
+ codex: { mode: "cli-only", local: null, global: null },
275
+ gemini: { mode: "cli-only", local: null, global: null },
198
276
  };
199
277
 
200
278
  // ── Framework detection (inline — no subprocess) ─────────────────────────────
@@ -371,26 +449,269 @@ function installSkill(skill, baseDir, skillFile) {
371
449
  return dest;
372
450
  }
373
451
 
374
- function installCopilotSkills(skillsToInstall, baseDir) {
452
+ /**
453
+ * Generate a short orienting AGENTS.md / CONVENTIONS.md / etc. (~3-5 KB)
454
+ * that tells the agent how to drive the cometchat CLI for any task.
455
+ *
456
+ * Why short instead of full SKILL.md concatenation:
457
+ * - Cursor / Continue / Cline read these as ALWAYS-ON context. A 430 KB
458
+ * concatenation burns tokens on every turn. Bad UX, bad cost.
459
+ * - The CLI is the universal surface — `cometchat init`, `apply-feature`,
460
+ * `builder open/export`, etc. Agents reliably execute CLI commands.
461
+ * - Inline help (`cometchat <cmd> --help`) carries the per-command
462
+ * guidance lazily, only when the agent needs it.
463
+ *
464
+ * The full SKILL.md tree still ships when the user installs with --ide claude
465
+ * (or replit / kiro). For non-Anthropic agents, this short orientation is
466
+ * the right shape.
467
+ */
468
+ function generateOrientingMd(skillsToInstall, families) {
469
+ const familyLabel = families.includes("all") ? "all platforms" : families.join(" + ");
470
+ const familyHint = families.length === 1 ? families[0] : "your project's framework";
471
+
472
+ let md = `# CometChat — AI Agent Instructions\n\n`;
473
+ md += `> Auto-generated by \`npx @cometchat/skills add\`. Do not hand-edit; rerun the installer to refresh.\n`;
474
+ md += `> Family: **${familyLabel}**. ${skillsToInstall.length} skills available.\n\n`;
475
+
476
+ md += `## When the user asks about CometChat\n\n`;
477
+ md += `If the user asks any of the following, run the matching CLI command — DO NOT improvise from training memory:\n\n`;
478
+ md += `| User says... | Run |\n|---|---|\n`;
479
+ md += `| "integrate cometchat" / "add chat" / "/cometchat" | \`cometchat init\` (or walk the user through \`detect\` → \`auth login\` → \`provision setup\` → \`apply\` → \`verify\`) |\n`;
480
+ md += `| "what's my framework" | \`cometchat detect --json\` |\n`;
481
+ md += `| "log me into CometChat" / "set up credentials" | \`cometchat auth login\` then \`cometchat provision setup --app-id <id> --framework <fw>\` |\n`;
482
+ md += `| "design chat visually" / "open the UI Kit Builder" | \`cometchat builder open --json\` (returns a deep URL into the dashboard's UI Kit Builder), then \`cometchat builder export --target . --json\` after the user designs |\n`;
483
+ md += `| "add polls" / "enable smart replies" / "turn on \\<feature\\>" | \`cometchat features list\` to find the feature id, then \`cometchat apply-feature <id>\` |\n`;
484
+ md += `| "match my brand" / "theme it like Slack" | \`cometchat apply-theme --preset slack\` (or \`--primary-color #...\`) |\n`;
485
+ md += `| "use real auth tokens, not the auth key" | \`cometchat production-auth\` |\n`;
486
+ md += `| "what went wrong" / "diagnose this" | \`cometchat doctor\` |\n`;
487
+ md += `| "what's installed already" | \`cometchat info\` or \`cometchat status\` |\n\n`;
488
+
489
+ md += `Run \`cometchat --help\` for the full command list. Each subcommand has \`--help\` with detailed usage.\n\n`;
490
+
491
+ md += `## How CometChat integration works (${familyHint})\n\n`;
492
+ md += `1. **Detect** the framework — \`cometchat detect --json\` returns framework, version, env-var prefix, and existing-integration state.\n`;
493
+ md += `2. **Authenticate** — the user logs into the CometChat dashboard via \`cometchat auth login\` (browser flow). Token is stored in OS keychain.\n`;
494
+ md += `3. **Provision** — \`cometchat provision setup --app-id <id> --framework <fw>\` writes credentials to the right env file (\`.env\` for Vite, \`.env.local\` for Next.js, \`local.properties\` for Android, \`Secrets.swift\` for iOS, etc.).\n`;
495
+ md += `4. **Apply** — \`cometchat apply --experience <N>\` writes the integration code (provider, components, placement). Idempotent.\n`;
496
+ md += `5. **Verify** — \`cometchat verify\` runs build + AST checks. \`cometchat doctor\` runs combined diagnostics.\n`;
497
+ md += `6. **Iterate** — features / theming / customization via the CLI commands above.\n\n`;
498
+
499
+ md += `## Hard rules (non-negotiable)\n\n`;
500
+ md += `- **Run \`cometchat detect\` BEFORE making framework assumptions.** The user's project might be React+Vite, Next.js App Router, React Router v7, Astro, Expo, bare RN, Angular 12-15, native Android (V5 stable + V6 beta), iOS V5, or Flutter (V5 stable + V6 beta) — each has different conventions.\n`;
501
+ md += `- **NEVER hardcode credentials.** Use \`cometchat provision setup\`, which writes the right env file with the right prefix. The Auth Key is for dev only — \`cometchat production-auth\` upgrades to server-minted tokens.\n`;
502
+ md += `- **NEVER hand-roll a custom search UI** — the UI Kit ships \`<CometChatSearch>\` (and \`showSearchBar\` on \`<CometChatConversations>\`). Hand-rolling silently breaks pagination + result highlighting.\n`;
503
+ md += `- **NEVER \`Skill()\`-style auto-load skills.** This file is your orientation; for deeper detail, run the CLI command for the specific task. The CLI's \`--help\` text is the source of truth.\n`;
504
+ md += `- **Component names + props** — for an unfamiliar component, run \`cometchat features info <name>\` or query the CometChat docs MCP if available. Don't invent from training data; the UI Kit's API surface has changed across versions.\n\n`;
505
+
506
+ md += `## When you need richer guidance\n\n`;
507
+ md += `Each \`cometchat <cmd> --help\` covers usage for that command. For deeper skill content (placement patterns, customization four-tier model, troubleshooting symptom-table, framework-specific gotchas) — install the multi-file skill set:\n\n`;
508
+ md += "```bash\n";
509
+ md += `npx @cometchat/skills add --family ${families[0] || "web"} --ide claude\n`;
510
+ md += "```\n\n";
511
+ md += `That writes ${skillsToInstall.length} per-skill markdown files to \`.claude/skills/cometchat-*/SKILL.md\`. Cursor / Continue / Cline can read those too — open the files directly when needed (\`@.claude/skills/cometchat-core/SKILL.md\` in Cursor, etc.).\n`;
512
+
513
+ return md;
514
+ }
515
+
516
+ /**
517
+ * Write a single orienting file (AGENTS.md / CONVENTIONS.md / etc.) at
518
+ * <baseDir>/<fileName>. Used for non-Anthropic-spec agents that read one
519
+ * always-on context file instead of a per-skill directory tree.
520
+ *
521
+ * The orienting file is short (~3-5 KB) and points the agent at the CLI as
522
+ * the universal surface. The full per-skill SKILL.md tree is opt-in via
523
+ * `--ide claude` (or replit / kiro) for agents that want the rich content.
524
+ */
525
+ function installSingleFileSkills(skillsToInstall, baseDir, fileName, families) {
375
526
  ensureDir(baseDir);
376
- const dest = path.join(baseDir, "copilot-instructions.md");
377
- let content = "# CometChat Skills\n\n";
378
- for (const skill of skillsToInstall) {
379
- const src = path.join(SKILLS_SRC_DIR, skill.name, "SKILL.md");
380
- if (!fs.existsSync(src)) continue;
381
- content += fs.readFileSync(src, "utf8") + "\n\n---\n\n";
382
- }
383
- fs.writeFileSync(dest, content, "utf8");
527
+ const dest = path.join(baseDir, fileName);
528
+ fs.writeFileSync(dest, generateOrientingMd(skillsToInstall, families), "utf8");
384
529
  return dest;
385
530
  }
386
531
 
532
+ /**
533
+ * For agents without a skill/rules format (Codex CLI, Gemini CLI), no file
534
+ * is written. The installer just prints CLI usage hints — the agent runs
535
+ * shell commands directly.
536
+ */
537
+ function printCliOnlyHints(ide, skillsToInstall) {
538
+ console.log(c.dim(`\n ${ide} has no skill/rules format. The cometchat CLI is the integration surface.`));
539
+ console.log(c.dim(` Available commands (run any from the project root):\n`));
540
+ console.log(` ${c.cyan("cometchat detect")} Identify framework`);
541
+ console.log(` ${c.cyan("cometchat auth login")} Authenticate to CometChat`);
542
+ console.log(` ${c.cyan("cometchat provision setup")} Wire credentials into .env`);
543
+ console.log(` ${c.cyan("cometchat init")} Apply the integration`);
544
+ console.log(` ${c.cyan("cometchat builder open")} Visual UI Kit Builder (deep URL)`);
545
+ console.log(` ${c.cyan("cometchat builder export")} Export visual builder output to project`);
546
+ console.log(` ${c.cyan("cometchat apply-feature <id>")} Toggle a feature (polls / smart-replies / etc.)`);
547
+ console.log(` ${c.cyan("cometchat doctor")} Diagnose drift / missing config`);
548
+ console.log(c.dim(`\n ${skillsToInstall.length} skills available — none copied (no compatible format).\n`));
549
+ }
550
+
551
+ // ── Multi-agent picker via vercel-labs/skills ────────────────────────────────
552
+ //
553
+ // Spawns `npx -y skills@<pin> add cometchat-team/cometchat-skills -s <names>`
554
+ // so the interactive multi-agent picker (Claude Code / Cursor / Codex /
555
+ // Cline / Kiro / Replit / 50+ agents) shows. The user picks which agents
556
+ // to write to; the skills CLI handles the per-agent path conventions.
557
+ //
558
+ // We pre-resolve the relevant skill list (BASE_SKILLS by default, full
559
+ // family if --family is set) and pass the names via `-s name1 name2 ...`
560
+ // so the user only sees skills relevant to their integration — not all
561
+ // 100+ in the marketplace.
562
+ //
563
+ // Pin: `skills@1.5.5` was the version verified against this codebase.
564
+ // Bump on intentional re-verification; pre-pin avoids breakage from a
565
+ // future major bump in the upstream CLI.
566
+ const SKILLS_CLI_PIN = "skills@1.5.5";
567
+ const SKILLS_REPO = "cometchat-team/cometchat-skills";
568
+
569
+ /**
570
+ * Read package.json + signal files to build a one-line "Detected" string
571
+ * we show the user before spawning the picker. Strictly cosmetic — the
572
+ * actual install doesn't depend on this.
573
+ *
574
+ * Returns something like:
575
+ * "Vite + React 19 + TypeScript (web family)"
576
+ * "Next.js 14 + TypeScript (web family)"
577
+ * "Expo 49 + React Native 0.72 (native family)"
578
+ * "no framework detected — base skills install fine without one"
579
+ */
580
+ function describeProjectContext(cwd) {
581
+ const pkg = (() => {
582
+ try { return JSON.parse(fs.readFileSync(path.join(cwd, "package.json"), "utf-8")); }
583
+ catch { return null; }
584
+ })();
585
+
586
+ const family = detectFamily(cwd);
587
+ const familyLabel = family ? FAMILY_LABELS[family] : null;
588
+ if (!pkg) {
589
+ return family
590
+ ? { line: `${familyLabel} project`, family }
591
+ : { line: "no framework detected — base skills install fine without one", family: null };
592
+ }
593
+
594
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
595
+ const hasTS = !!(deps.typescript || pkg.types || pkg.typings);
596
+ const reactV = deps.react ? deps.react.replace(/^[~^]/, "").split(".")[0] : null;
597
+ const parts = [];
598
+
599
+ if (deps.next) parts.push(`Next.js ${deps.next.replace(/^[~^]/, "").split(".")[0]}`);
600
+ else if (deps.vite || deps["@vitejs/plugin-react"]) parts.push(`Vite${reactV ? ` + React ${reactV}` : ""}`);
601
+ else if (deps.astro) parts.push(`Astro`);
602
+ else if (deps.expo) parts.push(`Expo ${deps.expo.replace(/^[~^]/, "").split(".")[0]}${deps["react-native"] ? ` + React Native ${deps["react-native"].replace(/^[~^]/, "").split(".")[0]}` : ""}`);
603
+ else if (deps["react-native"]) parts.push(`React Native ${deps["react-native"].replace(/^[~^]/, "").split(".")[0]}`);
604
+ else if (deps["@angular/core"]) parts.push(`Angular ${deps["@angular/core"].replace(/^[~^]/, "").split(".")[0]}`);
605
+ else if (deps.react) parts.push(`React ${reactV}`);
606
+ else if (familyLabel) parts.push(familyLabel);
607
+
608
+ if (hasTS && !parts.some(p => p.includes("TypeScript"))) parts.push("TypeScript");
609
+
610
+ const line = parts.length
611
+ ? `${parts.join(" + ")}${family ? ` (${family} family)` : ""}`
612
+ : familyLabel || "unknown framework — base install still works";
613
+
614
+ return { line, family };
615
+ }
616
+
617
+ async function delegateToSkillsCli({ skills, families, isGlobal }) {
618
+ const skillNames = skills.map(s => s.name);
619
+ const isBaseInstall = families.length === 1 && families[0] === "base";
620
+ const cwd = process.cwd();
621
+ const ctx = describeProjectContext(cwd);
622
+ const projectPath = cwd.replace(os.homedir(), "~");
623
+
624
+ // Pre-spawn: brand + project context + framing of what's about to happen
625
+ const installLabel = isBaseInstall
626
+ ? `base install ${c.dim("· dispatcher routes the rest at runtime")}`
627
+ : `${families.includes("all") ? "all" : families.join("+")} family ${c.dim(`· ${skillNames.length} skills`)}`;
628
+
629
+ console.log(``);
630
+ console.log(` ${c.bold(c.cyan("CometChat Skills"))} ${c.dim("·")} ${installLabel}`);
631
+ console.log(``);
632
+ console.log(` ${c.dim("Project")} ${projectPath}`);
633
+ console.log(` ${c.dim("Detected")} ${ctx.line}`);
634
+ console.log(``);
635
+ if (isBaseInstall) {
636
+ console.log(` ${c.gray(`We're about to install ${skillNames.length} cross-family skills (${skillNames.map(s => s.replace(/^cometchat-?/, "") || "router").filter(Boolean).join(", ")})`)}`);
637
+ console.log(` ${c.gray(`to whichever AI agents you pick. Once installed, run /cometchat in your IDE`)}`);
638
+ console.log(` ${c.gray(`— the dispatcher detects your framework and writes the integration.`)}`);
639
+ } else {
640
+ console.log(` ${c.gray(`Installing ${skillNames.length} ${families.join("+")} skills via the multi-agent picker.`)}`);
641
+ }
642
+ console.log(``);
643
+ console.log(` ${c.gray("Launching the multi-agent picker...")}`);
644
+ console.log(``);
645
+
646
+ const npxArgs = [
647
+ "-y", // auto-accept the npx install prompt for the skills CLI itself
648
+ SKILLS_CLI_PIN,
649
+ "add",
650
+ SKILLS_REPO,
651
+ "-s", ...skillNames, // space-separated skill names (skills CLI's flag shape)
652
+ ];
653
+ if (isGlobal) npxArgs.push("-g");
654
+
655
+ return new Promise((resolve) => {
656
+ const child = spawn("npx", npxArgs, {
657
+ stdio: "inherit",
658
+ shell: false,
659
+ });
660
+ child.on("close", (code) => {
661
+ if (code === 0) {
662
+ // Post-spawn success: celebrate + concrete next steps
663
+ printPostInstallNextSteps({ isBaseInstall, ctx, projectPath });
664
+ }
665
+ resolve(code ?? 1);
666
+ });
667
+ child.on("error", (err) => {
668
+ console.error(c.red(`\n ✗ Failed to spawn skills CLI: ${err.message}`));
669
+ console.error(c.dim(` Falling back to legacy direct-write — re-run with --ide <name> to bypass the picker.\n`));
670
+ resolve(2);
671
+ });
672
+ });
673
+ }
674
+
675
+ function printPostInstallNextSteps({ isBaseInstall, ctx, projectPath }) {
676
+ console.log(``);
677
+ console.log(` ${c.green("✓")} ${c.bold(isBaseInstall ? "Base skills installed." : "Skills installed.")}`);
678
+ console.log(``);
679
+ console.log(` ${c.bold("Next:")} open ${c.cyan(projectPath)} in any agent you picked, then in the chat panel:`);
680
+ console.log(``);
681
+ console.log(` ${c.cyan("/cometchat add chat to my app")}`);
682
+ console.log(``);
683
+ if (isBaseInstall) {
684
+ const detected = ctx.family ? ctx.line.replace(/ \(.*\)$/, "") : "your framework";
685
+ console.log(` ${c.gray(`The dispatcher detects ${detected}, walks you through CometChat signup,`)}`);
686
+ console.log(` ${c.gray(`and writes the integration code based on your project (~30 seconds).`)}`);
687
+ } else {
688
+ console.log(` ${c.gray("All skills are loaded; the dispatcher walks you through the rest.")}`);
689
+ }
690
+ console.log(``);
691
+ console.log(` ${c.dim("Docs:")} ${c.cyan("https://www.cometchat.com/docs/skills")}`);
692
+ console.log(``);
693
+ }
694
+
387
695
  function printHelp() {
388
696
  console.log(`
389
697
  ${c.bold("@cometchat/skills")} — Install CometChat AI coding skills
390
698
 
391
699
  ${c.bold("Usage:")}
392
- ${c.cyan("npx @cometchat/skills add")} Auto-detect framework + install
393
- ${c.cyan("npx @cometchat/skills add --family <name>")} Override detection
700
+ ${c.cyan("npx @cometchat/skills add")} Base install + interactive multi-agent picker
701
+ ${c.cyan("npx @cometchat/skills add --family <name>")} Install full family upfront (no runtime expansion)
702
+ ${c.cyan("npx @cometchat/skills add --ide <name>")} Direct-write base skills to one IDE (CI/scripted)
703
+
704
+ ${c.bold("Two install shapes:")}
705
+ ${c.bold("Base install")} (default — no --family flag): writes only the cross-family
706
+ skills (the cometchat dispatcher + cross-family helpers). Once installed,
707
+ open your project in your IDE and run /cometchat — the dispatcher detects
708
+ your framework and asks the agent to install the family-specific skills
709
+ via \`npx @cometchat/skills add --family <X> --ide <Y>\`. Smallest initial
710
+ install, dispatcher routes the rest. Recommended for most users.
711
+ ${c.bold("Full family install")} (--family flag): writes the dispatcher + every
712
+ skill registered for that family (web=13, android=31, flutter=28, etc.)
713
+ upfront. Use when you know the project's framework and prefer all skills
714
+ present immediately. Used by power users + CI smoke tests.
394
715
 
395
716
  ${c.bold("Family values:")}
396
717
  ${c.cyan("web")} React / Next.js / React Router / Astro
@@ -401,16 +722,27 @@ function printHelp() {
401
722
  ${c.cyan("ios")} iOS native (V5 stable)
402
723
  ${c.cyan("all")} Install every skill (legacy v3 behavior)
403
724
 
404
- ${c.bold("IDE selection (default: claude):")}
405
- ${c.cyan("--ide cursor")} ${c.cyan("--ide kiro")} ${c.cyan("--ide copilot")} ${c.cyan("--ide replit")} ${c.cyan("--ide all")}
725
+ ${c.bold("IDE selection (direct-write mode only — default: claude):")}
726
+ ${c.cyan("--ide claude")} Multi-file SKILL.md at .claude/skills/ (default)
727
+ ${c.cyan("--ide cursor")} Single AGENTS.md at project root
728
+ ${c.cyan("--ide copilot")} Single .github/copilot-instructions.md
729
+ ${c.cyan("--ide cline")} Single .clinerules/cometchat.md
730
+ ${c.cyan("--ide continue")} Single AGENTS.md at project root
731
+ ${c.cyan("--ide aider")} Single CONVENTIONS.md at project root
732
+ ${c.cyan("--ide kiro")} Multi-file SKILL.md at .kiro/skills/
733
+ ${c.cyan("--ide replit")} Multi-file SKILL.md at .agents/skills/
734
+ ${c.cyan("--ide codex")} No skill format — print CLI hints
735
+ ${c.cyan("--ide gemini")} No skill format — print CLI hints
736
+ ${c.cyan("--ide all")} Install for every IDE
406
737
 
407
738
  ${c.bold("Multi-family / monorepo:")}
408
739
  ${c.cyan("--family web --family native")} Install BOTH families (repeat flag)
409
740
 
410
741
  ${c.bold("Other:")}
411
742
  ${c.cyan("--global")} Install globally (~/.claude/skills/, etc.)
412
- ${c.cyan("--clean")} Wipe existing cometchat-* skill dirs before install
743
+ ${c.cyan("--clean")} Wipe existing cometchat-* skill dirs before install (direct-write mode only)
413
744
  ${c.cyan("--list")} Show every skill with its family tags
745
+ ${c.cyan("--no-picker")} Force direct-write even in interactive TTY (useful for testing the legacy path)
414
746
 
415
747
  ${c.bold("After installing, open your project in your IDE and run:")}
416
748
  ${c.cyan("/cometchat")}
@@ -448,37 +780,88 @@ async function main() {
448
780
  process.exit(0);
449
781
  }
450
782
 
451
- // Resolve which families to install (flag(s) → detect → prompt).
452
- const families = await resolveFamilies(args);
453
-
454
- // Build the set of skills to install — union over all selected families.
455
- // "all" is a singleton meaning "every published skill" (legacy v3 behavior).
783
+ // ── Install mode selection ─────────────────────────────────────────────
784
+ //
785
+ // Three valid invocation shapes:
786
+ //
787
+ // 1. `npx @cometchat/skills add` (TTY, no --family, no --ide)
788
+ // → BASE INSTALL: install only cross-family skills (cometchat
789
+ // dispatcher + cometchat-calls + i18n + a11y) via the multi-agent
790
+ // picker. The dispatcher detects the framework AT RUNTIME inside
791
+ // the user's IDE and asks the agent to install family-specific
792
+ // skills via `npx @cometchat/skills add --family <X> --ide <Y>`.
793
+ // Smallest initial install; routing is the dispatcher's job.
794
+ //
795
+ // 2. `npx @cometchat/skills add --family <X>` (TTY)
796
+ // → FAMILY INSTALL: install the dispatcher + every skill registered
797
+ // for family X (web=13, android=31, etc.) via the picker. Use this
798
+ // when you know upfront which family you want and prefer all
799
+ // skills present immediately.
800
+ //
801
+ // 3. `npx @cometchat/skills add --ide <Y>` (or non-TTY, e.g. CI)
802
+ // → DIRECT WRITE: skips the picker and writes directly to one IDE's
803
+ // directory. With --family, writes the family subset; without, falls
804
+ // back to BASE skills (CI smoke). Used by Dockerfiles and the
805
+ // legacy single-agent flow.
806
+ const ideExplicit = ideIdx !== -1;
807
+ const familyExplicit = args.includes("--family");
808
+ const isTTY = process.stdin.isTTY && process.stdout.isTTY;
809
+ const skipPicker = ideExplicit || !isTTY || args.includes("--no-picker");
810
+
811
+ // Resolve skill set based on mode:
812
+ // - --family X → install the dispatcher + every skill registered for X
813
+ // (legacy power-user / CI flow; everything present immediately)
814
+ // - No --family (with or without --ide) → BASE install only. The
815
+ // dispatcher handles family-specific install at runtime via its own
816
+ // `npx @cometchat/skills add --family <X>` invocation logic.
456
817
  let skillsToInstall;
457
- if (families.includes("all")) {
458
- skillsToInstall = SKILLS;
459
- } else {
460
- const seen = new Set();
461
- skillsToInstall = [];
462
- for (const fam of families) {
463
- for (const s of SKILLS) {
464
- if (s.families.includes(fam) && !seen.has(s.name)) {
465
- seen.add(s.name);
466
- skillsToInstall.push(s);
818
+ let families;
819
+ if (familyExplicit) {
820
+ families = await resolveFamilies(args);
821
+ if (families.includes("all")) {
822
+ skillsToInstall = SKILLS;
823
+ } else {
824
+ const seen = new Set();
825
+ skillsToInstall = [];
826
+ for (const fam of families) {
827
+ for (const s of SKILLS) {
828
+ if (s.families.includes(fam) && !seen.has(s.name)) {
829
+ seen.add(s.name);
830
+ skillsToInstall.push(s);
831
+ }
467
832
  }
468
833
  }
469
834
  }
835
+
836
+ // If no pattern skills matched (only the dispatcher), all selected
837
+ // families are "coming soon" — bail with a friendly message rather than
838
+ // installing a half-broken set.
839
+ const patternSkills = skillsToInstall.filter(s => s.name !== "cometchat");
840
+ if (patternSkills.length === 0) {
841
+ const labels = families.map(f => FAMILY_LABELS[f] || f).join(", ");
842
+ console.log(c.yellow(`\n ⚠ Pattern skills for ${labels} aren't published yet.`));
843
+ console.log(` Supported families today: ${c.cyan("web")}, ${c.cyan("native")}, ${c.cyan("angular")}, ${c.cyan("android")}, ${c.cyan("flutter")}, ${c.cyan("ios")}.`);
844
+ console.log(` Run with one of those, or wait for ${families.join(" + ")} skills to ship.\n`);
845
+ process.exit(1);
846
+ }
847
+ } else {
848
+ // Default: base install only (whether interactive or with --ide).
849
+ // The dispatcher detects the framework at runtime and installs the
850
+ // family-specific skills via its own runtime npx invocation. The
851
+ // user-facing intro is printed by delegateToSkillsCli (interactive
852
+ // flow) or the direct-write loop below (CI flow) — no duplicate
853
+ // banner here.
854
+ skillsToInstall = BASE_SKILLS;
855
+ families = ["base"];
470
856
  }
471
857
 
472
- // If no pattern skills matched (only the dispatcher), all selected families
473
- // are "coming soon" — bail with a friendly message rather than installing a
474
- // half-broken set.
475
- const patternSkills = skillsToInstall.filter(s => s.name !== "cometchat");
476
- if (patternSkills.length === 0) {
477
- const labels = families.map(f => FAMILY_LABELS[f] || f).join(", ");
478
- console.log(c.yellow(`\n ⚠ Pattern skills for ${labels} aren't published yet.`));
479
- console.log(` Supported families today: ${c.cyan("web")}, ${c.cyan("native")}, ${c.cyan("angular")}, ${c.cyan("android")}, ${c.cyan("flutter")}, ${c.cyan("ios")}.`);
480
- console.log(` Run with one of those, or wait for ${families.join(" + ")} skills to ship.\n`);
481
- process.exit(1);
858
+ if (!skipPicker) {
859
+ const exitCode = await delegateToSkillsCli({
860
+ skills: skillsToInstall,
861
+ families,
862
+ isGlobal,
863
+ });
864
+ process.exit(exitCode);
482
865
  }
483
866
 
484
867
  const targets = ideArg === "all" ? Object.keys(IDE_TARGETS) : [ideArg];
@@ -490,6 +873,14 @@ async function main() {
490
873
  process.exit(1);
491
874
  }
492
875
 
876
+ // CLI-only mode: no file write. Just print CLI usage hints.
877
+ if (target.mode === "cli-only") {
878
+ const familyLabel = families.includes("all") ? "all" : families.join("+");
879
+ console.log(`\n ${c.bold(c.cyan("CometChat Skills"))} — ${ide} — ${c.bold(familyLabel)} family\n`);
880
+ printCliOnlyHints(ide, skillsToInstall);
881
+ continue;
882
+ }
883
+
493
884
  if (isGlobal && !target.global) {
494
885
  console.log(`\n ${c.yellow("⚠")} ${ide} does not support global install — skipping.`);
495
886
  continue;
@@ -508,10 +899,9 @@ async function main() {
508
899
 
509
900
  // --clean: wipe existing cometchat-* skill dirs in baseDir before install.
510
901
  // Avoids stale skills accumulating across multiple --family runs in the
511
- // same project (e.g. user runs --family web then later switches to
512
- // --family native and wants only the new family present). Only touches
513
- // dirs prefixed `cometchat` so we never blow away unrelated skills.
514
- if (isClean && ide !== "copilot" && fs.existsSync(baseDir)) {
902
+ // same project. Only touches the cometchat-* skill dirs in multi-mode;
903
+ // single-mode rewrites the whole file.
904
+ if (isClean && target.mode === "multi" && fs.existsSync(baseDir)) {
515
905
  let wiped = 0;
516
906
  for (const entry of fs.readdirSync(baseDir)) {
517
907
  if (entry === "cometchat" || entry.startsWith("cometchat-")) {
@@ -522,17 +912,18 @@ async function main() {
522
912
  if (wiped > 0) console.log(c.dim(` ✓ cleaned ${wiped} existing cometchat-* skill ${wiped === 1 ? "dir" : "dirs"}\n`));
523
913
  }
524
914
 
525
- if (ide === "copilot") {
526
- const spinner = ora ? ora({ text: "copilot-instructions.md", prefixText: " " }).start() : null;
915
+ if (target.mode === "single") {
916
+ const spinner = ora ? ora({ text: target.fileName, prefixText: " " }).start() : null;
527
917
  try {
528
- installCopilotSkills(skillsToInstall, baseDir);
529
- if (spinner) spinner.succeed(c.green("✓ ") + c.bold("copilot-instructions.md") + ` ${c.dim(`(${skillsToInstall.length} skills concatenated)`)}`);
530
- else console.log(` ✓ copilot-instructions.md (${skillsToInstall.length} skills)`);
918
+ installSingleFileSkills(skillsToInstall, baseDir, target.fileName, families);
919
+ if (spinner) spinner.succeed(c.green("✓ ") + c.bold(target.fileName) + ` ${c.dim(`(${skillsToInstall.length} skills concatenated)`)}`);
920
+ else console.log(` ✓ ${target.fileName} (${skillsToInstall.length} skills)`);
531
921
  } catch (err) {
532
- if (spinner) spinner.fail(c.red(`✗ copilot-instructions.md: ${err.message}`));
533
- else console.error(` ✗ copilot-instructions.md: ${err.message}`);
922
+ if (spinner) spinner.fail(c.red(`✗ ${target.fileName}: ${err.message}`));
923
+ else console.error(` ✗ ${target.fileName}: ${err.message}`);
534
924
  }
535
925
  } else {
926
+ // multi mode: one SKILL.md per skill
536
927
  for (const skill of skillsToInstall) {
537
928
  const spinner = ora ? ora({ text: skill.name, prefixText: " " }).start() : null;
538
929
  try {