solidworks-bridge
Public Made by Adomby adom
Install?
adom-wiki pkg install adom/solidworks-bridge
Latest: v0.3.3, published
Download for your machine · v0.3.3?
v0.3.3 — no silent empties, retry-on-reject, add_component identity fix
Contents
README
markdownSOLIDWORKS bridge (swx)
Say swx to the AI to reach this bridge. It drives the SOLIDWORKS desktop app on Windows over its COM API: streamlined file management, BOM generation from assemblies, and first-line design analysis — all from any Adom container, with SOLIDWORKS staying quietly in the background.
One native binary. No Python, no PowerShell, no interpreter to provision:
ab spawns swx-bridge.exe directly (spawn.kind: "exe") and it is serving in
about ten milliseconds.
What it does — 61 verbs
| Area | Verbs |
|---|---|
| Create & open | swx_new_document (part/assembly/drawing from the stock template), swx_open, swx_import (STEP/IGES/Parasolid/STL), swx_save, swx_save_as, swx_close_doc, swx_find_files, swx_docs |
| Model | swx_run_script — a typed modelling DSL: new_part, sketch_rect, sketch_circle, extrude, cut, set_material, set_prop, save_as, rebuild, zoom_fit. Everything in millimetres. |
| Macros | swx_run_macro — ISldWorks::RunMacro2 on a .swp/.swb/.dll. Arbitrary code, so it needs the write opt-in every time. Scaffolding: not yet run live. |
| Export | swx_export plus per-format aliases swx_export_step/iges/stl/3mf/glb/sat/parasolid/pdf/dxf/dwg, swx_pack_and_go |
| Read the design back | swx_design_info, swx_inspect_bodies (geometry in mm), swx_get_parameters, swx_set_parameter, swx_mass_properties, swx_bom, swx_interference, swx_rebuild_check, swx_document_info |
| Metadata | swx_props_get, swx_props_set (custom properties, file- or configuration-scope) |
| App & documents | swx_get_app_state, swx_state, swx_status, swx_readiness, swx_progress, swx_start, swx_stop, swx_kill, swx_activate_document, swx_close_all_documents, swx_reset_workspace, swx_show_part/_assembly/_drawing |
| Windows & etiquette | swx_window_info, swx_dismiss_blocking_dialogs, swx_close_window, swx_check_recovery, swx_screenshot, swx_set_driving_badge, swx_action_ledger, swx_verb_times |
| Preferences & cloud | swx_get_preferences, swx_set_preference, swx_cloud_status |
| Bridge | swx_describe, swx_com_eval, swx_uninstall |
Verb names and arg names deliberately mirror the Adom Fusion 360 bridge
(outputPath, filePath, name, parameters, bodies, current,
applied, stages, wouldPrompt) so an AI that already knows fusion_* can
drive swx_* with nothing new to learn.
docs/FUSION-PARITY-REPORT.md covers all 132
Fusion verbs with a verdict, and is where the divergences are argued.
Two things to know before you drive it
SOLIDWORKS Connected is launched through the Platform's own shortcut. On
the 3DEXPERIENCE editions (including Design Professional for Makers),
CoCreateInstance spawns a process that refuses with "SOLIDWORKS Design must
be launched from the 3DEXPERIENCE Platform" and never attaches — verified
live, and for two rounds this bridge concluded from that the edition could not
be started at all. That was a conclusion about the wrong experiment. The
Start-Menu shortcut the Platform installs does not run sldworks.exe; it runs
CATSTART.exe -run "SWXDesktopLauncher.exe"
-object "--AppName=\"SWXCSWK_AP\" -tenant=<TENANT> -monoapp
-3DRegistryURL=https://<region>-makers-registry.3dexperience.3ds.com"
-nowindow
so the refusal was ours, for bypassing the launcher chain. swx_start now
invokes that shortcut — the sanctioned artefact, carrying the user's own tenant,
with nothing reverse-engineered and no argument invented — then polls for the
COM server. A cold start runs 1-3 minutes, so it answers
started:true, stillLaunching:true while the application comes up rather than
holding the request. Classic desktop installs still attach directly over COM.
errorCode:"host_app_launch_blocked" now means only that no shortcut could be
found (SWX_SOLIDWORKS_SHORTCUT points the bridge at one).
Exports are copies; save-as is a rename. swx_export* uses SaveAs3 in
Silent|Copy mode, so the open document keeps its identity (v0.2 did not, and
silently renamed it). swx_save_as is the deliberate rename; copy:true makes
it a copy. And because SaveAs3 picks the format from the DESTINATION
EXTENSION rather than the format argument, that is where the format rules are
enforced — swx_export_step {"outputPath":"x.wrl"} is refused.
Writes are DENY-BY-DEFAULT. These verbs pass through one choke point
(src/writes.rs), which refuses unless both: the document is one this
bridge created in this SOLIDWORKS session, and the destination path does not
already exist —
swx_save · swx_save_as · swx_export and its ten format aliases ·
swx_bom {format:"csv"} · swx_pack_and_go · swx_close_doc ·
swx_props_set · swx_set_parameter · swx_set_preference ·
swx_run_script · swx_rebuild_check (it calls ForceRebuild3) ·
swx_stop and swx_close_all_documents (which end the user's session, and are
gated unconditionally) · swx_run_macro (always gated: a macro is a VBA
project with the whole API in scope, and nothing about the call predicts what it
will touch).
The gate opens BOTH ways. When the user has opted in, in full, the bridge does the thing — it does not refuse anyway. The server and the com host check the identical chain independently, so a partial chain is refused twice and a complete one is honoured by both.
Anything refused returns errorCode:"user_writes_disabled",
"destination_exists" or "not_bridge_document". Exporting from any
document to a path that does not exist always works — that is the normal way
to get data out, and it needs no permission.
The only way past it is a deliberate opt-in that a caller cannot grant itself:
the bridge process must be started with SWX_ALLOW_USER_WRITES=1 and the
call must carry allowUserWrites:true, confirm:true and a reason. Every
granted exception is recorded in swx_action_ledger. swx_status and
swx_describe report userWrites: "disabled"|"enabled" so a caller knows the
posture before it plans anything.
The same rule covers ending or disturbing the user's session: swx_stop,
swx_kill, swx_close_all_documents, and closing ANY dialog —
swx_dismiss_blocking_dialogs {close:true} and swx_close_window alike,
including dialogs the bridge itself raised. swx_close_window additionally
refuses an application frame outright (closing one quits SOLIDWORKS, which is
swx_stop's job) and refuses a dialog that asks about the user's own work
(Save changes?, Document Recovery, licence) at any posture. It also covers
swx_open {readOnly:false}, which takes a write lock on the user's file and
converts-and-dirties an older-version document in memory.
For everything that reaches SOLIDWORKS, the com host enforces the same two rules independently, on its dispatch loop rather than per command: it keeps its own record of the documents it created (stamped with the SOLIDWORKS session, so a crash or a restart invalidates it), reads the opt-in from its own environment, and refuses any command not on its no-side-effects list. A command added tomorrow is therefore deny-by-default.
Where there is only one veto, and why: swx_kill, swx_close_window,
swx_dismiss_blocking_dialogs and swx_screenshot go out through ab rather
than the com host, so the host's veto is not in their path — the server-side
choke point is the only check they have. That is worth knowing when reading the
rest of this section. swx_screenshot captures BY HANDLE (the one COM reports,
or an hwnd swx_window_info attributes to SOLIDWORKS); it will not take a
picture of an arbitrary window on the desktop.
This posture is a response to five consecutive rounds of adversarial review, in each of which the bridge turned out to be able to write to the user's data through a route whose guard had been forgotten. Gating routes failed five times; denying by default at one choke point removes the class.
Architecture
ab (Adom Bridge) ── HTTP /command ──> swx-bridge.exe (server mode)
│ JSON-lines over stdio
└─> swx-bridge.exe --com-host
(child process holding the live
SldWorks.Application COM object)
- One exe, two modes. The server spawns the com host from its own
current_exe(), so there is exactly one file to ship and one image name for ab to stop (killImageName: "swx-bridge.exe"covers both processes). - The COM object lives in a CHILD PROCESS, not a thread. A wedged COM call
— SOLIDWORKS parked on a modal dialog, a rebuild that never returns — cannot
be killed as a thread. It can be killed as a process. The server owns that
lifecycle: lazy spawn, one request in flight, per-request timeout, kill and
respawn after a crash or hang, and the child's stderr tail surfaced in the
failing verb's
detail. A child that dies between requests is replaced transparently, so the next verb works. - The child is persistent: it attaches to (or launches) SOLIDWORKS once and
keeps the COM object, so verbs don't pay a per-call attach. It is initialized
as an STA and holds the apartment for its whole life. On Windows it is spawned
with
CREATE_NO_WINDOW— no console ever blips on the user's desktop — and it exits on its own when its parent goes away (stdin EOF), so nothing is left holding a COM object. - Late-bound IDispatch (
GetIDsOfNames+Invoke), like every SOLIDWORKS macro: it works against whichever version is installed, with no interop assemblies to match. - Mock mode (
SWX_MOCK=1, automatic on non-Windows) swaps the COM backend for an in-memory fake behind the sameBackendtrait — same protocol, same response shapes — so the whole verb surface is testable with no SOLIDWORKS and no Windows.
Host app status
SOLIDWORKS is a detect-only host app (ab tier-2): Dassault publishes no
silent installer — desktop trial serials come from a reseller, and the Makers
edition comes from the 3DEXPERIENCE Platform store — so the bridge reports
absence with errorCode:"host_app_not_installed" and a next-steps _hint
instead of ever attempting an install. The verbs that need no COM
(swx_status, swx_readiness, swx_describe, swx_progress,
swx_find_files, swx_action_ledger, swx_verb_times, swx_uninstall) work
regardless, so "what CAD files do I have?" is answerable today.
Export formats, verified rather than assumed
Every format below was exported from a real solid on a live SOLIDWORKS Design
Professional for Makers 2026 and the bytes on disk were checked — with the
caveat that those probes used SaveAs3 with Silent ALONE, which is how the
rename bug was found. The shipped export path uses Silent|Copy and has never
run; whether Copy is valid for PDF/PNG/JPG/TIF is unknown. Read the table as
"SOLIDWORKS can write this format", not "the bridge's export path is proven":
| Works from a part | Refused for a part (code 256) | Blocked by this bridge |
|---|---|---|
| STEP, STP, IGES, STL, X_T, X_B, SAT, 3MF, GLB, PLY, AMF, 3DXML, PNG, JPG, TIF, XAML, PDF | OBJ, DXF, DWG, U3D (DXF/DWG are drawing formats) | VRML (.wrl) |
VRML is refused outright with errorCode:"format_blocked": it raises a modal
option sheet that no unattended caller can answer, and on the live install it
hung the COM call until the watchdog killed the host.
Development
cargo build # native (mock mode: no SOLIDWORKS needed)
cargo test # unit + HTTP e2e + protocol e2e
cargo build --release --target x86_64-pc-windows-gnu # the shipped swx-bridge.exe
# run it by hand and poke it
SWX_MOCK=1 cargo run -- --port 24695
curl -s localhost:24695/status | jq
curl -s localhost:24695/command -d '{"command":"swx_describe","args":{}}' | jq
The suite is built so it cannot lie:
- No test asserts by reading source. Every check drives the real compiled
binary (
CARGO_BIN_EXE_swx-bridge) over HTTP or over the stdio protocol. - A verb-coverage gate compares the verbs actually CALLED during the suite
against
bridge.json, in both directions, and againstswx_describe. A new verb shipped without a test turns the suite red. - Response invariants on every call: 200, parses as JSON, boolean
success; malformed bodies get a clean 400, never a 500. - Effects, not existence: exports are read back off disk, the BOM CSV is
parsed and its columns checked,
find_filesruns against real fixture files. - Protocol e2e: the real server driving the real com-host child, including
crash recovery (kill the child, the next verb still works), junk on the
child's stdout, orphan cleanup, and a slow verb that must not block
swx_progress.
Everything the bridge writes goes under one root
(%LOCALAPPDATA%\Adom Bridge\bridges-cache\solidworks\, or SWX_SCRATCH_DIR
for tests), pruned at 48h / 300 files, and removed in full by swx_uninstall.
swx_com_eval {"expr":"$sw.RevisionNumber()","reason":"..."} is the maintainer
escape hatch: a late-bound call chain rooted at $sw or $doc, for proving out
a new capability against a real install before it becomes a verb.
Live validation
Mock-green is not green: v0.2 passed 49 mock tests while shipping four COM bugs, all of which the first live session found (see the parity report). Three tools close that gap:
python3 tools/swx-live.py <verb> '<json>' [timeoutSec] # one verb on the desktop
python3 tools/swx-batch.py calls.json # many verbs in ONE round trip
python3 tools/live-smoke.py # the full live suite
live-smoke.py creates its own scratch part, builds a real 50×30×20 mm solid,
reads the geometry back, drives a dimension, exports eight formats, checks the
bytes on disk, and then asserts SOLIDWORKS is left with exactly the
documents it started with. It never opens, saves or closes a document it did
not create, and it never launches or stops SOLIDWORKS.
Roadmap
- v0.1: full verb surface in Python + a PowerShell COM sidecar, mock-tested.
- v0.2: single Rust binary — 23 verbs, COM in a killable child process, crash recovery, a suite that drives the real binary.
- v0.3.1 (this): the launch answer — SOLIDWORKS Connected starts through the
Platform shortcut, so
host_app_launch_blockednow means only "no shortcut found";swx_run_macroscaffolding; and the write opt-in made openable on every path it guards (three live-proven cases where the human authorized an action in full and the bridge refused anyway — an escape hatch nobody can open is not a safety property). - v0.3: 60 verbs at Fusion-360-bridge parity — document creation, a modelling DSL, geometry read-back, parameters, per-format exports, window and dialog etiquette, an action ledger and measured verb timings. First live shakedown against a real SOLIDWORKS; four v0.2 COM bugs diagnosed with live evidence and fixed on reasoning (the fixes themselves are unverified — see the parity report). Writes made deny-by-default after five rounds of review.
- v0.4 candidates: drawing (
.slddrw) BOM-table extraction and DXF/DWG/PDF from drawings, per-component mass properties for assemblies, configuration management, a live screen feed, and — the big one — 3DEXPERIENCE 3DSpace access, which needs its own OAuth story.