New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@archxflow/bridge

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@archxflow/bridge

Connects the FreeCAD and Blender on an architect's machine to Agentic Arch in the cloud.

latest
npmnpm
Version
0.1.1
Version published
Weekly downloads
3
-57.14%
Maintainers
1
Weekly downloads
 
Created
Source

Agentic Arch bridge agent

Connects the FreeCAD and Blender already installed on an architect's machine to Agentic Arch running in the cloud, so the AI can build real geometry there instead of generating a picture of it.

Architect's machine                          Cloud (Cloud Run)
┌────────────────────────────┐              ┌──────────────────────────┐
│ FreeCAD GUI  ── XMLRPC :9875│             │ NestJS + Vertex (Gemini) │
│ Blender GUI  ── TCP    :9876│             │  BridgeGateway  (wss)    │
│         ▲                   │             │  device registry         │
│         │                   │   wss       │  job dispatch            │
│  archxflow-bridge run ──────────┼────────────►│  chat tool loop          │
│  (outbound only)            │  ticketed   │                          │
└────────────────────────────┘              └──────────────────────────┘

The agent dials out. Nothing listens on the architect's machine, so there is no port to forward, no firewall rule, and no inbound surface — which is also why this works from a laptop on hotel wifi.

Install and pair

Published as @archxflow/bridge. It needs Node 22 or newer and has no runtime dependencies of its own.

npm install -g @archxflow/bridge

In the web app, generate a pairing code, then on the machine with FreeCAD:

archxflow-bridge pair ABCD-EFGH --url https://your-cloud
archxflow-bridge run

Before it is published, build it from this repository instead — the commands are the same with node dist/index.js in place of archxflow-bridge:

cd agent
npm install    # typescript only; the agent itself has no runtime deps
npm run build  # compiles dist/ and copies cad/freecad/*.py into scripts/

pair swaps the code for a long-lived device token and stores it in the platform's own per-user config directory with 0600 permissions. The cloud keeps only a SHA-256 of it, so a leaked server database cannot be replayed.

Check what the agent can see at any time:

archxflow-bridge status

Approval — what runs without asking, and what does not

The cloud model can write arbitrary Python into FreeCAD and Blender. That is the point of the bridge, and it is also remote code execution on someone's workstation, so the two categories are treated differently:

freecad.build, freecad.sheets, freecad.presentation, blender.render, all the *.status/screenshot/scene readsRun unattended. The Python is the platform's own, bundled with this package. The cloud picks which script runs, never what is in it.
freecad.exec, blender.execPrompt. The source is printed in full and someone on the machine answers y / a (allow this verb for the rest of the run) / N.
────────────────────────────────────────────────────────────────────────
  Agentic Arch wants to run Python inside FreeCAD
  Why: measure the clear width of the stair well
────────────────────────────────────────────────────────────────────────
  │ import FreeCAD
  │ doc = FreeCAD.ActiveDocument
  │ print(doc.getObject('Stairwell').Shape.BoundBox)
────────────────────────────────────────────────────────────────────────
  [y] run once   [a] always allow this verb   [N] decline :

--bypass turns the prompt off:

archxflow-bridge run --bypass

Do that only where you trust the whole pipeline into the model. A prompt injection in an uploaded bye-law PDF or a survey drawing reaches the same tool the architect does, and with --bypass there is nothing between it and this machine. The agent announces the mode at startup and reports it to the cloud, so the web app can show which machines are unattended.

With no TTY attached (a service, a container) and no --bypass, code jobs are declined rather than silently run.

GUI or headless

Each driver prefers a running GUI and falls back to a headless process:

GUI (:9875 / :9876)Headless
freecad.buildyesFreeCADCmd
freecad.sheetsrequired— TechDraw builds view geometry on the Qt event loop
freecad.presentationrequired— viewport captures need a window
blender.renderyesblender --background

A job that needs a GUI fails with that reason rather than quietly producing an empty sheet.

Where files go

Jobs run in the agent's work directory, laid out the way build.py expects (it derives the project root from its own path):

<config dir>/work/cad/freecad/*.py      ← bundled from the repo at build time
<config dir>/work/cad/out/              ← model.json in, everything else out

Whatever a job produces is uploaded to the cloud and attached to the job, up to 64 MB per file and 256 MB per job. Anything larger is left on disk and reported.

Configuration

agent.json in the config directory, or flags, or environment:

--url, AGENTIC_ARCH_URLCloud base URL
AGENTIC_ARCH_TOKENDevice token, for a container that cannot pair interactively
--bypassRun code without prompting
--workDirWhere builds happen
--freecadCmd, FREECAD_CMDFreeCADCmd path, if it is somewhere unusual
--blenderCmd, BLENDER_CMDBlender path

Config directory: %APPDATA%\AgenticArch · ~/Library/Application Support/AgenticArch · $XDG_CONFIG_HOME/agentic-arch.

Revoking a machine

Revoke in the web app (DELETE /api/bridge/devices/:id). The record is tombstoned and any live socket is closed immediately, so a stolen laptop stops being able to run jobs the moment the button is pressed, not at the end of some token lifetime. archxflow-bridge unpair only clears the local copy — it does not tell the cloud to stop trusting it.

Protocol

src/protocol.ts is a verbatim copy of backend/src/bridge/bridge.protocol.ts and is refreshed by npm run build. It is type-only and dependency-free so the same file compiles on both sides.

The agent has no runtime dependencies — Node 22's native WebSocket, fetch and FormData, a hand-rolled XML-RPC client for FreeCAD (about forty lines, because the addon accepts six methods), and a raw TCP client for Blender's unframed JSON.

Pairing from the web app

Settings → Machines in the studio (/settings/machines) does the cloud half of this: it mints the pairing code, shows the three commands with the code and your cloud URL already filled in, and lists every paired machine with what is running on it. The panel closes itself the moment a machine pairs against the code, so there is no "did that work?" step.

The same page is where a machine is revoked. Revoking closes its live socket immediately — archxflow-bridge unpair only clears the local copy of the token and does not tell the cloud to stop trusting it.

Nothing is held back

Beyond the named build verbs, the bridge passes the whole surface of both applications through, so the cloud can do anything the architect's own MCP client can:

VerbReaches
agent.capabilitiesWhat both apps expose right now, with a read-only flag per method
freecad.rpcAny FreeCAD RPC method — create_object, edit_object, delete_object, insert_part_from_library, run_fem_analysis, execute_code, and the rest
blender.commandAny Blender addon command, including the optional Polyhaven, Sketchfab, PolyPizza and Hyper3D/Hunyuan handlers when that machine has them enabled

Blender's list is discovered, not hardcoded: agent.capabilities asks the addon itself, so handlers that are switched off do not appear and a new addon release does not need an agent release.

FreeCAD arguments are encoded as real XML-RPC values, so structs and arrays round-trip — create_object(doc, {Name, Type, Properties: {...}}) works, which is what makes the passthrough genuinely complete rather than string-only.

Approval is per-call, not per-verb

Exposing everything does not mean asking for nothing. Because one verb now covers both list_documents and execute_code, the gate looks at the payload:

Reads — get_*, search_*, poll_*, list_documents, pingrun unattended
Everything else — creating or editing objects, deleting, FEM runs, asset downloads and generation, execute_codeprompts, showing the method name and its arguments

"Always allow" is scoped to the method, not the verb — approving freecad.rpc:get_objects for the session does not silently approve freecad.rpc:execute_code. --bypass still skips the lot.

Who may call the bridge

Every bridge route is guarded, and the guard defaults to the strictest class — a route added later without a decorator refuses rather than inheriting an open door.

Route classRoutesCredential
agentPOST /bridge/session, POST /bridge/artifacts/:jobIdThe device token. An agent has no operator credential and never needs one.
pairingPOST /bridge/pairNone — the code is the credential: single use, ten minutes, ~2.8e11 combinations. Rate-limited to 10 failures per address per 10 minutes.
operatoreverything else — pairing-codes, devices, jobs, artifact downloadSee below.

The WebSocket upgrade is not a route: it is authenticated by the single-use ticket, which is itself minted only from a valid device token.

Configuring the operator class

There are no user accounts yet, so this cannot check who — only that the caller got past something. It fails closed: an unconfigured production deployment refuses, rather than serving POST /bridge/pairing-codes to the open internet. Pick one:

BRIDGE_ADMIN_TOKEN=…Callers send it as Authorization: Bearer ….
BRIDGE_TRUSTED_PROXY=trueAccept a request carrying an IAP identity header. Only set this when the service cannot be reached except through IAP — the header is trivially forged by anyone who can hit the container directly, so this is opt-in rather than assumed.
BRIDGE_ALLOW_UNAUTHENTICATED=trueNo check at all. Logs a warning at startup. For a private network you control.

In development (NODE_ENV is not production) loopback is allowed, so the local two-server setup keeps working with nothing configured. That exemption is never granted in production.

A note on IAP and the agent

If IAP fronts the whole service, it rejects the agent's Authorization: Bearer aab_… at the edge, before any of this runs — the agent would never connect. Reaching a deployment like that needs the agent paths exposed outside IAP (a second service, or an IAP path exclusion), which is infrastructure rather than code.

What ships in the package

dist/       the compiled agent — one file, no dependencies
scripts/    build.py, sheets.py, presentation.py, copied from cad/freecad at build time

scripts/ is not optional. jobs.ts loads it from ../scripts at runtime, so a package built without it installs cleanly and then fails every build job with "build.py is not bundled with this agent". Both directories are listed in files; check with npm pack --dry-run before publishing.

Neither directory is committed — npm run build regenerates both, and prepack runs it so npm publish cannot ship a stale one.

Keywords

freecad

FAQs

Package last updated on 10 Sep 2026

Related posts