·
Last changedVersion:
This version passed the hardening gate. Hardening updated the skill content and independently checked the resulting changes. Classified findings before hardening: 1. Classified findings closed: 0. Classified findings remaining: 1. Unclassified scanner findings remaining: 0. Review findings closed: 12. Review findings remaining: 8.
1
1
Expand | File | Group | Subtype | Severity | Status |
|---|---|---|---|---|---|
references/macros-and-loading.md | Tool & MCP Manipulation | MCP configuration abuse | Low | Open |
1 finding
Write production-quality scripts for Rhinoceros 3D. Covers the three scripting surfaces (RhinoScript/VBScript, RhinoPython, direct RhinoCommon .NET) and the Rhino 8+ Script Editor.
.rvb, .vbs, or .py Rhino scriptrhinoscriptsyntax, scriptcontext, RhinoCommon, Rhino.Geometry, RhinoDoc, or the Script EditorPick the surface based on the task, not preference. Recommend Python by default for new work.
| Surface | When to choose | File ext |
|---|---|---|
RhinoPython ( | Default for new scripts. Best ecosystem, readable, full RhinoCommon access. |
|
RhinoScript (VBScript) | Maintaining legacy |
|
RhinoCommon (C#/.NET) via Script Editor | Performance-critical loops, complex geometry, leveraging .NET libraries. |
|
Command macro | Pure sequence of existing Rhino commands; no logic. | toolbar/alias |
A macro is not a script — it is a string of command-line input (e.g. ! _-Line 0,0,0 10,0,0 _Enter). Use a script the moment you need a variable, loop, or conditional.
_ScriptEditor (Rhino 8) or _EditPythonScript / _EditScript (older)._-RunPythonScript or _LoadScript + _RunScript.rs.EnableRedraw(False).undo = doc.BeginUndoRecord("My Op") … doc.EndUndoRecord(undo).rhinoscriptsyntax overhead).doc.Views.Redraw() in a try/finally so a crash never leaves the viewport frozen..py / .rvb in a shared location with restricted write access or under version control. Recipients should review a script before running it, because scripts run with full access to Rhino and the user account.Options → Files → Search paths so Rhino can find it by name. Add only trusted folders that others cannot write to; a file with the same name in any search path folder could run instead, so prefer a full path in toolbar buttons and aliases.! _-RunPythonScript "MyScript.py"! _-LoadScript "MyScript.rvb" _-RunScript MySubName! cancels any running command; - runs the command in script (no-dialog) mode..rvb/.py in a search path.Tools → Options → RhinoScript (or Python) → add to Startup list. The file executes once per session.rhinoscriptsyntax returns GUIDs, RhinoCommon returns objects. Mixing them is fine, but doc.Objects.Find(guid) is the bridge from a rs.* id to a RhinoObject.(x, y, z) tuples or Rhino.Geometry.Point3d; VBScript uses 3-element Array(x, y, z). Never pass a Python list to a VBScript helper through COM.Option Explicit is off by default in VBScript. Typos silently create new variables. Always add Option Explicit at the top of .rvb files.Dims inside a Sub are hoisted to the top of the procedure. Loop counters leak.Nothing, Empty, and Null are different in VBScript. Use IsNull for Rhino.GetObject failure, IsEmpty for uninitialized Variant, Is Nothing for object refs.Call Foo(a, b) and Foo a, b are valid; Foo(a, b) (no Call, with parens) is not a call to a Sub — it’s a syntax error for multi-arg subs and a forced ByVal for single-arg.doc.ModelAbsoluteTolerance rather than hardcoding 0.001; users work in mm, m, inches, etc.Rhino.RhinoApp.EscapeKeyPressed so the user can cancel. Otherwise Rhino appears frozen.System.Guid. rhinoscriptsyntax accepts either; RhinoCommon wants System.Guid. Convert with System.Guid(str_id) if needed.doc.Views.Redraw() inside a tight loop. Toggle redraw once outside the loop..rvb is just .vbs renamed with a Rhino-specific extension so Rhino’s LoadScript recognizes it. Same VBScript engine.Rhino.RhinoApp.IsHeadless may not exist on older Rhino 8 builds. Use getattr(Rhino.RhinoApp, "IsHeadless", None) and check for None before using. Fall back to a heuristic (e.g. sc.doc.Views.Count == 0) or assume GUI present.RhinoMath is at Rhino.RhinoMath, not Rhino.DocObjects.RhinoMath. Accessing Rhino.DocObjects.RhinoMath raises AttributeError.doc.Objects.AddBrep() returns System.Guid.Empty on failure. In Rhino 8 CPython the System namespace may not be directly importable; check the return value as a string: str(obj_id) == "00000000-0000-0000-0000-000000000000".rhinoscriptsyntax has no type stubs. Static analysers (Pylance/Pyright) flag import rhinoscriptsyntax as rs as unresolvable. Suppress with # type: ignore on the import line; the module is always available at Rhino runtime.random.py, math.py, os.py). IronPython 2.7 (_-RunPythonScript) resolves the script directory before stdlib, so any import random inside the stdlib (e.g. tempfile imports random internally) will find your file instead and fail with Cannot import name <X>. CPython 3 (rhinocode) is unaffected because it resolves stdlib first. Rename the script or avoid importing modules that pull in the shadowed name. For the same reason, keep script folders writable only by you; any file there named like a standard library module will be imported and run._-RunPythonScript (IronPython 2.7). rhinocode script uses CPython 3 (UTF-8 by default) so the same file works there, making the failure non-obvious. IronPython 2.7 raises SyntaxError: Non-ASCII character '\xe2' at the first offending byte. The most common culprit is the em dash (-- auto-converted to -- by many editors). Add # -*- coding: utf-8 -*- as line 1 of every script that must run under both runtimes, and replace typographic characters with ASCII equivalents: em dash --, arrow ->, multiplication x.| Symptom | Fix |
|---|---|
| The user pressed Escape, or your |
“Unable to find script” when running by name | The folder isn’t in |
VBScript | You passed a 2-element array. Rhino requires 3-element |
Python | You’re running CPython outside Rhino. RhinoCommon is only available in Rhino’s embedded Python (or via |
Created geometry doesn’t appear | You forgot |
Undo undoes only the last object of a batch | Wrap the batch in |
Script works alone but fails as a startup script | Startup runs before any document is open — return early or skip document-dependent work when |
| The macro string is malformed. Prefix with |
| Property added in a later Rhino 8 build. Use |
| rhinocode concatenates extra tokens onto the file URI. Pass data via a temp file or a Rhino dialog instead. Use a uniquely named file in a folder only you can write to, check its contents before use, delete it afterwards, and prefer a dialog for sensitive input. See |
| Script filename shadows a stdlib module (e.g. |
| IronPython 2.7 ( |
rs.* functions by category.LoadScript / RunScript, search paths.Get started with chainctlchainctl skill install public/github/rhino3d-scripts:latest
Bring Chainguard's hardening pipeline to your first-party skills — custom rulesets, automated remediation, full audit trail.
skills.cgr.dev/public/github.com/github/skills/rhino3d-scripts:latest
MIT
HARDENING.md
LICENSE
SKILL.md
references/macros-and-loading.md
references/rhinocommon-map.md
references/rhinoscriptsyntax-cheatsheet.md
references/vbscript-quirks.md