main
Drew Owens 0.3.3 source + crate build: BOM exported from the SOLIDWORKS assembly, build log §1–11, release script 477e64f 1mo ago

Fusion 360 bridge — complete fusion_* verb inventory

Source of truth: describe.py (_T table -> fusion_describe) in the fusion-bridge clone, cross-checked against bridge.json, VERBS.md and README_VERBS.md. Extracted mechanically from the _T tuples, so arg names, arg type strings and response key names below are verbatim from the bridge. Long type/summary strings are truncated with ...; names are never truncated.

132 catalog entries, 131 live verbs (1 entry, fusion_open_by_urn_note, is a doc-only pseudo-entry that _verbs() filters out via the name.endswith("_note") rule).

Column notes:

  • category = canonical semantic bucket (my grouping, for mirroring into swx_*).
  • Section headings = the literal section comments inside describe.py's _T table. Two of those sections have drifted: the "Catalog completion" and "Library SHOW verbs" sections were appended over time and now also carry plain CAD/manufacturing verbs (fusion_export_iges, fusion_export_dxf, ...). The category column is the reliable grouping.
  • timeout = timeoutSeconds; LR = longRunning (keeps working after ab's timeout — poll statusVerb).

Lifecycle (22)

verb category args (exact names + types + defaults) key response fields what it does timeout LR statusVerb
fusion_preflight_lbr library libraryPath: str (Windows .lbr path) success bool
preflight {ok, checks[], errors[]}
PRE-ANALYZE a .lbr: will Fusion open it? Offline and instant - no Fusion needed, nothing launched. 10 yes -
fusion_install_library_bundle library zipPath: str (staged bundle zip on THIS machine)
lbrPath: str (staged .lbr, STEP models beside it)
libraryName: optional str (default: file stem)
capture: optional bool (default true: bind + prove; false: place only)
installed bool
libraryPath str
partsTotal int
partsToBind int
unbound [{package, why}]
partMetadata {ok, summary, warnings[]}
fusion {installed, running, addinReady, status, message}
runId str
statusVerb fusion_prove_result
COMPOSITE, the Fusion twin of kicad_install_library_bundle (#68): ONE call takes a staged Cloud Library bundle (zip of .lbr + .step models, or a bare lbrPath with STEPs beside... 60 yes fusion_prove_result
fusion_create_library library parts: optional [{package, lbrPath, modelPath}]
libraryPath: optional str (shape A, or output path for B)
kicadSymbolPath: optional str
kicadFootprintPath: optional str
stepPath: optional str (required for proven)
pinMap: optional {pinName: padName}
name: optional str
started bool
statusVerb str
ONE-CALL library creation for web-control (one call = one consent). 30 yes fusion_prove_result
fusion_start lifecycle {} (none) success bool
addinReady bool
status str
Launch Fusion 360 (if needed) and wait for the AdomBridge add-in to be ready. 150 yes -
fusion_stop lifecycle skipCleanClose: optional bool success bool
output str
Gracefully STOP Fusion 360: close docs cleanly + WM_CLOSE, then wait. 60 - -
fusion_kill lifecycle skipCleanClose: optional bool success bool
output str
Force-KILL Fusion 360 (taskkill /F) - the desperate path for when fusion_stop cannot close it (stuck modal / wedged process). 30 - -
fusion_close_window lifecycle hwnd: required int (the dialog window) success bool Close a DIALOG window by hwnd (WM_CLOSE, like clicking X) - for dialogs without Cancel/Escape handling (e.g. Recovered Documents). 30 - -
fusion_get_app_state lifecycle {} (none) activeDocument str
activeWorkspace str
isElectronics bool
Current app state: running, active document, workspace, isElectronics. 20 - -
fusion_readiness lifecycle {} (none) installed bool
running bool
ready bool
hostApp str
bridgeVersion str
FAST readiness check (does NOT launch Fusion): is the Fusion host app installed + running + the bridge ready to drive? ab DETECTS Fusion (never installs it) via bridge.json 'detect', and... 15 - -
fusion_new_electronics_from_eagle electronics schPath: required str (Windows path to .sch)
brdPath: optional str (defaults to sibling .brd)
success bool
imported list
Import a legacy EAGLE .sch (+ paired .brd) into a NEW Fusion electronics design so the parts INSTANTIATE (schematic + populated board, lands in the PCB editor). 200 - -
fusion_notify_owner lifecycle title: optional str
body: required str
level: optional str info|warning|error
success bool
targets list
LAST-RESORT human escalation: toast the user's MAIN computer (fans out cross-ab to every peer on the relay, so it reaches them even when this bridge runs on an unattended VM). 20 - -
fusion_signin auth profile: optional str (chrome:/edge:)
auto: optional bool (do click+capture+reopen in one on-box call)
waitSec: optional int (server-side poll budget for the fresh URL, default 32)
stage str
done bool
signinWhere str
signinProfile str
signinProfileReason str
signinWrongBrowser str
signinAuthUrl str
signinOpenedVia str (extension|extension_free)
signinWall str|null (twofactor_email_code|credentials|protocol_handoff)
notifyDelivered bool
signinWallHint str|null
narrate str
SELF-DRIVING as of 1.9.32: launches Fusion if needed, clicks Sign In, opens the OAuth in the right profile, TYPES THE EMAIL and advances to the exact remaining wall... 120 yes fusion_signin
fusion_mcp_status mcp/prefs {} (none) enabled bool
serverInfo obj
toolCount int
tools [{name,description}]
Is Autodesk's Fusion MCP server up, and what does it expose? Autodesk + Anthropic ship a LOCAL MCP server at http://127.0.0.1:27182/mcp exposing Fusion's own text-to-CAD surface (read... 45 - fusion_mcp_status
fusion_mcp_enable mcp/prefs {} (none) enabled bool
alreadyOn bool
steps list
serverInfo obj
Turn Autodesk's Fusion MCP server ON by driving Fusion's Preferences dialog for the user. 180 yes fusion_mcp_status
fusion_mcp_tools mcp/prefs {} (none) count int
tools list
Full tool list from Autodesk's Fusion MCP server INCLUDING input schemas, so you can construct a valid fusion_mcp_call. 45 - fusion_mcp_status
fusion_mcp_call mcp/prefs tool: required str (from fusion_mcp_tools)
arguments: optional obj (per that tool's inputSchema)
timeout: optional int seconds, default 120
result obj
tool str
Call any tool on Autodesk's Fusion MCP server (fusion_mcp_read, fusion_mcp_update, fusion_mcp_execute, fusion_mcp_electronics_read). 150 yes fusion_mcp_status
fusion_mcp_resources mcp/prefs uri: optional str (omit to list) count int
resources [str]
result obj
List Autodesk MCP resources, or read one by uri. 60 - fusion_mcp_status
fusion_prefs_open mcp/prefs section: optional str (see knownSections in the response) hwnd int
shotId str
screenshot str
knownSections [str]
steps list
Open Fusion's Preferences dialog and optionally jump to a section, then hand back a SCREENSHOT + shotId you can click in. 120 yes fusion_get_preferences
fusion_prefs_close mcp/prefs save: optional bool, default true closed bool
saved bool
Apply+OK (save:true, the default) or Cancel Fusion's Preferences dialog. 60 - fusion_get_preferences
fusion_set_auto_update lifecycle enabled: optional bool (omit to read current value) autoUpdateFusion bool
narrate str
Turn AUTOMATIC Fusion updating on/off for this user. 30 yes fusion_readiness
fusion_signin_2fa auth code: required str (the 6 digits; non-digits are stripped)
hwnd: optional int (the 2FA window; auto-detected)
submitted bool
steps list
narrate str
Submit Autodesk's emailed 6-DIGIT verification code to finish a Fusion sign-in, typed IN THE BACKGROUND (UIA SetValue + Invoke - never steals the user's foreground or moves their cursor). 90 yes fusion_readiness
fusion_demo lifecycle query: optional str (design to demo; else picked from APS search)
stage: optional str ('skip_aps' to proceed without cloud search)
stage str
done bool
narrate str
screenshots [{label,path}]
steps [str]
apsSampleSearch [{name,project}]
FIRST-TIME-USER DEMO in one verb - the thing to run when someone new wants to SEE what this bridge does (HD's installer calls this). 240 yes fusion_demo

Cloud search & files (APS) (19)

verb category args (exact names + types + defaults) key response fields what it does timeout LR statusVerb
fusion_aps_status auth {} (none) configured bool
signedIn bool
neverCharge bool
APS state: configured, signed in, token live, never-charge meter. 20 - -
fusion_aps_set_client_id auth clientId: required str success bool Set the org's APS (PKCE) client id used for cloud search. 20 - -
fusion_aps_signin auth exe: optional str (browser binary to launch+remember)
profileDir: optional str (e.g. 'Default','Profile 2')
name: optional str
allowDefaultBrowser: optional bool
success bool
authUrl str
openedVia str
needsExtensionOpen bool
Open the Autodesk sign-in in the REMEMBERED browser+profile (not the OS default); a background listener captures the token. 30 - fusion_aps_status
fusion_aps_set_browser auth name: optional str
exe: str (browser binary) OR how:'extension'
profileDir: optional str
how: optional 'extension'|'launch'
success bool
browser {name,exe,profileDir}
Remember the browser+profile that authed to Autodesk so every later sign-in reuses it (power users have many browsers/profiles; the OS default is usually the wrong one). 10 - -
fusion_aps_get_browser auth {} (none) success bool
browser {name,exe,profileDir}|null
Show the remembered Autodesk sign-in browser (None until set). 10 - -
fusion_aps_forget_browser auth {} (none) success bool
cleared bool
Forget the remembered Autodesk sign-in browser (re-detect next time). 10 - -
fusion_aps_search cloud query: required str
limit: optional int (default 50)
hubId: optional str
projectId: optional str
count int
results [{name,id,projectName,lastModified}]
Server-indexed search across the whole team hub (seconds, not a 30-min folder walk). 60 - -
fusion_aps_open cloud query: required str
wait: optional bool
opening bool
match {name}
statusVerb str
Find a cloud design by name and open it in Fusion (any folder depth). 60 yes fusion_get_app_state
fusion_open_by_urn cloud urn: required str success bool
output str
Open a cloud ELECTRONICS DESIGN by URN. 240 yes fusion_get_app_state
fusion_aps_browse cloud hubId: optional str
projectId: optional str
folderId: optional str
items [{name,type,id}] Browse hubs/projects/folders without launching Fusion. 60 - -
fusion_aps_recent cloud limit: optional int (default 25) count int
results [...]
Most-recently-modified designs across the team hub, newest first. 60 - -
fusion_aps_file_info cloud query: str OR projectId+urn versionCount int
tip {...}
versions [...]
Version history + who/when/size for a file (tip + recent versions). 40 - -
fusion_aps_versions cloud query: str OR projectId+urn versionCount int
versions [...]
Full (uncapped) version history of a file. 40 - -
fusion_aps_download cloud query: str OR projectId+urn
saveDir: optional str
fileName: optional str
path str
bytes int
Download a cloud file to the local machine (no Fusion needed). 90 - -
fusion_aps_upload cloud projectId: required str
folderId: required str (NON-ROOT subfolder)
localPath: required str
fileName: optional str
itemUrn str
bytes int
Upload a local file as a NEW cloud file (free Data Management; needs data:write scope). 90 - -
fusion_aps_create_folder cloud projectId: required str
parentFolderId: required str
name: required str
folderId str Create a subfolder in a project (free; needs data:create scope). 50 - -
fusion_aps_get cloud path: required str status int
body obj
Raw authenticated GET against a free APS path (dev/verify helper). 40 - -
fusion_walk_cloud_tree cloud {} (none) disabled bool ⛔ DISABLED (returns an error): the in-app add-in walk took 30+ min and CRASHED Fusion (WinError 10054). 15 - -
fusion_search_cloud_files cloud query: required str disabled bool ⛔ DISABLED (returns an error): the in-app add-in search took 30+ min and CRASHED Fusion (WinError 10054). 15 - -

Electronics (26)

verb category args (exact names + types + defaults) key response fields what it does timeout LR statusVerb
fusion_show_schematic electronics capture: optional bool [set captureMaxWidth to shrink it - 320 keeps a /command body small,...] success bool
activeWorkspace str
productType str
Switch the OPEN electronics design to its SCHEMATIC view (the symmetric partner of fusion_show_2d_board / fusion_show_3d_board, via Fusion's SwitchSchDocCmd). 70 yes -
fusion_show_2d_board electronics capture: optional bool [set captureMaxWidth to shrink it - 320 keeps a /command body small,...] activeWorkspace str Switch the OPEN electronics design to its 2D PCB Editor (board layout) view. 70 yes -
fusion_show_3d_board electronics capture: optional bool [set captureMaxWidth to shrink it - 320 keeps a /command body small,...] activeWorkspace str
screenshots [...]
Switch the OPEN electronics design to its 3D PCB view (populated board). 70 yes -
fusion_open_by_urn_note doc-only (filtered out of fusion_describe) {} (none) - (see fusion_open_by_urn) 30 - -
fusion_board_info electronics {} (none) rawXml str Raw board geometry XML (copper/arcs/lines) for the open board. 60 - -
fusion_alerts introspect/etiquette sinceSec: optional float (default 300) alerts [{at,text}] Fusion's OWN alert toasts, read from its log. 30 - -
fusion_web_signin auth url: required str (e.g. https://library.io/)
sessionId: optional str (default autodesk-web)
provider: optional str google|password (default google)
username: optional str (for the Google account chooser)
success bool
errorCode str?
url str
steps [...]
Sign a pup browser window into an Autodesk WEB surface (library.io, the hub portal at .autodesk360.com, Autodesk Account) via Google SSO. 240 yes fusion_get_app_state
fusion_managed_library_create library name: optional str (defaults to the library's own name)
description: optional str
success bool
library str
alerts [...]
Create a NEW managed library on library.io FROM the library in front (which must already be saved in a Fusion Hub). 240 yes fusion_get_app_state
fusion_managed_library_link library name: optional str (exact library name from the picker; omit to list read-only)
onUpdatePrompt: optional str cancel|merge|replace (default cancel; replace OVERWRITES the local library)
success bool
listedOnly bool?
managedLibraries [{name,type,version,managedFolder,description}]
linkedTo str?
updatePrompt obj?
alerts [...]
Link the library IN FRONT to an existing managed library on library.io. 180 yes fusion_get_app_state
fusion_managed_library_unlink library {} (none) success bool
library str
alerts [...]
Unlink the library in front from its managed library on library.io. 180 yes fusion_get_app_state
fusion_managed_library_push library onConfirm: optional str create|cancel (default create) success bool
library str
confirmed obj
alerts [...]
Push a NEW VERSION of the library in front up to its linked managed library on library.io. 240 yes fusion_get_app_state
fusion_managed_library_pull library onUpdatePrompt: optional str merge|replace|cancel (default merge) success bool
library str
upToDate bool
updatePrompt obj?
alerts [...]
Pull the newest version FROM library.io into the linked library in front. 240 yes fusion_get_app_state
fusion_library_manager library tab: optional str hub|public|private (default private) success bool
tab str
hwnd int
libraries [str] (usually empty - see pitfall)
tableReadable bool
Open Fusion's Library Manager and switch to one of its three tabs. 240 yes fusion_get_app_state
fusion_open_lbr library filePath: required str (.lbr WINDOWS path C:/...; stage from container first)
symbolName: optional str
verify: optional bool
success bool
postOpenScreenshot {savedTo}
Import an EAGLE .lbr library into Fusion's Electronics LIBRARY editor (Content Manager / Electronics Library workspace), not a PCB design. 50 - -
fusion_attach_3d_package library filePath: required str (.lbr WINDOWS path C:/...)
modelPath: required str (.step WINDOWS path C:/...)
packageName: optional str
success bool
savePending bool
data {steps}
_hint the Save-dialog click + verify steps
LOW-LEVEL primitive: attaches ONE model to ONE package. 240 yes fusion_get_app_state
fusion_install_fusion lifecycle {} (none) success bool
installing bool
alreadyInstalled bool?
mode globalinstall|per-user
statusVerb str
Install Fusion 360 FOR the user - downloads Autodesk's official Client Downloader and streams the free trial silently, with NO shell_execute and NO ab approval gate (runs inside the... 90 yes fusion_get_app_state
fusion_generate_package library type: required str (EPG family, e.g. chip|soic|qfn|qfp|bga|sot23|dfn2|melf|ecap|crystal|header_straight)
params: optional dict (generator dims in MM by default, e.g. chip: {D,E,A,L,L1}; soic: {A,A1,b,D,E,E1,e,L,DPins};...)
unitsCm: optional bool (params already EPG-native cm)
etch: optional str (marking text on the chip top: MPN / '103'; multi-line with newline, e.g. MPN+variant)
etchStyle: optional str raised|engraved (default raised = thin WHITE positive extrude, silkscreen-style contrast;...)
etchDepthMm: optional float (marking height/depth, default 0.03)
etchHeightMm: optional float (text height; default auto-fit: top-5%-band face, 10% margin, width-aware)
outputStep: optional str (WINDOWS path; exports STEP incl. the marking)
success bool
bodies [{name,vol}]
etched str|null
stepPath str|null
manifest obj (settings+why+bboxes; also written as .manifest.json sidecar for...
manifestPath str|null
epgDir str
Generate an IPC-7351-compliant parametric 3D package via Fusion's BUILT-IN ElectronicsPackageGenerator (EPG) - ~50 package families... 120 yes fusion_get_app_state
fusion_make_3d_package library lbrPath: required str (.lbr WINDOWS path; its FIRST package's footprint is loaded)
modelPath: required str (.step WINDOWS path)
projectId: optional str (default MAIN-project)
folderId: optional str (default upload folder)
fileName: optional str
captureLabel: optional str (capture before/after)
orient: optional bool (default true)
success bool
wip_urn str
dims_mm [x,y,z]
f3d str
before str|null
after str|null
Create a RENDERING component 3D package (FOOTPRINT + chip, aligned) for ONE part, fully programmatically with ZERO GUI dialogs. 200 yes fusion_get_app_state
fusion_build_library_3d library lbrPath: required str (combined .lbr WINDOWS path to bind + open)
parts: required [{package, lbrPath (per-part footprint .lbr), modelPath (.step)}]
outLbrPath: optional str (default: overwrite lbrPath)
capture: optional bool (default true)
projectId: optional str
folderId: optional str
openWhenDone: optional bool (default true)
success bool
boundLbr str
partsBound int
partsTotal int
parts [{package,success,wip_urn,dims_mm,error}]
screenshots [{package,stage,path}]
opened bool
Build a RENDERING multi-part 3D library in ONE call - the whole programmatic pipeline. 1800 yes fusion_get_app_state
fusion_capture_library_views library packages: required [] (or 'package': single name)
views: optional subset of ['symbol','footprint','3d','component'] (default ALL FOUR, in that assembly order)
settle: optional float secs after each EDIT before capture (default 1.5; raise if a shot shows the PREVIOUS part)
success bool
captured [{package,view,path,ok}]
Capture the LIBRARY-EDITOR views EEs trust: the schematic SYMBOL (full pinout), the FOOTPRINT (pads + layer stack), and the COMPONENT/device view (Content Manager: symbol + the package... 300 yes fusion_get_app_state
fusion_cleanup_cloud_files cloud fileIds: required []
projectName: optional str (default active project)
folderPath: optional str (default root)
success bool
deletedCount int
failedCount int
failed [{fileId,error}]
PRECISELY delete a list of cloud files by lineage urn - SAFE cleanup of AI-created clutter. 1800 yes fusion_get_app_state
fusion_run_modeling_script documents script: required str (Python using adsk; globals: adsk, app, ui, design) result obj
documentName str
Run an adsk.fusion modeling script in the live session (sketches/extrudes/params). 180 yes -
fusion_assembly_bom documents maxSeconds: optional float (walk budget, default 20; the verb REFUSES fast with bom_walk_budget_exceeded + a...)
treatAsUnit: optional [str] name substrings counted as one unit (default ['with fasteners'])
exclude: optional [str] top-level name prefixes to skip
includePhysicalProperties: optional bool (adds volume_cm3/mass_kg per line)
outputPath: optional str (Windows CSV path)
success bool
design str
partCount int
totalInstances int
parts [{componentName, partNumber, description, material, quantity, bodies}]
Structured, kit-aware MECHANICAL bill of materials for the active Design assembly (the counterpart to the electronics-only fusion_export_bom). 120 - -
fusion_physical_properties documents names: optional [str] component names to measure (default all)
accuracy: optional low|medium|high|veryhigh (default low)
success bool
count int
properties {name: {volume_cm3, mass_kg, density, area_cm2, center_of_mass}}
Per-component physical properties (volume cm3, mass kg, density, area, center of mass) for the active design. 120 - -
fusion_set_preference mcp/prefs theme: optional str
invertScrollZoom: optional bool
orbitScheme: optional str
modelingOrientation: optional str
gestureNav: optional bool
cameraPivot: optional bool
lengthUnit: optional str
applied obj
current obj
Set Fusion appearance/navigation preferences in the LIVE session - applies immediately, NO restart. 30 yes -
fusion_get_preferences mcp/prefs {} (none) current obj Read current Fusion appearance/navigation preferences (theme, activeTheme, invertScrollZoom, orbitScheme, modelingOrientation, gestureNav, cameraPivot, lengthUnit) as friendly values -... 20 - -

CAD & 3D export (2)

verb category args (exact names + types + defaults) key response fields what it does timeout LR statusVerb
fusion_export_step export outputPath: required str format str
fileSizeKB int
Export the active design to STEP (needs the 3D view). 300 yes -
fusion_import_step export filePath: required str (WINDOWS path C:/...; stage from container first) success bool
documentName str
Import a STEP/.stp (or other native-importable) file into a NEW Fusion design via the native import API. 300 yes -

Catalog completion (late-described verbs) (15)

verb category args (exact names + types + defaults) key response fields what it does timeout LR statusVerb
fusion_open_cloud_file cloud fileName: required str
projectName: optional str (defaults to active project)
folderPath: optional str
success bool
documentName str
Open a CLOUD file by name (the front door to every design flow). 240 yes fusion_get_app_state
fusion_open_design documents filePath: required str (WINDOWS path) success bool Open a LOCAL design file (routes through the add-in import). 240 yes -
fusion_close_document documents name: optional str (default: active document)
save: optional bool default false
success bool
closed str
Close ONE document WITHOUT the modal save dialog (save:false discards silently - the automation-safe close). 60 - -
fusion_close_all_documents documents save: optional bool default false
closeUntitled: optional bool default false
force: optional bool default false
success bool
closed [str]
wouldPrompt [str]|null
Close ALL open documents without save dialogs. 60 - -
fusion_reset_workspace documents force: optional bool default false success bool
closedByAddin list
untitledScratchClosed int
remaining list
Bring Fusion back to a clean slate between runs: closes named documents AND the Untitled scratch the library/bind flow leaves behind (page issue #59). 90 - -
fusion_document_info documents {} (none) success bool
name str
productType str
isSaved bool
Metadata for the ACTIVE document: name, product type, save state, version, parent project. 30 - -
fusion_execute_text_command documents command: required str
expectDocument: optional str (refuses wrong_document if the active doc does not match)
success bool
output str
Run a raw Fusion TEXT COMMAND (app.executeTextCommand) - the escape hatch to Fusion internals (Electron.* electronics commands included). 60 - -
fusion_get_design_info documents {} (none) success bool
components int
bodies int
Design-level summary of the active design: components, bodies, sketches, units, root name. 60 - -
fusion_get_parameters documents {} (none) success bool
parameters list
All user + model parameters of the active design (name, expression, value, unit). 60 - -
fusion_list_cloud_projects cloud {} (none) success bool
projects list
List the cloud PROJECTS visible to the signed-in Fusion session (hub walk - slow on big teams; prefer fusion_aps_search for finding files). 120 yes -
fusion_list_cloud_files cloud projectName: optional str (defaults to active project)
folderPath: optional str
success bool
files list
List files/folders in a cloud project (optionally a subfolder). 120 yes -
fusion_export_f3d export outputPath: required str format str Export the active design as a Fusion archive (.f3d). 300 yes -
fusion_export_fbx export outputPath: required str format str Export to FBX mesh. 300 yes -
fusion_export_sat export outputPath: required str format str Export to SAT (ACIS solid). 300 yes -
fusion_export_skp export outputPath: required str format str Export to SketchUp (.skp). 300 yes -

Library SHOW verbs + bare-artifact wrapping (23)

verb category args (exact names + types + defaults) key response fields what it does timeout LR statusVerb
fusion_show_symbol library capture: optional bool [set captureMaxWidth to shrink it - 320 keeps a /command body small,...]
name: str (deviceset/symbol name; optional if symbolXml carries name=)
libraryPath: optional str (WINDOWS path .lbr)
symbolXml: optional str (bare <symbol ...>...)
foreground: optional bool [DEFAULT IS BACKGROUND (no focus steal])
foregroundReason: required WITH foreground:true
success bool
view str
screenshot str path
wrappedLibrary str (when wrapped)
Open a schematic SYMBOL in Fusion's library editor - first-class, no hand-built EDIT strings. 180 yes -
fusion_show_footprint library capture: optional bool [set captureMaxWidth to shrink it - 320 keeps a /command body small,...]
name: str
libraryPath: optional str
packageXml: optional str (bare <package ...>...)
foreground: optional bool [DEFAULT IS BACKGROUND (no focus steal])
foregroundReason: required WITH foreground:true
success bool
view str
screenshot str path
wrappedLibrary str (when wrapped)
Open a FOOTPRINT (package) in Fusion's library editor. 180 yes -
fusion_show_3d_package library capture: optional bool [set captureMaxWidth to shrink it - 320 keeps a /command body small,...]
name: str
libraryPath: optional str (.lbr)
packageXml: optional str (bare fragment)
stepPath: optional str (WINDOWS path .step to attach)
foreground: optional bool [DEFAULT IS BACKGROUND (no focus steal])
foregroundReason: required WITH foreground:true
success bool
view str
screenshot str path
wrappedLibrary str
Open the 3D CHIP view (Package3DEnvironment) for a library package - and the RELIABLE way to get a 3D model into a library: pass stepPath and it is attached AFTER the library opens... 300 yes -
fusion_demo_progress lifecycle demoId: required str (from fusion_demo mode:tour; omitted = the single running tour)
imagesAs: optional str paths|base64|both
sinceShot: optional int
percent int
step str
stepLabel str
done bool
shots list
shotCount int
stepShot dict|absent
Poll a running fusion_demo tour: {percent, elapsedSec, estimatedSec, step, stepLabel, done, failed, shots, shotCount, stepShot}. 15 - -
fusion_make_test_project lifecycle libraryPath: required str (WINDOWS path .lbr; stage from container first)
deviceset: optional str (defaults to the library's first deviceset)
device: optional str: the DEVICE (package variant) to place, e.g. "-HV" (default: the deviceset's first device)
success bool
schPath str
brdPath str
circuit str
Create a NEW electronics test project FROM SCRATCH around a library part - the Web Control demo's PROJECT button, and the answer to 'a customer only has a component page'. 300 yes -
fusion_screenshot_fusion introspect/etiquette hwnd: optional int (a dialog; default the main window) success bool
savedTo str
sizeKB int
Background PrintWindow capture of Fusion's MAIN window (largest same-title window; works occluded/bottom-of-z-order, never raises anything) or a specific dialog by hwnd. 60 - -
fusion_bind_library_3d library libraryPath: required str (WINDOWS .lbr path)
stepPath: required str (WINDOWS .step path)
deviceset: optional str (defaults to the library's first)
success bool
wip_urn str
bound bool
reopened bool
LOW-LEVEL primitive: binds ONE STEP onto one deviceset. 480 yes -
fusion_show_library library capture: optional bool [set captureMaxWidth to shrink it - 320 keeps a /command body small,...]
libraryPath: optional str (WINDOWS .lbr)
name: optional str (already-open library name)
success bool
view str
screenshot str
Eight-surfaces contract: the LIBRARY surface. 240 yes -
fusion_show_project library capture: optional bool [set captureMaxWidth to shrink it - 320 keeps a /command body small,...]
query: optional str (cloud design name)
urn: optional str
fileName: alias of query
success bool
view str
document str
screenshot str
Eight-surfaces contract: bring the PROJECT/design to its top level. 240 yes fusion_get_app_state
fusion_set_window_sizing introspect/etiquette enabled: optional bool (omit to read) success bool
sizeFusionWindow bool
Read/toggle auto-sizing Fusion's WINDOW after launch (STICKY, default ON). 15 - fusion_state
fusion_set_driving_badge introspect/etiquette enabled: optional bool (omit to read) success bool
showDrivingBadge bool
Read/toggle the 'Adom is driving Fusion' TASKBAR OVERLAY BADGE (STICKY per user, default ON). 15 - fusion_state
fusion_set_seat_takeover introspect/etiquette enabled: optional bool (omit to read) success bool
autoTakeOverSeat bool
Read/toggle the mid-session Autodesk seat-takeover sweep (STICKY per user, default ON). 15 - fusion_readiness
fusion_state introspect/etiquette screenshot: optional bool (default true)
imageAs: optional str path|base64 (default path)
success bool
running bool
activeDocument str
mainThreadBusy dict|null
blockingDialogs list
focusEvents list - the QUIETNESS AUDIT LOG (SDK canonical): every time this bridge took the...
timings dict - measured launch history on THIS machine (p50/p90 per phase, cold vs warm)
screenshot str path
screenshotBase64 str (imageAs:base64 only)
The RENDER-ME verb (kicad_state parity, issues #28/#30): running + window + dialog + busy state PLUS a fresh background screenshot of whatever Fusion is showing - the one verb that makes... 60 - -
fusion_export_iges export outputPath: required str format str Export to IGES. 300 yes -
fusion_export_stl export outputPath: required str format str Export to STL mesh. 300 yes -
fusion_export_3mf export outputPath: required str format str Export to 3MF mesh. 300 yes -
fusion_export_usdz export outputPath: required str format str Export to USDZ (AR / Hydrogen 3D). 300 yes -
fusion_export_optimized_glb export outputPath: required str (.glb)
silkscreen: bool default true
pin: str medium|large default medium
wait: int seconds default 15 (keep under the ~60s relay timeout; re-call fetch until complete)
async: bool
glbPath str
jobId str
pending bool
meshesAfter int
sizeBytes int
moleculeAnchored bool
silkscreenApplied bool
Fusion board -> wiki-grade optimized GLB. 200 yes -
fusion_fetch_optimized_glb export jobId: str (service job form)
exportId: str (async form from export_optimized_glb async:true)
outputPath: str (.glb)
wait: int seconds default 15 (keep under the ~60s relay timeout; re-call fetch until complete)
glbPath str
status str
pending bool
sizeBytes int
Finish a fusion_export_optimized_glb job: bounded-poll the optimizer by jobId and write the GLB to outputPath when complete. 150 - -
fusion_board_stackup electronics {} (none) layerSetup str
copperLayers list
copperCount int
copperThickness_mm list
dielectricBonds list (prepreg/core order)
fr4 {x_mm,y_mm,dielectric_mm}
Read a board's PHYSICAL fabrication stackup (see the pcb-stackup skill): copper layer count + copper/dielectric thicknesses from the EAGLE design rules (layerSetup/mtCopper/mtIsolate)... 200 yes -
fusion_export_obj export outputPath: required str format str Export to OBJ mesh. 300 yes -
fusion_export_dxf export outputPath: required str format str Export 2D DXF. 120 yes -
fusion_export_dwg export outputPath: required str format str Export 2D DWG. 120 yes -

Manufacturing (24)

verb category args (exact names + types + defaults) key response fields what it does timeout LR statusVerb
fusion_export_gerbers manufacturing outputDir: optional str (default C:/tmp/adom-gerbers) fileCount int
files [{name,size}]
zipPath str
Run the bundled JLCPCB CAM job (auto 2/4-layer) to produce the gerber + drill ZIP. 180 yes -
fusion_export_bom manufacturing outputPath: optional str
grouped: optional bool (default true)
componentCount int
grouped bool
Export a Bill of Materials CSV (grouped by value+package) from the open board. 60 - -
fusion_export_cpl manufacturing outputPath: optional str
side: optional str (all|top|bottom)
topCount int
bottomCount int
Export the Component Placement List (pick-and-place) CSV. 60 - -
fusion_set_design_rules manufacturing action: optional str (apply|export|show)
layers: optional str (auto|2|4)
activeWorkspace str
description str
Load manufacturing-grade DRC into the open board (JLCPCB 2/4-layer profiles). 90 - -
fusion_detect_layers electronics {} (none) layerCount int
copperLayers [int]
Detect 2-layer vs 4-layer board (ULP + CAM comparison). 90 - -
fusion_dismiss_blocking_dialogs introspect/etiquette {} (none) dialogs [...] Detect + classify (and optionally dismiss) blocking Fusion dialogs. 30 - -
fusion_electron_run electronics command: required str success bool
output str
Run an EAGLE/Electron command in the open board (the generic extension point, e.g. RUN ). 90 - -
fusion_electron_zoom electronics factor: float (default 2.0)
fit: optional bool
steps: optional int (default 16)
frameDelayMs: optional int (default 35)
success bool
output str
Smoothly ZOOM the schematic/2D board for a recording (the whole motion is one call). 60 yes -
fusion_electron_pan electronics x1: float
y1: float
x2: float
y2: float
steps: optional int (default 16)
frameDelayMs: optional int (default 35)
success bool
output str
box [...]
Smoothly PAN + zoom the view to frame a board-coordinate box (mm; get part positions from fusion_board_info). 60 yes -
fusion_electron_select electronics name: str (refdes, e.g. R1)
x: optional float
y: optional float
properties: optional bool (default true)
success bool
output str
deviceInfo str
SELECT a part (by reference designator, or x/y board mm) and surface its properties - the way clicking a part reveals the properties panel. 30 yes -
fusion_prove_result introspect/etiquette runId: optional str (omit for the latest run)
inlineFrames: optional bool
shots: optional int
sinceShot: optional int
stage str
verdict str
evidence []
percent float
etaSec float
POLL a background run started by fusion_create_library or the detached fusion_build_library_3d. 20 yes -
fusion_cancel_run introspect/etiquette runId: optional str (omit for the latest run in flight) cancelRequested bool
runId str
stage str at the time of the request
statusVerb fusion_prove_result
STOP a library import that is in flight (fusion_install_library_bundle / fusion_create_library) - the user's escape hatch from a long run, wired to a Cancel button in web control. 10 yes fusion_prove_result
fusion_addin_status lifecycle {} (none) addinReady bool
port int
version str
busy bool
Is the AdomBridge add-in loaded and answering inside Fusion? Reports addinReady, port and version, plus busy when a long command holds the main thread. 15 yes -
fusion_activate_document documents name: required str (document name as reported by fusion_get_app_state) success bool
activeDocument str
Make a named open document the ACTIVE one before driving it. 60 - -
fusion_action_ledger introspect/etiquette limit: optional int (default 50) actions [{at, action, detail}] Read the append-only record of what the bridge did in the BACKGROUND on this machine - dialogs it answered, Untitled scratch docs it swept, Fusion auto-starts, add-in restarts. 15 yes -
fusion_save_to_cloud cloud name: required str
projectName: optional str
folderPath: optional str
description: optional str
success bool
urn str
Save the ACTIVE document to Autodesk cloud storage with an explicit name and destination. 180 - -
fusion_take_screenshot introspect/etiquette outputPath: optional str success bool
path str
Screenshot the Fusion window in the BACKGROUND (no focus steal, reads through occlusion). 60 yes -
fusion_verb_times introspect/etiquette {} (none) stages {name: {count, p50, p90}} This machine MEASURED timings per verb/stage - the same store that paces every progress bar and ETA. 15 yes -
fusion_library_parts library libraryPath: required str (also accepts lbrPath/filePath/path) success bool
devicesets [{name, description, variants:[{fullName, device, technology, package,...
totals {devicesets, variants, withMpn, withDistributor}
metadataOk bool
warnings []
Every ORDERABLE variant in a .lbr with its part numbers - offline, no Fusion needed. 15 yes -
fusion_plan_library_import library parts: optional [{package, lbrPath, modelPath}]
stepPath: optional single .step when not passing parts[]
libraryPath: optional .lbr for context
success bool
fusion {installed, running, addinReady, status, message}
plan [{stage, label, estimatedSec, confidence, needsUserConsent?}]
estimatedSec float
estimatedSecIfAlreadyOpen float
summary str
PRE-FLIGHT for a library import: does NO work and changes nothing. 20 yes -
fusion_live_feed introspect/etiquette action: start|stop|status|frames
intervalSec: optional float (default 1.0)
maxSec: optional float (default 600)
since: frames only: return ticks newer than this
success bool
running bool
tick int
frames [{tick, kind:main|popup, path, title, at}]
A ~1 fps look INTO Fusion while the bridge drives it, kept as a BOX-SIDE ring buffer (~10 min). 15 yes -
fusion_restart_for_addin lifecycle save: optional bool (default true) success bool
addinReady bool
tookSec float
steps [{step, ok}]
ASYNC: returns immediately (started:true) and restarts Fusion in the background, SAVING the user's open documents first; poll fusion_readiness until ready with the new addinVersion (a... 300 - -
fusion_inspect_bodies documents worldSpace: optional bool (resolve through occurrence transforms; default false = root component only)
occurrence: optional str (substring filter on occurrence name, worldSpace only)
success bool
units str (mm)
bodyCount int
documentName str
bodies [{name,owner,bbox:{x,y,z},sizeMm,volumeMm3,areaMm2,faceCount,cylindricalFaceCount,...
GEOMETRY READ-BACK: what actually got built, in MILLIMETRES. 130 - fusion_get_app_state
fusion_uninstall lifecycle dryRun: optional bool (report the paths, delete nothing)
cascade: optional bool (set by ab)
name: optional str (set by ab)
success bool
dryRun bool
fusionRunning bool
removed [{path,kind}]
failed [{path,kind,error}]
skipped [{path,kind,why}]
CASCADE CLEANUP, called by ab's bridge_uninstall BEFORE this bridge's cache is deleted (ab 2.0.35+). 60 - -

Self-describe (1)

verb category args (exact names + types + defaults) key response fields what it does timeout LR statusVerb
fusion_describe describe {} (none) success bool
verbs [{name,summary,input,output,timeoutSeconds,statusVerb,longRunning,example}]
Self-describe every verb the bridge exposes (this list) for ab's Verbs tab + runner. 20 - -

Appendix

(a) The exact verbs[] array in bridge.json

bridge.json (manifest_version: 1, name: "fusion360", version: 1.9.341, verbPrefixes: ["fusion_"]) lists 57 verbs — a hand-maintained subset of the 131 that fusion_describe returns. Routing is by verbPrefixes, not by this list, so the extra 75 still route; the array is advertising, not a gate.

fusion_aps_browse            fusion_aps_create_folder     fusion_aps_download
fusion_aps_file_info         fusion_aps_get               fusion_aps_open
fusion_aps_recent            fusion_aps_search            fusion_aps_set_client_id
fusion_aps_signin            fusion_aps_status            fusion_aps_upload
fusion_aps_versions          fusion_attach_3d_package     fusion_board_info
fusion_build_library_3d      fusion_capture_library_views fusion_cleanup_cloud_files
fusion_close_window          fusion_describe              fusion_detect_layers
fusion_dismiss_blocking_dialogs                           fusion_electron_pan
fusion_electron_run          fusion_electron_select       fusion_electron_zoom
fusion_export_3mf            fusion_export_bom            fusion_export_cpl
fusion_export_dwg            fusion_export_dxf            fusion_export_gerbers
fusion_export_iges           fusion_export_obj            fusion_export_step
fusion_export_stl            fusion_export_usdz           fusion_generate_package
fusion_get_app_state         fusion_get_preferences       fusion_install_fusion
fusion_kill                  fusion_load_design_rules     fusion_make_3d_package
fusion_open_by_urn           fusion_open_lbr              fusion_readiness
fusion_run_modeling_script   fusion_search_cloud_files    fusion_set_design_rules
fusion_set_preference        fusion_show_2d_board         fusion_show_3d_board
fusion_show_schematic        fusion_start                 fusion_stop
fusion_walk_cloud_tree

Drift found: fusion_load_design_rules is the ONLY verb in bridge.json's array that has no describe.py entry (it is documented in VERBS.md but was never added to _T). The reverse drift is 75 verbs live-and-described but absent from bridge.json.

Other manifest fields worth mirroring into a swx bridge: statusVerb: "fusion_get_app_state", uninstall: "fusion_uninstall", spawn: {kind: python, entrypoint: server.py, port: 0, healthEndpoint: "/status", stopMethod: kill, persistent: true}, detect.installVerb: "fusion_install_fusion", detect.hostAppOptionalVerbs (verbs allowed to run with the host app absent): readiness, describe, get_app_state, status, addin_status, aps_status, aps_search, aps_browse, aps_recent, install_fusion, and timeouts = {default: 60, verbs: {...per-verb, keys WITHOUT the fusion_ prefix...}, prefixes: [{prefix: "open", seconds: 150}]}. Note the manifest timeouts.verbs numbers and describe.py's timeoutSeconds are two separate stores and do not always agree (e.g. start: 90 in the manifest, 150 in describe).

(b) Response-envelope conventions the Fusion bridge uses

1. success + errorCode + error. Failures return {"success": false, "errorCode": "<snake_case>", "error": "<human sentence>"}. Only fusion_web_signin declares errorCode in its describe schema, but the whole bridge emits it. The full set of errorCode values found in server.py / aps.py / handlers:

3d_attach_failed            activation_refused          addin_not_answering
addin_restart_required      addin_restarting            adom_lbr_failed
adom_lbr_unavailable        artifact_not_in_library     bad_activity_mode
bad_bundle                  bad_code                    bad_menu_item
bad_name                    bom_walk_budget_exceeded    build_in_progress
code_field_not_found        command_running             confirm_missing
create_3d_package_failed    create_dialog_missing       file_not_found
foreground_reason_required  fusion_addin_busy           fusion_addin_not_responding
fusion_autostart_failed     fusion_host_hung            fusion_not_installed
fusion_not_running          google_sso_unavailable      human_credential_required
inspect_failed              installer_download_failed   installer_launch_failed
kicad_source_required       lbr_invalid                 lbr_preflight_failed
libio_menu_missing          library_manager_missing     library_not_active
library_open_failed         library_path_required       library_unreadable
main_thread_busy            no_2fa_window               no_3d_package_bound
no_3d_reference             no_cloud_project            no_fusion_window
no_input                    no_lbr                      no_path_argument
no_prove_run                no_run_in_flight            no_work_folder
not_a_library               not_found                   not_in_hub
not_linked_yet              not_listed                  picker_missing
pin_map_invalid             restart_failed              run_not_found
save_failed                 too_large                   unknown_package_type
unknown_run_id              unsaved_named_document      unsupported_extension
upload_in_flight_close_deferred                         use_open_board_instead
user_owns_restart           wrong_document              wrong_footprint_loaded

(from aps.py:)
aps_app_missing_product     aps_not_configured          aps_not_signed_in
refused_root_upload

(surfaced on a poll, not a direct return:)
cancelled_by_user           (with cancelledAt + how many parts were done)

The recurring shapes worth copying: *_not_running / *_not_installed / *_busy / *_not_responding (host-app health), *_restart_required (host must be restarted to load the add-in — returned as a payload the CALLER turns into the human ask, never a silent restart), foreground_reason_required (etiquette gate, below), unknown_run_id / run_not_found / no_run_in_flight (async run bookkeeping).

2. _hint — the ONE principle. Every meaningful response carries a _hint string telling the calling AI its exact next action; the bridge assumes the AI reads CLI output, not the on-disk skill. _hint is appended to, never replaced, by the etiquette wrapper (dispatch_command in server.py only appends its note if "focus was NOT touched" is not already in the hint). Declared explicitly in describe for fusion_attach_3d_package (_hint: "the Save-dialog click + verify steps") and referenced in the summaries of fusion_signin and fusion_demo.

3. No _next key. Grep of describe.py, server.py and the docs finds zero _next usage — the Fusion bridge folds "what to do next" into _hint plus the explicit statusVerb field. (If the SolidWorks bridge wants a _next, it is a new convention, not a mirrored one.)

4. windowEtiquette — a three-state ENUM, not a boolean. server.py sets res.setdefault("windowEtiquette", "foreground" | "background") on every verb in the _WINDOW_RAISING set. Absent = "this verb does not report etiquette". The background branch also appends this exact _hint:

"Window opened/changed in the BACKGROUND - the user's focus was NOT touched; do NOT foreground anything to compensate. Render results via fusion_state. If the USER asks to watch, re-call with {"foreground": true, "foregroundReason": "<why, shown to the user as a 3s caption>"}."

_WINDOW_RAISING (the annotated set, verb names WITHOUT the fusion_ prefix): close_document, close_window, open_cloud_file, open_by_urn, aps_open, open_design, open_lbr, open_schematic, open_board, import_electronics, import_step, new_electronics_from_eagle, show_schematic, show_2d_board, show_3d_board, run_modeling_script, execute_text_command, electron_run, attach_3d_package, make_3d_package, build_library_3d, capture_library_views, generate_package, export_optimized_glb, board_stackup, save_to_cloud, start, show_symbol, show_footprint, show_3d_package, make_test_project, bind_library_3d, show_library, show_project.

5. Progress / long-running frames. There is no inline progress block in any describe output. Progress is polled, via three distinct poll verbs:

poll verb started by progress fields
fusion_prove_result fusion_install_library_bundle, fusion_create_library, fusion_build_library_3d stage, verdict, evidence[], percent (float, MEASURED — never guessed), etaSec (float). Args runId, inlineFrames, shots, sinceShot
fusion_demo_progress fusion_demo {mode:"tour"} percent (int), step, stepLabel, done, shots[], shotCount, stepShot (dict|absent). Args demoId, imagesAs (paths|base64|both), sinceShot
fusion_live_feed {action:"start"} running, tick, frames[{tick, kind:main|popup, path, title, at}]. Args action (start|stop|status|frames), intervalSec (default 1.0), maxSec (default 600), since

The sinceShot windowing convention (send only frames the caller has not already received) appears on both fusion_prove_result and fusion_demo_progress; fusion_live_feed uses since for the same purpose. fusion_verb_times returns stages: {name: {count, p50, p90}} — the measured history the percent/eta come from. Rule stated in dev-skills/fusion-verb-timing: compute progress at READ time from measurements; never present a guessed number as a measured one.

6. Async handoff: runId + statusVerb + longRunning. 71 of 131 verbs are longRunning: true (they keep working after ab's relay timeout). A verb that cannot fit a relay window returns IMMEDIATELY with runId (str) and a statusVerb in the response body naming what to poll (fusion_install_library_bundle, fusion_create_library, fusion_aps_open, fusion_install_fusion, fusion_cancel_run, fusion_describe carry the statusVerb response key). fusion_cancel_run {runId?} → {cancelRequested, runId, stage, statusVerb: "fusion_prove_result"}; cancellation surfaces on the NEXT poll as errorCode: cancelled_by_user + cancelledAt. Per-verb statusVerb in the describe table: fusion_get_app_state (19 verbs), fusion_mcp_status (5), fusion_prove_result (3), fusion_readiness (3), fusion_get_preferences (2), fusion_state (2), and one each of fusion_signin, fusion_demo, fusion_aps_status; 95 verbs declare none.

7. capture: true = ONE call, ONE consent. On fusion_install_library_bundle, fusion_show_schematic, fusion_show_2d_board, fusion_show_3d_board, fusion_build_library_3d, fusion_show_symbol, fusion_show_footprint, fusion_show_3d_package, fusion_show_library, fusion_show_project. The bridge settles the surface (waits for the add-in main thread + a paint beat) and returns proof inline as shot: {title, image, thumbnailDataUrl, maxWidth} — base64 frame plus a ready-to-use data: URL for browser callers. captureMaxWidth shrinks it (320 keeps a /command body small; default 640). The bridge encodes PNG but the relay may transcode to WebP — sniff, do not assume. This exists so callers stop polling fusion_state after a show, because each page-side poll costs one human consent (issue #30).

8. Image return convention. Verbs that produce images accept an imageAs / imagesAs arg (path | base64 | both, default path) and return screenshot (str path) plus screenshotBase64 when base64 was asked for.

9. fusion_describe double-nesting. The describe handler returns {success, bridge:"fusion360", verbCount, verbs:[...], data:{bridge, verbCount, verbs}}. verbs at the TOP level is what ab's Verbs tab reads off the raw /command response; ab's relay STRIPS non-standard top-level fields on the CLI proxy path, so the same payload is repeated under data (which the relay forwards). Any swx_describe must do the same double-nesting. Per-verb entry shape: {name, summary, input, output, timeoutSeconds, statusVerb, longRunning, example}; entries whose name ends in _note are filtered out of the emitted list (doc-only rows in the table).

10. Quietness audit log. fusion_state returns focusEvents: [{at, verb, outcome: "foreground"|"refused", reason}] — every time the bridge took the user's foreground OR refused a bare foreground:true. fusion_action_ledger {limit=50} returns actions: [{at, action, detail}]; fusion_alerts {sinceSec=300} returns alerts: [{at, text}].

(c) Verbs that are gated / require a reason

Foreground etiquette gate (hard-enforced, returns errorCode: foreground_reason_required). Declared in describe.py on three verbs — fusion_show_symbol, fusion_show_footprint, fusion_show_3d_package — with the identical arg pair:

  • foreground: optional bool — DEFAULT IS BACKGROUND (no focus steal; response carries windowEtiquette:"background"). true REQUIRES foregroundReason and shows it to the user as a 3s ab caption before any focus change — only when the USER asked to watch.
  • foregroundReason: required WITH foreground:true — a short user-facing sentence shown as the 3s caption (e.g. "You asked to watch the 3D board build").

server.py enforces it for the whole _WINDOW_RAISING set (list in §b4), not just those three: a bare foreground:true with no foregroundReason is REFUSED with {"success": false, "errorCode": "foreground_reason_required", "error": "foreground:true needs foregroundReason (a short user-facing sentence)."} and the refusal is recorded in fusion_state.focusEvents as outcome:"refused". When the gate passes, the bridge strips foreground/foregroundReason before forwarding to the add-in.

Soft reason (optional, defaulted — used as the caption text, never blocking). server.py calls _notify_before_foreground(args.get("reason") or "<default sentence>") for the foreground-click and foreground-keypress paths, and passes reason: args.get("reason") or "sign in to an Autodesk web surface" on the fusion_web_signin path.

Other gates that are not reason-shaped but block the same way:

  • .lbr preflight gate — fusion_open_lbr and fusion_create_library run fusion_preflight_lbr's checks automatically and refuse with lbr_preflight_failed / library_unreadable / not_a_library / lbr_invalid.
  • Add-in restart gate — addin_restart_required / user_owns_restart: the add-in was installed or updated while Fusion was already open. The bridge returns the payload and the CALLER must turn it into a human ask (fusion_restart_for_addin exists but the restart is the user's to own).
  • Human-credential gate — human_credential_required, no_2fa_window, google_sso_unavailable on the sign-in verbs (fusion_signin, fusion_signin_2fa, fusion_web_signin, fusion_aps_signin); fusion_signin reports the exact wall in signinWall: twofactor_email_code | credentials | protocol_handoff (plus signinWallHint).
  • Never-charge gate — the manifest description states APS calls are capped to the free tier; fusion_aps_* refuse with aps_not_signed_in rather than falling back to a paid path.
  • Main-thread / busy gates — main_thread_busy, fusion_addin_busy, command_running, build_in_progress, upload_in_flight_close_deferred.
  • Root-upload refusal — refused_root_upload on fusion_aps_upload (no uploading to a hub root).