Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

RhinoClaw

v0.2.6

Control Rhino 3D via AI agents. 72+ tools for geometry, transforms, booleans, PBR materials, Grasshopper automation, VisualARQ BIM objects, and viewport cont...

0· 137·0 current·0 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for mcmuff86/rhinoclaw.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "RhinoClaw" (mcmuff86/rhinoclaw) from ClawHub.
Skill page: https://clawhub.ai/mcmuff86/rhinoclaw
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Canonical install target

openclaw skills install mcmuff86/rhinoclaw

ClawHub CLI

Package manager switcher

npx clawhub@latest install rhinoclaw
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Benign
medium confidence
Purpose & Capability
Name/description match the delivered artifacts: many Rhino-focused scripts, GH templates, and VisualARQ helpers. The scripts all call a Rhino client and perform CAD/BIM tasks described in the SKILL.md. There are no unrelated credentials or binaries requested.
Instruction Scope
SKILL.md and scripts instruct the agent to connect to a RhinoClaw plugin via TCP, copy config.json, run many local Python scripts, build/deploy Grasshopper defs, and execute arbitrary RhinoScript Python code via the plugin. Executing arbitrary code inside Rhino (execute_rhinoscript_python_code) and copying/running local meta_gen.py are powerful but coherent with the skill's stated purpose; users should be aware this grants the skill the ability to execute code on the Rhino host and write files into the user's home filesystem.
Install Mechanism
No install spec (instruction-only) and no remote download URLs in the registry metadata. The skill bundle contains scripts but does not instruct fetching or running code from an external release host, so there is no high-risk installer mechanism in the metadata provided.
Credentials
The skill requires no environment variables or keys. It does require a reachable Rhino host/port (config.json) which is proportionate to a tool that talks to a Rhino plugin. It does perform file operations (reading templates, writing .gh/.meta.json, copying to a Compute Platform definitions directory) which are expected for GH deploy workflows.
Persistence & Privilege
always:false (normal). The skill writes to user-space locations (home/compute platform defs) and may run subprocesses (meta_gen.py) on the user's machine when performing deploy flows. It does not declare elevated or system-wide persistence, nor does it modify other skills' configs in the bundle that was reviewed.
Assessment
This skill appears to do what it claims — control Rhino via a RhinoClaw plugin — but it is powerful and should be used with care. Before installing or running it: (1) Only connect to Rhino hosts you trust (prefer 127.0.0.1 for local Rhino). The SKILL relies on a Rhino plugin that listens on TCP; exposing that port to LAN/Internet is risky. (2) Be aware the skill can execute arbitrary Python inside Rhino (execute_rhinoscript_python_code) — do not allow untrusted agents or people to invoke those flows. (3) The GH deploy flow copies files into your home directory and may run a local meta_gen.py subprocess; review the destination path and meta_gen.py script before running. (4) If you need higher assurance, open and review scripts/rhino_client.py and script_exec.py to confirm there is no hidden network exfiltration or calls to unexpected endpoints. If you want help reviewing any specific file (for example rhino_client.py), provide its content and I can point out any risky lines.

Like a lobster shell, security has layers — review code before you run it.

latestvk979z6g8k3vv3175sc7bbp4tp583c285
137downloads
0stars
2versions
Updated 1mo ago
v0.2.6
MIT-0

RhinoClaw Skill

Control Rhino 3D directly via TCP socket connection to the RhinoClaw plugin. 72+ tools for geometry creation, BIM workflows, Grasshopper automation, and more.

Plugin: github.com/McMuff86/RhinoClaw · Author: Solid AI

Prerequisites

  1. Rhino 7/8 running on Windows
  2. RhinoClaw plugin installed and built
  3. Plugin started: In Rhino command line, type tcpstart (for WSL/remote access)

Note: Use mcpstart for local-only access (Cursor, Claude Desktop), tcpstart for WSL/Clawdbot.

Configuration

Copy config.example.json to config.json and edit:

cp config.example.json config.json
{
  "connection": {
    "host": "YOUR_RHINO_HOST_IP",
    "port": 1999,
    "timeout": 15.0
  },
  "screenshots": {
    "linux_dir": "./captures",
    "windows_dir": ""
  }
}

Host IP depends on your setup:

  • Same machine: 127.0.0.1
  • WSL2 → Windows: Your gateway IP (ip route show default | awk '{print $3}')
  • Remote (Tailscale/LAN): The IP of the Windows machine running Rhino

Quick Test

cd ~/clawd/skills/rhinoclaw/scripts
python3 rhino_client.py ping

Scripts Reference

ScriptPurpose
rhino_client.pyBase TCP client, raw commands
geometry.pyCreate primitives (box, sphere, cylinder, curves...)
transforms.pyMove, rotate, scale, copy, mirror, arrays
booleans.pyUnion, difference, intersection
selection.pySelect by layer, type, name, IDs
analysis.pyObject info, properties, bounding box, volume
curves.pyOffset, fillet, chamfer, join, explode
surfaces.pyLoft, extrude, revolve, sweep
layers.pyCreate, set, list, delete layers
materials.pyPBR materials, assign to layers
viewport.pyViews, camera, screenshots
render.pyLights, render settings, render to file
files.pyOpen, save, import, export (STEP, OBJ, STL...)
groups.pyGroups and block definitions
scene.pyDocument info, batch operations
presets.pyPreset & Template manager for GH definitions
ghscript.pyGH Definition builder + Compute Platform deployer
visualarq.pyVisualARQ BIM objects (walls, doors, windows, levels, IFC)
utils.pyShared utilities (parse_coords, parse_color, format_result)

🎯 Geometry Creation

# Primitives
python3 geometry.py sphere --radius 5 --position 0,0,0 --name "Ball"
python3 geometry.py box --width 10 --length 10 --height 5 --color 255,0,0
python3 geometry.py cylinder --radius 2 --height 8 --layer "Parts"
python3 geometry.py cone --radius 3 --height 6
python3 geometry.py line --start 0,0,0 --end 10,10,0
python3 geometry.py circle --radius 5
python3 geometry.py arc --radius 5 --angle 90
python3 geometry.py polyline --points "0,0,0 10,0,0 10,10,0 0,10,0"

Supported Geometry Types

TypeKey Parameters
POINTlocation
LINEstart, end
POLYLINEpoints
CIRCLEcenter, radius
ARCcenter, radius, angle
ELLIPSEcenter, radius_x, radius_y
CURVEpoints, degree
BOXwidth, length, height
SPHEREradius
CONEradius, height
CYLINDERradius, height
MESHvertices, faces

🔨 Solid Operations

# Fillet (round) edges of a solid
python3 solids.py fillet <object_id> --radius 2.0

# Fillet specific edges only
python3 solids.py fillet <object_id> --radius 2.0 --edges 0,1,3

# Chamfer edges
python3 solids.py chamfer <object_id> --distance 1.5

# Keep original (don't delete input)
python3 solids.py fillet <object_id> --radius 2.0 --keep

🔄 Transform Operations

# Move object
python3 transforms.py move <id> --vector 10,0,0

# Rotate object (degrees around axis through point)
python3 transforms.py rotate <id> --angle 45 --axis 0,0,1 --center 0,0,0

# Scale object
python3 transforms.py scale <id> --factor 2.0 --center 0,0,0

# Copy with offset
python3 transforms.py copy <id> --offset 10,0,0

# Mirror across plane
python3 transforms.py mirror <id> --origin 0,0,0 --normal 1,0,0

# Linear array: 5 copies along X
python3 transforms.py linear <id> --direction 1,0,0 --count 5 --distance 10

# Polar array: 8 copies around Z axis
python3 transforms.py polar <id> --center 0,0,0 --axis 0,0,1 --count 8

⚡ Boolean Operations

# Union multiple solids
python3 booleans.py union <id1> <id2> <id3>

# Difference: subtract cutter(s) from base
python3 booleans.py difference <base_id> <cutter_id>

# Intersection
python3 booleans.py intersection <id1> <id2>

# Keep input objects (don't delete)
python3 booleans.py union <id1> <id2> --keep

Note: Objects must be closed solids (Breps).


🎯 Selection

# Select all
python3 selection.py all

# Clear selection
python3 selection.py none

# Get info about selected objects
python3 selection.py get

# Select by layer
python3 selection.py layer "MyLayer"

# Select by object type
python3 selection.py type solid    # solid, curve, surface, mesh, point, etc.

# Select by name (partial match)
python3 selection.py name "Box"

# Select specific IDs
python3 selection.py ids <id1> <id2> <id3>

# Combined filters
python3 selection.py filter --layer "Parts" --type solid

📊 Object Analysis

# Basic object info
python3 analysis.py info <object_id>

# Detailed properties (bounding box, area, volume, centroid)
python3 analysis.py properties <object_id>

# Info about selected objects
python3 analysis.py selected

# Document summary
python3 analysis.py document

〰️ Curve Operations

# Offset curve
python3 curves.py offset <curve_id> --distance 5

# Fillet two curves
python3 curves.py fillet <curve1_id> <curve2_id> --radius 2

# Chamfer two curves
python3 curves.py chamfer <curve1_id> <curve2_id> --distance 3

# Join curves into polycurve
python3 curves.py join <id1> <id2> <id3>

# Explode polycurve into segments
python3 curves.py explode <polycurve_id>

# Keep input (don't delete)
python3 curves.py join <id1> <id2> --keep

🏔️ Surface Operations

# Loft through curves
python3 surfaces.py loft <curve1_id> <curve2_id> <curve3_id>

# Extrude curve along vector
python3 surfaces.py extrude <curve_id> --direction 0,0,10

# Revolve curve around axis
python3 surfaces.py revolve <curve_id> --axis-start 0,0,0 --axis-end 0,0,1 --angle 360

# Sweep curve along rail
python3 surfaces.py sweep <profile_id> <rail_id>

# Create planar surface from closed curve
python3 surfaces.py planar <closed_curve_id>

📁 Layers

python3 layers.py create "MyLayer" --color 255,100,100
python3 layers.py set "MyLayer"
python3 layers.py list
python3 layers.py delete "OldLayer"

🎨 Materials (PBR)

# Metal presets
python3 materials.py preset gold
python3 materials.py preset silver
python3 materials.py preset copper

# Custom PBR material
python3 materials.py pbr "Chrome" --color 200,200,210 --metallic 0.95 --roughness 0.02

# Assign material to layer
python3 materials.py assign "MyLayer" <material_id>

📷 Viewport & Screenshots

# Set standard view
python3 viewport.py view Perspective
python3 viewport.py view Top

# Zoom to fit all
python3 viewport.py zoom

# Zoom to selection
python3 viewport.py zoom --selected

# Orbit camera
python3 viewport.py orbit --yaw 45 --pitch 30

# Set camera position
python3 viewport.py camera --position 100,100,50 --target 0,0,0 --lens 35

# Capture screenshot (saves to linux_dir, returns linux_path)
python3 viewport.py screenshot --width 1920 --height 1080
python3 viewport.py screenshot --output myrender.png

# Render with materials
python3 viewport.py render --output render.png

Screenshots are saved directly to the Linux filesystem via WSL UNC path. The returned linux_path can be read directly.


💡 Render & Lighting

# Set render quality
python3 render.py settings --width 1920 --height 1080 --quality high
python3 render.py settings --background 50,50,50

# Add lights
python3 render.py light point --position 50,50,100 --intensity 1.5
python3 render.py light directional --direction -1,-1,-1
python3 render.py light spot --position 0,0,100 --target 0,0,0

# Render to file
python3 render.py render --output scene.png

📦 Files (Import/Export)

# Open 3DM file
python3 files.py open "/path/to/file.3dm"

# Save current document
python3 files.py save
python3 files.py save --path "/path/to/new.3dm"

# Export to various formats
python3 files.py export output.step
python3 files.py export output.obj --ids <id1> <id2>
python3 files.py export output.stl --format stl

# Import mesh
python3 files.py import model.obj

Supported Export Formats

STEP, IGES, OBJ, STL, DXF, DWG, 3DS, FBX, DAE


📦 Groups & Blocks

# Create group
python3 groups.py group <id1> <id2> --name "MyGroup"

# Ungroup
python3 groups.py ungroup --name "MyGroup"

# Create block definition
python3 groups.py block-create "MyBlock" <id1> <id2> --base 0,0,0

# Insert block instance
python3 groups.py block-insert "MyBlock" --position 10,0,0 --scale 2 --rotation 45

# Explode block
python3 groups.py block-explode <instance_id>

🌿 Grasshopper Player Automation

Run Grasshopper definitions with custom parameters directly from CLI.

# Show available parameters in a GH file
python3 grasshopper.py info "C:/path/to/definition.gh"

# Run with default parameters
python3 grasshopper.py run "C:/path/to/definition.gh"

# Run with custom parameters
python3 grasshopper.py run "C:/path/to/definition.gh" --Lichthoehe 2200 --Lichtbreite 1000

# Set insertion point
python3 grasshopper.py run "C:/path/to/definition.gh" --Point 100,200,0

Parameter Discovery

python3 grasshopper.py info "C:/path/to/definition.gh"
# Output shows: parameter name, default value, min/max range, type

How It Works

  1. info loads the GH file via Grasshopper SDK to extract parameter metadata
  2. run starts Rhino's GrasshopperPlayer via SendKeystrokes (non-blocking)
  3. Script monitors command prompts and sends parameter values
  4. Get Point prompts receive the --Point coordinate or default 0,0,0

Presets (YAML-based)

# List available presets
python3 grasshopper.py preset --list

# Run a preset
python3 grasshopper.py preset door_standard

# Override preset parameters
python3 grasshopper.py preset door_standard --Lichthoehe 2200

Presets are defined in config/presets.yaml, templates in config/templates.yaml.


🏗️ GH Definition Builder (NEW)

Programmatically create Grasshopper definitions with Python script components. The full pipeline: Generate Code → Build .gh → Deploy to Compute Platform → Solve via API

Build a Definition via RhinoClaw

# Build a .gh file with inputs + Python script
python3 ghscript.py build \
  --name "ParametricBox" \
  --script my_script.py \
  --inputs inputs.json \
  --output "C:/temp/gh_definitions/ParametricBox.gh"

Build + Deploy to Rhino Compute Platform

# Build .gh and deploy to ~/projects/rhino-compute-platform/definitions/
python3 ghscript.py deploy \
  --name "ParametricBox" \
  --script my_script.py \
  --inputs inputs.json

After deploy, the definition is immediately solvable:

POST http://localhost:8100/solve
{ "definition": "ParametricBox.gh", "inputs": { "Width": 200, "Height": 100 } }

Input Spec Format (inputs.json)

[
  { "name": "Width",  "type": "number",  "default": 200, "min": 10, "max": 1000 },
  { "name": "Height", "type": "number",  "default": 100, "min": 10, "max": 500 },
  { "name": "Count",  "type": "integer", "default": 5,   "min": 1,  "max": 20 },
  { "name": "Label",  "type": "string",  "default": "Part-A" },
  { "name": "Mirror", "type": "boolean", "default": false }
]

GHPython Script Template

The script receives inputs as variables matching the input names:

# Inputs: Width, Height (injected by Grasshopper)
# Output: Geometry (assigned to 'a' output)
import Rhino.Geometry as rg

plane = rg.Plane.WorldXY
box = rg.Box(plane, rg.Interval(-Width/2, Width/2), 
             rg.Interval(-Height/2, Height/2), 
             rg.Interval(0, Height))
Geometry = box.ToBrep()

Execute Python Directly in Rhino

# Quick test without building a GH definition
python3 ghscript.py exec --code "import Rhino; print(Rhino.RhinoApp.Version)"
python3 ghscript.py exec --file my_script.py

How It Works

  1. build_gh_definition command in RhinoClaw creates a GH document with:
    • Number Sliders / Boolean Toggles / Panels for each input
    • A Python 3 Script component with the provided code
    • Wired connections between inputs and script
  2. The document is saved as binary .gh file
  3. deploy copies to Compute Platform definitions/ and writes .meta.json
  4. /solve endpoint picks it up automatically

📜 RhinoScript Execution

# Execute inline code
python3 script_exec.py -c "import rhinoscriptsyntax as rs; rs.AddSphere([0,0,0], 10)"

# Execute script file
python3 script_exec.py -f ~/scripts/my_script.py

🔍 Log Monitoring

Check the Rhino log for debugging (requires Windows filesystem access / TOTP):

# View recent log entries (needs TOTP unlock for /mnt/c access)
tail -30 "/mnt/c/Users/YOUR_USERNAME/AppData/Local/Temp/rhinoclaw.log"

# Alternative: use rhino_client to query logs via TCP
python3 rhino_client.py get_logs

Example: Complete PBR Scene Workflow

# 1. Create layer with material
python3 layers.py create "Gold_Parts" --color 255,215,0
python3 materials.py preset gold
# → Note material_id

# 2. Assign material to layer
python3 materials.py assign "Gold_Parts" <material_id>
python3 layers.py set "Gold_Parts"

# 3. Create geometry
python3 geometry.py sphere --radius 5 --name "Gold_Ball"
python3 geometry.py box --width 10 --length 10 --height 2 --position 0,0,-3

# 4. Boolean difference (cut hole)
python3 geometry.py cylinder --radius 2 --height 5 --position 0,0,-3
python3 booleans.py difference <box_id> <cylinder_id>

# 5. Set camera and capture
python3 viewport.py camera --position 30,30,20 --target 0,0,0 --lens 35
python3 viewport.py screenshot --width 1920 --height 1080
# → Returns linux_path, read directly with Read tool

⚠️ Error Handling

The rhino_client.py provides custom exceptions for robust error handling:

ExceptionWhen
RhinoConnectionErrorCan't connect or connection lost
RhinoTimeoutErrorNo response within timeout
RhinoCommandErrorRhino returned an error
ValidationErrorInvalid parameters

Auto-retry: The client has a @with_retry decorator for automatic reconnection with exponential backoff (default: 3 retries).

Context Manager: Use with RhinoClient() as client: for automatic connect/disconnect.


🏗️ VisualARQ BIM Objects (OPTIONAL)

Control VisualARQ BIM objects (walls, doors, windows, columns, beams, etc.).

Note: VisualARQ is an optional add-on. All commands gracefully degrade if not installed - no crashes or errors.

Check Availability

# Check if VisualARQ is installed
python3 visualarq.py check

# Get available styles, levels, and buildings
python3 visualarq.py info

Walls

# Create a wall
python3 visualarq.py wall --style "Generic - 200mm" \
  --start 0,0,0 --end 10,0,0 --height 3.0 \
  --layer "Walls" --name "ExtWall_01"

# List available wall styles
python3 visualarq.py wall-styles

# Add a new wall style
python3 visualarq.py add-wall-style --name "Custom 300mm" --width 0.3

Doors & Windows

# Create a door (requires existing wall)
python3 visualarq.py door --style "Single Swing" \
  --wall-id <wall_guid> --position 0.5 \
  --width 0.9 --height 2.1 --name "MainEntry"

# Create a window
python3 visualarq.py window --style "Fixed" \
  --wall-id <wall_guid> --position 0.3 \
  --width 1.2 --height 1.5 --name "Window_01"

# List available styles
python3 visualarq.py door-styles
python3 visualarq.py window-styles

Position Parameter: 0.0 = start of wall, 1.0 = end of wall, 0.5 = middle

Structural Elements

# Create a column
python3 visualarq.py column --style "Rectangular" \
  --position 0,0,0 --height 3.0 --name "Col_A1"

# Create a beam
python3 visualarq.py beam --style "Rectangular" \
  --start 0,0,3 --end 5,0,3 --name "Beam_B1"

# Create a slab (requires boundary curves)
python3 visualarq.py slab --boundary <curve_id1>,<curve_id2> \
  --thickness 0.25 --name "Slab_01"

Levels & Buildings

# List all levels
python3 visualarq.py levels

# Add a new level
python3 visualarq.py add-level --name "OG1" --elevation 3.0

# Add a building
python3 visualarq.py add-building --name "Haus A"

Custom BIM Parameters

# Add a custom parameter to an object
python3 visualarq.py add-param --name "FireRating" --type text \
  --object-id <guid>

# Set parameter value
python3 visualarq.py set-param --name "FireRating" \
  --value "EI30" --object-id <guid>

# Get parameter value
python3 visualarq.py get-param --name "FireRating" --object-id <guid>

Parameter Types: text, number, integer, boolean, length

IFC Import/Export

# Export to IFC
python3 visualarq.py ifc-export --path "output.ifc" --version "IFC4"

# Import IFC file
python3 visualarq.py ifc-import --path "model.ifc"

Supported IFC Versions: IFC2x3, IFC4, IFC4.3

Query VisualARQ Objects

# List all walls with properties
python3 visualarq.py list-walls

# List all doors with properties
python3 visualarq.py list-doors

# List all windows
python3 visualarq.py list-windows

# Overview of all VisualARQ objects by type
python3 visualarq.py list-objects

Example: Complete BIM Workflow

# 1. Check if VisualARQ is available
python3 visualarq.py check
# → {"available": true, "version": "detected"}

# 2. Create building structure
python3 visualarq.py add-building --name "Office Building"
python3 visualarq.py add-level --name "Ground Floor" --elevation 0.0
python3 visualarq.py add-level --name "First Floor" --elevation 3.5

# 3. Create walls
python3 visualarq.py wall --style "Generic - 200mm" \
  --start 0,0,0 --end 10,0,0 --height 3.0 --name "SouthWall"
# → Note wall_id for door/window insertion

# 4. Add openings
python3 visualarq.py door --style "Single Swing" \
  --wall-id <wall_id> --position 0.7 \
  --width 0.9 --height 2.1 --name "MainEntry"

python3 visualarq.py window --style "Fixed" \
  --wall-id <wall_id> --position 0.3 \
  --width 1.5 --height 1.2 --name "SouthWindow"

# 5. Add custom BIM data
python3 visualarq.py add-param --name "FireRating" --type text \
  --object-id <wall_id>
python3 visualarq.py set-param --name "FireRating" \
  --value "EI90" --object-id <wall_id>

# 6. Export to IFC
python3 visualarq.py ifc-export --path "office_building.ifc" --version "IFC4"

Troubleshooting

ProblemSolution
Connection refusedRun tcpstart in Rhino command line
TimeoutIncrease timeout in config.json (max 120s)
Boolean failedEnsure objects are closed solids (Breps)
Screenshot path issuesCheck windows_dir UNC path in config
Command not foundRebuild plugin after C# changes
Objects on wrong layerSet layer first with layers.py set "LayerName"
PBR material not visibleMaterials use RenderMaterials table (fixed in 0.1.3.7+)
Script timeoutUse --timeout 60 for large scripts
RhinoConnectionErrorAuto-retry is built in (3 attempts), check if plugin running
VisualARQ not availableInstall VisualARQ plugin or gracefully ignore VA commands

Comments

Loading comments...