@rainbow-robotics/muscat-plugin-kit
v1.3.2
Published
Muscat plugin kit: muscat-pk CLI, plugin scaffold, build/pack/dev tools
Readme
@rainbow-robotics/muscat-plugin-kit
CLI for developing Muscat plugins. Provides scaffolding, build/pack, and dev servers (UI + backend).
Install
Option 1 — npm (requires Node.js 20+)
# latest stable
npm install -g @rainbow-robotics/muscat-plugin-kit
# dev channel (latest dev build)
npm install -g @rainbow-robotics/muscat-plugin-kit@dev
# specific version
npm install -g @rainbow-robotics/[email protected]Option 2 — S3 install script (no Node.js required)
macOS / Linux / WSL:
# latest stable
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | sh
# dev channel
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | MUSCAT_PK_TAG=dev sh
# specific version
curl -fsSL https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.sh | MUSCAT_PK_TAG=1.2.3 shWindows PowerShell:
# latest stable
irm https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.ps1 | iex
# dev channel
$env:MUSCAT_PK_TAG="dev"; irm https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/install.ps1 | iexThe install script uses npm when Node.js 20+ is present, otherwise it downloads a self-contained binary from S3.
Option 3 — direct binary download
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/v{version}/{binary}
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/stable/{binary}
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/dev/{binary}| OS | File |
|---|---|
| Linux x64 | muscat-pk-linux-x64 |
| macOS ARM64 | muscat-pk-darwin-arm64 |
| macOS x64 | muscat-pk-darwin-x64 |
| Windows x64 | muscat-pk-win-x64.exe |
Channel pointers:
# latest stable version string
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/latest-version.txt
# latest dev version string
https://rainbow-deploy.s3.ap-northeast-2.amazonaws.com/muscat-plugin-kit/dev-version.txtUninstall
Regardless of how it was installed, muscat-pk can remove itself:
muscat-pk uninstallManual removal:
# if installed via npm
npm uninstall -g @rainbow-robotics/muscat-plugin-kit
# if installed via the S3 binary (default macOS/Linux path)
sudo rm -f /usr/local/bin/muscat-pkQuick start
muscat-pk new my-plugin # scaffold a plugin project (choose python / cpp / ros2 / ros2-cpp)
cd my-plugin
muscat-pk dev # run UI + backend together
muscat-pk dev:ui # UI preview only
muscat-pk dev:back # backend only (Docker: python/cpp/ros2)
muscat-pk build # build dist/ and produce a distributable ZIP (skip the ZIP with --no-zip)Command list
| Command | Description |
|---|---|
| muscat-pk new [dir] | Scaffold a plugin project (also creates an IDE-only python .venv) |
| muscat-pk type change | Switch backend type (python / cpp / ros2 / ros2-cpp) |
| muscat-pk build | Build ui/*.tsx → dist/*.js (one per contributes[].ui entry in the manifest) and produce a distributable ZIP |
| muscat-pk dev | UI + backend dev server together |
| muscat-pk dev:ui | Mini-Muscat preview server |
| muscat-pk dev:back | Backend dev server (Docker, hot-reload) |
| muscat-pk storybook | Browse the bundled rb-components Storybook |
| muscat-pk mcp | Run an MCP server for AI coding agents (exposes rb-components/design-token/SDK docs) |
| muscat-pk update | Update the kit + plugin-ui to the latest version |
| muscat-pk sdk <list\|update> | Manage the Python rainbow-rb-sdk version |
| muscat-pk version | Print the installed CLI version (-v / --version also work) |
| muscat-pk completion [shell] | Print a shell completion script (bash / zsh / fish / powershell; defaults to $SHELL) |
Update policy
muscat-pk can be installed globally (npm -g or the S3 binary) and/or per
plugin project (node_modules). Two rules keep those from drifting apart:
The project's local install wins. When you run muscat-pk inside a plugin
project that has its own install, the CLI hands off to that copy. So the CLI,
the vite preset your vite.config.ts imports, and the preview-host that
dev:ui launches are always the single version the project pinned — a global
CLI that is newer or older than the project can't half-apply itself.
update only touches what you're in.
| Where you run it | What it updates |
|---|---|
| Inside a project with a local install | that project's muscat-plugin-kit + plugin-ui only |
| Same, with --global | the above, plus the global CLI |
| Anywhere else | the global CLI (and local deps if you're in a project) |
muscat-pk update # this project only
muscat-pk update --global # this project + the global CLI
muscat-pk update dev # follow the dev channel instead of latest
muscat-pk version # which version is actually running heredev:ui also prints a one-line notice when a newer version is published. It is
skipped by MUSCAT_PK_NO_UPDATE_CHECK=1 and fails silently offline.
Offline / air-gapped use
Docker images are only built when they are missing. docker build contacts the
registry to resolve the base image tag on every run — even when every layer is
cached — so rebuilding an image you already have would break dev with no
network. Once an image exists locally, muscat-pk skips the build entirely.
Move images to a machine with no internet:
# on a machine with network
docker save muscat-pk-python-dev muscat-pk-bridge | gzip > muscat-pk-images.tar.gz
# on the offline machine
gunzip -c muscat-pk-images.tar.gz | docker loadForce a rebuild with MUSCAT_PK_REBUILD_IMAGE=1.
Shell completion
| OS / shell | Command |
|---|---|
| macOS (zsh) | muscat-pk completion zsh >> ~/.zshrc && source ~/.zshrc |
| Linux (bash) | muscat-pk completion bash >> ~/.bashrc && source ~/.bashrc |
| fish | muscat-pk completion fish > ~/.config/fish/completions/muscat-pk.fish |
| Windows (PowerShell) | muscat-pk completion powershell >> $PROFILE; . $PROFILE |
Windows cmd.exe has no completion mechanism to hook into — use PowerShell, Git Bash, or WSL.
Backend port policy
A plugin backend that opens a TCP listener must declare every such port in
manifest.json:
{ "ports": [28600, 28601] }| Rule | Enforced by |
|---|---|
| Ports must be within 28600-28999 | muscat-pk build / dev (manifest validation) |
| Reserved robot/industrial ports are rejected | same — 502, 2222, 4840, 5170-5179, 8000-8999, 10000, 30004, 34964, 44818, 50000-50005, 50051 |
| Every listening port must be declared | dev / dev:back runtime monitor — stops the backend on the first undeclared port |
| No two enabled plugins may claim the same port | the robot, at install time (HTTP 409) |
The runtime monitor is strict on purpose: an undeclared port outside the plugin range is invisible to both the monitor and the robot's conflict check, so it would only surface as a collision after deployment.
muscat-pk's own dev plumbing (the Socket.IO bridge on 10000, the Zenoh dev
peer port) is excluded from the check — it isn't the plugin's traffic.
Declared ports are published to 127.0.0.1 on macOS and Windows so you can
reach the backend from the host; native Linux uses host networking, where they
already are.
Variables (pyfm)
Variables the plugin wants to expose to pyfm programs must be pre-declared in
manifest.json — the Muscat UI lists only declared variables in its variable
picker:
{
"variables": [
{ "name": "RBP_grip_force", "type": "number", "init": 0.5, "description": { "ko": "그리퍼 힘 (0~1)", "en": "Gripper force (0–1)" } },
{ "name": "RBP_target_pose", "type": "array", "init": [0, 0, 0] }
]
}| Field | Required | Rule |
|---|---|---|
| name | yes | must start with RBP_, then letters/digits/underscore; unique per plugin |
| type | yes | "number" | "string" | "array" |
| init | yes | initial value, must match type |
| description | no | string or i18n object (en required in object form). Without it the UI shows the variable with no explanation — write one. |
Validated by muscat-pk build / dev alongside the rest of the manifest.
IDE support (Python)
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).
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:
Could not create .venv (no local Python/uv?) — skipping, Docker dev still works.Install uv (recommended) or a system Python 3.12, then re-run muscat-pk new (or muscat-pk type change) to create it.
AI coding agent setup (muscat-pk mcp)
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.
Claude Code
Claude Code reads a project-scoped .mcp.json at the plugin's root:
{
"mcpServers": {
"muscat": {
"command": "muscat-pk",
"args": ["mcp"]
}
}
}Codex
Codex has no project-scoped config file — it reads a single, per-user ~/.codex/config.toml. Add:
[mcp_servers.muscat]
command = "muscat-pk"
args = ["mcp"]You don't run muscat-pk mcp yourself either way — the agent spawns and manages it automatically once it's registered.
Package roles
| Package | Role |
|---|---|
| @rainbow-robotics/plugin-ui | UI runtime contract: React direct mount, useRb() context, host services |
| @rainbow-robotics/muscat-plugin-kit | CLI, templates, build/pack, preview host |
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.
