@rainbow-robotics/muscat-plugin-kit 1.10.1-dev.1 → 1.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +282 -282
- package/cli/README.md +274 -274
- package/cli/bin/create-muscat-plugin.mjs +8 -8
- package/cli/bin/muscat-pk.mjs +155 -155
- package/cli/bundle-templates.mjs +31 -31
- package/cli/docker/Dockerfile.cpp +28 -28
- package/cli/docker/Dockerfile.dev +30 -30
- package/cli/docker/Dockerfile.python +21 -21
- package/cli/m5-e2e.mjs +69 -69
- package/cli/prepack.mjs +10 -10
- package/cli/src/ai-rules.mjs +70 -70
- package/cli/src/build.mjs +447 -447
- package/cli/src/check-package.mjs +13 -13
- package/cli/src/completion.mjs +166 -166
- package/cli/src/cpp.mjs +78 -78
- package/cli/src/cppIde.mjs +75 -75
- package/cli/src/dev.mjs +165 -165
- package/cli/src/devBack.mjs +734 -727
- package/cli/src/devUi.mjs +247 -243
- package/cli/src/esbuild.mjs +56 -56
- package/cli/src/host_agent.py +223 -223
- package/cli/src/manifest.mjs +287 -287
- package/cli/src/mcp.mjs +1071 -1071
- package/cli/src/muscatLocal.mjs +209 -209
- package/cli/src/new.mjs +343 -343
- package/cli/src/pluginDevServer.mjs +111 -111
- package/cli/src/ports.mjs +193 -193
- package/cli/src/python.mjs +112 -112
- package/cli/src/ros2.mjs +109 -109
- package/cli/src/sdk.mjs +117 -117
- package/cli/src/storybook.mjs +168 -168
- package/cli/src/type.mjs +141 -141
- package/cli/src/uninstall.mjs +81 -81
- package/cli/src/update.mjs +295 -295
- package/cli/src/util.mjs +441 -441
- package/cli/src/zenohDev.mjs +83 -81
- package/cli/storybook-dist/_design-tokens.css +4957 -4957
- package/cli/storybook-dist/_stories-src/NxAvatar.stories.tsx +27 -27
- package/cli/storybook-dist/_stories-src/NxPagination.stories.tsx +28 -28
- package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordion.stories.tsx +46 -46
- package/cli/storybook-dist/_stories-src/RBAccordion/RBAccordionGroup.stories.tsx +73 -73
- package/cli/storybook-dist/_stories-src/RBBadge/RBBadge.stories.tsx +93 -93
- package/cli/storybook-dist/_stories-src/RBBattery/RBBattery.stories.tsx +74 -74
- package/cli/storybook-dist/_stories-src/RBButton/RBCheckIconButton.stories.tsx +28 -28
- package/cli/storybook-dist/_stories-src/RBButton/RBCheckLabelButton.stories.tsx +84 -84
- package/cli/storybook-dist/_stories-src/RBButton/RBIconButton.stories.tsx +57 -57
- package/cli/storybook-dist/_stories-src/RBButton/RBInlineLabelButton.stories.tsx +41 -41
- package/cli/storybook-dist/_stories-src/RBButton/RBLabelButton.stories.tsx +60 -60
- package/cli/storybook-dist/_stories-src/RBDatePicker/RBDateInput.stories.tsx +44 -44
- package/cli/storybook-dist/_stories-src/RBDatePicker/RBRangeDateInput.stories.tsx +56 -56
- package/cli/storybook-dist/_stories-src/RBDialog/RBAlert.stories.tsx +51 -51
- package/cli/storybook-dist/_stories-src/RBDialog/RBConfirm.stories.tsx +55 -55
- package/cli/storybook-dist/_stories-src/RBDialog/RBPrompt.stories.tsx +52 -52
- package/cli/storybook-dist/_stories-src/RBDivider/RBDivider.stories.tsx +93 -93
- package/cli/storybook-dist/_stories-src/RBEmptyView/RBEmptyView.stories.tsx +49 -49
- package/cli/storybook-dist/_stories-src/RBIcons/RBColorIcons.stories.tsx +108 -108
- package/cli/storybook-dist/_stories-src/RBIcons/RBIcons.stories.tsx +106 -106
- package/cli/storybook-dist/_stories-src/RBInput/RBCheckBox.stories.tsx +89 -89
- package/cli/storybook-dist/_stories-src/RBInput/RBMultiRangeInput.stories.tsx +64 -64
- package/cli/storybook-dist/_stories-src/RBInput/RBRadioBox.stories.tsx +65 -65
- package/cli/storybook-dist/_stories-src/RBInput/RBRadioButton.stories.tsx +68 -68
- package/cli/storybook-dist/_stories-src/RBInput/RBSelectBox.stories.tsx +216 -216
- package/cli/storybook-dist/_stories-src/RBInput/RBSideNumberInput.stories.tsx +90 -90
- package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextArea.stories.tsx +45 -45
- package/cli/storybook-dist/_stories-src/RBInput/RBText/RBTextInput.stories.tsx +50 -50
- package/cli/storybook-dist/_stories-src/RBInput/RBTextField.stories.tsx +102 -102
- package/cli/storybook-dist/_stories-src/RBJoyStick/RBJoyStick.stories.tsx +31 -31
- package/cli/storybook-dist/_stories-src/RBLight/RBLight.stories.tsx +36 -36
- package/cli/storybook-dist/_stories-src/RBPagination/RBPagination.stories.tsx +49 -49
- package/cli/storybook-dist/_stories-src/RBShadcn/RBCard/RBCard.stories.tsx +89 -89
- package/cli/storybook-dist/_stories-src/RBShadcn/RBCommand/RBCommand.stories.tsx +116 -116
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDialog/RBDialog.stories.tsx +74 -74
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDrawer/RBDrawer.stories.tsx +99 -99
- package/cli/storybook-dist/_stories-src/RBShadcn/RBDropdownMenu/RBDropdownMenu.stories.tsx +123 -123
- package/cli/storybook-dist/_stories-src/RBShadcn/RBMenubar/RBMenubar.stories.tsx +135 -135
- package/cli/storybook-dist/_stories-src/RBShadcn/RBPopover/RBPopover.stories.tsx +69 -69
- package/cli/storybook-dist/_stories-src/RBShadcn/RBResizable/RBResizable.stories.tsx +49 -49
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSheet/RBSheet.stories.tsx +91 -91
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSlider/RBSlider.stories.tsx +38 -38
- package/cli/storybook-dist/_stories-src/RBShadcn/RBSwitch/RBSwitch.stories.tsx +112 -112
- package/cli/storybook-dist/_stories-src/RBShadcn/RBTabs/RBTabs.stories.tsx +75 -75
- package/cli/storybook-dist/_stories-src/RBShadcn/RBToggle/RBToggle.stories.tsx +51 -51
- package/cli/storybook-dist/_stories-src/RBShadcn/RBToggleGroup/RBToggleGroup.stories.tsx +84 -84
- package/cli/storybook-dist/_stories-src/RBTab/RBChipTab.stories.tsx +102 -102
- package/cli/storybook-dist/_stories-src/RBTab/RBChipsBoxTab.stories.tsx +78 -78
- package/cli/storybook-dist/_stories-src/RBTab/RBTab.stories.tsx +57 -57
- package/cli/storybook-dist/_stories-src/RBTable/RBTable.stories.tsx +177 -177
- package/cli/storybook-dist/_stories-src/RBTable/RBTableRow.stories.tsx +64 -64
- package/cli/storybook-dist/_stories-src/RBToast/RBToast.stories.tsx +117 -117
- package/cli/storybook-dist/_stories-src/RBTooltip/RBTooltip.stories.tsx +50 -50
- package/cli/storybook-dist/_stories-src/loading/RBSpinner.stories.tsx +30 -30
- package/cli/storybook-dist/_stories-src/nx-button/NxButton.stories.tsx +54 -54
- package/cli/storybook-dist/_stories-src/nx-button/NxPointerHoldButton.stories.tsx +57 -57
- package/cli/storybook-dist/_stories-src/nx-icons/NxIcons.stories.tsx +48 -48
- package/cli/storybook-dist/_stories-src/nx-inputs/NxNumberInput.stories.tsx +103 -103
- package/cli/storybook-dist/_stories-src/nx-inputs/NxRangeInput.stories.tsx +27 -27
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSelectBox.stories.tsx +67 -67
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSlideRange.stories.tsx +45 -45
- package/cli/storybook-dist/_stories-src/nx-inputs/NxSwitch.stories.tsx +27 -27
- package/cli/storybook-dist/_stories-src/nx-inputs/NxTextArea.stories.tsx +48 -48
- package/cli/storybook-dist/_stories-src/nx-inputs/NxTextInput.stories.tsx +46 -46
- package/cli/storybook-dist/assets/{Color-YHDXOIA2-D6JqZzDJ.js → Color-YHDXOIA2-B4IER17l.js} +1 -1
- package/cli/storybook-dist/assets/{Docs-ESb7JAHg.js → Docs-C8GCHFtK.js} +3 -3
- package/cli/storybook-dist/assets/{Docs-6gD2kUo1.js → Docs-CgdEMPQP.js} +2 -2
- package/cli/storybook-dist/assets/{Docs-B9wd8Ok7.js → Docs-Ck3WHvk6.js} +3 -3
- package/cli/storybook-dist/assets/{Docs-CgFbWWXM.js → Docs-D9NHsoeZ.js} +2 -2
- package/cli/storybook-dist/assets/{Docs-DBQup8Bu.js → Docs-DNYQC7nl.js} +3 -3
- package/cli/storybook-dist/assets/{Docs-CMjovnSY.js → Docs-DUfeiM4I.js} +4 -4
- package/cli/storybook-dist/assets/{DocsRenderer-CFRXHY34-BOUI1AHi.js → DocsRenderer-CFRXHY34-C0WhyDoR.js} +1 -1
- package/cli/storybook-dist/assets/{NxAvatar.stories-DsYFMUh3.js → NxAvatar.stories-CwnK8AUF.js} +1 -1
- package/cli/storybook-dist/assets/{NxButton.stories-CHfNcqsc.js → NxButton.stories-ueYdosfQ.js} +8 -8
- package/cli/storybook-dist/assets/{NxNumberInput.stories-BFw_4vFE.js → NxNumberInput.stories-M5ZCLbrK.js} +1 -1
- package/cli/storybook-dist/assets/{NxPagination.stories-DVfxyw4M.js → NxPagination.stories-bxxUnHEL.js} +1 -1
- package/cli/storybook-dist/assets/{NxPointerHoldButton.stories-BzyxUWoZ.js → NxPointerHoldButton.stories-BHxB2kr5.js} +1 -1
- package/cli/storybook-dist/assets/{NxRangeInput.stories-DmRdzBc1.js → NxRangeInput.stories-BKfr-fp4.js} +6 -6
- package/cli/storybook-dist/assets/{NxSelectBox.stories-B1KkNUOf.js → NxSelectBox.stories-CG8FuTBq.js} +1 -1
- package/cli/storybook-dist/assets/{NxSlideRange.stories-CyOdvfQ6.js → NxSlideRange.stories-BRTFtMTL.js} +1 -1
- package/cli/storybook-dist/assets/{NxSwitch.stories-DrDBw0qp.js → NxSwitch.stories-Bwuyzn-R.js} +1 -1
- package/cli/storybook-dist/assets/{NxTextArea.stories-DTB2aqNS.js → NxTextArea.stories-COq2sGqu.js} +1 -1
- package/cli/storybook-dist/assets/{NxTextInput.stories-DU0rucmM.js → NxTextInput.stories-CjsBLz05.js} +1 -1
- package/cli/storybook-dist/assets/{RBAccordion.stories-DTfOtXtp.js → RBAccordion.stories-BARwuZ0Q.js} +3 -3
- package/cli/storybook-dist/assets/{RBAccordionGroup.stories-9y9BjrUe.js → RBAccordionGroup.stories-COrPxETW.js} +10 -10
- package/cli/storybook-dist/assets/{RBAlert.stories-DLTAv9fT.js → RBAlert.stories-BQrkjZPt.js} +3 -3
- package/cli/storybook-dist/assets/{RBBadge.stories-BNMACewA.js → RBBadge.stories-BTsLL-lK.js} +1 -1
- package/cli/storybook-dist/assets/{RBBattery.stories-B3kXMAt5.js → RBBattery.stories-DAeQdJbc.js} +1 -1
- package/cli/storybook-dist/assets/{RBCard.stories-Y-s8R2n7.js → RBCard.stories-HyhOE80R.js} +39 -39
- package/cli/storybook-dist/assets/{RBCheckBox.stories-DBuT9tL4.js → RBCheckBox.stories-KFk0WqX_.js} +1 -1
- package/cli/storybook-dist/assets/{RBCheckIconButton.stories-CWu1TL56.js → RBCheckIconButton.stories-CXbbktF5.js} +1 -1
- package/cli/storybook-dist/assets/{RBCheckLabelButton.stories-sCu2MGCX.js → RBCheckLabelButton.stories-DWfYz_9Z.js} +17 -17
- package/cli/storybook-dist/assets/{RBChipTab.stories-BX9qLJkR.js → RBChipTab.stories-JPEgVFAS.js} +5 -5
- package/cli/storybook-dist/assets/{RBChipsBoxTab.stories-35u1aJ-P.js → RBChipsBoxTab.stories-CTPuWXrQ.js} +1 -1
- package/cli/storybook-dist/assets/{RBColorIcons.stories-DAOZ5Ies.js → RBColorIcons.stories-DiFRZ5jk.js} +1 -1
- package/cli/storybook-dist/assets/RBCommand.stories-Pf1HAVIR.js +73 -0
- package/cli/storybook-dist/assets/{RBConfirm.stories-iMXcUh7Z.js → RBConfirm.stories-D1cEPUXk.js} +3 -3
- package/cli/storybook-dist/assets/{RBDateInput.stories-hK5rXECf.js → RBDateInput.stories-RPYpCjig.js} +1 -1
- package/cli/storybook-dist/assets/RBDialog.stories-DJH-0XSR.js +38 -0
- package/cli/storybook-dist/assets/{RBDivider.stories-BAK-iZ1Z.js → RBDivider.stories-uEj1vOgK.js} +1 -1
- package/cli/storybook-dist/assets/{RBDrawer.stories-B2nqf2Nh.js → RBDrawer.stories-BiMzElb2.js} +12 -12
- package/cli/storybook-dist/assets/RBDropdownMenu.stories-Da_TBkla.js +86 -0
- package/cli/storybook-dist/assets/{RBEmptyView.stories-nCenrgBh.js → RBEmptyView.stories-BHeKGfPS.js} +1 -1
- package/cli/storybook-dist/assets/{RBIconButton.stories-DRH7O3sp.js → RBIconButton.stories-NEsRFoYp.js} +1 -1
- package/cli/storybook-dist/assets/{RBIcons.stories-D3PyJXG8.js → RBIcons.stories-CcZ-TTLS.js} +1 -1
- package/cli/storybook-dist/assets/{RBInlineLabelButton.stories-modQbt10.js → RBInlineLabelButton.stories-B0wpdQyR.js} +1 -1
- package/cli/storybook-dist/assets/{RBJoyStick.stories-BY14qVgR.js → RBJoyStick.stories-DEgBou3K.js} +1 -1
- package/cli/storybook-dist/assets/{RBLabelButton.stories-DzF7vGwm.js → RBLabelButton.stories-DT8drIsF.js} +1 -1
- package/cli/storybook-dist/assets/{RBLight.stories-lF4FRmVh.js → RBLight.stories-Dh-aoeyG.js} +1 -1
- package/cli/storybook-dist/assets/{RBMenubar.stories-XhrI7bsV.js → RBMenubar.stories-D-H7UqVh.js} +1 -1
- package/cli/storybook-dist/assets/{RBMultiRangeInput.stories-DprllQDl.js → RBMultiRangeInput.stories-hlclv6jI.js} +1 -1
- package/cli/storybook-dist/assets/{RBPagination.stories-2v2gBJfC.js → RBPagination.stories-DWCeoZ_S.js} +1 -1
- package/cli/storybook-dist/assets/{RBPopover.stories-C8iLIZpv.js → RBPopover.stories-C514M09_.js} +1 -1
- package/cli/storybook-dist/assets/{RBPrompt.stories-Th_HrWHI.js → RBPrompt.stories-BSItvfiT.js} +1 -1
- package/cli/storybook-dist/assets/{RBRadioBox.stories-CoHuLaN3.js → RBRadioBox.stories-BBb4YbFU.js} +1 -1
- package/cli/storybook-dist/assets/{RBRadioButton.stories-DULxE_ff.js → RBRadioButton.stories-CXyOGJCv.js} +1 -1
- package/cli/storybook-dist/assets/{RBRangeDateInput.stories-D8A9KBSS.js → RBRangeDateInput.stories-qvhubu0e.js} +1 -1
- package/cli/storybook-dist/assets/{RBResizable.stories-C41QfrQ3.js → RBResizable.stories-CZKeyGjH.js} +14 -14
- package/cli/storybook-dist/assets/{RBSelectBox.stories-C1gNmwzw.js → RBSelectBox.stories-CRKP3ybf.js} +1 -1
- package/cli/storybook-dist/assets/RBSheet.stories-sCM3ZJUa.js +39 -0
- package/cli/storybook-dist/assets/{RBSideNumberInput.stories-9LlgQ8nh.js → RBSideNumberInput.stories-Bb7gw8RF.js} +3 -3
- package/cli/storybook-dist/assets/{RBSlider.stories-oUgo5K9d.js → RBSlider.stories-23OAQU5z.js} +3 -3
- package/cli/storybook-dist/assets/{RBSpinner.stories-DDpohbY2.js → RBSpinner.stories-2xcQdcmt.js} +1 -1
- package/cli/storybook-dist/assets/{RBSwitch.stories-gW-GN7QO.js → RBSwitch.stories-BACUaJm_.js} +7 -7
- package/cli/storybook-dist/assets/{RBTab.stories-CN-PV3HH.js → RBTab.stories-CDHE3sVs.js} +1 -1
- package/cli/storybook-dist/assets/{RBTable.stories-BAZLpxtM.js → RBTable.stories-C0Cfhfl7.js} +29 -29
- package/cli/storybook-dist/assets/{RBTableRow.stories-CwjVrszB.js → RBTableRow.stories-BF8kIkpp.js} +1 -1
- package/cli/storybook-dist/assets/{RBTabs.stories-JuEo2sUL.js → RBTabs.stories-BdJWRq1o.js} +7 -7
- package/cli/storybook-dist/assets/{RBTextArea.stories-D0_Pv4qZ.js → RBTextArea.stories-CGy2xeYH.js} +3 -3
- package/cli/storybook-dist/assets/{RBTextField.stories-CCsOvZqV.js → RBTextField.stories-IfUOzxCM.js} +15 -15
- package/cli/storybook-dist/assets/{RBTextInput.stories-Cccn3VNm.js → RBTextInput.stories-VjXNFo4R.js} +3 -3
- package/cli/storybook-dist/assets/{RBToast.stories-I5617t0K.js → RBToast.stories-BzcobblV.js} +1 -1
- package/cli/storybook-dist/assets/{RBToggle.stories-DsgKjGsJ.js → RBToggle.stories-DuLE5mKv.js} +4 -4
- package/cli/storybook-dist/assets/{RBToggleGroup.stories-BZEzSDuz.js → RBToggleGroup.stories-CuR0N0GJ.js} +5 -5
- package/cli/storybook-dist/assets/{RBTooltip.stories-4oSyAWsA.js → RBTooltip.stories--aAgNC8_.js} +1 -1
- package/cli/storybook-dist/assets/{SideNumberInput-DSKbd0bG.js → SideNumberInput-DyWQxYUj.js} +743 -743
- package/cli/storybook-dist/assets/{entry-preview-B35XREGs.js → entry-preview-D7IHsza_.js} +1 -1
- package/cli/storybook-dist/assets/{iframe-BB797lmL.js → iframe-CbaIp5I-.js} +2 -2
- package/cli/storybook-dist/assets/{index-BU2567EP.js → index-C6CBgMuG.js} +3 -3
- package/cli/storybook-dist/assets/{preview-C7DaSWyc.js → preview-B-iYLDuW.js} +2 -2
- package/cli/storybook-dist/assets/{preview-CbuRHit4.js → preview-CRWqc9DH.js} +1 -1
- package/cli/storybook-dist/assets/{react-resizable-panels.browser-ChIvlwo7.js → react-resizable-panels.browser-8hC8dr-6.js} +8 -8
- package/cli/storybook-dist/iframe.html +2 -2
- package/cli/storybook-dist/index.html +1 -1
- package/cli/storybook-dist/project.json +1 -1
- package/cli/templates/common/.mcp.json +8 -8
- package/cli/templates/common/README.md +1231 -1231
- package/cli/templates/common/assets/icon.svg +45 -45
- package/cli/templates/common/manifest.json +26 -26
- package/cli/templates/common/package.json +22 -22
- package/cli/templates/common/py/main.py +125 -125
- package/cli/templates/common/tsconfig.json +13 -13
- package/cli/templates/common/ui/content.tsx +216 -216
- package/cli/templates/common/ui/style.css +6 -6
- package/cli/templates/common/vite.config.ts +10 -10
- package/cli/templates/cpp/cpp/main.cpp +73 -73
- package/cli/templates/ros2/ros2_ws/src/__PLUGIN_SLUG__/__PLUGIN_SLUG__/node.py +25 -25
- package/cli/templates/ros2/ros2_ws/src/__PLUGIN_SLUG__/package.xml +10 -10
- package/cli/templates/ros2/ros2_ws/src/__PLUGIN_SLUG__/setup.py +18 -18
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/package.xml +11 -11
- package/cli/templates/ros2-cpp/ros2_ws/src/__PLUGIN_SLUG__/src/node.cpp +23 -23
- package/cli/vite.d.mts +25 -25
- package/cli/vite.mjs +292 -292
- package/package.json +3 -3
- package/cli/storybook-dist/assets/RBCommand.stories-BSqXDkKw.js +0 -73
- package/cli/storybook-dist/assets/RBDialog.stories-BAktz-ku.js +0 -38
- package/cli/storybook-dist/assets/RBDropdownMenu.stories-DbW2fWAj.js +0 -86
- package/cli/storybook-dist/assets/RBSheet.stories-_6VH-RUm.js +0 -39
package/README.md
CHANGED
|
@@ -1,282 +1,282 @@
|
|
|
1
|
-
# @rainbow-robotics/muscat-plugin-kit
|
|
2
|
-
|
|
3
|
-
CLI for developing Muscat plugins. Provides scaffolding, build/pack, and dev servers (UI + backend).
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
### Option 1 — npm (requires Node.js 20+)
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# latest stable
|
|
11
|
-
npm install -g @rainbow-robotics/muscat-plugin-kit
|
|
12
|
-
|
|
13
|
-
# dev channel (latest dev build)
|
|
14
|
-
npm install -g @rainbow-robotics/muscat-plugin-kit@dev
|
|
15
|
-
|
|
16
|
-
# specific version
|
|
17
|
-
npm install -g @rainbow-robotics/muscat-plugin-kit@1.2.3
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
### Option 2 — S3 install script (no Node.js required)
|
|
21
|
-
|
|
22
|
-
macOS / Linux / WSL:
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# latest stable
|
|
26
|
-
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | sh
|
|
27
|
-
|
|
28
|
-
# dev channel
|
|
29
|
-
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | MUSCAT_PK_TAG=dev sh
|
|
30
|
-
|
|
31
|
-
# specific version
|
|
32
|
-
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | MUSCAT_PK_TAG=1.2.3 sh
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
Windows PowerShell:
|
|
36
|
-
|
|
37
|
-
```powershell
|
|
38
|
-
# latest stable
|
|
39
|
-
irm https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.ps1 | iex
|
|
40
|
-
|
|
41
|
-
# dev channel
|
|
42
|
-
$env:MUSCAT_PK_TAG="dev"; irm https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.ps1 | iex
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
> The install script uses npm when Node.js 20+ is present, otherwise it downloads a self-contained binary from S3.
|
|
46
|
-
|
|
47
|
-
### Option 3 — direct binary download
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/v{version}/{binary}
|
|
51
|
-
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/stable/{binary}
|
|
52
|
-
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/dev/{binary}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
| OS | File |
|
|
56
|
-
|---|---|
|
|
57
|
-
| Linux x64 | `muscat-pk-linux-x64` |
|
|
58
|
-
| macOS ARM64 | `muscat-pk-darwin-arm64` |
|
|
59
|
-
| macOS x64 | `muscat-pk-darwin-x64` |
|
|
60
|
-
| Windows x64 | `muscat-pk-win-x64.exe` |
|
|
61
|
-
|
|
62
|
-
Channel pointers:
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
# latest stable version string
|
|
66
|
-
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/latest-version.txt
|
|
67
|
-
|
|
68
|
-
# latest dev version string
|
|
69
|
-
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/dev-version.txt
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### Uninstall
|
|
73
|
-
|
|
74
|
-
Regardless of how it was installed, `muscat-pk` can remove itself:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
muscat-pk uninstall
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Manual removal:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
# if installed via npm
|
|
84
|
-
npm uninstall -g @rainbow-robotics/muscat-plugin-kit
|
|
85
|
-
|
|
86
|
-
# if installed via the S3 binary (default macOS/Linux path)
|
|
87
|
-
sudo rm -f /usr/local/bin/muscat-pk
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## Quick start
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
muscat-pk new my-plugin # scaffold a plugin project (choose python / cpp / ros2 / ros2-cpp)
|
|
96
|
-
cd my-plugin
|
|
97
|
-
|
|
98
|
-
muscat-pk dev # run UI + backend together
|
|
99
|
-
muscat-pk dev:ui # UI preview only
|
|
100
|
-
muscat-pk dev:back # backend only (Docker: python/cpp/ros2)
|
|
101
|
-
|
|
102
|
-
muscat-pk build # build dist/ and produce a distributable ZIP (skip the ZIP with --no-zip)
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Command list
|
|
106
|
-
|
|
107
|
-
| Command | Description |
|
|
108
|
-
|---|---|
|
|
109
|
-
| `muscat-pk new [dir]` | Scaffold a plugin project (also creates an IDE-only python `.venv`) |
|
|
110
|
-
| `muscat-pk type change` | Switch backend type (`python` / `cpp` / `ros2` / `ros2-cpp`) |
|
|
111
|
-
| `muscat-pk build` | Build `ui/*.tsx` → `dist/*.js` (one per `contributes[].ui` entry in the manifest) and produce a distributable ZIP |
|
|
112
|
-
| `muscat-pk dev` | UI + backend dev server together |
|
|
113
|
-
| `muscat-pk dev:ui` | Mini-Muscat preview server |
|
|
114
|
-
| `muscat-pk dev:back` | Backend dev server (Docker, hot-reload) |
|
|
115
|
-
| `muscat-pk storybook` | Browse the bundled rb-components Storybook |
|
|
116
|
-
| `muscat-pk mcp` | Run an MCP server for AI coding agents (exposes rb-components/design-token/SDK docs) |
|
|
117
|
-
| `muscat-pk update` | Update the kit + plugin-ui to the latest version |
|
|
118
|
-
| `muscat-pk sdk <list\|update>` | Manage the `rainbow-rb-sdk` version — python: `requirements.txt`, C++ (cpp / ros2-cpp): `find_package(rb_sdk <ver> EXACT REQUIRED)` in `CMakeLists.txt` |
|
|
119
|
-
| `muscat-pk version` | Print the installed CLI version (`-v` / `--version` also work) |
|
|
120
|
-
| `muscat-pk completion [shell]` | Print a shell completion script (`bash` / `zsh` / `fish` / `powershell`; defaults to `$SHELL`) |
|
|
121
|
-
|
|
122
|
-
### Update policy
|
|
123
|
-
|
|
124
|
-
`muscat-pk` can be installed globally (npm `-g` or the S3 binary) and/or per
|
|
125
|
-
plugin project (`node_modules`). Two rules keep those from drifting apart:
|
|
126
|
-
|
|
127
|
-
**The project's local install wins.** When you run `muscat-pk` inside a plugin
|
|
128
|
-
project that has its own install, the CLI hands off to that copy. So the CLI,
|
|
129
|
-
the `vite` preset your `vite.config.ts` imports, and the `preview-host` that
|
|
130
|
-
`dev:ui` launches are always the single version the project pinned — a global
|
|
131
|
-
CLI that is newer or older than the project can't half-apply itself.
|
|
132
|
-
|
|
133
|
-
**`update` only touches what you're in.**
|
|
134
|
-
|
|
135
|
-
| Where you run it | What it updates |
|
|
136
|
-
|---|---|
|
|
137
|
-
| Inside a project with a local install | that project's `muscat-plugin-kit` + `plugin-ui` only |
|
|
138
|
-
| Same, with `--global` | the above, plus the global CLI |
|
|
139
|
-
| Anywhere else | the global CLI (and local deps if you're in a project) |
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
muscat-pk update # this project only
|
|
143
|
-
muscat-pk update --global # this project + the global CLI
|
|
144
|
-
muscat-pk update dev # follow the dev channel instead of latest
|
|
145
|
-
muscat-pk version # which version is actually running here
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
`dev:ui` also prints a one-line notice when a newer version is published. It is
|
|
149
|
-
skipped by `MUSCAT_PK_NO_UPDATE_CHECK=1` and fails silently offline.
|
|
150
|
-
|
|
151
|
-
### Offline / air-gapped use
|
|
152
|
-
|
|
153
|
-
Docker images are only built when they are missing. `docker build` contacts the
|
|
154
|
-
registry to resolve the base image tag on every run — even when every layer is
|
|
155
|
-
cached — so rebuilding an image you already have would break `dev` with no
|
|
156
|
-
network. Once an image exists locally, `muscat-pk` skips the build entirely.
|
|
157
|
-
|
|
158
|
-
Move images to a machine with no internet:
|
|
159
|
-
|
|
160
|
-
```bash
|
|
161
|
-
# on a machine with network
|
|
162
|
-
docker save muscat-pk-python-dev muscat-pk-runtime | gzip > muscat-pk-images.tar.gz
|
|
163
|
-
|
|
164
|
-
# on the offline machine
|
|
165
|
-
gunzip -c muscat-pk-images.tar.gz | docker load
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Force a rebuild with `MUSCAT_PK_REBUILD_IMAGE=1`.
|
|
169
|
-
|
|
170
|
-
### Shell completion
|
|
171
|
-
|
|
172
|
-
| OS / shell | Command |
|
|
173
|
-
|---|---|
|
|
174
|
-
| macOS (zsh) | `muscat-pk completion zsh >> ~/.zshrc && source ~/.zshrc` |
|
|
175
|
-
| Linux (bash) | `muscat-pk completion bash >> ~/.bashrc && source ~/.bashrc` |
|
|
176
|
-
| fish | `muscat-pk completion fish > ~/.config/fish/completions/muscat-pk.fish` |
|
|
177
|
-
| Windows (PowerShell) | `muscat-pk completion powershell >> $PROFILE; . $PROFILE` |
|
|
178
|
-
|
|
179
|
-
Windows `cmd.exe` has no completion mechanism to hook into — use PowerShell, Git Bash, or WSL.
|
|
180
|
-
|
|
181
|
-
## Backend port policy
|
|
182
|
-
|
|
183
|
-
A plugin backend that opens a TCP listener must declare every such port in
|
|
184
|
-
`manifest.json`:
|
|
185
|
-
|
|
186
|
-
```json
|
|
187
|
-
{ "ports": [28600, 28601] }
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
| Rule | Enforced by |
|
|
191
|
-
|---|---|
|
|
192
|
-
| Ports must be within `28600-28999` | `muscat-pk build` / `dev` (manifest validation) |
|
|
193
|
-
| Reserved robot/industrial ports are rejected | same — `502`, `2222`, `4840`, `5170-5179`, `8000-8999`, `10000`, `30004`, `34964`, `44818`, `50000-50005`, `50051` |
|
|
194
|
-
| **Every listening port must be declared** | `dev` / `dev:back` runtime monitor — stops the backend on the first undeclared port |
|
|
195
|
-
| No two enabled plugins may claim the same port | the robot, at install time (HTTP 409) |
|
|
196
|
-
|
|
197
|
-
The runtime monitor is strict on purpose: an undeclared port outside the plugin
|
|
198
|
-
range is invisible to both the monitor and the robot's conflict check, so it
|
|
199
|
-
would only surface as a collision after deployment.
|
|
200
|
-
|
|
201
|
-
`muscat-pk`'s own dev plumbing (the plugin gateway on `10000`, the Zenoh dev
|
|
202
|
-
peer port) is excluded from the check — it isn't the plugin's traffic.
|
|
203
|
-
|
|
204
|
-
Under `muscat-pk dev` declared ports are published to `127.0.0.1` from the local
|
|
205
|
-
Muscat container (the backend shares its network), so you can reach the backend
|
|
206
|
-
from the host.
|
|
207
|
-
|
|
208
|
-
## Variables (pyfm)
|
|
209
|
-
|
|
210
|
-
Variables the plugin wants to expose to pyfm programs must be pre-declared in
|
|
211
|
-
`manifest.json` — the Muscat UI lists only declared variables in its variable
|
|
212
|
-
picker:
|
|
213
|
-
|
|
214
|
-
```json
|
|
215
|
-
{
|
|
216
|
-
"variables": [
|
|
217
|
-
{ "name": "RBP_grip_force", "type": "number", "init": 0.5, "description": { "ko": "그리퍼 힘 (0~1)", "en": "Gripper force (0–1)" } },
|
|
218
|
-
{ "name": "RBP_target_pose", "type": "array", "init": [0, 0, 0] }
|
|
219
|
-
]
|
|
220
|
-
}
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
| Field | Required | Rule |
|
|
224
|
-
|---|---|---|
|
|
225
|
-
| `name` | yes | must start with `RBP_`, then letters/digits/underscore; unique per plugin |
|
|
226
|
-
| `type` | yes | `"number"` \| `"string"` \| `"array"` |
|
|
227
|
-
| `init` | yes | initial value, must match `type` |
|
|
228
|
-
| `description` | no | string or i18n object (`en` required in object form). Without it the UI shows the variable with no explanation — write one. |
|
|
229
|
-
|
|
230
|
-
Validated by `muscat-pk build` / `dev` alongside the rest of the manifest.
|
|
231
|
-
|
|
232
|
-
## IDE support (Python)
|
|
233
|
-
|
|
234
|
-
`muscat-pk new` creates a `.venv` at the project root with `requirements.txt` installed. The real backend still runs in a Docker container — this `.venv` exists purely for editor linting (pylint/pyright).
|
|
235
|
-
|
|
236
|
-
If it can't be created (no local Python 3 or `uv` found), scaffolding prints a warning and continues — Docker-based dev still works without it:
|
|
237
|
-
|
|
238
|
-
```
|
|
239
|
-
Could not create .venv (no local Python/uv?) — skipping, Docker dev still works.
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
Install `uv` (recommended) or a system Python 3.12, then re-run `muscat-pk new` (or `muscat-pk type change`) to create it.
|
|
243
|
-
|
|
244
|
-
## AI coding agent setup (`muscat-pk mcp`)
|
|
245
|
-
|
|
246
|
-
`muscat-pk mcp` runs an MCP server (stdio) that gives an AI coding agent grounded info about `rb-components`, design tokens, and the Python `rainbow-rb-sdk` — actual prop types, real Storybook examples, and live-introspected SDK signatures/docstrings, instead of the agent guessing from training data. Use it while working inside a plugin project scaffolded by `muscat-pk new`.
|
|
247
|
-
|
|
248
|
-
### Claude Code
|
|
249
|
-
|
|
250
|
-
Claude Code reads a project-scoped `.mcp.json` at the plugin's root:
|
|
251
|
-
|
|
252
|
-
```json
|
|
253
|
-
{
|
|
254
|
-
"mcpServers": {
|
|
255
|
-
"muscat": {
|
|
256
|
-
"command": "muscat-pk",
|
|
257
|
-
"args": ["mcp"]
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
### Codex
|
|
264
|
-
|
|
265
|
-
Codex has no project-scoped config file — it reads a single, per-user `~/.codex/config.toml`. Add:
|
|
266
|
-
|
|
267
|
-
```toml
|
|
268
|
-
[mcp_servers.muscat]
|
|
269
|
-
command = "muscat-pk"
|
|
270
|
-
args = ["mcp"]
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
You don't run `muscat-pk mcp` yourself either way — the agent spawns and manages it automatically once it's registered.
|
|
274
|
-
|
|
275
|
-
## Package roles
|
|
276
|
-
|
|
277
|
-
| Package | Role |
|
|
278
|
-
|---|---|
|
|
279
|
-
| `@rainbow-robotics/plugin-ui` | UI runtime contract: React direct mount, `useRb()` context, host services |
|
|
280
|
-
| `@rainbow-robotics/muscat-plugin-kit` | CLI, templates, build/pack, preview host |
|
|
281
|
-
|
|
282
|
-
A plugin ZIP only contains the plugin's own code and assets. `@rainbow-robotics/plugin-ui`, `react`, and `react-dom` are provided by the host's (Muscat/robot) import map.
|
|
1
|
+
# @rainbow-robotics/muscat-plugin-kit
|
|
2
|
+
|
|
3
|
+
CLI for developing Muscat plugins. Provides scaffolding, build/pack, and dev servers (UI + backend).
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
### Option 1 — npm (requires Node.js 20+)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# latest stable
|
|
11
|
+
npm install -g @rainbow-robotics/muscat-plugin-kit
|
|
12
|
+
|
|
13
|
+
# dev channel (latest dev build)
|
|
14
|
+
npm install -g @rainbow-robotics/muscat-plugin-kit@dev
|
|
15
|
+
|
|
16
|
+
# specific version
|
|
17
|
+
npm install -g @rainbow-robotics/muscat-plugin-kit@1.2.3
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Option 2 — S3 install script (no Node.js required)
|
|
21
|
+
|
|
22
|
+
macOS / Linux / WSL:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# latest stable
|
|
26
|
+
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | sh
|
|
27
|
+
|
|
28
|
+
# dev channel
|
|
29
|
+
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | MUSCAT_PK_TAG=dev sh
|
|
30
|
+
|
|
31
|
+
# specific version
|
|
32
|
+
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | MUSCAT_PK_TAG=1.2.3 sh
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Windows PowerShell:
|
|
36
|
+
|
|
37
|
+
```powershell
|
|
38
|
+
# latest stable
|
|
39
|
+
irm https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.ps1 | iex
|
|
40
|
+
|
|
41
|
+
# dev channel
|
|
42
|
+
$env:MUSCAT_PK_TAG="dev"; irm https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.ps1 | iex
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> The install script uses npm when Node.js 20+ is present, otherwise it downloads a self-contained binary from S3.
|
|
46
|
+
|
|
47
|
+
### Option 3 — direct binary download
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/v{version}/{binary}
|
|
51
|
+
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/stable/{binary}
|
|
52
|
+
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/dev/{binary}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
| OS | File |
|
|
56
|
+
|---|---|
|
|
57
|
+
| Linux x64 | `muscat-pk-linux-x64` |
|
|
58
|
+
| macOS ARM64 | `muscat-pk-darwin-arm64` |
|
|
59
|
+
| macOS x64 | `muscat-pk-darwin-x64` |
|
|
60
|
+
| Windows x64 | `muscat-pk-win-x64.exe` |
|
|
61
|
+
|
|
62
|
+
Channel pointers:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
# latest stable version string
|
|
66
|
+
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/latest-version.txt
|
|
67
|
+
|
|
68
|
+
# latest dev version string
|
|
69
|
+
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/dev-version.txt
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Uninstall
|
|
73
|
+
|
|
74
|
+
Regardless of how it was installed, `muscat-pk` can remove itself:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
muscat-pk uninstall
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Manual removal:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# if installed via npm
|
|
84
|
+
npm uninstall -g @rainbow-robotics/muscat-plugin-kit
|
|
85
|
+
|
|
86
|
+
# if installed via the S3 binary (default macOS/Linux path)
|
|
87
|
+
sudo rm -f /usr/local/bin/muscat-pk
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Quick start
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
muscat-pk new my-plugin # scaffold a plugin project (choose python / cpp / ros2 / ros2-cpp)
|
|
96
|
+
cd my-plugin
|
|
97
|
+
|
|
98
|
+
muscat-pk dev # run UI + backend together
|
|
99
|
+
muscat-pk dev:ui # UI preview only
|
|
100
|
+
muscat-pk dev:back # backend only (Docker: python/cpp/ros2)
|
|
101
|
+
|
|
102
|
+
muscat-pk build # build dist/ and produce a distributable ZIP (skip the ZIP with --no-zip)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Command list
|
|
106
|
+
|
|
107
|
+
| Command | Description |
|
|
108
|
+
|---|---|
|
|
109
|
+
| `muscat-pk new [dir]` | Scaffold a plugin project (also creates an IDE-only python `.venv`) |
|
|
110
|
+
| `muscat-pk type change` | Switch backend type (`python` / `cpp` / `ros2` / `ros2-cpp`) |
|
|
111
|
+
| `muscat-pk build` | Build `ui/*.tsx` → `dist/*.js` (one per `contributes[].ui` entry in the manifest) and produce a distributable ZIP |
|
|
112
|
+
| `muscat-pk dev` | UI + backend dev server together |
|
|
113
|
+
| `muscat-pk dev:ui` | Mini-Muscat preview server |
|
|
114
|
+
| `muscat-pk dev:back` | Backend dev server (Docker, hot-reload) |
|
|
115
|
+
| `muscat-pk storybook` | Browse the bundled rb-components Storybook |
|
|
116
|
+
| `muscat-pk mcp` | Run an MCP server for AI coding agents (exposes rb-components/design-token/SDK docs) |
|
|
117
|
+
| `muscat-pk update` | Update the kit + plugin-ui to the latest version |
|
|
118
|
+
| `muscat-pk sdk <list\|update>` | Manage the `rainbow-rb-sdk` version — python: `requirements.txt`, C++ (cpp / ros2-cpp): `find_package(rb_sdk <ver> EXACT REQUIRED)` in `CMakeLists.txt` |
|
|
119
|
+
| `muscat-pk version` | Print the installed CLI version (`-v` / `--version` also work) |
|
|
120
|
+
| `muscat-pk completion [shell]` | Print a shell completion script (`bash` / `zsh` / `fish` / `powershell`; defaults to `$SHELL`) |
|
|
121
|
+
|
|
122
|
+
### Update policy
|
|
123
|
+
|
|
124
|
+
`muscat-pk` can be installed globally (npm `-g` or the S3 binary) and/or per
|
|
125
|
+
plugin project (`node_modules`). Two rules keep those from drifting apart:
|
|
126
|
+
|
|
127
|
+
**The project's local install wins.** When you run `muscat-pk` inside a plugin
|
|
128
|
+
project that has its own install, the CLI hands off to that copy. So the CLI,
|
|
129
|
+
the `vite` preset your `vite.config.ts` imports, and the `preview-host` that
|
|
130
|
+
`dev:ui` launches are always the single version the project pinned — a global
|
|
131
|
+
CLI that is newer or older than the project can't half-apply itself.
|
|
132
|
+
|
|
133
|
+
**`update` only touches what you're in.**
|
|
134
|
+
|
|
135
|
+
| Where you run it | What it updates |
|
|
136
|
+
|---|---|
|
|
137
|
+
| Inside a project with a local install | that project's `muscat-plugin-kit` + `plugin-ui` only |
|
|
138
|
+
| Same, with `--global` | the above, plus the global CLI |
|
|
139
|
+
| Anywhere else | the global CLI (and local deps if you're in a project) |
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
muscat-pk update # this project only
|
|
143
|
+
muscat-pk update --global # this project + the global CLI
|
|
144
|
+
muscat-pk update dev # follow the dev channel instead of latest
|
|
145
|
+
muscat-pk version # which version is actually running here
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`dev:ui` also prints a one-line notice when a newer version is published. It is
|
|
149
|
+
skipped by `MUSCAT_PK_NO_UPDATE_CHECK=1` and fails silently offline.
|
|
150
|
+
|
|
151
|
+
### Offline / air-gapped use
|
|
152
|
+
|
|
153
|
+
Docker images are only built when they are missing. `docker build` contacts the
|
|
154
|
+
registry to resolve the base image tag on every run — even when every layer is
|
|
155
|
+
cached — so rebuilding an image you already have would break `dev` with no
|
|
156
|
+
network. Once an image exists locally, `muscat-pk` skips the build entirely.
|
|
157
|
+
|
|
158
|
+
Move images to a machine with no internet:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# on a machine with network
|
|
162
|
+
docker save muscat-pk-python-dev muscat-pk-runtime | gzip > muscat-pk-images.tar.gz
|
|
163
|
+
|
|
164
|
+
# on the offline machine
|
|
165
|
+
gunzip -c muscat-pk-images.tar.gz | docker load
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Force a rebuild with `MUSCAT_PK_REBUILD_IMAGE=1`.
|
|
169
|
+
|
|
170
|
+
### Shell completion
|
|
171
|
+
|
|
172
|
+
| OS / shell | Command |
|
|
173
|
+
|---|---|
|
|
174
|
+
| macOS (zsh) | `muscat-pk completion zsh >> ~/.zshrc && source ~/.zshrc` |
|
|
175
|
+
| Linux (bash) | `muscat-pk completion bash >> ~/.bashrc && source ~/.bashrc` |
|
|
176
|
+
| fish | `muscat-pk completion fish > ~/.config/fish/completions/muscat-pk.fish` |
|
|
177
|
+
| Windows (PowerShell) | `muscat-pk completion powershell >> $PROFILE; . $PROFILE` |
|
|
178
|
+
|
|
179
|
+
Windows `cmd.exe` has no completion mechanism to hook into — use PowerShell, Git Bash, or WSL.
|
|
180
|
+
|
|
181
|
+
## Backend port policy
|
|
182
|
+
|
|
183
|
+
A plugin backend that opens a TCP listener must declare every such port in
|
|
184
|
+
`manifest.json`:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{ "ports": [28600, 28601] }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
| Rule | Enforced by |
|
|
191
|
+
|---|---|
|
|
192
|
+
| Ports must be within `28600-28999` | `muscat-pk build` / `dev` (manifest validation) |
|
|
193
|
+
| Reserved robot/industrial ports are rejected | same — `502`, `2222`, `4840`, `5170-5179`, `8000-8999`, `10000`, `30004`, `34964`, `44818`, `50000-50005`, `50051` |
|
|
194
|
+
| **Every listening port must be declared** | `dev` / `dev:back` runtime monitor — stops the backend on the first undeclared port |
|
|
195
|
+
| No two enabled plugins may claim the same port | the robot, at install time (HTTP 409) |
|
|
196
|
+
|
|
197
|
+
The runtime monitor is strict on purpose: an undeclared port outside the plugin
|
|
198
|
+
range is invisible to both the monitor and the robot's conflict check, so it
|
|
199
|
+
would only surface as a collision after deployment.
|
|
200
|
+
|
|
201
|
+
`muscat-pk`'s own dev plumbing (the plugin gateway on `10000`, the Zenoh dev
|
|
202
|
+
peer port) is excluded from the check — it isn't the plugin's traffic.
|
|
203
|
+
|
|
204
|
+
Under `muscat-pk dev` declared ports are published to `127.0.0.1` from the local
|
|
205
|
+
Muscat container (the backend shares its network), so you can reach the backend
|
|
206
|
+
from the host.
|
|
207
|
+
|
|
208
|
+
## Variables (pyfm)
|
|
209
|
+
|
|
210
|
+
Variables the plugin wants to expose to pyfm programs must be pre-declared in
|
|
211
|
+
`manifest.json` — the Muscat UI lists only declared variables in its variable
|
|
212
|
+
picker:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"variables": [
|
|
217
|
+
{ "name": "RBP_grip_force", "type": "number", "init": 0.5, "description": { "ko": "그리퍼 힘 (0~1)", "en": "Gripper force (0–1)" } },
|
|
218
|
+
{ "name": "RBP_target_pose", "type": "array", "init": [0, 0, 0] }
|
|
219
|
+
]
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
| Field | Required | Rule |
|
|
224
|
+
|---|---|---|
|
|
225
|
+
| `name` | yes | must start with `RBP_`, then letters/digits/underscore; unique per plugin |
|
|
226
|
+
| `type` | yes | `"number"` \| `"string"` \| `"array"` |
|
|
227
|
+
| `init` | yes | initial value, must match `type` |
|
|
228
|
+
| `description` | no | string or i18n object (`en` required in object form). Without it the UI shows the variable with no explanation — write one. |
|
|
229
|
+
|
|
230
|
+
Validated by `muscat-pk build` / `dev` alongside the rest of the manifest.
|
|
231
|
+
|
|
232
|
+
## IDE support (Python)
|
|
233
|
+
|
|
234
|
+
`muscat-pk new` creates a `.venv` at the project root with `requirements.txt` installed. The real backend still runs in a Docker container — this `.venv` exists purely for editor linting (pylint/pyright).
|
|
235
|
+
|
|
236
|
+
If it can't be created (no local Python 3 or `uv` found), scaffolding prints a warning and continues — Docker-based dev still works without it:
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
Could not create .venv (no local Python/uv?) — skipping, Docker dev still works.
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Install `uv` (recommended) or a system Python 3.12, then re-run `muscat-pk new` (or `muscat-pk type change`) to create it.
|
|
243
|
+
|
|
244
|
+
## AI coding agent setup (`muscat-pk mcp`)
|
|
245
|
+
|
|
246
|
+
`muscat-pk mcp` runs an MCP server (stdio) that gives an AI coding agent grounded info about `rb-components`, design tokens, and the Python `rainbow-rb-sdk` — actual prop types, real Storybook examples, and live-introspected SDK signatures/docstrings, instead of the agent guessing from training data. Use it while working inside a plugin project scaffolded by `muscat-pk new`.
|
|
247
|
+
|
|
248
|
+
### Claude Code
|
|
249
|
+
|
|
250
|
+
Claude Code reads a project-scoped `.mcp.json` at the plugin's root:
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"mcpServers": {
|
|
255
|
+
"muscat": {
|
|
256
|
+
"command": "muscat-pk",
|
|
257
|
+
"args": ["mcp"]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Codex
|
|
264
|
+
|
|
265
|
+
Codex has no project-scoped config file — it reads a single, per-user `~/.codex/config.toml`. Add:
|
|
266
|
+
|
|
267
|
+
```toml
|
|
268
|
+
[mcp_servers.muscat]
|
|
269
|
+
command = "muscat-pk"
|
|
270
|
+
args = ["mcp"]
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
You don't run `muscat-pk mcp` yourself either way — the agent spawns and manages it automatically once it's registered.
|
|
274
|
+
|
|
275
|
+
## Package roles
|
|
276
|
+
|
|
277
|
+
| Package | Role |
|
|
278
|
+
|---|---|
|
|
279
|
+
| `@rainbow-robotics/plugin-ui` | UI runtime contract: React direct mount, `useRb()` context, host services |
|
|
280
|
+
| `@rainbow-robotics/muscat-plugin-kit` | CLI, templates, build/pack, preview host |
|
|
281
|
+
|
|
282
|
+
A plugin ZIP only contains the plugin's own code and assets. `@rainbow-robotics/plugin-ui`, `react`, and `react-dom` are provided by the host's (Muscat/robot) import map.
|