@rainbow-robotics/muscat-plugin-kit 1.3.8-dev.2 → 1.10.1-dev.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 (213) hide show
  1. package/README.md +282 -282
  2. package/cli/README.md +274 -274
  3. package/cli/bin/create-muscat-plugin.mjs +8 -8
  4. package/cli/bin/muscat-pk.mjs +155 -153
  5. package/cli/bundle-templates.mjs +31 -31
  6. package/cli/docker/Dockerfile.cpp +28 -28
  7. package/cli/docker/Dockerfile.dev +30 -30
  8. package/cli/docker/Dockerfile.python +21 -21
  9. package/cli/m5-e2e.mjs +69 -69
  10. package/cli/prepack.mjs +10 -10
  11. package/cli/src/ai-rules.mjs +70 -0
  12. package/cli/src/build.mjs +447 -437
  13. package/cli/src/check-package.mjs +13 -13
  14. package/cli/src/completion.mjs +166 -166
  15. package/cli/src/cpp.mjs +78 -79
  16. package/cli/src/cppIde.mjs +75 -75
  17. package/cli/src/dev.mjs +165 -164
  18. package/cli/src/devBack.mjs +727 -670
  19. package/cli/src/devUi.mjs +243 -238
  20. package/cli/src/esbuild.mjs +56 -56
  21. package/cli/src/host_agent.py +223 -222
  22. package/cli/src/manifest.mjs +287 -283
  23. package/cli/src/mcp.mjs +1071 -1016
  24. package/cli/src/muscatLocal.mjs +209 -198
  25. package/cli/src/new.mjs +343 -338
  26. package/cli/src/pluginDevServer.mjs +111 -112
  27. package/cli/src/ports.mjs +193 -193
  28. package/cli/src/python.mjs +112 -113
  29. package/cli/src/ros2.mjs +109 -110
  30. package/cli/src/sdk.mjs +117 -117
  31. package/cli/src/storybook.mjs +168 -168
  32. package/cli/src/type.mjs +141 -141
  33. package/cli/src/uninstall.mjs +81 -81
  34. package/cli/src/update.mjs +295 -295
  35. package/cli/src/util.mjs +441 -437
  36. package/cli/src/zenohDev.mjs +81 -81
  37. package/cli/storybook-dist/_design-tokens.css +4957 -4957
  38. package/cli/storybook-dist/_stories-src/NxAvatar.stories.tsx +27 -27
  39. package/cli/storybook-dist/_stories-src/NxPagination.stories.tsx +28 -28
  40. package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordion.stories.tsx +46 -46
  41. package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordionGroup.stories.tsx +73 -73
  42. package/cli/storybook-dist/_stories-src/RBBadge/RBBadge.stories.tsx +93 -93
  43. package/cli/storybook-dist/_stories-src/RBBattery/RBBattery.stories.tsx +74 -74
  44. package/cli/storybook-dist/_stories-src/RBButton/RBCheckIconButton.stories.tsx +28 -28
  45. package/cli/storybook-dist/_stories-src/RBButton/RBCheckLabelButton.stories.tsx +84 -84
  46. package/cli/storybook-dist/_stories-src/RBButton/RBIconButton.stories.tsx +57 -57
  47. package/cli/storybook-dist/_stories-src/RBButton/RBInlineLabelButton.stories.tsx +41 -41
  48. package/cli/storybook-dist/_stories-src/RBButton/RBLabelButton.stories.tsx +60 -60
  49. package/cli/storybook-dist/_stories-src/RBDatePicker/RBDateInput.stories.tsx +44 -44
  50. package/cli/storybook-dist/_stories-src/RBDatePicker/RBRangeDateInput.stories.tsx +56 -56
  51. package/cli/storybook-dist/_stories-src/RBDialog/RBAlert.stories.tsx +51 -51
  52. package/cli/storybook-dist/_stories-src/RBDialog/RBConfirm.stories.tsx +55 -55
  53. package/cli/storybook-dist/_stories-src/RBDialog/RBPrompt.stories.tsx +52 -52
  54. package/cli/storybook-dist/_stories-src/RBDivider/RBDivider.stories.tsx +93 -93
  55. package/cli/storybook-dist/_stories-src/RBEmptyView/RBEmptyView.stories.tsx +49 -49
  56. package/cli/storybook-dist/_stories-src/RBIcons/RBColorIcons.stories.tsx +108 -108
  57. package/cli/storybook-dist/_stories-src/RBIcons/RBIcons.stories.tsx +106 -106
  58. package/cli/storybook-dist/_stories-src/RBInput/RBCheckBox.stories.tsx +89 -89
  59. package/cli/storybook-dist/_stories-src/RBInput/RBMultiRangeInput.stories.tsx +64 -64
  60. package/cli/storybook-dist/_stories-src/RBInput/RBRadioBox.stories.tsx +65 -65
  61. package/cli/storybook-dist/_stories-src/RBInput/RBRadioButton.stories.tsx +68 -68
  62. package/cli/storybook-dist/_stories-src/RBInput/RBSelectBox.stories.tsx +216 -216
  63. package/cli/storybook-dist/_stories-src/RBInput/RBSideNumberInput.stories.tsx +90 -90
  64. package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextArea.stories.tsx +45 -45
  65. package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextInput.stories.tsx +50 -50
  66. package/cli/storybook-dist/_stories-src/RBInput/RBTextField.stories.tsx +102 -102
  67. package/cli/storybook-dist/_stories-src/RBJoyStick/RBJoyStick.stories.tsx +31 -31
  68. package/cli/storybook-dist/_stories-src/RBLight/RBLight.stories.tsx +36 -36
  69. package/cli/storybook-dist/_stories-src/RBPagination/RBPagination.stories.tsx +49 -49
  70. package/cli/storybook-dist/_stories-src/RBShadcn/RBCard/RBCard.stories.tsx +89 -89
  71. package/cli/storybook-dist/_stories-src/RBShadcn/RBCommand/RBCommand.stories.tsx +116 -116
  72. package/cli/storybook-dist/_stories-src/RBShadcn/RBDialog/RBDialog.stories.tsx +74 -74
  73. package/cli/storybook-dist/_stories-src/RBShadcn/RBDrawer/RBDrawer.stories.tsx +99 -99
  74. package/cli/storybook-dist/_stories-src/RBShadcn/RBDropdownMenu/RBDropdownMenu.stories.tsx +123 -123
  75. package/cli/storybook-dist/_stories-src/RBShadcn/RBMenubar/RBMenubar.stories.tsx +135 -135
  76. package/cli/storybook-dist/_stories-src/RBShadcn/RBPopover/RBPopover.stories.tsx +69 -69
  77. package/cli/storybook-dist/_stories-src/RBShadcn/RBResizable/RBResizable.stories.tsx +49 -49
  78. package/cli/storybook-dist/_stories-src/RBShadcn/RBSheet/RBSheet.stories.tsx +91 -91
  79. package/cli/storybook-dist/_stories-src/RBShadcn/RBSlider/RBSlider.stories.tsx +38 -38
  80. package/cli/storybook-dist/_stories-src/RBShadcn/RBSwitch/RBSwitch.stories.tsx +112 -112
  81. package/cli/storybook-dist/_stories-src/RBShadcn/RBTabs/RBTabs.stories.tsx +75 -75
  82. package/cli/storybook-dist/_stories-src/RBShadcn/RBToggle/RBToggle.stories.tsx +51 -51
  83. package/cli/storybook-dist/_stories-src/RBShadcn/RBToggleGroup/RBToggleGroup.stories.tsx +84 -84
  84. package/cli/storybook-dist/_stories-src/RBTab/RBChipTab.stories.tsx +102 -102
  85. package/cli/storybook-dist/_stories-src/RBTab/RBChipsBoxTab.stories.tsx +78 -78
  86. package/cli/storybook-dist/_stories-src/RBTab/RBTab.stories.tsx +57 -57
  87. package/cli/storybook-dist/_stories-src/RBTable/RBTable.stories.tsx +177 -177
  88. package/cli/storybook-dist/_stories-src/RBTable/RBTableRow.stories.tsx +64 -64
  89. package/cli/storybook-dist/_stories-src/RBToast/RBToast.stories.tsx +117 -117
  90. package/cli/storybook-dist/_stories-src/RBTooltip/RBTooltip.stories.tsx +50 -50
  91. package/cli/storybook-dist/_stories-src/loading/RBSpinner.stories.tsx +30 -30
  92. package/cli/storybook-dist/_stories-src/nx-button/NxButton.stories.tsx +54 -54
  93. package/cli/storybook-dist/_stories-src/nx-button/NxPointerHoldButton.stories.tsx +57 -57
  94. package/cli/storybook-dist/_stories-src/nx-icons/NxIcons.stories.tsx +48 -48
  95. package/cli/storybook-dist/_stories-src/nx-inputs/NxNumberInput.stories.tsx +103 -103
  96. package/cli/storybook-dist/_stories-src/nx-inputs/NxRangeInput.stories.tsx +27 -27
  97. package/cli/storybook-dist/_stories-src/nx-inputs/NxSelectBox.stories.tsx +67 -67
  98. package/cli/storybook-dist/_stories-src/nx-inputs/NxSlideRange.stories.tsx +45 -45
  99. package/cli/storybook-dist/_stories-src/nx-inputs/NxSwitch.stories.tsx +27 -27
  100. package/cli/storybook-dist/_stories-src/nx-inputs/NxTextArea.stories.tsx +48 -48
  101. package/cli/storybook-dist/_stories-src/nx-inputs/NxTextInput.stories.tsx +46 -46
  102. package/cli/storybook-dist/assets/{Color-YHDXOIA2-DeirXVfl.js → Color-YHDXOIA2-D6JqZzDJ.js} +1 -1
  103. package/cli/storybook-dist/assets/{Docs-BLxyi8cP.js → Docs-6gD2kUo1.js} +2 -2
  104. package/cli/storybook-dist/assets/{Docs-NrBqEYvM.js → Docs-B9wd8Ok7.js} +3 -3
  105. package/cli/storybook-dist/assets/{Docs-wzFMK-XA.js → Docs-CMjovnSY.js} +4 -4
  106. package/cli/storybook-dist/assets/{Docs-Buyf7Djy.js → Docs-CgFbWWXM.js} +2 -2
  107. package/cli/storybook-dist/assets/{Docs-CnfIOwf8.js → Docs-DBQup8Bu.js} +3 -3
  108. package/cli/storybook-dist/assets/{Docs-BxmwdaYa.js → Docs-ESb7JAHg.js} +3 -3
  109. package/cli/storybook-dist/assets/{DocsRenderer-CFRXHY34-CWc43rTP.js → DocsRenderer-CFRXHY34-BOUI1AHi.js} +1 -1
  110. package/cli/storybook-dist/assets/{NxAvatar.stories-DfL0kqmN.js → NxAvatar.stories-DsYFMUh3.js} +1 -1
  111. package/cli/storybook-dist/assets/{NxButton.stories-WxSc_gsR.js → NxButton.stories-CHfNcqsc.js} +8 -8
  112. package/cli/storybook-dist/assets/{NxNumberInput.stories-C1D3oUiY.js → NxNumberInput.stories-BFw_4vFE.js} +1 -1
  113. package/cli/storybook-dist/assets/{NxPagination.stories-C1Qa88rn.js → NxPagination.stories-DVfxyw4M.js} +1 -1
  114. package/cli/storybook-dist/assets/{NxPointerHoldButton.stories-CmteJX3t.js → NxPointerHoldButton.stories-BzyxUWoZ.js} +1 -1
  115. package/cli/storybook-dist/assets/{NxRangeInput.stories-B7E-mhyI.js → NxRangeInput.stories-DmRdzBc1.js} +6 -6
  116. package/cli/storybook-dist/assets/{NxSelectBox.stories-De67vMdU.js → NxSelectBox.stories-B1KkNUOf.js} +1 -1
  117. package/cli/storybook-dist/assets/{NxSlideRange.stories-DvCV1MGk.js → NxSlideRange.stories-CyOdvfQ6.js} +1 -1
  118. package/cli/storybook-dist/assets/{NxSwitch.stories-DuHDZ9-v.js → NxSwitch.stories-DrDBw0qp.js} +1 -1
  119. package/cli/storybook-dist/assets/{NxTextArea.stories-BT1o0ngg.js → NxTextArea.stories-DTB2aqNS.js} +1 -1
  120. package/cli/storybook-dist/assets/{NxTextInput.stories-CSLBT83Q.js → NxTextInput.stories-DU0rucmM.js} +1 -1
  121. package/cli/storybook-dist/assets/{RBAccordion.stories-QavkYgV0.js → RBAccordion.stories-DTfOtXtp.js} +3 -3
  122. package/cli/storybook-dist/assets/{RBAccordionGroup.stories-C0RPGnO7.js → RBAccordionGroup.stories-9y9BjrUe.js} +10 -10
  123. package/cli/storybook-dist/assets/{RBAlert.stories-BUCAT0Sd.js → RBAlert.stories-DLTAv9fT.js} +3 -3
  124. package/cli/storybook-dist/assets/{RBBadge.stories-CnBXTQ4J.js → RBBadge.stories-BNMACewA.js} +1 -1
  125. package/cli/storybook-dist/assets/{RBBattery.stories-5FbsZcdy.js → RBBattery.stories-B3kXMAt5.js} +1 -1
  126. package/cli/storybook-dist/assets/{RBCard.stories-FwTKjtCi.js → RBCard.stories-Y-s8R2n7.js} +39 -39
  127. package/cli/storybook-dist/assets/{RBCheckBox.stories-C0y5psMI.js → RBCheckBox.stories-DBuT9tL4.js} +1 -1
  128. package/cli/storybook-dist/assets/{RBCheckIconButton.stories-sJjAZBVh.js → RBCheckIconButton.stories-CWu1TL56.js} +1 -1
  129. package/cli/storybook-dist/assets/{RBCheckLabelButton.stories-COJqEkDr.js → RBCheckLabelButton.stories-sCu2MGCX.js} +17 -17
  130. package/cli/storybook-dist/assets/{RBChipTab.stories-BnXj-Woa.js → RBChipTab.stories-BX9qLJkR.js} +5 -5
  131. package/cli/storybook-dist/assets/{RBChipsBoxTab.stories-DE1yl3rz.js → RBChipsBoxTab.stories-35u1aJ-P.js} +1 -1
  132. package/cli/storybook-dist/assets/{RBColorIcons.stories-CYASERLQ.js → RBColorIcons.stories-DAOZ5Ies.js} +1 -1
  133. package/cli/storybook-dist/assets/RBCommand.stories-BSqXDkKw.js +73 -0
  134. package/cli/storybook-dist/assets/{RBConfirm.stories-XLLTJZRf.js → RBConfirm.stories-iMXcUh7Z.js} +3 -3
  135. package/cli/storybook-dist/assets/{RBDateInput.stories-DpVylrQl.js → RBDateInput.stories-hK5rXECf.js} +1 -1
  136. package/cli/storybook-dist/assets/RBDialog.stories-BAktz-ku.js +38 -0
  137. package/cli/storybook-dist/assets/{RBDivider.stories-NOTo-jJG.js → RBDivider.stories-BAK-iZ1Z.js} +1 -1
  138. package/cli/storybook-dist/assets/{RBDrawer.stories-CUZaQyw8.js → RBDrawer.stories-B2nqf2Nh.js} +12 -12
  139. package/cli/storybook-dist/assets/RBDropdownMenu.stories-DbW2fWAj.js +86 -0
  140. package/cli/storybook-dist/assets/{RBEmptyView.stories-BIRNPjwt.js → RBEmptyView.stories-nCenrgBh.js} +1 -1
  141. package/cli/storybook-dist/assets/{RBIconButton.stories-CJWeIQTt.js → RBIconButton.stories-DRH7O3sp.js} +1 -1
  142. package/cli/storybook-dist/assets/{RBIcons.stories-Cu0txCUp.js → RBIcons.stories-D3PyJXG8.js} +1 -1
  143. package/cli/storybook-dist/assets/{RBInlineLabelButton.stories-DnGhYrxa.js → RBInlineLabelButton.stories-modQbt10.js} +1 -1
  144. package/cli/storybook-dist/assets/{RBJoyStick.stories-BlfvKcGb.js → RBJoyStick.stories-BY14qVgR.js} +1 -1
  145. package/cli/storybook-dist/assets/{RBLabelButton.stories-CFwmlhAE.js → RBLabelButton.stories-DzF7vGwm.js} +1 -1
  146. package/cli/storybook-dist/assets/{RBLight.stories-wMrFLJ7u.js → RBLight.stories-lF4FRmVh.js} +1 -1
  147. package/cli/storybook-dist/assets/{RBMenubar.stories-Bu5wtV-T.js → RBMenubar.stories-XhrI7bsV.js} +1 -1
  148. package/cli/storybook-dist/assets/{RBMultiRangeInput.stories-Db1d940z.js → RBMultiRangeInput.stories-DprllQDl.js} +1 -1
  149. package/cli/storybook-dist/assets/{RBPagination.stories-NCpjg-2W.js → RBPagination.stories-2v2gBJfC.js} +1 -1
  150. package/cli/storybook-dist/assets/{RBPopover.stories-CqsM8byU.js → RBPopover.stories-C8iLIZpv.js} +1 -1
  151. package/cli/storybook-dist/assets/{RBPrompt.stories-TMQEaHk-.js → RBPrompt.stories-Th_HrWHI.js} +1 -1
  152. package/cli/storybook-dist/assets/{RBRadioBox.stories-pnsBvtzU.js → RBRadioBox.stories-CoHuLaN3.js} +1 -1
  153. package/cli/storybook-dist/assets/{RBRadioButton.stories-BMDBfq82.js → RBRadioButton.stories-DULxE_ff.js} +1 -1
  154. package/cli/storybook-dist/assets/{RBRangeDateInput.stories-ljAsdz0Q.js → RBRangeDateInput.stories-D8A9KBSS.js} +1 -1
  155. package/cli/storybook-dist/assets/{RBResizable.stories-B5YDW687.js → RBResizable.stories-C41QfrQ3.js} +14 -14
  156. package/cli/storybook-dist/assets/{RBSelectBox.stories-DPtyIwEr.js → RBSelectBox.stories-C1gNmwzw.js} +1 -1
  157. package/cli/storybook-dist/assets/RBSheet.stories-_6VH-RUm.js +39 -0
  158. package/cli/storybook-dist/assets/{RBSideNumberInput.stories-DLsS3mzL.js → RBSideNumberInput.stories-9LlgQ8nh.js} +3 -3
  159. package/cli/storybook-dist/assets/{RBSlider.stories-BjTYZ3ri.js → RBSlider.stories-oUgo5K9d.js} +3 -3
  160. package/cli/storybook-dist/assets/{RBSpinner.stories-BWBvOGUY.js → RBSpinner.stories-DDpohbY2.js} +1 -1
  161. package/cli/storybook-dist/assets/{RBSwitch.stories-tpthe98k.js → RBSwitch.stories-gW-GN7QO.js} +7 -7
  162. package/cli/storybook-dist/assets/{RBTab.stories-BijmaLIo.js → RBTab.stories-CN-PV3HH.js} +1 -1
  163. package/cli/storybook-dist/assets/{RBTable.stories-Dojsz28q.js → RBTable.stories-BAZLpxtM.js} +29 -29
  164. package/cli/storybook-dist/assets/{RBTableRow.stories-CQajMiEa.js → RBTableRow.stories-CwjVrszB.js} +1 -1
  165. package/cli/storybook-dist/assets/{RBTabs.stories-BslRXoCw.js → RBTabs.stories-JuEo2sUL.js} +7 -7
  166. package/cli/storybook-dist/assets/{RBTextArea.stories-N44Q45Xp.js → RBTextArea.stories-D0_Pv4qZ.js} +3 -3
  167. package/cli/storybook-dist/assets/{RBTextField.stories-scpiy0Kx.js → RBTextField.stories-CCsOvZqV.js} +15 -15
  168. package/cli/storybook-dist/assets/{RBTextInput.stories-D_suHJaA.js → RBTextInput.stories-Cccn3VNm.js} +3 -3
  169. package/cli/storybook-dist/assets/{RBToast.stories-B73JQcKo.js → RBToast.stories-I5617t0K.js} +1 -1
  170. package/cli/storybook-dist/assets/{RBToggle.stories-CmujM833.js → RBToggle.stories-DsgKjGsJ.js} +4 -4
  171. package/cli/storybook-dist/assets/{RBToggleGroup.stories-DhCAfiKu.js → RBToggleGroup.stories-BZEzSDuz.js} +5 -5
  172. package/cli/storybook-dist/assets/{RBTooltip.stories-BixEjKZy.js → RBTooltip.stories-4oSyAWsA.js} +1 -1
  173. package/cli/storybook-dist/assets/{SideNumberInput-B7fbx2jk.js → SideNumberInput-DSKbd0bG.js} +743 -743
  174. package/cli/storybook-dist/assets/{entry-preview-BeR5Td7C.js → entry-preview-B35XREGs.js} +1 -1
  175. package/cli/storybook-dist/assets/{iframe-D3pKf_6w.js → iframe-BB797lmL.js} +2 -2
  176. package/cli/storybook-dist/assets/{index-gXlU0WyC.js → index-BU2567EP.js} +3 -3
  177. package/cli/storybook-dist/assets/{preview-GwaHbm9r.js → preview-C7DaSWyc.js} +2 -2
  178. package/cli/storybook-dist/assets/preview-CbuRHit4.js +3 -0
  179. package/cli/storybook-dist/assets/preview-CigNHo-I.css +1 -0
  180. package/cli/storybook-dist/assets/react-resizable-panels-Dp9zi-o3.css +1 -0
  181. package/cli/storybook-dist/assets/{react-resizable-panels.browser-D49JKwKo.js → react-resizable-panels.browser-ChIvlwo7.js} +8 -8
  182. package/cli/storybook-dist/iframe.html +2 -2
  183. package/cli/storybook-dist/index.html +1 -1
  184. package/cli/storybook-dist/project.json +1 -1
  185. package/cli/templates/common/.mcp.json +8 -8
  186. package/cli/templates/common/README.md +1231 -1226
  187. package/cli/templates/common/assets/icon.svg +45 -45
  188. package/cli/templates/common/manifest.json +26 -26
  189. package/cli/templates/common/package.json +22 -22
  190. package/cli/templates/common/py/main.py +125 -125
  191. package/cli/templates/common/requirements.txt +4 -4
  192. package/cli/templates/common/tsconfig.json +13 -13
  193. package/cli/templates/common/ui/content.tsx +216 -216
  194. package/cli/templates/common/ui/style.css +6 -6
  195. package/cli/templates/common/vite.config.ts +10 -10
  196. package/cli/templates/cpp/cpp/main.cpp +73 -73
  197. package/cli/templates/readme-cpp/README.md +6 -1
  198. package/cli/templates/ros2/ros2_ws/src/__PLUGIN_SLUG__/__PLUGIN_SLUG__/node.py +25 -25
  199. package/cli/templates/ros2/ros2_ws/src/__PLUGIN_SLUG__/package.xml +10 -10
  200. package/cli/templates/ros2/ros2_ws/src/__PLUGIN_SLUG__/setup.py +18 -18
  201. package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/package.xml +11 -11
  202. package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/src/node.cpp +23 -23
  203. package/cli/vite.d.mts +25 -25
  204. package/cli/vite.mjs +292 -292
  205. package/package.json +4 -4
  206. package/cli/src/templates-embedded.mjs +0 -4
  207. package/cli/storybook-dist/assets/RBCommand.stories-BYkWjdMG.js +0 -73
  208. package/cli/storybook-dist/assets/RBDialog.stories-DcPRAan8.js +0 -38
  209. package/cli/storybook-dist/assets/RBDropdownMenu.stories-5UC0ZA3H.js +0 -86
  210. package/cli/storybook-dist/assets/RBSheet.stories-DMTeF_hx.js +0 -39
  211. package/cli/storybook-dist/assets/preview-BYhMD55w.css +0 -1
  212. package/cli/storybook-dist/assets/preview-D-VpQB0_.js +0 -3
  213. package/cli/storybook-dist/assets/react-resizable-panels-DJMuB2U0.css +0 -1
@@ -1,216 +1,216 @@
1
- import { useMemo, useState } from "react";
2
- import {
3
- RBCheckBox,
4
- RBLabelButton,
5
- RBRadioBox,
6
- RBSelectBox,
7
- RBSlider,
8
- RBSwitch,
9
- RBTextArea,
10
- RBTextField,
11
- RBTextInput,
12
- Option
13
- } from "@rainbow-robotics/plugin-ui/react";
14
- import { useRb } from "@rainbow-robotics/plugin-ui/sdk";
15
-
16
- type RunMode = "inspect" | "assist" | "auto";
17
-
18
- const MODE_OPTIONS: Array<{ label: string; value: RunMode }> = [
19
- { label: "Inspect", value: "inspect" },
20
- { label: "Assist", value: "assist" },
21
- { label: "Auto", value: "auto" },
22
- ];
23
-
24
- const TASK_OPTIONS = [
25
- { label: "Publish status", value: "publish" },
26
- { label: "Run grip action", value: "grip" },
27
- { label: "Save snapshot", value: "snapshot" },
28
- ];
29
-
30
- // Export your UI as the default. The host mounts it (dev: with HMR).
31
- export default function App() {
32
- const rb = useRb();
33
- const [targetName, setTargetName] = useState("demo_target");
34
- const [gripType, setGripType] = useState<string>();
35
- const [gripWidth, setGripWidth] = useState(24);
36
- const [speed, setSpeed] = useState(45);
37
- const [mode, setMode] = useState<RunMode>("assist");
38
- const [enabled, setEnabled] = useState(true);
39
- const [tasks, setTasks] = useState<Array<string>>(["publish", "grip"]);
40
- const [memo, setMemo] = useState("Use this area for operator notes.");
41
-
42
- const payload = useMemo(
43
- () => ({
44
- targetName,
45
- gripWidth,
46
- speed,
47
- mode,
48
- enabled,
49
- tasks,
50
- memo,
51
- }),
52
- [targetName, gripWidth, speed, mode, enabled, tasks, memo],
53
- );
54
-
55
- const showRequestError = (error: unknown) => {
56
- const message = error instanceof Error ? error.message : "Request failed";
57
- rb.toast({ type: "danger", message });
58
- };
59
-
60
- const runAction = async () => {
61
- try {
62
- await rb.action("grip", payload);
63
- rb.toast({ type: "success", message: `Sent ${targetName}` });
64
- } catch (error) {
65
- showRequestError(error);
66
- }
67
- };
68
-
69
- const publishPreview = async () => {
70
- try {
71
- const isConfirm = await rb.confirm({
72
- message: "Are you sure publish?",
73
- buttonText: { yes: "confirm", no: "cancel" },
74
- });
75
-
76
- if (isConfirm) {
77
- await rb.pub("event", payload);
78
- }
79
- } catch (error) {
80
- showRequestError(error);
81
- }
82
- };
83
-
84
- return (
85
- <div className="max-h-[70vh] w-[420px] p-4 max-w-full overflow-y-auto bg-bg-elevated text-fg-default">
86
- <div className="flex flex-col gap-5">
87
- <header>
88
- <div className="flex items-center justify-between gap-12">
89
- <div>
90
- <h2 className="typo-heading-xs-semibold">Demo Control</h2>
91
- <p className="typo-body-xs2-normal text-fg-subtle">
92
- Input patterns for Muscat plugin UIs
93
- </p>
94
- </div>
95
- <RBSwitch
96
- checked={enabled}
97
- onCheckedChange={(next: boolean) => {
98
- setEnabled(next);
99
- rb.toast({message: next ? "Plugin enabled" : "Plugin paused"});
100
- }}
101
- />
102
- </div>
103
- </header>
104
-
105
- <section className="flex flex-col gap-4">
106
- <RBTextField
107
- label="Target name"
108
- required
109
- helperText="Used as the backend action target."
110
- >
111
- <RBTextInput
112
- name="targetName"
113
- value={targetName}
114
- placeholder="target id"
115
- handleChange={(value) => setTargetName(String(value))}
116
- />
117
- </RBTextField>
118
-
119
- <RBTextField label="Select Grip">
120
- <RBSelectBox className="w-full" value={gripType} handleChange={setGripType}>
121
- <Option value="A">A Grip</Option>
122
- <Option value="B">B Grip</Option>
123
- </RBSelectBox>
124
- </RBTextField>
125
-
126
- <div className="flex gap-4">
127
- <RBTextField className="flex-1" label="Grip width" helperText="0-100 mm">
128
- <RBTextInput
129
- className="w-full"
130
- name="gripWidth"
131
- type="number"
132
- value={gripWidth}
133
- validate={(value: number) =>
134
- Math.max(0, Math.min(100, Number(value) || 0))
135
- }
136
- handleChange={(value) => setGripWidth(Number(value) || 0)}
137
- />
138
- </RBTextField>
139
-
140
- <RBTextField className="flex-1" label="Speed" helperText={`${speed}%`}>
141
- <div className="flex items-center px-2">
142
- <RBSlider
143
- value={[speed]}
144
- min={0}
145
- max={100}
146
- step={5}
147
- onValueChange={(values: number[]) =>
148
- setSpeed(values[0] ?? 0)
149
- }
150
- />
151
- </div>
152
- </RBTextField>
153
- </div>
154
- </section>
155
-
156
- <section className="mb-4">
157
- <RBTextField label="Run mode">
158
- <div className="flex justify-between border-1 border-border-subtle rounded-sm p-2">
159
- {MODE_OPTIONS.map((item) => (
160
- <RBRadioBox
161
- key={item.value}
162
- name="mode"
163
- checkValue={item.value}
164
- value={mode}
165
- handleChange={(value) => setMode(value as RunMode)}
166
- >
167
- {item.label}
168
- </RBRadioBox>
169
- ))}
170
- </div>
171
- </RBTextField>
172
- </section>
173
-
174
- <section className="mb-4">
175
- <RBTextField label="Tasks">
176
- <div className="flex justify-between border-1 border-border-subtle rounded-sm p-2">
177
- {TASK_OPTIONS.map((item) => (
178
- <RBCheckBox
179
- key={item.value}
180
- name="tasks"
181
- checkValue={item.value}
182
- value={tasks}
183
- handleChange={(value) =>
184
- setTasks(Array.isArray(value) ? value.map(String) : [])
185
- }
186
- >
187
- {item.label}
188
- </RBCheckBox>
189
- ))}
190
- </div>
191
- </RBTextField>
192
-
193
- </section>
194
-
195
- <RBTextField label="Memo">
196
- <RBTextArea
197
- name="memo"
198
- value={memo}
199
- maxLength={120}
200
- rows={4}
201
- handleChange={setMemo}
202
- />
203
- </RBTextField>
204
-
205
- <footer className="grid grid-cols-2 gap-8 pt-4">
206
- <RBLabelButton variant="outlined" onClick={publishPreview}>
207
- Publish
208
- </RBLabelButton>
209
- <RBLabelButton onClick={runAction} disabled={!enabled}>
210
- Run Action
211
- </RBLabelButton>
212
- </footer>
213
- </div>
214
- </div>
215
- );
216
- }
1
+ import { useMemo, useState } from "react";
2
+ import {
3
+ RBCheckBox,
4
+ RBLabelButton,
5
+ RBRadioBox,
6
+ RBSelectBox,
7
+ RBSlider,
8
+ RBSwitch,
9
+ RBTextArea,
10
+ RBTextField,
11
+ RBTextInput,
12
+ Option
13
+ } from "@rainbow-robotics/plugin-ui/react";
14
+ import { useRb } from "@rainbow-robotics/plugin-ui/sdk";
15
+
16
+ type RunMode = "inspect" | "assist" | "auto";
17
+
18
+ const MODE_OPTIONS: Array<{ label: string; value: RunMode }> = [
19
+ { label: "Inspect", value: "inspect" },
20
+ { label: "Assist", value: "assist" },
21
+ { label: "Auto", value: "auto" },
22
+ ];
23
+
24
+ const TASK_OPTIONS = [
25
+ { label: "Publish status", value: "publish" },
26
+ { label: "Run grip action", value: "grip" },
27
+ { label: "Save snapshot", value: "snapshot" },
28
+ ];
29
+
30
+ // Export your UI as the default. The host mounts it (dev: with HMR).
31
+ export default function App() {
32
+ const rb = useRb();
33
+ const [targetName, setTargetName] = useState("demo_target");
34
+ const [gripType, setGripType] = useState<string>();
35
+ const [gripWidth, setGripWidth] = useState(24);
36
+ const [speed, setSpeed] = useState(45);
37
+ const [mode, setMode] = useState<RunMode>("assist");
38
+ const [enabled, setEnabled] = useState(true);
39
+ const [tasks, setTasks] = useState<Array<string>>(["publish", "grip"]);
40
+ const [memo, setMemo] = useState("Use this area for operator notes.");
41
+
42
+ const payload = useMemo(
43
+ () => ({
44
+ targetName,
45
+ gripWidth,
46
+ speed,
47
+ mode,
48
+ enabled,
49
+ tasks,
50
+ memo,
51
+ }),
52
+ [targetName, gripWidth, speed, mode, enabled, tasks, memo],
53
+ );
54
+
55
+ const showRequestError = (error: unknown) => {
56
+ const message = error instanceof Error ? error.message : "Request failed";
57
+ rb.toast({ type: "danger", message });
58
+ };
59
+
60
+ const runAction = async () => {
61
+ try {
62
+ await rb.action("grip", payload);
63
+ rb.toast({ type: "success", message: `Sent ${targetName}` });
64
+ } catch (error) {
65
+ showRequestError(error);
66
+ }
67
+ };
68
+
69
+ const publishPreview = async () => {
70
+ try {
71
+ const isConfirm = await rb.confirm({
72
+ message: "Are you sure publish?",
73
+ buttonText: { yes: "confirm", no: "cancel" },
74
+ });
75
+
76
+ if (isConfirm) {
77
+ await rb.pub("event", payload);
78
+ }
79
+ } catch (error) {
80
+ showRequestError(error);
81
+ }
82
+ };
83
+
84
+ return (
85
+ <div className="max-h-[70vh] w-[420px] p-4 max-w-full overflow-y-auto bg-bg-elevated text-fg-default">
86
+ <div className="flex flex-col gap-5">
87
+ <header>
88
+ <div className="flex items-center justify-between gap-12">
89
+ <div>
90
+ <h2 className="typo-heading-xs-semibold">Demo Control</h2>
91
+ <p className="typo-body-xs2-normal text-fg-subtle">
92
+ Input patterns for Muscat plugin UIs
93
+ </p>
94
+ </div>
95
+ <RBSwitch
96
+ checked={enabled}
97
+ onCheckedChange={(next: boolean) => {
98
+ setEnabled(next);
99
+ rb.toast({message: next ? "Plugin enabled" : "Plugin paused"});
100
+ }}
101
+ />
102
+ </div>
103
+ </header>
104
+
105
+ <section className="flex flex-col gap-4">
106
+ <RBTextField
107
+ label="Target name"
108
+ required
109
+ helperText="Used as the backend action target."
110
+ >
111
+ <RBTextInput
112
+ name="targetName"
113
+ value={targetName}
114
+ placeholder="target id"
115
+ handleChange={(value) => setTargetName(String(value))}
116
+ />
117
+ </RBTextField>
118
+
119
+ <RBTextField label="Select Grip">
120
+ <RBSelectBox className="w-full" value={gripType} handleChange={setGripType}>
121
+ <Option value="A">A Grip</Option>
122
+ <Option value="B">B Grip</Option>
123
+ </RBSelectBox>
124
+ </RBTextField>
125
+
126
+ <div className="flex gap-4">
127
+ <RBTextField className="flex-1" label="Grip width" helperText="0-100 mm">
128
+ <RBTextInput
129
+ className="w-full"
130
+ name="gripWidth"
131
+ type="number"
132
+ value={gripWidth}
133
+ validate={(value: number) =>
134
+ Math.max(0, Math.min(100, Number(value) || 0))
135
+ }
136
+ handleChange={(value) => setGripWidth(Number(value) || 0)}
137
+ />
138
+ </RBTextField>
139
+
140
+ <RBTextField className="flex-1" label="Speed" helperText={`${speed}%`}>
141
+ <div className="flex items-center px-2">
142
+ <RBSlider
143
+ value={[speed]}
144
+ min={0}
145
+ max={100}
146
+ step={5}
147
+ onValueChange={(values: number[]) =>
148
+ setSpeed(values[0] ?? 0)
149
+ }
150
+ />
151
+ </div>
152
+ </RBTextField>
153
+ </div>
154
+ </section>
155
+
156
+ <section className="mb-4">
157
+ <RBTextField label="Run mode">
158
+ <div className="flex justify-between border-1 border-border-subtle rounded-sm p-2">
159
+ {MODE_OPTIONS.map((item) => (
160
+ <RBRadioBox
161
+ key={item.value}
162
+ name="mode"
163
+ checkValue={item.value}
164
+ value={mode}
165
+ handleChange={(value) => setMode(value as RunMode)}
166
+ >
167
+ {item.label}
168
+ </RBRadioBox>
169
+ ))}
170
+ </div>
171
+ </RBTextField>
172
+ </section>
173
+
174
+ <section className="mb-4">
175
+ <RBTextField label="Tasks">
176
+ <div className="flex justify-between border-1 border-border-subtle rounded-sm p-2">
177
+ {TASK_OPTIONS.map((item) => (
178
+ <RBCheckBox
179
+ key={item.value}
180
+ name="tasks"
181
+ checkValue={item.value}
182
+ value={tasks}
183
+ handleChange={(value) =>
184
+ setTasks(Array.isArray(value) ? value.map(String) : [])
185
+ }
186
+ >
187
+ {item.label}
188
+ </RBCheckBox>
189
+ ))}
190
+ </div>
191
+ </RBTextField>
192
+
193
+ </section>
194
+
195
+ <RBTextField label="Memo">
196
+ <RBTextArea
197
+ name="memo"
198
+ value={memo}
199
+ maxLength={120}
200
+ rows={4}
201
+ handleChange={setMemo}
202
+ />
203
+ </RBTextField>
204
+
205
+ <footer className="grid grid-cols-2 gap-8 pt-4">
206
+ <RBLabelButton variant="outlined" onClick={publishPreview}>
207
+ Publish
208
+ </RBLabelButton>
209
+ <RBLabelButton onClick={runAction} disabled={!enabled}>
210
+ Run Action
211
+ </RBLabelButton>
212
+ </footer>
213
+ </div>
214
+ </div>
215
+ );
216
+ }
@@ -1,6 +1,6 @@
1
- @layer theme, utilities;
2
-
3
- @import "tailwindcss/theme.css" layer(theme);
4
- @import "tailwindcss/utilities.css" layer(utilities);
5
-
6
- @source "./**/*.{ts,tsx}";
1
+ @layer theme, utilities;
2
+
3
+ @import "tailwindcss/theme.css" layer(theme);
4
+ @import "tailwindcss/utilities.css" layer(utilities);
5
+
6
+ @source "./**/*.{ts,tsx}";
@@ -1,10 +1,10 @@
1
- import { defineConfig } from "vite";
2
- import tailwindcss from "@tailwindcss/vite";
3
- import { muscat } from "@rainbow-robotics/muscat-plugin-kit/vite";
4
-
5
- // The muscat() preset wires react-refresh, ui/ entry discovery, and marks the
6
- // host-provided runtime (plugin-ui, react) as external. Add your own plugins or
7
- // overrides here as needed.
8
- export default defineConfig({
9
- plugins: [tailwindcss(), muscat()],
10
- });
1
+ import { defineConfig } from "vite";
2
+ import tailwindcss from "@tailwindcss/vite";
3
+ import { muscat } from "@rainbow-robotics/muscat-plugin-kit/vite";
4
+
5
+ // The muscat() preset wires react-refresh, ui/ entry discovery, and marks the
6
+ // host-provided runtime (plugin-ui, react) as external. Add your own plugins or
7
+ // overrides here as needed.
8
+ export default defineConfig({
9
+ plugins: [tailwindcss(), muscat()],
10
+ });
@@ -1,73 +1,73 @@
1
- // __PLUGIN_NAME__ — C++ plugin back end.
2
- //
3
- // The Rainbow Robotics C++ SDK (apt: rainbow-rb-sdk-dev) is installed in the
4
- // dev container and linked via CMake (rb_sdk::rb_sdk). Headers live under
5
- // <rainbow/rb_sdk/...>:
6
- // - plugin/rb_plugin.hpp rb_plugin::RBPluginCall — plugin UI <-> backend
7
- // (serve/subscribe/publish) and external endpoints (router)
8
- // - manipulate/rb_manipulate_sdk.hpp RBManipulateSDK — control the robot
9
- // - program/plugin_program_context.hpp rb_plugin::PluginProgramContext —
10
- // program.panel commands (done/pause/stop,
11
- // program variables)
12
-
13
- #include <rainbow/rb_sdk/manipulate/rb_manipulate_sdk.hpp>
14
- #include <rainbow/rb_sdk/plugin/rb_plugin.hpp>
15
-
16
- #include <nlohmann/json.hpp>
17
-
18
- #include <chrono>
19
- #include <cstdlib>
20
- #include <iostream>
21
- #include <string>
22
- #include <thread>
23
-
24
- using nlohmann::json;
25
- using rb_plugin::RBPluginCall;
26
-
27
- int main() {
28
- const std::string name = "__PLUGIN_NAME__";
29
-
30
- // Remote dev: connect before registering handlers (connect() reopens the session).
31
- RBManipulateSDK manipulate;
32
- const char* host = std::getenv("MUSCAT_ROBOT_HOST");
33
- const char* token = std::getenv("MUSCAT_ROBOT_TOKEN");
34
- if (host && token) manipulate.connect({.token = token, .host = host});
35
-
36
- // plugin id comes from RB_PLUGIN_ID.
37
- auto plugin = RBPluginCall::get_instance(RBPluginCall::resolve_plugin_id(std::nullopt));
38
-
39
- // --- Plugin UI <-> backend (not reachable from outside Muscat) ---
40
-
41
- // UI: await rb.action("grip", { width })
42
- plugin->serve("grip", [&](const json& payload) {
43
- const int width = payload.is_object() ? payload.value("width", 20) : 20;
44
- std::cout << "[" << name << "] grip requested: width=" << width << std::endl;
45
- plugin->publish("state", {{"ready", true}, {"last_grip_width", width}}); // -> rb.sub("state")
46
- return json{{"ok", true}, {"width", width}};
47
- });
48
-
49
- // UI: rb.pub("event", ...)
50
- auto event_sub = plugin->subscribe("event", [&](const std::string&, const json& payload) {
51
- std::cout << "[" << name << "] event: " << payload.dump() << std::endl;
52
- });
53
-
54
- // --- External endpoints (REST / Socket.IO / TCP / MQTT / WebRTC) ---
55
- // curl -X POST http://<robot>/common/plugin/<plugin_id>/hello -d '{"name":"kim"}'
56
- plugin->router().on("/hello", [](const json& payload, const json& meta) {
57
- const std::string who = payload.is_object() ? payload.value("name", std::string("there")) : "there";
58
- return json{{"msg", "hi " + who}, {"via", meta.value("transport", std::string())}};
59
- });
60
-
61
- // Example: robot control (not called automatically — add safety checks first).
62
- // IPC::MoveInput_TargetT t; t.tar_values = {0, 0, 0, 0, 0, 0};
63
- // manipulate.move.call_move_j("C500920", t);
64
-
65
- plugin->publish("state", {{"ready", true}, {"plugin", name}});
66
- std::cout << "[" << name << "] backend ready" << std::endl;
67
-
68
- // Keep the process alive.
69
- while (true) {
70
- std::this_thread::sleep_for(std::chrono::seconds(1));
71
- }
72
- return 0;
73
- }
1
+ // __PLUGIN_NAME__ — C++ plugin back end.
2
+ //
3
+ // The Rainbow Robotics C++ SDK (apt: rainbow-rb-sdk-dev) is installed in the
4
+ // dev container and linked via CMake (rb_sdk::rb_sdk). Headers live under
5
+ // <rainbow/rb_sdk/...>:
6
+ // - plugin/rb_plugin.hpp rb_plugin::RBPluginCall — plugin UI <-> backend
7
+ // (serve/subscribe/publish) and external endpoints (router)
8
+ // - manipulate/rb_manipulate_sdk.hpp RBManipulateSDK — control the robot
9
+ // - program/plugin_program_context.hpp rb_plugin::PluginProgramContext —
10
+ // program.panel commands (done/pause/stop,
11
+ // program variables)
12
+
13
+ #include <rainbow/rb_sdk/manipulate/rb_manipulate_sdk.hpp>
14
+ #include <rainbow/rb_sdk/plugin/rb_plugin.hpp>
15
+
16
+ #include <nlohmann/json.hpp>
17
+
18
+ #include <chrono>
19
+ #include <cstdlib>
20
+ #include <iostream>
21
+ #include <string>
22
+ #include <thread>
23
+
24
+ using nlohmann::json;
25
+ using rb_plugin::RBPluginCall;
26
+
27
+ int main() {
28
+ const std::string name = "__PLUGIN_NAME__";
29
+
30
+ // Remote dev: connect before registering handlers (connect() reopens the session).
31
+ RBManipulateSDK manipulate;
32
+ const char* host = std::getenv("MUSCAT_ROBOT_HOST");
33
+ const char* token = std::getenv("MUSCAT_ROBOT_TOKEN");
34
+ if (host && token) manipulate.connect({.token = token, .host = host});
35
+
36
+ // plugin id comes from RB_PLUGIN_ID.
37
+ auto plugin = RBPluginCall::get_instance(RBPluginCall::resolve_plugin_id(std::nullopt));
38
+
39
+ // --- Plugin UI <-> backend (not reachable from outside Muscat) ---
40
+
41
+ // UI: await rb.action("grip", { width })
42
+ plugin->serve("grip", [&](const json& payload) {
43
+ const int width = payload.is_object() ? payload.value("width", 20) : 20;
44
+ std::cout << "[" << name << "] grip requested: width=" << width << std::endl;
45
+ plugin->publish("state", {{"ready", true}, {"last_grip_width", width}}); // -> rb.sub("state")
46
+ return json{{"ok", true}, {"width", width}};
47
+ });
48
+
49
+ // UI: rb.pub("event", ...)
50
+ auto event_sub = plugin->subscribe("event", [&](const std::string&, const json& payload) {
51
+ std::cout << "[" << name << "] event: " << payload.dump() << std::endl;
52
+ });
53
+
54
+ // --- External endpoints (REST / Socket.IO / TCP / MQTT / WebRTC) ---
55
+ // curl -X POST http://<robot>/common/plugin/<plugin_id>/hello -d '{"name":"kim"}'
56
+ plugin->router().on("/hello", [](const json& payload, const json& meta) {
57
+ const std::string who = payload.is_object() ? payload.value("name", std::string("there")) : "there";
58
+ return json{{"msg", "hi " + who}, {"via", meta.value("transport", std::string())}};
59
+ });
60
+
61
+ // Example: robot control (not called automatically — add safety checks first).
62
+ // IPC::MoveInput_TargetT t; t.tar_values = {0, 0, 0, 0, 0, 0};
63
+ // manipulate.move.call_move_j("C500920", t);
64
+
65
+ plugin->publish("state", {{"ready", true}, {"plugin", name}});
66
+ std::cout << "[" << name << "] backend ready" << std::endl;
67
+
68
+ // Keep the process alive.
69
+ while (true) {
70
+ std::this_thread::sleep_for(std::chrono::seconds(1));
71
+ }
72
+ return 0;
73
+ }
@@ -762,7 +762,7 @@ export default function Camera() {
762
762
  - `icons` — SVG: single string path ending in `.svg`; PNG/JPG: object with `"16"`, `"48"`, `"128"` all present
763
763
  - `targetModels` — `"all"` or a non-empty array of robot model ID strings (at least one of `targetModels` / `targetCategorys` required)
764
764
  - `targetCategorys` — `"all"` or a non-empty array of `"manipulate" | "amr" | "rby1" | "vision"` (at least one of `targetModels` / `targetCategorys` required)
765
- - `contributes` — required array; must contain at least one `toolbar` entry
765
+ - `contributes` — the plugin's screens; when present it must contain at least one `toolbar` entry. Leave it out (or `[]`) for a backend-only plugin: no UI is built, and Node.js is not needed to build it
766
766
  - `ui` — each contribution must have a unique value
767
767
  - `commandInfo` — required when `point` is `"program.panel"`
768
768
  - `ports` — optional `number[]`; every port must be within `28600-28999`
@@ -899,6 +899,11 @@ letting it guess. `muscat-pk mcp` is an MCP server exposing:
899
899
 
900
900
  **Browse the components live** with `muscat-pk storybook`.
901
901
 
902
+ `muscat-pk new` also writes `AGENTS.md` (read by Codex, Cursor, Gemini CLI, Copilot)
903
+ and a `CLAUDE.md` that imports it: the UI rules (plugin-ui components instead of
904
+ native `<select>`/`<input>`/`<button>`, design tokens for colors) for assistants that
905
+ do not call the MCP tools on their own. Add your own project notes there.
906
+
902
907
  ### Register the server
903
908
 
904
909
  **Claude Code** — a `.mcp.json` is already scaffolded at your plugin root, so