h hopperCode

Architecture

hoppercode is a Pi extension that talks to a Grasshopper plugin in Rhino over three ZeroMQ channels.

At a glance

data flow
Pi agent  →  hopper-pi (Node/TS)  →  ZMQ  →  Hopper Code Backend (Grasshopper in Rhino)

The agent lives in Pi (Node/TypeScript). It sends commands and queries to a small C# Grasshopper plugin (rhino-zmq-poc.gha) that runs inside Rhino and marshals work onto Rhino’s UI thread via InvokeOnUiThread. Edits within an agent turn are wrapped in a single RhinoAgentTransaction so they undo as one step.

ZeroMQ channels

PortPatternPurpose
5555PUB/SUBEvents: job status, canvas XML snapshots
5556PUSH/PULLCommands: edits, scripts, widgets
5557REQ/REPQueries: canvas state, component search, errors

Connection discovery

The backend tries the legacy 55555557 ports first. If any are already in use, it automatically binds a free loopback port triplet and writes the live endpoints — plus a local connection token — to a user-local connection profile:

OSProfile path
Windows%APPDATA%\hopper-pi\connection.json
macOS~/Library/Application Support/hopper-pi/connection.json
Linux~/.local/share/hopper-pi/connection.json (or $XDG_DATA_HOME/hopper-pi/)

The token is generated once and reused across backend/frontend restarts, so normal restarts do not require re-pairing. Override discovery with HOPPER_CONNECTION_PROFILE, or set endpoints manually with GH_ZMQ_PUB, GH_ZMQ_PUSH, and GH_ZMQ_REQ. If you point at a token-protected backend manually, also set GH_ZMQ_TOKEN.

Repo layout

PathRole
src/Pi extension: ZMQ client, tools, XML parsing
grasshopper-plugin/C# Grasshopper plugin (rhino-zmq-poc.gha)
scripts/install-grasshopper-plugin.mjsBuild + install plugin to Libraries
mds/Skills, prompts, and reference docs for the agent