skill
EDA Bridge Standard: one way for an AI to drive every PCB tool
Public Made by Adomby adom
The standard every Adom EDA bridge follows so one AI can drive Altium, KiCad, Fusion 360 and any future PCB tool the same way: shared verb names in tiers, the board model JSON, reply and refusal conventions, and a coverage table of each bridge against the Altium reference.
main
{
"standard": "0.32.0",
"reference": {
"bridge": "altium",
"version": "0.2.93"
},
"proposed": 100,
"compared": {
"kicad": "1.0.107",
"fusion360": "1.13.64"
},
"tiers": {
"core": "Read and edit the design. Every bridge provides these: they are how an AI sees and changes a board.",
"native": "Wraps the EDA tool's own feature (its DRC, ERC, Gerbers, pours, Update PCB). Every tool has one; the bridge exposes it under this name.",
"checks": "Engineering computed from the board model, not by the tool: one shared engine, so every bridge that serves the model gets them all.",
"app": "Driving the application itself (launch, licence, dialogs, windows, views). Each bridge has its own; the names are shared where the job is.",
"platform": "Specific to one tool's platform (Altium 365, OutJobs, integrated libraries). Not part of the standard; listed so nothing is lost."
},
"verbs": [
{
"name": "add_body",
"tier": "core",
"source": "altium",
"summary": "Put a 3D body on a footprint of a PcbLib: a STEP model, or an extruded box when no step is given. It REPLACES the footprint's existing 3D bodies (a re-import never stacks a second model) unless keepExisting:true. The bridge then re-aligns bodies onto the pads (normalize_bodies) and returns a frame.",
"input": {
"bhMil": "int, default 100 - box depth",
"bwMil": "int, default 100 - box width",
"footprintName": "string - required when the library holds more than one footprint",
"hMil": "int, default 40 - box height",
"keepExisting": "bool, default false - ADD next to the existing bodies instead of replacing them (a deliberate second body)",
"libraryPath": "path to a .PcbLib (required)",
"soMil": "int, default 0 - standoff",
"step": "Windows path to a .step - optional",
"timeout": "seconds, default 90"
},
"output": {
"_hint": "string - what was replaced, and a WARNING when bodies are still stacked",
"data": "{footprint, body, replacedBodies, keptExisting, bodiesBefore, sameNameFootprints, bodiesNow, bodiesOnCanvas}",
"normalized": "string - the shifts applied",
"replacedBodies": "int - old bodies removed before the add",
"shot": "{image: base64 png, width, height}"
},
"hint": "altium_save {filePath: libraryPath}, then altium_show_3d_chip to look at it; boards that already place the part need PCB:UpdateFootprints. Never engrave the MPN into the STEP.",
"pitfalls": [
"It REPLACES by default (from 0.2.52): data.replacedBodies says how many old bodies went and data.bodiesNow should read 1. keepExisting:true is the only way to stack a second body.",
"A bad step path ('could not load model') removes nothing: the old body stays.",
"data.sameNameFootprints > 1 = several footprints share the name and only the FIRST got the body: altium_remove_footprint the stale copies.",
"Without footprintName it acts on the only footprint in the library (name_required when there are several).",
"'could not load model' = the STEP path is not on THIS machine: stage it with send_files."
],
"related": [
"normalize_bodies",
"show_3d_chip",
"pcb_report",
"import_part",
"footprint_primitives"
],
"example": {
"footprintName": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.PcbLib",
"step": "C:/lib/VL53L5CX.step"
},
"longRunning": false,
"timeoutSeconds": 90,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "add_models",
"tier": "core",
"source": "altium",
"summary": "Attach one or more PCBLIB footprint models, parameters, comment and description to a SchLib component (Altium's several-footprints-per-symbol mechanism).",
"input": {
"comment": "string",
"description": "string",
"libraryPath": "path to a .SchLib (required)",
"models": "[{name, pcblib, description}]",
"params": "{key: value}",
"symbolName": "string (required)",
"timeout": "seconds, default 120"
},
"output": {
"data": "{libref, models: int, params: int}",
"shot": "{image: base64 png, width, height}"
},
"hint": "Check data.models is what you sent, then altium_save. To REPLACE the footprint use altium_set_models.",
"pitfalls": [
"NOT idempotent: every call APPENDS another implementation. Repair = altium_set_models, or altium_remove_symbol + re-import.",
"';' and '|' inside a description are rewritten (they are the spec separators).",
"altium_read_symbol does not report models; use altium_symbol_prims {models:true}."
],
"related": [
"set_models",
"set_params",
"symbol_prims",
"remove_symbol"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"models": [
{
"description": "LGA-16 6.4x3.0",
"name": "VL53L5CX",
"pcblib": "C:/lib/Adom_ToF.PcbLib"
}
],
"params": {
"Manufacturer Part Number": "VL53L5CXV0GC/1"
},
"symbolName": "VL53L5CX"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "add_symbol_art",
"tier": "core",
"source": "altium",
"summary": "Draw the chip-outline artwork (the chip-thumbnailer polylines adom-symbol baked into the KiCad symbol) into a SchLib component, fitted to its body rectangle, so the Altium symbol shows the same chip as KiCad and Fusion.",
"input": {
"clear": "bool, default true: remove the component's existing polylines/lines first",
"kicadSym": "Windows path to the .kicad_sym that carries the baked outline (stage it with send_files)",
"libraryPath": "path (.SchLib)",
"mode": "lines (default) | polyline",
"symbolName": "string (LibReference)"
},
"output": {
"bodyRectMil": "[x0,y0,x1,y1]",
"points": "int",
"polylines": "int"
},
"hint": "Run once per part right after assemble-altium / build_symbol_modes, then altium_save the SchLib and altium_show_symbol to check.",
"pitfalls": [
"clear:true (default) also removes hand-drawn lines on the symbol; only the pins and the body rectangle survive.",
"The KiCad symbol must already carry the outline (adom-symbol create bakes it; --outline-name none for side-etched chips)."
],
"related": [
"show_symbol",
"symbol_prims",
"save"
],
"example": {
"kicadSym": "C:/lib/VL53L5CX.kicad_sym",
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"symbolName": "VL53L5CX"
},
"longRunning": false,
"timeoutSeconds": 180,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "align_parts",
"tier": "core",
"source": "proposed",
"summary": "Line parts up on a common left, right, top, bottom or centre line, or space them evenly, by courtyard box or by anchor point. One undo step, with move_parts' checks.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"expectedRevision": "string: the revision you last read (routing_state); refused with stale_board if the board changed",
"refs": "[\"C1\", \"C2\", \"C3\"] (required)",
"mode": "left|right|top|bottom|centerX|centerY|distributeX|distributeY (required)",
"by": "courtyard|anchor, default courtyard",
"to": "mm: the line to align on (default from the group)",
"gapMm": "number: the spacing for distribute (default even spacing between the outer two)",
"allowOverlap": "bool, default false",
"allowOutside": "bool, default false",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"targets": "[{ref, x, y}]",
"mismatches": "[{ref, asked, got}]",
"revision": "string: the board's new revision"
},
"hint": "Without to, left takes the group's smallest x, right the largest, top the highest edge and bottom the lowest (y up); centre lines take the mean. distribute keeps the outer two in place.",
"pitfalls": [
"Rotation and side are kept: align parts of the same orientation for a clean row.",
"A courtyard collision or a part off the board is refused, as in move_parts."
],
"related": [
"move_parts",
"placement_check"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"refs": [
"C4",
"C5",
"C6"
],
"mode": "top",
"expectedRevision": "<rev>"
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "apply_silkscreen",
"tier": "core",
"source": "altium",
"summary": "Land a silkscreen plan in one undo step: designators and comments moved, sized and turned (or hidden), free overlay texts and lines added (bottom texts mirrored), earlier ones removed; answers silk_state after.",
"input": {
"comments": "[same] - the value",
"lines": "[{x1, y1, x2, y2, width?: mm (0.15), side?}]",
"names": "[{ref, x, y, size, rotation?, show?}] - the designator's own location, mm",
"remove": "{texts:[raw], lines:[raw]} - silk_state raw handles of earlier free items",
"texts": "[{text, x, y, size, rotation?, side?: top|bottom}]"
},
"output": {
"after": "silk_state",
"applied": "int",
"failed": "int",
"results": "[ok|err:...]"
},
"hint": "A text's location is its lower left before rotation (for 90 degrees: the box's lower right). Stroke width is a seventh of the height.",
"pitfalls": [
"Needs the board current.",
"Removal matches the raw handle exactly: pass what silk_state answered."
],
"related": [
"silk_state",
"routing_drc"
],
"example": {
"lines": [
{
"x1": 1,
"x2": 5,
"y1": 1,
"y2": 1
}
],
"names": [
{
"ref": "U1",
"size": 0.8,
"x": 12.0,
"y": 14.2
}
]
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "board_outline",
"tier": "core",
"source": "altium",
"summary": "Draw the board shape as tracks and arcs on a mechanical layer: the outline a fab house reads from the Gerbers. A board built by script has its shape but nothing on an outline layer, so its GM1/GKO Gerbers are empty.",
"input": {
"filePath": "path to the .PcbDoc - optional",
"mech": "mechanical layer number, default 1",
"replace": "bool - draw even when the layer already holds primitives",
"widthMm": "line width, default 0.1"
},
"output": {
"alreadyThere": "primitives the layer held",
"drawn": "segments drawn",
"layer": "string"
},
"hint": "altium_export_manufacturing checks the outline Gerbers and calls this itself when they are empty (addOutline:false stops it). altium_save keeps the outline.",
"pitfalls": [
"A layer that already holds anything is left alone unless replace:true (it may be the outline already, drawn by hand)."
],
"related": [
"export_manufacturing",
"set_outline",
"board_shape"
],
"example": {
"mech": 1,
"widthMm": 0.1
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "board_shape",
"tier": "core",
"source": "altium",
"summary": "Redefine the CURRENT board's outline as a wMm x hMm rectangle at (x0Mm, y0Mm) by rewriting the board outline's segments.",
"input": {
"hMm": "number, default 15",
"mechOutline": "bool - also draw the rectangle as 0.1 mm tracks on Mechanical 1 so the fab Gerber (.GM1) has an outline",
"pcbPath": "path to a .PcbDoc - optional; opened first",
"timeout": "seconds, default 120",
"wMm": "number, default 15",
"x0Mm": "number, default 0",
"y0Mm": "number, default 0"
},
"output": {
"data": "{outlineMil: [left, bottom, right, top] read from the outline vertices, outlineSource, mechOutlineTracks}",
"roundtripMs": "int"
},
"hint": "Then altium_save {filePath: pcbPath} and altium_show_2d_board {filePath} to see it. altium_pcb_report {want:'board'} reads outlineMil back.",
"pitfalls": [
"errorCode no_board_outline: the current document is a PcbLib (its internal board has no outline) - pass pcbPath.",
"bad_size = wMm/hMm not greater than 0; bad_number = a value was not numeric.",
"It REPLACES the outline; the previous shape is not kept.",
"The board shape alone is NOT plotted into any Gerber: pass mechOutline:true (once, at the final size: each call adds a new set of tracks)."
],
"related": [
"test_board",
"pcb_report",
"show_2d_board",
"save"
],
"example": {
"hMm": 14,
"pcbPath": "C:/proj/tof.PcbDoc",
"wMm": 39
},
"longRunning": false,
"timeoutSeconds": 120,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "board_summary",
"tier": "core",
"source": "altium",
"summary": "One-screen summary of the current board, shaped from one read_board round trip: component counts by side, nets, copper layers actually in use, rule counts.",
"input": {
"limit": "int, default 2000",
"raw": "bool - return the unshaped agent payload",
"sections": "string csv - optional"
},
"output": {
"roundtripMs": "int",
"summary": "{board, components, componentsTop, componentsBottom, nets, copperLayersInUse, copperLayersInUseNames, layersWithPrimitives, copperLayersAddressable, rules, rulesEnabled}"
},
"hint": "Start here on an unknown board, then altium_review_board for findings or altium_component_data / altium_net_connections for detail.",
"pitfalls": [
"Needs a .PcbDoc current (altium_activate_document).",
"copperLayersAddressable is what Altium CAN address (top + 30 mid + 16 planes + bottom), not this board's stack: report copperLayersInUse."
],
"related": [
"read_board",
"layers_in_use",
"rules_by_kind",
"review_board"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "bodies",
"tier": "core",
"source": "proposed",
"summary": "Every part's 3D body as a box: its footprint rectangle on the board and its height range above the surface it sits on (a bottom part measures down from the bottom). Names the parts with no 3D body and the ones whose body is not where the board puts the part. Read only.",
"input": {
"filePath": "path to the board (optional; default the open board)",
"refs": "[ref] (default every part)"
},
"output": {
"bodies": "[{ref, side: top|bottom, x0, y0, x1, y1, z0, z1}]: the bodies companion (schema/companions.schema.json), mm",
"noBody": "[ref]: parts with no 3D body, so no height",
"suspect": "[{ref, why: [string]}]: a body off its footprint, floating above the board or sunk into it",
"tallest": "{top: {ref, heightMm}, bottom: {ref, heightMm}}",
"surfaceZMm": "{top, bottom}: the z of each board surface",
"revision": "string"
},
"hint": "The rows are the bodies companion, which height_check, placement_check and enclosure checks read. One box per body and one box per part are both valid; checks take the union per part.",
"pitfalls": [
"A part whose library has no 3D model is in noBody: it has no height, not a height of 0.",
"A body in suspect usually comes from a wrong or offset library model: fix it before trusting its height."
],
"related": [
"height_check",
"placement_check",
"add_body",
"render_board_3d"
],
"example": {
"refs": [
"U1",
"J2"
]
},
"longRunning": false,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "clone_symbol",
"tier": "core",
"source": "altium",
"summary": "Copy a symbol inside the current SchLib under a new name, all display modes included.",
"input": {
"from": "string - existing LibReference",
"libraryPath": "path to a .SchLib - optional; opened first",
"timeout": "seconds, default 90",
"to": "string - new LibReference"
},
"output": {
"data": "{from, to, primitives: int, displayModeCount}",
"roundtripMs": "int"
},
"hint": "Then altium_set_params on the clone (its own MPN and comment) and altium_save.",
"pitfalls": [
"'target already exists' - pick another name or altium_remove_symbol first.",
"Same library only; there is no cross-library symbol copy."
],
"related": [
"rename_symbol",
"remove_symbol",
"set_params",
"save"
],
"example": {
"from": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"to": "VL53L7CX"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "component_data",
"tier": "core",
"source": "altium",
"summary": "Placement data for one board component, or for all of them: footprint pattern, comment, layer/side, position, rotation, size, pad count and the nets on its pads.",
"input": {
"designator": "string - optional; omit for every component",
"limit": "int, default 500"
},
"output": {
"data": "{component: {designator, pattern, comment, layerId, bottom, xMil, yMil, rotation, wMil, hMil, pads, nets}} | {count, components: [..]}",
"roundtripMs": "int"
},
"hint": "Then altium_component_pins {designator} for pad-level nets, or altium_footprint_primitives {designator} for the geometry.",
"pitfalls": [
"Needs a .PcbDoc current.",
"Units are mils; the designator match ignores case. limit only applies to the all-components form."
],
"related": [
"list_designators",
"component_pins",
"footprint_primitives"
],
"example": {
"designator": "U1"
},
"longRunning": false,
"timeoutSeconds": 90,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "component_pins",
"tier": "core",
"source": "altium",
"summary": "Every pad of one board component with its net, position, layer, size and hole.",
"input": {
"designator": "string (required), e.g. U1"
},
"output": {
"data": "{designator, count, pins: [{name, net, xMil, yMil, layerId, wMil, hMil, holeMil}]}",
"roundtripMs": "int"
},
"hint": "Use pins[].net with altium_net_connections {net} to follow a signal across the board.",
"pitfalls": [
"Needs a .PcbDoc current.",
"holeMil 0 = an SMD pad."
],
"related": [
"component_data",
"net_connections",
"footprint_primitives"
],
"example": {
"designator": "U1"
},
"longRunning": false,
"timeoutSeconds": 90,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "copper_layers",
"tier": "core",
"source": "altium",
"summary": "Every copper layer Altium can address on the current board (top, mid 1-30, planes 1-16, bottom) with names and visibility.",
"input": {},
"output": {
"data": "{layers: [{name, id, kind, displayed}]}",
"roundtripMs": "int"
},
"hint": "Do not count these as the board's layers: altium_layers_in_use says which carry copper.",
"pitfalls": [
"Needs a .PcbDoc current.",
"A capability list (the same on any board), not the stack in use."
],
"related": [
"layers",
"layers_in_use"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "copy_footprint",
"tier": "core",
"source": "altium",
"summary": "Duplicate a footprint inside the current PcbLib under a new name (every primitive replicated).",
"input": {
"from": "string",
"libraryPath": "path to a .PcbLib - optional; opened first",
"timeout": "seconds, default 90",
"to": "string"
},
"output": {
"data": "{from, to, primitives: int}",
"roundtripMs": "int"
},
"hint": "For a footprint from ANOTHER library use altium_xcopy_footprint. Then altium_save.",
"pitfalls": [
"'target already exists' - choose another name or altium_remove_footprint first."
],
"related": [
"xcopy_footprint",
"rename_footprint",
"pcb_report"
],
"example": {
"from": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.PcbLib",
"to": "VL53L5CX_HANDSOLDER"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "copy_routing",
"tier": "core",
"source": "proposed",
"summary": "Copy the tracks and vias inside a box to an offset, remapping nets by pairing parts (a designator map or pattern), so a repeated channel gets the same routing. One undo step.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"expectedRevision": "string: the revision you last read (routing_state); refused with stale_board if the board changed",
"box": "[x1, y1, x2, y2] mm (required): the source",
"offset": "[dx, dy] mm (required)",
"refMap": "{\"U1\": \"U5\"}: pair parts, so each pad's net maps to the partner pad's net",
"refPattern": "{from: \"CH1_*\", to: \"CH2_*\"}: pair parts by designator pattern",
"netMap": "{\"SIG\": \"SIG2\"}: overrides",
"keepUnmappedNets": "bool, default false",
"layers": "[layer]: copy only these",
"validate": "bool, default true: run the tool's DRC on the result before committing",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"copied": "{tracks: int, vias: int}",
"netMap": "{from: to}: the pairing used",
"skipped": "[{item, why}]",
"drc": "{ran, newErrors}",
"revision": "string: the board's new revision"
},
"hint": "A track is copied when both ends are in the box, a via when its centre is. Without a remap the copy keeps its nets. Dry-run first and check netMap.",
"pitfalls": [
"Only through vias are copied: blind and buried vias are skipped.",
"The copy connects only where the target pads sit at the same offset: place the target channel identically first (replicate_layout).",
"One source net mapping to two target nets is refused (net_map_conflict) unless netMap settles it."
],
"related": [
"replicate_layout",
"route_net",
"routing_state"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"box": [
10,
10,
30,
25
],
"offset": [
25,
0
],
"refPattern": {
"from": "CH1_*",
"to": "CH2_*"
},
"expectedRevision": "<rev>"
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "create_footprint",
"tier": "core",
"source": "altium",
"summary": "Create one footprint from a pad list in a PcbLib (the library is created and saved if the path does not exist) and return a proof frame.",
"input": {
"description": "string",
"footprints": "[{name, pads, ...}] - optional: make several in one call (each over the shared args)",
"libraryPath": "path to a .PcbLib (required)",
"name": "string (required)",
"pads": "'des,x_mil,y_mil,w_mil,h_mil,rect|round,hole_mil;...' - hole 0 = SMD",
"timeout": "seconds, default 90"
},
"output": {
"data": "{footprint, library, libraryState: opened|created, pads: int}",
"shot": "{image: base64 png, width, height}",
"windowEtiquette": "background"
},
"hint": "The footprint is registered but the library is NOT saved: altium_save {filePath: libraryPath}. Then altium_add_body for 3D and altium_show_footprint to check. For a real part use altium_build_footprint (spec with silkscreen and courtyard).",
"pitfalls": [
"errorCode bad_number = a pad field that must be a number was not; nothing is created.",
"Units are MILS here; altium_build_footprint specs are millimetres.",
"A fresh library carries the stray PCBComponent_1: altium_cleanup_libs."
],
"related": [
"build_footprint",
"add_body",
"save",
"show_footprint"
],
"example": {
"libraryPath": "C:/lib/Test.PcbLib",
"name": "R0603",
"pads": "1,-30,0,35,37,rect,0;2,30,0,35,37,rect,0"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "create_symbol",
"tier": "core",
"source": "altium",
"summary": "Create one rectangular symbol from a pin list in a SchLib (the library is created and saved if the path does not exist) and return a proof frame.",
"input": {
"bodyHeightMil": "int, default 600",
"bodyWidthMil": "int, default 800",
"description": "string",
"designator": "string, default 'U'",
"libraryPath": "path to a .SchLib (required)",
"name": "string (required)",
"pins": "'des,name,left|right|top|bottom,offset_mil[,part[,hiddenNet]];...' - part 1..N makes a multi-part symbol (a dual op-amp: its A pins part 1, B pins part 2), 0 puts a pin on every part (power); hiddenNet hides the pin and joins it to that net by name (shared power pins: '8,V+,left,300,0,VCC', or the compiler reports duplicate pins)",
"symbols": "[{name, pins, ...}] - optional: make several in one call (each over the shared args)",
"timeout": "seconds, default 90"
},
"output": {
"data": "{symbol, library, libraryState: opened|created, pins: int}",
"shot": "{image: base64 png, width, height}",
"windowEtiquette": "background"
},
"hint": "Library is UNSAVED: altium_set_params {footprint, params}, then altium_save {filePath: libraryPath}. For multi-mode symbols use altium_build_symbol_modes.",
"pitfalls": [
"A fresh library carries the stray Component_1: altium_cleanup_libs.",
"Pin offsets are mils along the chosen side; check shot.image for overlapping pins."
],
"related": [
"build_symbol_modes",
"set_params",
"read_symbol",
"save"
],
"example": {
"libraryPath": "C:/lib/Test.SchLib",
"name": "CH340G",
"pins": "1,GND,left,100;2,TXD,left,200;16,VCC,right,100"
},
"longRunning": false,
"timeoutSeconds": 90,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "doc_params",
"tier": "core",
"source": "altium",
"summary": "Read or set a sheet's document parameters: the title block (Title, DocumentNumber, Revision, DrawnBy, Author, CompanyName, ...).",
"input": {
"save": "bool, default true",
"set": "{name: value} (optional; missing parameters are added)",
"sheet": "path to the .SchDoc (required)"
},
"output": {
"params": "[{name, value}]",
"saved": "bool",
"set": "int"
},
"hint": "The title block shows them through =Title, =DocumentNumber, =Revision ... special strings.",
"pitfalls": [],
"related": [
"sch_edit",
"export_pdf"
],
"example": {
"set": {
"Revision": "B",
"Title": "12 V to 5 V buck"
},
"sheet": "C:/proj/Main.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "edit_footprint",
"tier": "core",
"source": "proposed",
"summary": "Edit a library footprint in place: change, delete, add or renumber pads; add, replace or delete graphics on a layer; set its description, tags and attributes; replace, add or delete 3D models. Everything not edited stays as it was.",
"input": {
"libraryPath": "path to the footprint library (required)",
"name": "the footprint's name (required)",
"pads": "[{number, set?: {sizeMm, at, shape, drillMm, layers, rotation, type, newNumber}, delete?: true}]",
"addPads": "[pad]",
"renumber": "{map: {\"1\": \"A1\"}} | {sequential: true, start?: 1}",
"graphics": "[{layer, mode: append|replace|delete, widthMm?, shapes: [{type: line|arc|rect|circle|poly, ...}]}]",
"metadata": "{description?, tags?, attributes?: {mount, excludeFromBom, excludeFromPos, dnp}}",
"models": "{mode: replace|append|delete, list: [{path, offset, scale, rotate}]}",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"changes": "[string]: what was done, in order"
},
"hint": "Operations run in the order pads, addPads, renumber, graphics, metadata, models. An edited pad keeps its id.",
"pitfalls": [
"Boards that already use the footprint keep their own copy: update them with swap_footprint.",
"Graphics replace and delete touch shapes only, never text on that layer."
],
"related": [
"read_footprint",
"create_footprint",
"swap_footprint",
"add_body"
],
"example": {
"libraryPath": "C:/lib/Mine.PcbLib",
"name": "SOT-23_Mine",
"pads": [
{
"number": "1",
"set": {
"sizeMm": [
1.0,
0.8
]
}
}
]
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "edit_parts",
"tier": "core",
"source": "proposed",
"summary": "Edit placed parts: value, designator, any field (add, change, remove), do-not-populate, exclusion from the BOM or position files, mounting type and the lock. One undo step.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"expectedRevision": "string: the revision you last read (routing_state); refused with stale_board if the board changed",
"edits": "[{ref, value?, newRef?, fields?: {name: value | null (remove)}, dnp?: bool, excludeFromBom?: bool, excludeFromPos?: bool, mount?: smd|through_hole|other, locked?: bool}] (required)",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"edited": "[{ref, before, after}]",
"failed": "[{ref, error}]",
"revision": "string: the board's new revision"
},
"hint": "Fields the tool requires (designator, value) cannot be removed. Read the parts first with component_data.",
"pitfalls": [
"Board-side edits of what the schematic owns are lost at the next update_pcb: change the schematic instead (sch_edit).",
"A designator already taken is refused."
],
"related": [
"component_data",
"part_parameters",
"sch_edit"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"edits": [
{
"ref": "R7",
"value": "4k7",
"dnp": true
}
],
"expectedRevision": "<rev>"
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "find_symbol",
"tier": "core",
"source": "altium",
"summary": "Find symbols (or footprints with kind:'footprint') by part of their name across libraries: the given ones, or every installed .SchLib/.PcbLib.",
"input": {
"kind": "symbol (default) | footprint",
"libraries": "[paths] - optional, default the installed libraries",
"query": "part of the name (required)"
},
"output": {
"best": "the exact match, else the shortest name containing it",
"matches": "[{name, library, exact}]"
},
"hint": "altium_show_symbol / altium_read_symbol on the best match; it is a style reference for a new symbol too.",
"pitfalls": [
".IntLib files are not searched (altium_extract_intlib gives their sources); the Altium 365 workspace is searched with altium_workspace_search."
],
"related": [
"show_symbol",
"read_symbol",
"list_library",
"workspace_search"
],
"example": {
"query": "LM358"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "footprint_primitives",
"tier": "core",
"source": "altium",
"summary": "Geometry dump of one PLACED component: its tracks, arcs, pads (with solder and paste mask expansion in um) and texts in mils with layer ids; other primitive kinds are counted.",
"input": {
"designator": "string (required) - a component on the current board, e.g. U1"
},
"output": {
"data": "{designator, pattern, count, otherPrimitives, primitives: [{kind: track|arc|pad|text, layerId, ...}]}",
"roundtripMs": "int"
},
"hint": "Use it to verify an imported footprint on a altium_test_board: pad layerId 74 = multi-layer (plated through), which is what altium_plate_vias produces.",
"pitfalls": [
"Needs a .PcbDoc current: it reads a placed component, not a PcbLib member (altium_pcb_report reads libraries).",
"3D bodies, fills and regions only show up in otherPrimitives."
],
"related": [
"component_pins",
"plate_vias",
"test_board",
"pcb_report"
],
"example": {
"designator": "U1"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "generate_body",
"tier": "core",
"source": "proposed",
"summary": "Make a part's 3D body from its package family and its datasheet dimensions (chip, SOIC, QFN, QFP, BGA, SOT-23, DFN, MELF, electrolytic can, crystal, pin header and others), to IPC-7351 proportions, optionally with a marking on its top, and write it as a STEP file.",
"input": {
"family": "chip | soic | qfn | qfp | bga | sot23 | dfn | melf | ecap | crystal | header and others (required; an unknown one is answered with the families the bridge supports)",
"dimensionsMm": "{letter: mm}: the package drawing's JEDEC letters (A height, D body length, E lead span, E1 body width, b lead width, e pitch, L lead length; D2 and E2 the exposed pad's length and width, drawn when given) plus pins, always the part's total pin count for any family (a bridge converts it to its generator's own per-side or per-pair count); a missing one takes the family's default",
"marking": "text on the top face (an MPN or a value code); a newline starts a second line",
"markingStyle": "raised | engraved (default raised)",
"outputPath": "the .step file to write (required)"
},
"output": {
"stepPath": "path",
"family": "string",
"dimensionsMm": "{letter: mm}: every dimension used, defaults included",
"bboxMm": "{x, y, z}",
"marking": "string | null",
"families": "[string] (when family is unknown)"
},
"hint": "The body is in the package's own frame (IPC-7351 zero orientation, seated on z = 0), ready for add_body. Compare bboxMm with the datasheet's body size before attaching it.",
"pitfalls": [
"A wrong dimension gives a plausible but wrong body: nothing checks it against a datasheet.",
"A marking is real geometry: very small text on a small package is unreadable, which is not an error.",
"pins is the total: QFN-32 is pins 32, not 8 per side."
],
"related": [
"add_body",
"bodies",
"height_check",
"library_views"
],
"example": {
"family": "soic",
"dimensionsMm": {
"pins": 8,
"D": 4.9,
"E": 6.0,
"E1": 3.9,
"A": 1.75,
"e": 1.27
},
"marking": "LM358",
"outputPath": "C:/parts/LM358.step"
},
"longRunning": false,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "import_svg",
"tier": "core",
"source": "proposed",
"summary": "Import SVG artwork (a logo, a label) as filled polygons on a silkscreen, copper, mask or user layer, at a position and size; curves flattened, holes kept. One undo step.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"expectedRevision": "string: the revision you last read (routing_state); refused with stale_board if the board changed",
"svgPath": "path to the .svg",
"svg": "the SVG text (instead of svgPath)",
"at": "[x, y] mm (required)",
"widthMm": "number: the artwork's width (or scale)",
"scale": "number, default 1",
"anchor": "topleft|center, default topleft: which point of the artwork at names",
"layer": "default F.SilkS",
"mirror": "bool, default true on bottom layers",
"net": "a net for artwork on copper",
"toleranceMm": "number, default 0.02: curve flattening",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"polygons": "int",
"sizeMm": "[w, h]",
"ids": "[id]",
"skipped": "[{element, why}]",
"revision": "string: the board's new revision"
},
"hint": "Filled shapes import; text and images are listed in skipped (convert text to paths first). A shape inside another becomes a hole.",
"pitfalls": [
"Stroke-only artwork imports nothing: give the SVG filled shapes.",
"On copper the shapes are graphics: give net to tie them to a net, and run run_drc.",
"On a bottom layer the artwork is mirrored so it reads correctly from the back; mirror:false keeps it as drawn."
],
"related": [
"apply_silkscreen",
"silk_state",
"run_drc"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"svgPath": "C:/proj/logo.svg",
"at": [
120,
95
],
"widthMm": 10,
"layer": "F.SilkS",
"expectedRevision": "<rev>"
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "layer_stack",
"tier": "core",
"source": "altium",
"summary": "The CURRENT board's stack-up: copper layers in order with copper thickness and the dielectric under each (height, constant, material), and the total thickness. For impedance, current capacity and fab quotes.",
"input": {},
"output": {
"data": "{copperLayers, totalUm, layers: [{name, copperUm, dielectricUm (the dielectric BELOW this layer), dk1000 (dielectric constant x 1000), material}]}"
},
"hint": "Open the board first (altium_show_2d_board). dk1000 is the dielectric constant times 1000 (4200 = 4.2).",
"pitfalls": [
"Solder mask and overlay layers are not part of this list; the copper and the dielectric under each are."
],
"related": [
"layers",
"copper_layers",
"read_rules"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "layers",
"tier": "core",
"source": "altium",
"summary": "The current board's layer set with ids, names, kind and whether each is displayed.",
"input": {},
"output": {
"data": "{layers: [{name, id, kind, displayed}]}",
"roundtripMs": "int"
},
"hint": "ids feed altium_set_layer_visibility {layerId}. For what is actually used, altium_layers_in_use.",
"pitfalls": [
"Needs a .PcbDoc current.",
"The fixed layer set, not the stackup: thickness and dielectric detail are not read."
],
"related": [
"copper_layers",
"layers_in_use",
"set_layer_visibility"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "layers_in_use",
"tier": "core",
"source": "altium",
"summary": "Which layers of the current board actually carry primitives: copper layers with copper (densest first) and every layer with anything on it.",
"input": {
"limit": "int, default 2000",
"sections": "string csv - optional"
},
"output": {
"board": "path",
"copperLayersInUse": "[{layerId, name, primitives}]",
"layersWithPrimitives": "[{layerId, name, primitives}]",
"roundtripMs": "int"
},
"hint": "The honest answer to 'how many layers is this board'. altium_set_layer_visibility {layerId} to isolate one, then altium_show_2d_board for a frame.",
"pitfalls": [
"Needs a .PcbDoc current.",
"A floor, not the stack: an empty inner plane carries no primitives and is invisible here."
],
"related": [
"board_summary",
"layers",
"copper_layers",
"set_layer_visibility"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "list_designators",
"tier": "core",
"source": "altium",
"summary": "Every component designator on the current board.",
"input": {},
"output": {
"data": "{count, designators: [string]}",
"roundtripMs": "int"
},
"hint": "Then altium_component_data {designator} or altium_component_pins {designator}.",
"pitfalls": [
"Needs a .PcbDoc current: 'no current PCB board' carries the _hint to open one."
],
"related": [
"component_data",
"component_pins",
"read_board"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "list_library",
"tier": "core",
"source": "altium",
"summary": "Names of every component in a .SchLib or every footprint in a .PcbLib (kind taken from the extension). Opens the library; no screenshot.",
"input": {
"libraryPath": "path to a .SchLib/.PcbLib (alias: filePath) - default: the bundled SpiritLevel SchLib",
"limit": "int, default 500"
},
"output": {
"data": "{kind: sch|pcb, count, names: [string]}",
"kind": "sch | pcb",
"path": "string",
"roundtripMs": "int"
},
"hint": "Use the exact names with altium_show_symbol / altium_read_symbol / altium_show_footprint / altium_pcb_report.",
"pitfalls": [
"It makes the library the current document.",
"count is the true total; names[] stops at limit."
],
"related": [
"show_library",
"read_symbol",
"pcb_report"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.PcbLib"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "list_nets",
"tier": "core",
"source": "altium",
"summary": "Every net on the current board with its pad count.",
"input": {},
"output": {
"data": "{count, nets: [{name, pads}]}",
"roundtripMs": "int"
},
"hint": "Then altium_net_connections {net} for the pads of one net.",
"pitfalls": [
"Needs a .PcbDoc current.",
"Pad counts are tallied over pads: a net with no pads on it does not appear."
],
"related": [
"net_connections",
"read_board"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "move_parts",
"tier": "core",
"source": "altium",
"summary": "Move, rotate and flip placed components (side top or bottom; flip:true turns a part over); each part is read back to 0.001 mm, the exact rotation and its side. One undo step.",
"input": {
"boardId": "string (optional) - refused with board_mismatch unless this is the current board",
"expectPath": "string (optional)",
"expectedRevision": "string (optional) - the revision you last read; refused with stale_board if the board changed",
"parts": "[{ref, x, y, rotation, side?: top|bottom, flip?: bool}] - mm and degrees, Altium's frame; or {ref, dx, dy} to move by an offset; rotation and side kept when left out"
},
"output": {
"mismatches": "[{ref, asked, got}] when a part did not land where asked (errorCode readback_mismatch)",
"results": "[ok|err:...]",
"revision": "string"
},
"hint": "Rotation is absolute, not a delta. A part flipped to the bottom is mirrored by Altium; give the rotation you want as seen from the top.",
"pitfalls": [
"Flipping a part leaves its tracks where they were: they no longer reach its pads on the other side. Re-route after a flip."
],
"related": [
"routing_state",
"route_net"
],
"example": {
"parts": [
{
"ref": "U1",
"rotation": 90,
"x": 112.0,
"y": 92.0
}
]
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "net_connections",
"tier": "core",
"source": "altium",
"summary": "Every pad on the board with its net and owner (Designator.Pad), plus a bounding span and the airline length (minimum spanning tree over its pads, airlineMm) per net. net filters to one net.",
"input": {
"limit": "int, default 4000 - caps pads",
"net": "string - optional net name"
},
"output": {
"data": "{count, pads: [{net, pad: 'U1.3', xMil, yMil}], nets: [{net, minXminYmaxXmaxYpads}]}",
"roundtripMs": "int"
},
"hint": "Pass net on anything but a small board. The span string is 'minX,minY,maxX,maxY,pads' in mils: a quick measure of how far a net travels.",
"pitfalls": [
"Needs a .PcbDoc current.",
"limit truncates silently: count is what was returned, not what exists."
],
"related": [
"list_nets",
"component_pins"
],
"example": {
"net": "GND"
},
"longRunning": false,
"timeoutSeconds": 120,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "normalize_bodies",
"tier": "core",
"source": "altium",
"summary": "Move every 3D body of a PcbLib's footprints (or one footprint) onto its pad cluster. A body added through the canvas lands 50000 mil from the pads in the stored frame, which makes Zoom All frame 50 inches of nothing.",
"input": {
"footprintName": "string - optional filter",
"libraryPath": "path to a .PcbLib - optional; opened first",
"timeout": "seconds, default 120"
},
"output": {
"data": "{moved: int, shifts: string}",
"roundtripMs": "int"
},
"hint": "altium_add_body already runs it. Use it on libraries built elsewhere when altium_show_footprint shows an empty canvas; then altium_save.",
"pitfalls": [
"Without libraryPath it acts on whatever PcbLib is current ('no PCB library is current' otherwise).",
"It centres bodies on the pad-cluster centre: a deliberately offset body is moved too."
],
"related": [
"add_body",
"pcb_report",
"show_3d_chip",
"save"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.PcbLib"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "part_parameters",
"tier": "core",
"source": "altium",
"summary": "The parameter names a project's parts carry (with how many parts carry each), or with name, that parameter's value on every part.",
"input": {
"name": "a parameter name - optional",
"projectPath": "path to the .PrjPcb (required)"
},
"output": {
"names": "[{name, parts}]",
"values": "[{designator, value, sheet}] (with name)"
},
"hint": "Change values with altium_sheet_params; altium_bom groups the purchasing ones by MPN.",
"pitfalls": [],
"related": [
"sheet_params",
"bom",
"schematic_data"
],
"example": {
"name": "MPN",
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "place_on_pcb",
"tier": "core",
"source": "altium",
"summary": "Place ONE footprint from a PcbLib on a new board and return a proof frame. The single-part predecessor of altium_test_board.",
"input": {
"footprintName": "string",
"libraryPath": "path to a .PcbLib (required)",
"pcbPath": "path to save the new .PcbDoc - optional",
"timeout": "seconds, default 90"
},
"output": {
"data": "{pcb, placed, libFile, libBodies, primitives, padsOnComp, bodiesOnComp}",
"shot": "{image: base64 png, width, height}",
"windowEtiquette": "background"
},
"hint": "Prefer altium_test_board (outline, several parts, nets). bodiesOnComp:0 with libBodies>0 means the body did not copy: report it.",
"pitfalls": [
"Every call creates a NEW PcbDoc; without pcbPath it exists only unsaved.",
"'footprint not found in PcbLib' - names from altium_list_library."
],
"related": [
"test_board",
"place_on_sch",
"show_3d_board"
],
"example": {
"footprintName": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.PcbLib",
"pcbPath": "C:/proj/one.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "place_on_sch",
"tier": "core",
"source": "altium",
"summary": "Place one symbol, or a ';' list of symbols, from the open SchLib on ONE new sheet (sheet sized FROM the measured parts: 500 mil gaps, 600 mil margins, A4 minimum; parts inside the frame as U1..Un with the part number as Comment); fills the title block from title/number/revision/drawnBy and places description as a text frame; saves to schPath when given. When schPath names an EXISTING .SchDoc the symbols are APPENDED to it (right of the current ones, designators continuing; sheet size and title block untouched, issue 11).",
"input": {
"description": "string (what the sheet shows, 2-3 sentences)",
"drawnBy": "string",
"libraryPath": "path (.SchLib)",
"number": "string (DocumentNumber)",
"revision": "string",
"schPath": "path (.SchDoc, optional save)",
"symbolName": "string | 'A;B;C'",
"title": "string (Title)"
},
"output": {
"count": "int",
"designator": "string",
"placed": "string",
"primitives": "int",
"sch": "path"
},
"hint": "Three parts on one sheet: symbolName 'VL53L5CX;VL53L7CX;VL53L8CX' + schPath, then altium_show_schematic {filePath: schPath}.",
"pitfalls": [
"Every call creates a NEW SchDoc; there is no append-to-sheet yet.",
"The SchLib must be the current document (the verb opens it)."
],
"related": [
"test_board",
"show_schematic",
"read_schematic"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"schPath": "C:/proj/tof.SchDoc",
"symbolName": "VL53L5CX;VL53L7CX;VL53L8CX"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "place_parts",
"tier": "core",
"source": "proposed",
"summary": "Put footprints from a library onto the current board, each with its position, rotation and side, and read them back. One undo step.",
"input": {
"filePath": "the board (default the current one)",
"parts": "[{library, footprint, ref?, value?, x, y, rotation?: 0, side?: top|bottom, nets?: {pad: net}}] mm and degrees (required)",
"dryRun": "bool, default false: answer the plan and change nothing",
"expectedRevision": "optional: refused with stale_board if the board changed"
},
"output": {
"results": "[ok|err:...] per part",
"placed": "[{ref, x, y, rotation, side}]",
"revision": "string"
},
"hint": "For parts with no sheet behind them: mounting hardware, test points, or a board built without a schematic. A taken designator is refused and the next free one is named.",
"pitfalls": [
"On a board with a schematic, parts normally arrive through update_pcb: a part placed here is on no sheet, and the next update_pcb lists it in removeParts.",
"Fusion's linked board is partial: only a standalone board takes a direct add."
],
"related": [
"update_pcb",
"move_parts",
"remove_parts",
"routing_state"
],
"example": {
"parts": [
{
"library": "Resistor_SMD",
"footprint": "R_0603_1608Metric",
"ref": "R12",
"x": 120.0,
"y": 95.0
}
]
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.31.1",
"agreedBy": [
"altium-lane"
]
},
{
"name": "place_vias",
"tier": "core",
"source": "altium",
"summary": "Place vias (through, top to bottom). One undo step, read back.",
"input": {
"boardId": "string (optional) - refused with board_mismatch unless this is the current board",
"expectPath": "string (optional)",
"expectedRevision": "string (optional) - the revision you last read; refused with stale_board if the board changed",
"vias": "[{net, x, y, size, drill}] - mm"
},
"output": {
"counts": "{vias, ...}",
"results": "[ok|err:...]",
"revision": "string"
},
"hint": "Through vias, top to bottom, on the named net. Heatsink vias under a pad: place them here, then pour or route to them.",
"pitfalls": [],
"related": [
"route_net",
"routing_state"
],
"example": {
"vias": [
{
"drill": 0.3,
"net": "GND",
"size": 0.6,
"x": 110.0,
"y": 90.0
}
]
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "plate_vias",
"tier": "core",
"source": "altium",
"summary": "Make every drilled pad in a PcbLib a plated MULTI-LAYER pad (all footprints, or footprintName). adom-lbr writes heatsink vias as pads with a hole; Altium loaded them on the Top Layer, so a thermal pad's vias were not through-holes until this ran.",
"input": {
"footprintName": "string (optional filter)",
"libraryPath": "path (.PcbLib)"
},
"output": {
"fixed": "Fp:Pad;...",
"holes": "int",
"plated": "int"
},
"hint": "altium_save the PcbLib afterwards; footprint_primitives on a placed part should then report layerId 74 for the vias.",
"pitfalls": [
"Read-modify in place: run once per library install."
],
"related": [
"normalize_bodies",
"footprint_primitives",
"save"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.PcbLib"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "project_create",
"tier": "core",
"source": "proposed",
"summary": "Create a new project folder with a project file, an empty schematic and an empty board (2 to 32 copper layers), with a title and text variables.",
"input": {
"parentDir": "folder to create the project in (required)",
"name": "string (required): the project and folder name",
"title": "string",
"layers": "int, default 2",
"fabRules": "a fab name from adom/pcb-design-rules, recorded to apply once the board has content",
"textVariables": "{\"REV\": \"A\"}",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"project": "path",
"files": "[path]"
},
"hint": "Next: draw the outline (set_outline), then place and route. fabRules is recorded, not applied.",
"pitfalls": [
"A folder that already holds a project is refused.",
"The board has no outline yet: set it before routing or exporting."
],
"related": [
"project_info",
"sch_create",
"set_outline"
],
"example": {
"parentDir": "C:/Users/me/Documents/Projects",
"name": "widget",
"layers": 4
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "project_info",
"tier": "core",
"source": "proposed",
"summary": "A project at a glance: name, files with sizes and dates, the sheet tree, the board (layers, parts, nets, size), text variables, net classes, last change, and whether the tool has it open. Read only.",
"input": {
"project": "path to the project file, its folder or any of its documents (required)"
},
"output": {
"name": "string",
"files": "[{path, bytes, modified}]",
"sheets": "the sheet tree, as sch_hierarchy answers it",
"board": "{layers, parts, nets, sizeMm}",
"textVariables": "{name: value}",
"netClasses": "[string]",
"modified": "date",
"open": "bool: the tool has a document of this project open"
},
"hint": "Read this before renaming, snapshotting or editing a project.",
"pitfalls": [],
"related": [
"sch_hierarchy",
"board_summary",
"open_project"
],
"example": {
"project": "C:/proj/Board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "project_rename",
"tier": "core",
"source": "proposed",
"summary": "Rename a project: the project file, the root sheet, the board and the tool's side files, with the references inside them updated. Refused while the tool has the project open.",
"input": {
"project": "path to the project file (required)",
"newName": "string (required)",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"renamed": "[{from, to}]",
"changed": "[{file, what}]"
},
"hint": "Dry-run first: the plan lists every file renamed and what changes inside each. Close the project in the tool first.",
"pitfalls": [
"Child sheet files keep their names; only the documents named after the project are renamed.",
"The folder keeps its name.",
"Take a project_snapshot first if the project is not under version control."
],
"related": [
"project_snapshot",
"project_info",
"close"
],
"example": {
"project": "C:/proj/Old.PrjPcb",
"newName": "widget-v2",
"dryRun": true
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "read_board",
"tier": "core",
"source": "altium",
"summary": "ONE round trip: components, nets, layers, copper, rules, occupancy, outline.",
"input": {
"limit": "int",
"sections": "string csv - optional"
},
"output": {
"data": "object - the agent's payload",
"roundtripMs": "int",
"success": "bool"
},
"hint": "The primitive every board view derives from; board_summary / rules_by_kind / layers_in_use are shaped from the same read.",
"pitfalls": [
"Needs a .PcbDoc current."
],
"related": [
"board_summary",
"review_board"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "read_footprint",
"tier": "core",
"source": "proposed",
"summary": "Every detail of one library footprint: pads (number, type, shape, position, size, drill, layers), the layers it uses, its courtyard box, graphics per layer, attributes, properties and 3D models. The library mirror of read_symbol; footprint_primitives reads a part placed on the board.",
"input": {
"libraryPath": "path to the footprint library",
"name": "the footprint's name (with libraryPath)",
"libId": "\"Lib:Name\": resolved through the project's and then the global library table",
"project": "path to the project, for libId"
},
"output": {
"name": "string",
"pads": "[{number, type, shape, at, sizeMm, drillMm, layers, rotation}]",
"layers": "[string]",
"courtyardMm": "[x1, y1, x2, y2]",
"graphics": "{layer: count}",
"attributes": "{mount, excludeFromBom, excludeFromPos, dnp}",
"properties": "{name: value}",
"models": "[{path, offset, scale, rotate}]"
},
"hint": "Read before edit_footprint, and to check pin 1 and the pad numbers against the symbol.",
"pitfalls": [],
"related": [
"edit_footprint",
"read_symbol",
"footprint_primitives",
"list_library"
],
"example": {
"libId": "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm"
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "read_rules",
"tier": "core",
"source": "altium",
"summary": "Every design rule on the current board, flat, disabled ones included: name, kind ordinal, enabled, priority, both scope expressions, comment, and Altium's descriptor with the rule's VALUES (e.g. 'Clearance Constraint (Gap=6mil) (All),(All)').",
"input": {},
"output": {
"data": "{count, rules: [{name, kind: int, enabled, priority, scope1, scope2, comment, descriptor}]}",
"roundtripMs": "int"
},
"hint": "altium_rules_by_kind groups the enabled ones under readable kind names; altium_run_drc checks the board against them.",
"pitfalls": [
"Needs a .PcbDoc current.",
"kind is Altium's TRuleKind ORDINAL; the values are in descriptor, as Altium words them."
],
"related": [
"rules_by_kind",
"run_drc"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "read_schematic",
"tier": "core",
"source": "altium",
"summary": "Components on the CURRENT schematic sheet (designator, library reference, comment, position, parameters) in one agent round trip.",
"input": {
"limit": "int, default 500",
"params": "bool, default true - include component parameters",
"sections": "string csv, default 'components'"
},
"output": {
"components": "[{designator, libReference, comment, ...}]",
"count": "int",
"designators": "[string]",
"document": "string",
"roundtripMs": "int"
},
"hint": "Then altium_cross_check {board, sheet} to compare against the layout, or altium_schematic_data {designator} for one part's pins.",
"pitfalls": [
"The CURRENT sheet only: a hierarchical parent holds sheet symbols, not parts. Read each leaf sheet.",
"Needs a .SchDoc current; 'no current schematic' -> altium_open_document / altium_show_schematic."
],
"related": [
"schematic_data",
"cross_check",
"show_schematic",
"activate_document"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "read_symbol",
"tier": "core",
"source": "altium",
"summary": "Read a SchLib component back: description, display-mode count, the pins of mode 0 (designator, name, electrical type), every parameter with its hidden flag, and its model links (footprints, 3D, sim).",
"input": {
"libraryPath": "path to a .SchLib - optional; opened first",
"symbolName": "string",
"timeout": "seconds, default 90"
},
"output": {
"data": "{libref, description, displayModeCount, pinsMode0: int, pins: [{des, name, electrical: 0 Input, 1 IO, 2 Output, 3 OpenCollector, 4 Passive, 5 HiZ, 6 OpenEmitter, 7 Power}], params: [{name, value, hidden}], models: [{type, name, isCurrent}]}",
"roundtripMs": "int"
},
"hint": "The verification step after altium_import_part / altium_set_params: models[] shows which footprint the symbol is bound to (type PCBLIB, isCurrent true for the one a placed part uses). For the drawing use altium_symbol_prims.",
"pitfalls": [
"The SCH Library panel's Model pane can lag behind altium_show_symbol; models[] here is the symbol's own record.",
"Only mode 0 pins are listed."
],
"related": [
"symbol_prims",
"set_params",
"list_library",
"show_symbol"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"symbolName": "VL53L5CX"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "remove_footprint",
"tier": "core",
"source": "altium",
"summary": "Delete one footprint from the current PcbLib.",
"input": {
"footprintName": "string",
"libraryPath": "path to a .PcbLib - optional; opened first",
"timeout": "seconds, default 90"
},
"output": {
"data": "{removed: string}",
"roundtripMs": "int"
},
"hint": "altium_save afterwards. Symbols that linked it keep a dangling model: altium_set_models.",
"pitfalls": [
"No undo through the bridge; closing the library without saving is the way back."
],
"related": [
"remove_symbol",
"cleanup_libs",
"list_library",
"save"
],
"example": {
"footprintName": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.PcbLib"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "remove_graphics",
"tier": "core",
"source": "proposed",
"summary": "Remove board graphics (lines, rectangles, circles, arcs, polygons, texts, dimensions) by id, or every one on a layer and of a kind. One undo step.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"expectedRevision": "string: the revision you last read (routing_state); refused with stale_board if the board changed",
"ids": "[id]",
"layer": "\"F.SilkS\": every graphic on this layer",
"kinds": "[line|rect|circle|arc|polygon|text|dimension]",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"removed": "[{id, kind, layer, points}]",
"revision": "string: the board's new revision"
},
"hint": "Board-level graphics only; graphics inside parts are footprint_primitives. An unknown id refuses the whole call (unknown_ids).",
"pitfalls": [
"Removing Edge.Cuts graphics removes the board outline.",
"A layer or kind filter without ids removes every match: dry-run it first."
],
"related": [
"remove_items",
"footprint_primitives",
"silk_state"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"layer": "Dwgs.User",
"dryRun": true
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "remove_items",
"tier": "core",
"source": "altium",
"summary": "Delete specific free tracks and vias, given exactly as altium_routing_state returned them. One undo step.",
"input": {
"boardId": "string (optional) - refused with board_mismatch unless this is the current board",
"expectPath": "string (optional)",
"expectedRevision": "string (optional) - the revision you last read; refused with stale_board if the board changed",
"tracks": "[{start{x,y}, end{x,y}, layer}]",
"vias": "[{position{x,y}}] or [{x,y}]"
},
"output": {
"results": "[ok|err:not found]",
"revision": "string"
},
"hint": "Undo a bad segment or via without touching the rest of the net; altium_ripup_nets clears a whole net.",
"pitfalls": [
"Matching is exact to the internal unit: pass the coordinates you read, not rounded ones."
],
"related": [
"ripup_nets",
"routing_state"
],
"example": {
"vias": [
{
"x": 110.0,
"y": 90.0
}
]
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "remove_parts",
"tier": "core",
"source": "proposed",
"summary": "Remove placed parts from the board by designator, as one undo step. The library is not touched (that is remove_footprint).",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"expectedRevision": "string: the revision you last read (routing_state); refused with stale_board if the board changed",
"refs": "[\"R7\", \"R8\"] (required)",
"allowLocked": "bool, default false",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"removed": "[{ref, nets: [string]}]",
"failed": "[{ref, error}]",
"revision": "string: the board's new revision"
},
"hint": "Each removed part lists the nets its pads carried. A locked part is refused (part_locked) unless allowLocked:true.",
"pitfalls": [
"Tracks and vias that met the pads stay: routing_state shows what is left dangling.",
"A part still in the schematic comes back at the next update_pcb."
],
"related": [
"move_parts",
"routing_state",
"update_pcb"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"refs": [
"TP3"
],
"expectedRevision": "<rev>"
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "remove_symbol",
"tier": "core",
"source": "altium",
"summary": "Delete one component from the current SchLib.",
"input": {
"libraryPath": "path to a .SchLib - optional; opened first",
"symbolName": "string",
"timeout": "seconds, default 60"
},
"output": {
"data": "{removed: string}",
"roundtripMs": "int"
},
"hint": "The repair step for a symbol with duplicate models: remove, altium_import_part again, altium_save.",
"pitfalls": [
"No undo through the bridge; the library is unsaved until altium_save, so altium_close_document without saving is the way back."
],
"related": [
"import_part",
"cleanup_libs",
"list_library",
"save"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"symbolName": "VL53L5CX"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "rename_footprint",
"tier": "core",
"source": "altium",
"summary": "Rename a footprint in the current PcbLib.",
"input": {
"from": "string",
"libraryPath": "path to a .PcbLib - optional; opened first",
"timeout": "seconds, default 90",
"to": "string"
},
"output": {
"data": "{renamed: string}",
"roundtripMs": "int"
},
"hint": "altium_save, then re-link symbols that referenced the old name: altium_set_models {footprint: <new name>}.",
"pitfalls": [
"'to' is NOT checked: an empty or already-used name is applied as given.",
"Symbols link footprints BY NAME: a rename silently breaks their models."
],
"related": [
"copy_footprint",
"rename_symbol",
"set_models",
"save"
],
"example": {
"from": "PCBComponent_1",
"libraryPath": "C:/lib/Adom_ToF.PcbLib",
"to": "VL53L5CX"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "rename_symbol",
"tier": "core",
"source": "altium",
"summary": "Rename a component (LibReference) in the current SchLib.",
"input": {
"from": "string",
"libraryPath": "path to a .SchLib - optional; opened first",
"timeout": "seconds, default 90",
"to": "string"
},
"output": {
"data": "{renamed: string}",
"roundtripMs": "int"
},
"hint": "altium_save, then altium_list_library to confirm.",
"pitfalls": [
"'to' is NOT checked: an empty or already-used name is applied as given. altium_list_library first."
],
"related": [
"clone_symbol",
"rename_footprint",
"list_library",
"save"
],
"example": {
"from": "Component_1",
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"to": "VL53L5CX"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "ripup_nets",
"tier": "core",
"source": "altium",
"summary": "Delete every free track, arc and via on each named net. One undo step.",
"input": {
"boardId": "string (optional) - refused with board_mismatch unless this is the current board",
"expectPath": "string (optional)",
"expectedRevision": "string (optional) - the revision you last read; refused with stale_board if the board changed",
"nets": "[string]"
},
"output": {
"results": "[ok:<deleted count>]",
"revision": "string"
},
"hint": "Pours are not touched.",
"pitfalls": [],
"related": [
"remove_items",
"route_net"
],
"example": {
"nets": [
"SW",
"VOUT"
]
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "route_net",
"tier": "core",
"source": "altium",
"summary": "Route one net as tracks, segment by segment; a waypoint on another layer drops a via there. One undo step, read back.",
"input": {
"boardId": "string (optional) - refused with board_mismatch unless this is the current board",
"expectPath": "string (optional)",
"expectedRevision": "string (optional) - the revision you last read; refused with stale_board if the board changed",
"layer": "F.Cu|B.Cu|In<n>.Cu or an Altium layer id (default F.Cu)",
"net": "string (required)",
"paths": "[[waypoint,...]] - a waypoint is [x,y], {x,y,layer} or {pad:\"U1.3\"}",
"viaDrill": "mm (default 0.3)",
"viaSize": "mm (default 0.6)",
"width": "mm (default 0.25)"
},
"output": {
"applied": "int",
"counts": "{tracks, vias, ...}",
"failed": "int",
"results": "[ok|err:...] per segment/via",
"revision": "string - the board after the edit",
"state": "the full altium_routing_state after",
"unconnected": "int"
},
"hint": "Coordinates are mm in Altium's frame, the same as altium_routing_state. There is no clearance check here yet: run your own DRC (AI Flow's gate) or altium_run_drc after.",
"pitfalls": [
"Needs the board current.",
"A net name must already exist on the board (nets come from the schematic / pads)."
],
"related": [
"routing_state",
"place_vias",
"remove_items",
"ripup_nets"
],
"example": {
"net": "VOUT",
"paths": [
[
{
"pad": "L1.2"
},
[
120.0,
90.0
],
{
"pad": "C6.1"
}
]
],
"width": 0.5
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "routing_state",
"tier": "core",
"source": "altium",
"summary": "The WHOLE current board as data, in mm: tracks, arcs, vias, pads (with owner and net), components (ref, x, y, rotation, side), polygon pours, the outline, the unrouted (ratsnest) count, and a revision hash.",
"input": {
"expectPath": "string (optional) - refuse with wrong_board unless this .PcbDoc is the current board"
},
"output": {
"altiumRatsnest": "int - Altium's own count",
"boardId": "string (the .PcbDoc path)",
"components": "[{ref, x, y, rotation, side, pattern}]",
"counts": "{tracks, arcs, vias, pads, components, polygons, nets}",
"isolatedCopper": "[{net, layer, at{x,y}}] - pours that touch nothing else of their net: not counted in unconnected",
"outline": "[[x,y]]",
"pads": "[{ref, name, x, y, sizeX, sizeY, rotation, layer, drill, net}]",
"polygons": "[{net, layer, points[[x,y]]}]",
"revision": "string - pass as expectedRevision to the edit verbs",
"splitNets": "[{net, groups}]",
"tracks": "[{start{x,y}, end{x,y}, width, layer, net}]",
"unconnected": "int - connections still to make, from the copper",
"vias": "[{position{x,y}, size, drill, layers[2], net}]"
},
"hint": "Layers use KiCad names (F.Cu, B.Cu, In<n>.Cu; *.Cu = a multi-layer pad) with Altium's layerId alongside. Coordinates are Altium's own frame (y up), in mm. This is the read AI Flow's Altium lane calls before and after every edit.",
"pitfalls": [
"Needs a .PcbDoc current (altium_show_2d_board {filePath}).",
"Footprint-internal tracks and arcs are left out; only free copper is listed.",
"unconnected is computed from the copper (Altium's ratsnest skips parts off the board; its count rides along as altiumRatsnest). A pour that reaches nothing else of its net is listed under isolatedCopper and not counted. Re-read after an edit for a fresh count."
],
"related": [
"read_board",
"net_connections",
"footprint_primitives"
],
"example": {
"expectPath": "C:/designs/buck/buck.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "rules_by_kind",
"tier": "core",
"source": "altium",
"summary": "The current board's ENABLED design rules grouped by rule kind (Clearance, Width, RoutingVias, ...), each group sorted by priority. Shaped from one read_board round trip.",
"input": {
"limit": "int, default 2000",
"sections": "string csv - optional"
},
"output": {
"board": "path",
"roundtripMs": "int",
"rulesByKind": "{KindName: [{name, kind, enabled, priority, scope1, scope2, comment}]}"
},
"hint": "Use it to answer 'what clearance/width does this board enforce'. altium_read_rules gives the flat list including disabled rules; altium_run_drc checks the board against them.",
"pitfalls": [
"Needs a .PcbDoc current.",
"Disabled rules are dropped; a rule kind the bridge has no name for appears as 'kind <n>'."
],
"related": [
"read_rules",
"run_drc",
"board_summary"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "sch_batch",
"tier": "core",
"source": "proposed",
"summary": "Apply a list of schematic edits to one sheet in one read and one write, all or nothing: each op is a standard schematic verb with its own arguments, seeing the sheet as the earlier ops left it.",
"input": {
"filePath": "the sheet (required)",
"ops": "[{op: a standard schematic verb's name (sch_place_part, sch_connect_pins, sch_connect, sch_edit, sch_edit_label, sch_junction, sch_bus, sch_bus_entry, sch_text, sch_delete_wire, sch_split_wire, sch_move_region, sch_reset_fields, sch_update_from_library, annotate, ...), ...that verb's arguments}] (required)",
"dryRun": "bool: report the plan, write nothing"
},
"output": {
"results": "[{op, output, uuid?}] in order",
"ercBefore": "the sheet's ERC counts before",
"ercAfter": "and after",
"failedOp": "the index of the op that failed (nothing is written then)",
"mutated": "bool"
},
"hint": "A part placed in op 0 can be wired in op 1. A failing op aborts the whole batch: failedOp names it and the sheet is unchanged.",
"pitfalls": [
"A bridge whose tool cannot undo a partial batch answers partial: it says which ops ran before the failure."
],
"related": [
"build_schematic",
"sch_place_part",
"sch_connect_pins",
"run_erc"
],
"example": {
"filePath": "C:/proj/board.kicad_sch",
"ops": [
{
"op": "sch_place_part",
"libId": "Device:R",
"reference": "R9",
"at": [
100,
80
]
},
{
"op": "sch_connect_pins",
"pairs": [
[
"R9.1",
"U1.3"
]
]
}
]
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.26.4",
"agreedBy": [
"standard-lane",
"fusion-lane"
]
},
{
"name": "sch_bus",
"tier": "core",
"source": "proposed",
"summary": "Draw a bus as a polyline (one bus segment per pair of points), optionally with a bus label such as D[0..7] or a group {SDA SCL} at its first point. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"points": "[[x, y], [x, y], ...] mm (required)",
"label": "\"D[0..7]\" or \"{SDA SCL}\": the nets the bus carries",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"ids": "[bus segment id]",
"label": "{id, text} or null",
"saved": "bool"
},
"hint": "A bus carries the nets its label names, and each member wire needs its own label. sch_connect_to_bus does the member wires, entries and labels for a set of pins.",
"pitfalls": [
"A bus with no label carries nothing: ERC reports its members as unconnected."
],
"related": [
"sch_bus_entry",
"sch_connect_to_bus",
"sch_delete_wire",
"sch_items"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"points": [
[
203.2,
50.8
],
[
203.2,
101.6
]
],
"label": "D[0..7]"
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_bus_entry",
"tier": "core",
"source": "proposed",
"summary": "Add 45-degree bus entries: the short diagonal that joins a member wire's end to a bus. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"entries": "[{at: [x, y] mm (the wire end), direction: up-right|down-right|up-left|down-left as seen (default down-right)}] (required)",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"added": "[{id, at, end: [x, y] (the bus side), onBus: bool}]",
"saved": "bool"
},
"hint": "end is the bus side of each entry; onBus says whether it lands on a bus segment.",
"pitfalls": [
"The bus side must touch a bus and the other end a wire end, exactly, or ERC reports the entry as unconnected."
],
"related": [
"sch_bus",
"sch_connect_to_bus",
"sch_items"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"entries": [
{
"at": [
200.66,
63.5
],
"direction": "up-right"
}
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_connect",
"tier": "core",
"source": "altium",
"summary": "Connect pins of placed parts: a wire stub from each pin's outer end plus a net label (kind label), a power port (kind power: GND-like nets get a ground symbol) or the stub alone (kind wire); or mark a pin left open on purpose with a No ERC marker (kind noerc, no net). One undo step.",
"input": {
"connections": "[{designator, pin (number or name), net, kind: label|power|wire|noerc|port (default label), io?: input|output|bidirectional (port), stubMil (default 200)}] (required)",
"save": "bool, default true",
"sheet": "path to the .SchDoc (required)"
},
"output": {
"connected": "int",
"failed": "[..]",
"results": "[{designator, pin, net, kind, result, endMil}]",
"saved": "bool"
},
"hint": "Net labels with the same text connect across the project; power ports connect by net name everywhere. Check the result with altium_compile (ERC) or altium_schematic_data.",
"pitfalls": [
"A pin that already has a wire gets a second stub; read the sheet first when unsure.",
"A part rotated after connecting leaves its stubs behind."
],
"related": [
"sch_place_part",
"compile",
"schematic_data"
],
"example": {
"connections": [
{
"designator": "U2",
"kind": "power",
"net": "GND",
"pin": "1"
},
{
"designator": "U2",
"net": "VIN",
"pin": "VIN"
}
],
"sheet": "C:/proj/Main.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 90,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "sch_connect_pins",
"tier": "core",
"source": "proposed",
"summary": "Wire pins to pins on a sheet by Ref.Pin: an L-shaped route (one horizontal and one vertical leg) for each pair, with a junction dot wherever a route meets an existing wire in a T. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"pairs": "[{from: \"U1.1\", to: \"R5.2\", first?: h|v (the leg to draw first; default along the axis the from pin points), via?: [[x, y], ...] mm waypoints}] (required)",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"wired": "int",
"routes": "[{from, to, points: [[x, y]], ids: [wire id]}]",
"junctionsAdded": "[[x, y]]",
"failed": "[{from, to, error}]",
"saved": "bool"
},
"hint": "Pins are matched by number, then by name. Aligned pins get one straight wire; otherwise the route turns once. Check the result with sch_pins (connectedPins) or run_erc.",
"pitfalls": [
"The route does not avoid part bodies or other wires: a leg running along another wire merges the two nets. Steer with first or via, and check with sch_pins."
],
"related": [
"sch_pins",
"sch_connect",
"sch_delete_wire",
"run_erc"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"pairs": [
{
"from": "U1.1",
"to": "R2.1"
},
{
"from": "U1.2",
"to": "C3.1",
"first": "v"
}
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_connect_to_bus",
"tier": "core",
"source": "proposed",
"summary": "Fan pins onto a bus: for each pin a wire running to the bus, a 45-degree bus entry onto it and a member label (D0, D1 ...) on the wire. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"pins": "[\"U1.1\", \"U1.2\"] Ref.Pin, in member order (required)",
"bus": "id of the bus segment (default the only bus on the sheet)",
"members": "[\"D0\", \"D1\"]: the member names in pin order",
"prefix": "\"D\": or name members prefix + number",
"start": "int, default 0: the first number with prefix",
"entry": "up|down (a vertical bus) or left|right (a horizontal bus): the way the entries lean",
"busLabel": "\"D[0..7]\": also label the bus",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"connected": "[{pin, member, wireId, entryId}]",
"busLabel": "string or null",
"failed": "[{pin, error}]",
"saved": "bool"
},
"hint": "Members name the nets: members lists them in pin order, or prefix plus start counts up. Refused with entry_off_bus when an entry would miss the bus: extend the bus with sch_bus first.",
"pitfalls": [
"Pins should face the bus; a pin facing away gets a wire across its own part.",
"Two pins at the same height on a vertical bus share an entry point and collide: offset them or lean the entries differently."
],
"related": [
"sch_bus",
"sch_bus_entry",
"sch_pins"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"pins": [
"U1.1",
"U1.7"
],
"prefix": "D",
"busLabel": "D[0..1]"
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_create",
"tier": "core",
"source": "proposed",
"summary": "Create an empty schematic sheet with a paper size and title block; optionally add it to a project as a child sheet of the root. It places no parts or nets (build_schematic does).",
"input": {
"sheet": "path of the sheet to create (required)",
"paper": "A4, A3 ... USLetter or custom",
"orientation": "portrait|landscape",
"widthMm": "number (custom)",
"heightMm": "number (custom)",
"title": "string",
"date": "string",
"rev": "string",
"company": "string",
"comments": "[string]",
"project": "path: add the sheet to this project under its root sheet",
"sheetName": "string: the sheet symbol's name in the root",
"at": "[x, y] mm: where the sheet symbol goes on the root",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"sheet": "path",
"page": "int",
"sheetSymbol": "{id, name, at} or null",
"created": "bool"
},
"hint": "Without project the sheet stands alone. With project it is linked from the root sheet as a child sheet with the next page number.",
"pitfalls": [
"Never overwrites: an existing file is refused.",
"A new child sheet has no pins on its symbol: add hierarchical ports inside, then sch_sheet_pins {import:true}."
],
"related": [
"sch_page",
"sch_hierarchy",
"sch_sheet_pins",
"sch_place_part"
],
"example": {
"sheet": "C:/proj/Power.SchDoc",
"project": "C:/proj/Board.PrjPcb",
"sheetName": "Power",
"title": "Power"
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_delete_wire",
"tier": "core",
"source": "proposed",
"summary": "Delete wires or bus segments by id, by their two ends, or every wire through a point, and remove junction dots that no longer join three or more items. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"ids": "[wire id, ...]",
"from": "[x, y] mm, with to: the wire with exactly these ends (either order)",
"to": "[x, y] mm",
"at": "[x, y] mm: every wire passing through the point",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"deleted": "[{id, from, to}]",
"junctionsRemoved": "[[x, y]]",
"saved": "bool"
},
"hint": "Read ids with sch_items. from/to matches one segment, not a whole route.",
"pitfalls": [
"A polyline drawn in the editor is several wires sharing ends: from/to names one segment of it."
],
"related": [
"sch_items",
"sch_split_wire",
"sch_junction",
"sch_connect_pins"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"from": [
100.33,
60.96
],
"to": [
120.65,
60.96
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_edit",
"tier": "core",
"source": "altium",
"summary": "Change placed parts on a sheet: move (to x,y mil), moveBy (dx,dy), rotate (degrees), rename (designator), re-comment (comment), delete. One undo step.",
"input": {
"edits": "[{designator, action: move|moveBy|rotate|designator|comment|delete, x,y | dx,dy | degrees | to | text}] (required)",
"save": "bool, default true",
"sheet": "path to the .SchDoc (required)"
},
"output": {
"applied": "int",
"failed": "[..]",
"results": "[{designator, action, result}]",
"saved": "bool"
},
"hint": "Wires do not follow a moved part; reconnect with altium_sch_connect. Renames and deletions reach the board with altium_update_pcb.",
"pitfalls": [
"Every part of a multi-part component with that designator is changed together."
],
"related": [
"sch_connect",
"update_pcb",
"sheet_params"
],
"example": {
"edits": [
{
"action": "comment",
"designator": "R5",
"text": "10k"
},
{
"action": "delete",
"designator": "C9"
}
],
"sheet": "C:/proj/Main.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "sch_edit_label",
"tier": "core",
"source": "proposed",
"summary": "Edit net labels: rotate, move to a point or by a delta, rename, or move every label of a net at once. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"edits": "[{id | text (with at?: [x, y] to pick one) | net (every label of the net), rotation?: 0|90|180|270, to?: [x, y] mm (one label only), by?: [dx, dy] mm, rename?: string}] (required)",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"edited": "[{id, text, at, rotation}]",
"failed": "[{edit, error}]",
"saved": "bool"
},
"hint": "text picks every label with that text (or the one at at); net picks every label of the net. Read ids with sch_items.",
"pitfalls": [
"A label joins a net only where it sits on a wire or a pin end: moving it off disconnects it.",
"rename changes only the labels picked: other labels with the old name stay on the old net."
],
"related": [
"sch_items",
"sch_connect",
"sch_edit"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"edits": [
{
"net": "VOUT",
"by": [
0,
2.54
]
}
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_fix_connectivity",
"tier": "core",
"source": "proposed",
"summary": "Snap near-miss wire ends onto the pin, label, sheet pin or wire end they almost touch, within a tolerance. dryRun (the default) lists the moves; dryRun:false makes them.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"toleranceMm": "number, default 0.5",
"dryRun": "bool, default TRUE",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"moves": "[{wireId, from, to, onto: {kind, id}, diagonal: bool}]",
"unresolved": "[[x, y]]: dangling ends with nothing close",
"saved": "bool"
},
"hint": "Only dangling wire ends move. Read the moves before applying them: diagonal:true means the snapped wire is no longer horizontal or vertical. Check with run_erc after.",
"pitfalls": [
"dryRun defaults to true: nothing changes until dryRun:false.",
"A wide tolerance can snap onto the wrong pin: keep it under half the sheet's grid."
],
"related": [
"sch_trace_point",
"run_erc"
],
"example": {
"sheet": "C:/proj/Power.SchDoc",
"toleranceMm": 0.5,
"dryRun": false
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_hierarchy",
"tier": "core",
"source": "proposed",
"summary": "The sheet tree of a design, recursively: each sheet's name, file, id, instance path, page number, position, size and pins. renumber:true renumbers pages depth-first from the root.",
"input": {
"sheet": "path to the root sheet",
"project": "path to the project (instead of sheet)",
"renumber": "bool, default false",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"tree": "[{name, file, id, path, page, at, sizeMm, pins: [{name, kind}], children: [...]}]",
"problems": "[{sheet, problem: missing|unreadable|recursive}]",
"duplicatePages": "[int]",
"renumbered": "[{sheet, from, to}]"
},
"hint": "Pass the root sheet or the project. renumber writes only the numbers that change.",
"pitfalls": [
"A sheet file used by two sheet symbols appears twice in the tree (one instance each) but is one file."
],
"related": [
"sch_sheet_pins",
"sch_sheet_symbol",
"sch_create"
],
"example": {
"project": "C:/proj/Board.PrjPcb",
"renumber": true
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_items",
"tier": "core",
"source": "proposed",
"summary": "List a sheet's wiring items with ids and coordinates: wires, buses, bus entries, net labels (local, global, hierarchical), power ports, junctions, no-connect markers, texts and sheet symbols. Read only.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"kinds": "[wires, buses, busEntries, labels, powerPorts, junctions, noConnects, texts, sheets] (default all)"
},
"output": {
"wires": "[{id, from, to}]",
"buses": "[{id, from, to}]",
"busEntries": "[{id, at, end}]",
"labels": "[{id, text, kind: local|global|hierarchical, at, rotation}]",
"powerPorts": "[{id, net, at}]",
"junctions": "[{id, at}]",
"noConnects": "[{id, at}]",
"texts": "[{id, text, at}]",
"sheets": "[{id, name, file, at, sizeMm}]",
"counts": "{kind: int}"
},
"hint": "The ids feed sch_delete_wire, sch_edit_label, sch_junction and sch_edit. Parts are in schematic_data.",
"pitfalls": [
"A wire is one straight segment: a polyline drawn in the editor is several wires sharing ends."
],
"related": [
"schematic_data",
"sch_pins",
"sch_delete_wire",
"sch_edit_label"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"kinds": [
"wires",
"labels"
]
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_junction",
"tier": "core",
"source": "proposed",
"summary": "Add junction dots at points, or remove dots by id or point. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"points": "[[x, y], ...] mm: where to add dots",
"remove": "[id or [x, y], ...]: dots to remove",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"added": "[{id, at}]",
"removed": "[id]",
"skipped": "[[x, y]]: points that already had a dot",
"notNeeded": "[[x, y]]: added dots where fewer than three items meet (legal, but they join nothing extra)",
"saved": "bool"
},
"hint": "The wiring verbs add the dots they need on their own; use this for a T made by hand, or to clean up.",
"pitfalls": [
"Items join only where their coordinates match exactly: use pin ends from sch_pins, or points on the sheet's grid."
],
"related": [
"sch_items",
"sch_split_wire",
"sch_delete_wire"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"points": [
[
110.49,
60.96
]
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_label",
"tier": "core",
"source": "proposed",
"summary": "Put a net label on an existing wire at a point, or delete one. sch_connect labels a pin through a new stub, and sch_edit_label changes labels that already exist.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"text": "the net name (required to add)",
"at": "[x, y] mm: a point on the wire",
"kind": "local|global|hierarchical, default local",
"rotation": "0|90|180|270, default 0",
"remove": "bool, default false: delete the label named by id, or by text with at",
"id": "a label's id from sch_items (with remove)",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"label": "{id, text, kind, at, rotation} when added",
"removed": "[id]",
"saved": "bool"
},
"hint": "The label names the net of the wire it touches: check with sch_trace_point at the same point, or netlist.",
"pitfalls": [
"A label placed where no wire runs connects nothing, and is reported by the ERC, not by this verb."
],
"related": [
"sch_connect",
"sch_edit_label",
"sch_items",
"sch_trace_point"
],
"example": {
"sheet": "C:/proj/board.kicad_sch",
"text": "VIN",
"at": [
63.5,
54.61
]
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.31.1",
"agreedBy": [
"altium-lane",
"fusion-lane"
]
},
{
"name": "sch_move_region",
"tier": "core",
"source": "proposed",
"summary": "Move everything inside a box by (dx, dy): parts, wire ends inside the box (wires crossing its edge stretch), labels, junctions, no-connect markers, texts, bus entries and sheet symbols. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"box": "[x1, y1, x2, y2] mm (required)",
"by": "[dx, dy] mm (required)",
"wires": "bool, default true: move wires, buses and bus entries",
"labels": "bool, default true: move labels and texts",
"junctions": "bool, default true: move junctions and no-connect markers",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"moved": "{parts, wires, buses, busEntries, labels, texts, junctions, noConnects, sheets: [id]}",
"saved": "bool"
},
"hint": "Parts move by their anchor point. Move by a pure dx or a pure dy to keep stretched wires straight.",
"pitfalls": [
"A wire with one end in the box stretches diagonally when dx and dy are both non-zero.",
"Keep the move on the sheet's grid, or pins and wires stop meeting.",
"A multi-part component whose parts sit on both sides of the edge splits up."
],
"related": [
"sch_edit",
"sch_items"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"box": [
90,
40,
160,
120
],
"by": [
25.4,
0
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_no_connect",
"tier": "core",
"source": "proposed",
"summary": "Put a no-connect marker on a sheet, at a point or on a pin, or remove one by its sch_items id. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"at": "[x, y] mm: a point",
"points": "[[x, y]] mm: several points",
"pin": "designator.pin, e.g. U1.12",
"pins": "[designator.pin]",
"id": "a marker's id from sch_items (with remove)",
"remove": "bool, default false: remove the marker at id or at",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"added": "[{id, at}]",
"removed": "[id]",
"failed": "[{item, error}]",
"saved": "bool"
},
"hint": "Use it for a pin left open on purpose, so the ERC stops reporting it. sch_items {kinds:[noConnects]} lists the markers with their ids.",
"pitfalls": [
"A bridge whose tool has no such marker answers not_supported, with the reason (Fusion's schematic has none)."
],
"related": [
"sch_items",
"sch_connect",
"run_erc"
],
"example": {
"sheet": "C:/proj/board.kicad_sch",
"pin": "U1.12"
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.31.1",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_page",
"tier": "core",
"source": "proposed",
"summary": "Read or set a sheet's page: paper size, orientation and title block (title, date, revision, company, comment lines).",
"input": {
"sheet": "path to the schematic sheet file (required)",
"paper": "A5 to A0, A to E, USLetter, USLegal, USLedger or custom",
"orientation": "portrait|landscape",
"widthMm": "number (custom paper)",
"heightMm": "number (custom paper)",
"title": "string",
"date": "string",
"rev": "string",
"company": "string",
"comments": "[string]: comment lines in order",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"paper": "string",
"widthMm": "number",
"heightMm": "number",
"orientation": "string",
"titleBlock": "{title, date, rev, company, comments}",
"changed": "bool",
"saved": "bool"
},
"hint": "With no change arguments it only reads. An empty string removes a title-block field. Each sheet of a hierarchy has its own page.",
"pitfalls": [
"Shrinking the paper moves nothing: items outside the new frame stay where they are (render_schematic shows it)."
],
"related": [
"sch_create",
"render_schematic"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"paper": "A3",
"title": "Main board",
"rev": "B"
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_pins",
"tier": "core",
"source": "proposed",
"summary": "Every pin of the named parts on a sheet: its absolute position (rotation and mirror applied), number, name, electrical type, the side it leaves the body, and the wires, labels and nets touching it. Read only.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"references": "[\"U1\", \"R5\"] (default every part)",
"connections": "bool, default true: add what touches each pin"
},
"output": {
"pins": "[{ref, number, name, type, at: [x, y], direction: right|left|up|down as seen, hidden, touching: [{kind, id}], nets: [string], connectedPins: [Ref.Pin]}]"
},
"hint": "at is where a wire or label must land on the pin. connectedPins lists the other pins on the same copper on this sheet.",
"pitfalls": [
"Nets here come from this sheet's wires and labels only: netlist gives the project-wide nets.",
"Hidden power pins (hidden:true) connect by name, not by wire."
],
"related": [
"sch_connect_pins",
"sch_connect",
"schematic_data",
"netlist"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"references": [
"U1",
"R5"
]
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_place_part",
"tier": "core",
"source": "altium",
"summary": "Place a component from a .SchLib onto an EXISTING sheet at a position, with its library parameters (MPN, Manufacturer, distributor numbers) and its footprint link.",
"input": {
"comment": "string, default the library's",
"designator": "string, default the library's (e.g. R?)",
"footprint": "a PcbLib footprint name to link instead of the library's own",
"library": "path to the .SchLib (required)",
"partId": "int, default 1 (a multi-part component's part)",
"pcbLib": "path of the .PcbLib the footprint lives in (optional)",
"rotation": "0|90|180|270",
"save": "bool, default true",
"sheet": "path to the .SchDoc (required)",
"symbol": "the component's name in that library (required)",
"x": "mil, default 1000 (snapped to 100)",
"y": "mil, default 1000"
},
"output": {
"atMil": "[x, y]",
"designator": "string",
"footprints": "[string]",
"libref": "string",
"pins": "int",
"saved": "bool"
},
"hint": "Then wire it: altium_sch_connect {sheet, connections:[{designator, pin, net}]}; number a '?' designator with altium_annotate; push it to the board with altium_update_pcb.",
"pitfalls": [
"Places part 1 of a multi-part component unless partId says otherwise.",
"Sheet coordinates are mils from the sheet's lower-left corner; altium_schematic_data shows where the other parts are."
],
"related": [
"sch_connect",
"annotate",
"update_pcb",
"list_library"
],
"example": {
"designator": "U2",
"library": "C:/proj/Lib.SchLib",
"sheet": "C:/proj/Main.SchDoc",
"symbol": "TPS54202DDCR",
"x": 3000,
"y": 4000
},
"longRunning": false,
"timeoutSeconds": 120,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "sch_reset_fields",
"tier": "core",
"source": "proposed",
"summary": "Put parts' designator and value text (or the named fields) back where the library symbol places them, through each part's rotation and mirror. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"references": "[\"R5\", \"C3\"]",
"all": "bool: every part on the sheet",
"fields": "[designator, value] by default; other field names as the tool names them",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"reset": "[{ref, field}]",
"saved": "bool"
},
"hint": "Font and visibility stay as they are; only position, angle and justification move.",
"pitfalls": [
"The library's offsets are what the symbol's author drew; the tool's automatic field placement may put them elsewhere."
],
"related": [
"sch_edit",
"schematic_data"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"references": [
"R5",
"C3"
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_sheet_pins",
"tier": "core",
"source": "proposed",
"summary": "A sheet symbol's pins: list, add, edit (rename, kind, move along an edge) or delete. import:true adds a pin for every hierarchical port inside the child sheet that the symbol lacks; validate:true reports ports without pins, pins without ports and kind mismatches.",
"input": {
"sheet": "path to the parent sheet (required)",
"sheetSymbol": "the sheet symbol's name or id (default: validate checks every one)",
"action": "list|add|edit|delete, default list",
"name": "string: the pin",
"kind": "input|output|bidirectional|tri_state|passive",
"side": "left|right|top|bottom",
"at": "[x, y] mm: snapped to the nearest edge point",
"newName": "string (edit)",
"import": "bool",
"validate": "bool",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"pins": "[{id, name, kind, side, at}]",
"added": "[name]",
"problems": "[{sheetSymbol, pin, problem: no_port|no_pin|kind_mismatch}]",
"saved": "bool"
},
"hint": "Inputs go on the left edge and outputs on the right by default, in the first free slot. A pin joins the child's hierarchical port of the same name; wire it on the parent side at its at.",
"pitfalls": [
"Renaming a pin does not rename the port inside the child sheet: validate afterwards.",
"A pin moved or deleted leaves its parent-side wire dangling."
],
"related": [
"sch_sheet_symbol",
"sch_hierarchy",
"sch_connect"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"sheetSymbol": "Power",
"import": true
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_sheet_symbol",
"tier": "core",
"source": "altium",
"summary": "Make a design hierarchical: a sheet symbol on the parent sheet for a child sheet, its entries joined to the parent's nets, and matching ports on the child. A child that does not exist yet is made from Altium's sheet template and added to the project.",
"input": {
"child": "the child .SchDoc (required; a name alone sits beside the parent)",
"entries": "[{name, io: input|output|bidirectional|passive, side?: left|right (default inputs left), net?: a parent net to join (a stub and a net label), stubMil?: 300}]",
"name": "the symbol's designator (default the child's name)",
"ports": "bool, default true: put a port on the child for each entry it lacks",
"portsAt": "{left, right, top} mil on the child (defaults 1000, 15000, 9500)",
"projectPath": ".PrjPcb: lists the child when it is not listed yet",
"save": "bool, default true",
"sheet": "the parent .SchDoc (required)",
"widthMil": "default 1400",
"x": "mil, the symbol's top-left corner (default 2000)",
"y": "mil (default 8000)"
},
"output": {
"childCreated": "bool",
"ports": "{placed:[{name, io, atMil, stubEndMil}], alreadyThere:[name]}",
"steps": "[childCreated | addedToProject]",
"symbol": "{name, file, atMil, sizeMil, entries:[{name, side, io, net, atMil}]}"
},
"hint": "Then connect the child's circuit to its ports (altium_sch_connect kind:'port', or a wire to stubEndMil) and altium_compile {projectPath}: entries and ports join by name.",
"pitfalls": [
"Altium never places a sheet entry by itself (its position stays 0,0 and it draws nowhere): the bridge puts each one on the symbol's edge, 100 mil apart.",
"Ports already on the child (by name) are reported in alreadyThere, not doubled."
],
"related": [
"sch_connect",
"compile",
"schematic_data",
"build_schematic"
],
"example": {
"child": "Power.SchDoc",
"entries": [
{
"io": "input",
"name": "VIN",
"net": "VBUS"
},
{
"io": "output",
"name": "3V3",
"net": "3V3"
},
{
"io": "passive",
"name": "GND",
"net": "GND"
}
],
"projectPath": "C:\\work\\Board.PrjPcb",
"sheet": "C:\\work\\Top.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 240,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "sch_split_wire",
"tier": "core",
"source": "proposed",
"summary": "Split the wire through a point into two wires there, with a junction dot at the cut, so a new branch can end on a wire end. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"at": "[x, y] mm on the sheet (the tool's sheet origin, y up) (required)",
"id": "the wire's id, when several wires pass through the point",
"junction": "bool, default true",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"ids": "[first half (keeps the wire's id), second half (new id)]",
"junction": "{id, at} or null",
"saved": "bool"
},
"hint": "Split a wire where a new branch should join it, then wire to the cut.",
"pitfalls": [
"The point must lie on the wire and not at either end (not_on_wire otherwise)."
],
"related": [
"sch_delete_wire",
"sch_junction",
"sch_items"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"at": [
110.49,
60.96
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_swap_part",
"tier": "core",
"source": "altium",
"summary": "Replace a placed part with another library part (a different value, package or symbol) at the same place, designator and rotation, keeping its connections: where a new pin ends elsewhere, a wire joins it to where the old pin ended.",
"input": {
"designator": "the part to replace (required)",
"footprint": "optional footprint name",
"keepComment": "bool, default false (the new part's own comment)",
"library": "path to the .SchLib (required)",
"pcbLib": "optional .PcbLib for that footprint",
"save": "bool, default true",
"sheet": "path to the .SchDoc (required)",
"symbol": "the new part's name in it (required)"
},
"output": {
"newPinsNotOnOld": "[pin]",
"now": "{libReference, footprints}",
"oldPinsNotOnNew": "[pin]",
"pinsJoined": "[{pin, from, to}]"
},
"hint": "Then altium_update_pcb carries the new part's footprint and parameters to the board. A workspace part: altium_workspace_place it beside, connect, then altium_sch_edit delete the old one.",
"pitfalls": [
"Pins are matched by number.",
"Multi-part components are refused."
],
"related": [
"sch_place_part",
"sch_edit",
"sch_connect",
"update_pcb"
],
"example": {
"designator": "C10",
"library": "C:/proj/Lib.SchLib",
"sheet": "C:/proj/Main.SchDoc",
"symbol": "CC0402-100NF"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "sch_text",
"tier": "core",
"source": "proposed",
"summary": "Add free text to a sheet (a note, a title, a design comment) with size, angle, justification, bold and italic. Text has no electrical meaning. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"texts": "[{text, at: [x, y] mm, rotation?: 0|90|180|270, sizeMm?: 1.27, justify?: \"left bottom\", bold?: false, italic?: false}] (required)",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"added": "[{id, text, at}]",
"saved": "bool"
},
"hint": "Net names are labels, not text: use sch_connect for them. Newlines in text become line breaks.",
"pitfalls": [],
"related": [
"sch_items",
"sch_edit_label"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"texts": [
{
"text": "USB input stage",
"at": [
50.8,
30.48
],
"sizeMm": 2.54,
"bold": true
}
]
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_trace_point",
"tier": "core",
"source": "proposed",
"summary": "Everything electrically connected at a point on a sheet: the wires, labels, pins, junctions, sheet pins and no-connect markers there, and for each net they belong to the whole net with its name. Read only.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"at": "[x, y] mm on the sheet (the tool's sheet origin, y up) (required)",
"toleranceMm": "number, default 0.05"
},
"output": {
"items": "[{kind, id, at}]",
"nets": "[{name, pins: [Ref.Pin], labels, powerPorts, wires, leavesSheet: bool}]",
"crossingWithoutJunction": "bool: two wires cross here without connecting",
"nearest": "[x, y]: the nearest connectable point, when nothing is within tolerance"
},
"hint": "Read with the tool's own rules: wire ends join wires and wire middles (a T), labels and junction dots join a wire anywhere along it, pins join wire ends.",
"pitfalls": [
"One sheet only: a net that leaves through a global, hierarchical or power label (leavesSheet:true) continues on other sheets. netlist gives the compiled net."
],
"related": [
"sch_pins",
"net_connections",
"netlist"
],
"example": {
"sheet": "C:/proj/Power.SchDoc",
"at": [
109.22,
73.66
]
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "sch_wire",
"tier": "core",
"source": "proposed",
"summary": "Draw a wire through given points on a sheet, in the same units as the other sch_* wiring verbs. One undo step.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"points": "[[x, y], ...] mm, two or more (required)",
"junctions": "bool, default true: add a junction where the wire ends on another wire",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"wires": "[{id, from, to}] one per segment",
"junctionsAdded": "[{id, at}]",
"saved": "bool"
},
"hint": "For wiring between points that aren't pins, such as a bus of stubs or a route around a part. sch_connect_pins draws between two pins and works out the path.",
"pitfalls": [
"Points that are not on the sheet's grid may not reach a pin: read the pin's position first with sch_pins."
],
"related": [
"sch_connect_pins",
"sch_split_wire",
"sch_delete_wire",
"sch_items"
],
"example": {
"sheet": "C:/proj/board.kicad_sch",
"points": [
[
50.8,
54.61
],
[
76.2,
54.61
]
]
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.31.1",
"agreedBy": [
"altium-lane"
]
},
{
"name": "schematic_data",
"tier": "core",
"source": "altium",
"summary": "Components on a schematic sheet (filePath, else the CURRENT sheet) with their pins (number, name, electrical type), position and orientation. designator filters to one part.",
"input": {
"designator": "string - optional filter",
"filePath": "path to the .SchDoc - optional, made current first (alias sheet)",
"limit": "int, default 500",
"paramBudgetSec": "number, default 60 (0-100): the time Altium gets for parameters and descriptions; parts past it come back with their parameters read from the saved file (paramsFromFile, paramsSkipped, paramsComplete false) instead of the call timing out",
"paramNamesOnly": "bool, default false - parameter names without values (a library with blob parameters reads fast)",
"params": "bool, default false - include each component's parameters",
"pins": "bool, default true"
},
"output": {
"data": "{document, count, components: [{designator, partId, libReference, comment, description (empty for a workspace-managed part), kind (ComponentKind: 0 Standard, 1 Mechanical, 2 Graphical, 3 Net Tie BOM, 4 Net Tie, 5 Standard no BOM, 6 Jumper), itemGuid, vaultGuid, sourceLibrary, xMil, yMil, orientation, pins: [{number, name, electrical (0 Input, 1 IO, 2 Output, 3 OpenCollector, 4 Passive, 5 HiZ, 6 OpenEmitter, 7 Power), xMil, yMil, orientation, lengthMil}], params: []}]}",
"roundtripMs": "int"
},
"hint": "Pin-level view of a sheet. params[] is empty unless you pass params:true; altium_read_schematic is the fuller parameter view.",
"pitfalls": [
"One sheet per call. Without filePath the current document must be a .SchDoc: a schematic library is refused (no_current_schematic), not read as an empty sheet.",
"electrical is Altium's pin-type ordinal, not a name."
],
"related": [
"read_schematic",
"cross_check",
"show_schematic"
],
"example": {
"designator": "U1"
},
"longRunning": false,
"timeoutSeconds": 120,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "set_layer_count",
"tier": "core",
"source": "proposed",
"summary": "Set the board's copper layer count (2, 4, 6 or 8): the layer table and the stack-up, keeping the board thickness.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"count": "2|4|6|8 (required)",
"expectedRevision": "string: the revision you last read (routing_state); refused with stale_board if the board changed",
"dryRun": "bool, default false: answer the plan and change nothing"
},
"output": {
"layers": "[string]: the copper layers now",
"stackup": "the new stack-up, as layer_stack answers it",
"revision": "string: the board's new revision"
},
"hint": "New inner layers are signal layers In1.Cu ... Read the result with layer_stack.",
"pitfalls": [
"A layer being removed that still carries copper or graphics is refused (layers_in_use, with the counts per layer).",
"New dielectrics are generic: re-check an impedance-controlled stack-up with layer_stack.",
"Net classes and design rules are not changed."
],
"related": [
"layer_stack",
"copper_layers",
"layers_in_use"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"count": 4
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "set_models",
"tier": "core",
"source": "altium",
"summary": "Replace every footprint model on a SchLib component with ONE PCBLIB model (set_params footprint and add_models APPEND, which is how a symbol ends up with two).",
"input": {
"footprint": "string (PcbLib footprint name)",
"libraryPath": "path (.SchLib)",
"symbolName": "string"
},
"output": {
"footprint": "string",
"removed": "int"
},
"hint": "altium_save the SchLib afterwards.",
"pitfalls": [
"Removes every existing model, including 3D-only ones."
],
"related": [
"symbol_prims",
"set_params",
"add_models"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "set_outline",
"tier": "core",
"source": "altium",
"summary": "Reshape the current board's outline (a rectangle with rounded corners, or a polygon). One undo step.",
"input": {
"expectedRevision": "string (optional) - refused with stale_board if the board changed",
"outline": "{rect:[x0,y0,w,h], cornerRadius?} or {points:[[x,y]...]} (mm)"
},
"output": {
"outlineEdges": "[{kind: line|arc, ...}]",
"revision": "string",
"vertices": "int"
},
"hint": "Rounding corners: pass the same rectangle with cornerRadius (1 mm is a common default).",
"pitfalls": [
"Needs the board current."
],
"related": [
"build_board",
"routing_state",
"repour"
],
"example": {
"outline": {
"cornerRadius": 1,
"rect": [
0,
0,
28,
20
]
}
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "set_params",
"tier": "core",
"source": "altium",
"summary": "Set parameters on a SchLib component, optionally its comment, and optionally link a footprint by name.",
"input": {
"comment": "string",
"footprint": "string - PcbLib footprint name to link",
"libraryPath": "path to a .SchLib (required)",
"params": "{key: value} or 'Key=Value;Key=Value'",
"symbolName": "string - omit for the FIRST component",
"timeout": "seconds, default 90"
},
"output": {
"data": "{component, paramsSet: int, footprint}",
"roundtripMs": "int"
},
"hint": "Unsaved: altium_save {filePath: libraryPath}. 'LCSC Part #' and 'Manufacturer Part Number' are the JLC/BOM keys. altium_read_symbol shows the result.",
"pitfalls": [
"footprint APPENDS an implementation on every call; use altium_set_models to end up with exactly one.",
"Parameters are created HIDDEN (visible ones pile up over the symbol): altium_set_visibility to show one.",
"Without symbolName it edits the first component in the library."
],
"related": [
"read_symbol",
"set_visibility",
"set_models",
"save"
],
"example": {
"comment": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"params": {
"LCSC Part #": "C2888092",
"Manufacturer": "ST"
},
"symbolName": "VL53L5CX"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "set_track_width",
"tier": "core",
"source": "altium",
"summary": "Set the width of the EXISTING tracks and arcs on nets or a net class (rules only steer new routing). Widen power nets after routing, or thin a net that fails clearance.",
"input": {
"filePath": "path to the .PcbDoc - optional",
"layer": "top | bottom | mid N - optional, default every layer",
"netClass": "class name (its nets)",
"nets": "[string] board net names",
"widthMm": "number (required)"
},
"output": {
"byNet": "{NET: count}",
"changed": "int",
"drcAfter": "{errors, unconnected}"
},
"hint": "Run altium_routing_drc {full:true} after: wider copper can break clearance to neighbours.",
"pitfalls": [
"Copper inside footprints (pads' own tracks) is left alone."
],
"related": [
"net_classes",
"route_net",
"routing_drc",
"add_rule"
],
"example": {
"netClass": "Power",
"widthMm": 0.5
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "set_visibility",
"tier": "core",
"source": "altium",
"summary": "Show or hide one named parameter on a SchLib component.",
"input": {
"libraryPath": "path to a .SchLib - optional; opened first",
"param": "string - the parameter name",
"symbolName": "string",
"timeout": "seconds, default 90",
"visible": "bool, default true"
},
"output": {
"data": "{param, visible: '1'|'0'}",
"roundtripMs": "int"
},
"hint": "altium_save afterwards; altium_show_symbol to see where the text landed.",
"pitfalls": [
"'parameter not found' = the name must match a parameter altium_read_symbol lists.",
"Visible parameters stack over the symbol body: show few."
],
"related": [
"set_params",
"read_symbol",
"show_symbol"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"param": "Manufacturer Part Number",
"symbolName": "VL53L5CX",
"visible": true
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "sheet_params",
"tier": "core",
"source": "altium",
"summary": "Write parameters onto PLACED parts on the schematic sheets (the BOM write-back): MPN, Manufacturer, Mouser/DigiKey/LCSC numbers, anything. A missing parameter is added hidden; one undo step per sheet; each touched sheet is saved.",
"input": {
"designators": "[string] or 'R1,R2' (required; every part of a multi-part component)",
"params": "{name: value} or 'Key=Value;Key=Value' (required)",
"projectPath": "path to the .PrjPcb: each designator is found on whichever sheet holds it",
"save": "bool, default true",
"sheet": "path to a .SchDoc - or",
"timeout": "seconds, default 90"
},
"output": {
"notFound": "[designator]",
"sheets": "[{sheet, designators, paramsSet}]",
"updated": "[designator]"
},
"hint": "The board picks the new parameters up with Design > Update PCB Document; altium_bom reads the sheets, so it shows them at once.",
"pitfalls": [
"Sheet parameters, not the library: altium_set_params changes a library part."
],
"related": [
"bom",
"read_schematic",
"set_params"
],
"example": {
"designators": [
"R1",
"R2"
],
"params": {
"MPN": "RC0402FR-0710KL",
"Manufacturer": "YAGEO",
"Mouser Part #": "603-RC0402FR-0710KL"
},
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "silk_state",
"tier": "core",
"source": "altium",
"summary": "The silkscreen as it stands: every part's body box, its designator and comment (text, location, size, rotation, shown, Altium's measured box), and the free overlay texts and lines on both faces.",
"input": {},
"output": {
"components": "[{ref, pattern, x, y, rotation, side, body:[l,b,r,t], name:{text,x,y,size,rotation,shown,box}, comment:{...}}]",
"lines": "[{side, x1, y1, x2, y2, width, raw}]",
"texts": "[{side, text, x, y, size, rotation, mirror, box, raw}]"
},
"hint": "The input to a silkscreen plan (AI Flow's `altium silkscreen`), and its check after landing: compare each box with the pads and vias from routing_state.",
"pitfalls": [
"Needs the board current.",
"raw is the exact handle apply_silkscreen's remove takes."
],
"related": [
"apply_silkscreen",
"routing_state"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "swap_footprint",
"tier": "core",
"source": "altium",
"summary": "Replace the FIRST component on the current board with a footprint from a PcbLib at the same position, re-assigning nets by pad designator. Tracks are untouched, so the wiring survives.",
"input": {
"assigns": "'padDes=NET;...'",
"footprintName": "string",
"libraryPath": "path to the .PcbLib holding the new footprint",
"pcbPath": "path to the .PcbDoc - optional; opened first",
"timeout": "seconds, default 240"
},
"output": {
"data": "{placed, padsOnComp, bodiesOnComp}",
"windowEtiquette": "background"
},
"hint": "Built for single-part test boards (altium_test_board): iterate on a footprint and re-prove with altium_show_3d_board. altium_save the board afterwards.",
"pitfalls": [
"There is NO designator argument: on a multi-part board it replaces whichever component the iterator returns first.",
"Nets come ONLY from assigns (padDes=NET, all pads sharing a designator get the net): pads you do not list end up with no net."
],
"related": [
"test_board",
"show_3d_board",
"footprint_primitives"
],
"example": {
"assigns": "1=GND;2=VDD",
"footprintName": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.PcbLib",
"pcbPath": "C:/proj/tof.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 240
},
{
"name": "symbol_prims",
"tier": "core",
"source": "altium",
"summary": "Read a SchLib component's drawing: primitive counts by kind, body rectangle, polyline bounding box, display mode and the footprint models. Read-only, use it to verify add_symbol_art / set_models.",
"input": {
"libraryPath": "path (.SchLib)",
"models": "bool, default false (the model walk halts the engine on some builds)",
"symbolName": "string"
},
"output": {
"bodyRectMil": "[l, b, r, t] - the union of the current display mode's rectangles (mode 0, as a sheet draws it)",
"lines": "int",
"models": "[\"PCBLIB:NAME\"]",
"pins": "int",
"polyBboxMil": "[..]",
"polylines": "int",
"rectangles": "int"
},
"hint": "polylines should equal what add_symbol_art reported and polyBboxMil should sit inside bodyRectMil.",
"pitfalls": [],
"related": [
"add_symbol_art",
"set_models",
"read_symbol"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "update_footprints_from_library",
"tier": "core",
"source": "altium",
"summary": "Compare each placed footprint with its library's current one and, with apply:true, replace the ones that differ, keeping where the part sits (position, rotation, side), its designator and comment, its pad nets by pad number and its schematic link. KiCad's verb of the same name.",
"input": {
"apply": "bool, default false: a plan; true replaces every differing footprint",
"expectedRevision": "string: refuse with stale_board if the board changed since the plan",
"filePath": "the .PcbDoc (required)",
"libraries": "[.PcbLib]: several",
"libraryPath": "a .PcbLib to take footprints from (default: the .PcbLibs the board's project lists; a part's own source library first)",
"refs": "[\"U1\"] (default every footprint)"
},
"output": {
"differs": "int",
"footprints": "[{ref, footprint, library, status: up_to_date | differs | library_not_found, diff?: {padsAdded, padsRemoved, padsChanged: [{pad, changes}], bodies3d?}, why?}]",
"mutated": "bool",
"plan": "bool",
"problems": "[read-back problems] (apply)",
"replaced": "[{ref, replaced, netsKept, netsBefore}] (apply)",
"revision": "string"
},
"hint": "Plan first: each differing part's diff names the pads added, removed or changed (moved, resized, reshaped, redrilled, surface or through-hole) and a 3D body count that differs. apply:true replaces every differing part and reads them back: each must sit where it did and match its library. Save with altium_save.",
"pitfalls": [
"A pad new in the library has no net, and a removed pad's net goes with it: read padsAdded and padsRemoved before apply.",
"Tracks are not moved to follow pads that moved: run altium_routing_drc after."
],
"related": [
"edit_footprint",
"footprint_from_land_pattern",
"swap_footprint",
"routing_drc",
"save"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"refs": [
"U1"
]
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "xcopy_footprint",
"tier": "core",
"source": "altium",
"summary": "Copy a footprint ACROSS libraries: from fromLib into toLib (opened and made current), optionally under a new name.",
"input": {
"from": "string - footprint name in the source",
"fromLib": "path to the source .PcbLib",
"timeout": "seconds, default 120",
"to": "string - default: same as from",
"toLib": "path to the destination .PcbLib - optional; else the current PcbLib"
},
"output": {
"data": "{to, primitives: int}",
"roundtripMs": "int"
},
"hint": "altium_pcb_report {path: toLib, name} to confirm pads and bodies arrived, then altium_save {filePath: toLib}.",
"pitfalls": [
"'open the destination PcbLib first' = pass toLib.",
"'target already exists' in the destination: pass a different to."
],
"related": [
"copy_footprint",
"pcb_report",
"save"
],
"example": {
"from": "LGA-16",
"fromLib": "C:/lib/Vendor.PcbLib",
"to": "VL53L5CX",
"toLib": "C:/lib/Adom_ToF.PcbLib"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "add_rule",
"tier": "native",
"source": "altium",
"summary": "Add one SCOPED design rule that set_design_rules' board-wide values cannot express: a net's or class's clearance or width, a length limit, a matched-length group, a differential pair's width and gap, a routing via style, or how a net's pads join a pour (direct, relief, none).",
"input": {
"comment": "optional",
"drill": "mm (via)",
"gap": "mm (clearance; diffpair: the pair's gap)",
"kind": "clearance|width|length|matched|diffpair|via|polyconnect",
"max": "mm (width, optional; length: required)",
"maxDrill": "via, optional",
"maxGap": "diffpair, optional",
"maxSize": "via, optional",
"maxUncoupled": "mm, diffpair, optional",
"maxWidth": "diffpair, optional",
"min": "mm (width; length)",
"minDrill": "via, optional",
"minGap": "diffpair, optional",
"minSize": "via, optional",
"minWidth": "diffpair, optional",
"name": "string - the rule is named 'Adom <name>'; the same name replaces it",
"preferred": "mm (width, optional)",
"reliefEntries": "2 | 4, polyconnect relief",
"reliefWidth": "mm, polyconnect relief spokes",
"remove": "bool - delete the Adom rule of this kind and name instead",
"scope1": "Altium query, e.g. InNet('SW'), InNetClass('DDR_D0'), InDifferentialPair('USB')",
"scope2": "query (default All; clearance, and polyconnect: the polygon, e.g. InPolygon('GND pour'))",
"size": "mm (via)",
"style": "polyconnect: direct | relief | none",
"tolerance": "mm (matched)",
"width": "mm (diffpair)"
},
"output": {
"name": "string",
"priority": "int (1 = first of its kind)"
},
"hint": "AI Flow's net clearances (a switch node kept farther from everything) land here. A scope with a typo matches nothing and DRC then passes silently: check it in the rules editor (Test Queries).",
"pitfalls": [
"Needs the board current.",
"One rule per call."
],
"related": [
"set_design_rules",
"read_rules",
"routing_drc"
],
"example": {
"gap": 0.3,
"kind": "clearance",
"name": "SW node",
"scope1": "InNet('SW')",
"scope2": "All"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "annotate",
"tier": "native",
"source": "altium",
"summary": "Number every '?' designator (R?, C?, U?) across the project's sheets: the lowest free number per prefix, top-left first on each sheet. dryRun shows the plan.",
"input": {
"dryRun": "bool, default false",
"projectPath": "path to the .PrjPcb (required)",
"save": "bool, default true"
},
"output": {
"planned": "[..] (dryRun)",
"renamed": "[{sheet, from, to, result}]",
"skippedMultiPart": "[{sheet, designator, libReference, partId}]"
},
"hint": "Then altium_update_pcb carries the designators to the board.",
"pitfalls": [
"Multi-part components with '?' are left alone (their parts share one designator); use Altium's Tools > Annotation for those."
],
"related": [
"sch_place_part",
"update_pcb",
"sch_edit"
],
"example": {
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "apply_pours",
"tier": "native",
"source": "altium",
"summary": "Add solid polygon pours from outlines and pour them, each with its own connect style (solid joints or thermal spokes), plus pour keepouts (polygon cutouts); answers each pour's real poured copper area. One undo step.",
"input": {
"cutouts": "(optional) [{layer, points:[[x,y]...] mm, name?}] - areas every pour on that layer stays out of (KiCad's pour keepout); landed before the pours",
"expectedRevision": "string (optional) - refused with stale_board if the board changed since you read it",
"pours": "[{net, layer (F.Cu|B.Cu|In<n>.Cu), points:[[x,y]...] mm, order?: pour order (1 = poured first), name?: polygon name, connect?: direct|relief|none, reliefWidth?: mm spoke width, reliefGap?: mm air gap (not settable by script on AD 26: Altium keeps 10 mil and notes[] says so), reliefEntries?: 2|4, removeDead?: bool (default true), removeSmallIslands?: bool (default false: connected copper of any size stays, as in KiCad; true = Altium's own 2500 sq mil island filter), minNeck?: mm - copper narrower than this is removed (KiCad's zone min thickness), solidPads?: [[x1,y1,x2,y2]] mm - pads completely inside each rect join THIS pour solid whatever its connect (KiCad's small solid joint zone over a pad; Altium pours nothing for a same-net polygon inside another)}]"
},
"output": {
"filledAreaByLayerMm2": "{F.Cu: mm2, ...}",
"results": "[ok:<polygon name>|err:...]",
"revision": "string",
"unfilled": "[zone] that poured nothing",
"zones": "[{net, layer, outline, filledMm2, islands, filled}]"
},
"hint": "connect writes a PolygonConnect rule 'AdomPC <name>' scoped IsNamedPolygon('<name>') that outranks the board's own, so a power patch can join its pads solid while the ground pour keeps spokes. Without connect the board's Polygon Connect Style applies (Altium's default is 4 relief spokes of 10 mil, a current neck). Clearance comes from the board's Clearance rule. Dead copper is removed unless removeDead is false.",
"pitfalls": [
"Needs the board current.",
"The outline need not repeat its first point.",
"A name already on the board gets a ' 2' suffix: read the real name from results."
],
"related": [
"pour_state",
"repour",
"remove_pours",
"routing_state",
"set_design_rules"
],
"example": {
"cutouts": [
{
"layer": "F.Cu",
"name": "Kelvin tap",
"points": [
[
20,
2
],
[
22,
2
],
[
22,
4
],
[
20,
4
]
]
}
],
"pours": [
{
"connect": "relief",
"layer": "B.Cu",
"net": "GND",
"points": [
[
0,
0
],
[
28,
0
],
[
28,
20
],
[
0,
20
]
],
"reliefGap": 0.25,
"reliefWidth": 0.35
},
{
"connect": "direct",
"layer": "F.Cu",
"net": "SW",
"order": 1,
"points": [
[
10,
5
],
[
16,
5
],
[
16,
9
],
[
10,
9
]
]
}
]
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "autoroute",
"tier": "native",
"source": "altium",
"summary": "Altium's own autorouter (Situs) on the current board: picks a strategy, keeps existing routing locked by default, routes, and answers the unconnected count and DRC errors before and after. Not saved unless save:true.",
"input": {
"filePath": "path to the .PcbDoc - optional, else the current board",
"lockPreroutes": "bool, default true - existing tracks are kept",
"ripupViolations": "bool, default false",
"save": "bool, default false",
"strategy": "Default 2 Layer Board | Default Multi Layer Board | Default 2 Layer With Edge Connectors | General Orthogonal | Via Miser | Cleanup (default: the dialog's current)",
"timeout": "seconds, default 600"
},
"output": {
"after": "{unconnected, errors}",
"before": "{unconnected, errors}",
"saved": "bool",
"steps": "[..]"
},
"hint": "Look at the result before keeping it (altium_show_2d_board) and check it with altium_routing_drc. Altium's rules drive Situs: set them first (altium_set_design_rules, altium_add_rule).",
"pitfalls": [
"Parts outside the board outline get routed to where they sit: place them first (altium_move_parts).",
"With lockPreroutes:false Situs rips up and reroutes existing tracks."
],
"related": [
"route_net",
"routing_drc",
"set_design_rules",
"save"
],
"example": {
"filePath": "C:/proj/board.PcbDoc",
"strategy": "Default 2 Layer Board"
},
"longRunning": false,
"timeoutSeconds": 900
},
{
"name": "build_symbol_modes",
"tier": "native",
"source": "altium",
"summary": "Build ONE SchLib component with N display modes (Normal + Alternate 1..N-1) from a symbol_modes spec file on this machine, and return a proof frame.",
"input": {
"libraryPath": "path to a .SchLib (required; created if missing)",
"spec": "Windows path to the spec (tools/symbol_modes.py output; mils, Y up) (required)",
"timeout": "seconds, default 240"
},
"output": {
"data": "{libref, library, libraryState, modes, pins, lines, displayModeCount}",
"shot": "{image: base64 png, width, height}",
"windowEtiquette": "background"
},
"hint": "Then altium_add_symbol_art for the chip outline, altium_add_models / altium_set_models for the footprint, altium_save. altium_symbol_mode {mode} frames each alternate.",
"pitfalls": [
"libref comes from the spec's META line.",
"Compare data.displayModeCount with data.modes before trusting the alternates.",
"Library is left UNSAVED."
],
"related": [
"import_part",
"add_symbol_art",
"symbol_mode",
"add_models"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"spec": "C:/lib/specs/VL53L5CX.sym.txt"
},
"longRunning": false,
"timeoutSeconds": 240
},
{
"name": "cleanup_libs",
"tier": "native",
"source": "altium",
"summary": "Remove the factory-default stray every fresh library carries: Component_1 from the current SchLib and an empty (no pads) PCBComponent_1 from the current PcbLib.",
"input": {
"libraryPath": "path to a .SchLib/.PcbLib - optional; opened first",
"timeout": "seconds, default 90"
},
"output": {
"data": "{removed: int}",
"roundtripMs": "int"
},
"hint": "Run once per new library after the first import, then altium_save and altium_list_library.",
"pitfalls": [
"The SchLib side removes ANY component named Component_1 without checking that it is empty.",
"removed:0 is normal on a library that was already clean."
],
"related": [
"list_library",
"remove_symbol",
"remove_footprint",
"save"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "compile",
"tier": "native",
"source": "altium",
"summary": "Compile a project and return Altium's Messages panel (ERC + connectivity) with counts by class. With no path it compiles Altium's bundled example project.",
"input": {
"limit": "int, default 200 messages",
"objectKind": "string, default 'Project'",
"projectPath": "path to a .PrjPcb (alias: filePath) - default: the bundled Bluetooth Sentinel example",
"timeout": "seconds"
},
"output": {
"byClass": "{class: n}",
"elapsedSec": "float",
"messageCount": "int",
"messages": "[{class, source, document, text}]",
"project": "path",
"windowEtiquette": "background"
},
"hint": "Zero messages = clean. Fix what messages[] names, recompile, then altium_run_drc for the board side.",
"pitfalls": [
"ALWAYS pass projectPath: the default compiles Altium's example project in the user's session.",
"messages[] is the WHOLE Messages panel after the compile, capped at limit; messageCount is the true total."
],
"related": [
"run_erc",
"run_drc",
"open_project",
"cross_check"
],
"example": {
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "component_classes",
"tier": "native",
"source": "altium",
"summary": "List, make or remove component classes on the board, each optionally with a room: a placement area that keeps its parts together (fitted around the parts or a rectangle). The classes scope rules and group a channel for replicate_layout.",
"input": {
"filePath": "the .PcbDoc (opened first)",
"members": "[designators]",
"name": "class name (omit to list)",
"remove": "bool - delete the class and its room",
"room": "true (fit around the members' pads, 1 mm margin) | {marginMm} | {rect: [x1, y1, x2, y2] mm}"
},
"output": {
"classes": "[{name, members}] (list)",
"members": "[designator]",
"missing": "[designator not on the board]",
"room": "Altium's description of the room rule",
"roomMm": "[x1, y1, x2, y2]"
},
"hint": "Use a class per channel or block: rules scope with InComponentClass('<name>'), and the room shows the block's area to the user and to DRC.",
"pitfalls": [
"The room is a confinement rule ('Adom room <name>', top layer): a part outside it is a DRC violation, not a move.",
"The same name replaces the class and its room."
],
"related": [
"net_classes",
"replicate_layout",
"add_rule",
"find_space"
],
"example": {
"members": [
"U1",
"R1",
"C1"
],
"name": "CH1",
"room": true
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "create_part_project",
"tier": "native",
"source": "proposed",
"summary": "Generate a small real project (schematic and board) around one library part, so the part can be shown and tested in every view: schematic, 2D board and 3D board.",
"input": {
"part": "the part's symbol name or library id (required)",
"footprint": "a footprint name (default the symbol's own)",
"projectName": "string (default from the part)",
"outputDir": "folder (default the user's projects folder)",
"overwrite": "bool, default false: replace a project of that name"
},
"output": {
"project": "path",
"schematic": "path",
"board": "path"
},
"hint": "The board keeps the footprint's 3D model, so render_board_3d and show_3d_board show the real part. One part by design.",
"pitfalls": [
"The part's symbol and footprint must both be in a library the tool can find.",
"An existing project of that name is refused unless overwrite:true."
],
"related": [
"export_library_part",
"render_board_3d",
"show_3d_board",
"import_part"
],
"example": {
"part": "IN-S42ATR"
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "diff_pairs",
"tier": "native",
"source": "altium",
"summary": "Differential pairs on the current board: list them, define one from two nets (replacing a pair of that name), or remove one. Altium's differential-pair router and rules work on these.",
"input": {
"filePath": "path to the .PcbDoc - optional",
"name": "pair name; omit to list",
"neg": "negative net (e.g. USB_N)",
"pos": "positive net (e.g. USB_P)",
"remove": "bool"
},
"output": {
"pair": "string",
"pairs": "[{name, pos, neg}] (list)",
"replaced": "bool"
},
"hint": "Pair impedance and gap come from Altium's Differential Pairs Routing rule; set width/clearance for the pair's nets with altium_net_classes or altium_add_rule.",
"pitfalls": [
"Both nets must exist on the board."
],
"related": [
"net_classes",
"list_nets",
"add_rule"
],
"example": {
"name": "USB",
"neg": "USB_DN",
"pos": "USB_DP"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "edit_pours",
"tier": "native",
"source": "proposed",
"summary": "Change existing pours in place without redrawing them: clearance, minimum width, thermal relief (on/off, spoke width, gap), priority or rank, the net, and whether islands are kept. The copper is refilled and read back.",
"input": {
"pours": "[{id or net+layer, clearanceMm?, minWidthMm?, thermals?: {on, spokeMm, gapMm}, priority?, net?, keepIslands?}] (required)",
"expectedRevision": "string",
"dryRun": "bool"
},
"output": {
"edited": "[{id, before, after}]",
"pourState": "the pours after refill, as pour_state answers",
"revision": "string",
"mutated": "bool"
},
"hint": "pour_state lists the pours and their ids first. One undo step; a pour that refills to nothing is reported, not hidden.",
"pitfalls": [
"Changing the net of a pour reconnects copper: run_drc afterwards.",
"A tool that keeps a pour's clearance and thermals in its design rules (Altium) writes rules scoped to that pour rather than changing the pour itself; the reply says which."
],
"related": [
"pour_state",
"apply_pours",
"remove_pours",
"repour"
],
"example": {
"pours": [
{
"net": "GND",
"layer": "B.Cu",
"clearanceMm": 0.3
}
]
},
"longRunning": false,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.28.1",
"agreedBy": [
"standard-lane",
"kicad-lane",
"altium-lane"
]
},
{
"name": "edit_tracks",
"tier": "native",
"source": "proposed",
"summary": "Change given tracks by the handle routing_state returns: width, layer and ends. One undo step, read back.",
"input": {
"filePath": "the board (default the current one)",
"tracks": "[{id, width?, layer?, start?: [x, y], end?: [x, y]}] mm; id is the track's handle from routing_state (required)",
"dryRun": "bool, default false: answer the plan and change nothing",
"expectedRevision": "optional: refused with stale_board if the board changed"
},
"output": {
"results": "[ok|err:...] per track",
"changes": "[{id, before, after}]",
"verified": "bool: every change read back",
"revision": "string"
},
"hint": "set_track_width works by net or class; this works on the tracks you name, for one neck or one layer swap. A track that moves off its pad is refused or shows in routing_drc, depending on the bridge.",
"pitfalls": [
"Changing a track's layer does not add the vias its ends now need: check with routing_drc."
],
"related": [
"routing_state",
"set_track_width",
"remove_items",
"routing_drc"
],
"example": {
"tracks": [
{
"id": "<handle>",
"width": 0.5
}
]
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.31.1",
"agreedBy": [
"altium-lane"
]
},
{
"name": "export_3d",
"tier": "native",
"source": "proposed",
"summary": "Export the board's 3D model in a mesh or CAD format other than STEP (export_step has STEP), through the tool's own exporter, with an optional web-optimized glb. format is an open list; each bridge answers the ones its tool writes.",
"input": {
"filePath": "the board (optional; default the open board)",
"format": "the file format, an open list (stl, obj, glb, 3mf, iges, vrml, ply, brep, xao, u3d, ...); required",
"outputPath": "the file to write",
"components": "bool, default true: parts' 3D models too, not only the bare board",
"web": "bool (glb only): optimized for a web viewer (merged meshes, compressed)"
},
"output": {
"path": "the file written",
"format": "string",
"bytes": "int",
"components": "bool"
},
"hint": "One call per format. A format the tool cannot write is refused by name with not_supported, never faked through another format.",
"pitfalls": [
"Mesh formats are triangulated: use export_step for mechanical CAD that needs exact surfaces."
],
"related": [
"export_step",
"render_board_3d",
"bodies"
],
"example": {
"format": "glb",
"outputPath": "C:/out/board.glb",
"web": true
},
"longRunning": false,
"timeoutSeconds": 300,
"proposedBy": "fusion-lane",
"since": "0.28.1",
"agreedBy": [
"standard-lane",
"kicad-lane",
"altium-lane"
]
},
{
"name": "export_bom",
"tier": "native",
"source": "altium",
"summary": "Bill of materials export: altium_run_outjob with the assembly OutJob and the 'Folder Structure' medium as defaults.",
"input": {
"medium": "string, default 'Folder Structure'",
"outjobPath": "path to an .OutJob - default: the bundled example Assembly.OutJob",
"projectPath": "path to the .PrjPcb",
"timeout": "seconds, default 300"
},
"output": {
"dialogs": "[..]",
"elapsedSec": "float",
"files": "[relative paths]",
"outjob": "path",
"outputDir": "path | null",
"surface": "bom"
},
"hint": "files[] names the BOM the OutJob wrote; pull it with ab's pull_file. For part data without an OutJob, altium_read_schematic returns parameters per component.",
"pitfalls": [
"Without outjobPath it exports the BOM of Altium's EXAMPLE design.",
"The default OutJob is the example's Assembly.OutJob, which runs every output in that medium, not only a BOM."
],
"related": [
"run_outjob",
"export_gerber",
"read_schematic"
],
"example": {
"outjobPath": "C:/proj/Assembly.OutJob",
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "export_dxf",
"tier": "native",
"source": "proposed",
"summary": "Export chosen board layers to DXF, one file per layer (the outline, panel drawings, stencils, enclosure work).",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"layers": "[\"Edge.Cuts\", \"F.Cu\"]: layer names (required; there is no sensible default)",
"outputDir": "folder for the output (default beside the board)",
"units": "mm|in, default mm",
"contours": "bool, default false: join outline segments into polylines (most CAM and laser tools want it)",
"titleBlock": "bool, default false",
"excludeDesignators": "bool, default false",
"excludeValues": "bool, default false",
"useDrillOrigin": "bool, default false"
},
"output": {
"files": "[{layer, path}]"
},
"hint": "One file per layer, named after the board and the layer. For an enclosure drawing export Edge.Cuts with contours:true.",
"pitfalls": [
"The board's DXF only: a mechanical DXF of a 3D design is a different job and not this verb."
],
"related": [
"render_board_layers",
"export_step"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"layers": [
"Edge.Cuts"
],
"contours": true
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "export_gencad",
"tier": "native",
"source": "proposed",
"summary": "Export the board as GenCAD 1.4, the input of test-fixture tools and some assembly houses' CAM.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"outputDir": "folder for the output (default beside the board)",
"uniquePins": "bool, default false: rename duplicate pad numbers (several fixture tools need it)",
"flipBottomPads": "bool, default false",
"useDrillOrigin": "bool, default false: coordinates from the drill origin instead of the board's origin"
},
"output": {
"file": "path"
},
"hint": "Ask the fixture or assembly house which options it needs; uniquePins is the common one.",
"pitfalls": [
"Run run_drc first: the file carries the board's errors with it."
],
"related": [
"export_manufacturing",
"export_ipc356"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"uniquePins": true
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "export_gerber",
"tier": "native",
"source": "altium",
"summary": "Gerber/drill export: altium_run_outjob with the fabrication OutJob and the 'Folder Structure' medium as defaults.",
"input": {
"medium": "string, default 'Folder Structure'",
"outjobPath": "path to an .OutJob - default: the bundled example Fabrication.OutJob",
"projectPath": "path to the .PrjPcb",
"timeout": "seconds, default 300"
},
"output": {
"dialogs": "[..]",
"elapsedSec": "float",
"files": "[relative paths]",
"outjob": "path",
"outputDir": "path | null",
"surface": "gerber"
},
"hint": "Check files[] for the gerber and NC drill files, then pull them with ab's pull_file. Close the CAMtastic documents the OutJob opened (altium_state, altium_close_document).",
"pitfalls": [
"There is NO board-path argument: without outjobPath it exports Altium's EXAMPLE design. The user's project needs its own OutJob.",
"OutJobs open what they generate: expect CAM documents left open in the user's session."
],
"related": [
"run_outjob",
"export_bom",
"export_step",
"run_drc"
],
"example": {
"outjobPath": "C:/proj/Fabrication.OutJob",
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "export_ipc2581",
"tier": "native",
"source": "proposed",
"summary": "Export the board as IPC-2581: one XML file with copper, drill, stack-up, netlist and BOM, through the tool's own exporter.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"outputDir": "folder for the output (default beside the board)",
"version": "B|C, default C",
"units": "mm|in, default mm",
"compress": "bool, default false: zip the XML",
"bomFields": "{mpn, manufacturer, distributorPn, distributor}: the part field names that carry these, so the embedded BOM is useful to the fab"
},
"output": {
"file": "path"
},
"hint": "Name the part fields with bomFields, or the BOM inside the file carries no part numbers.",
"pitfalls": [
"Run run_drc first: the file carries the board's errors with it."
],
"related": [
"export_odb",
"export_manufacturing",
"run_drc"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"bomFields": {
"mpn": "MPN"
}
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "export_ipc356",
"tier": "native",
"source": "proposed",
"summary": "Export the IPC-D-356 netlist of the board, for bare-board electrical test (flying probe or bed of nails).",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"outputDir": "folder for the output (default beside the board)"
},
"output": {
"file": "path"
},
"hint": "Send it with the Gerbers when the fab tests boards against the netlist.",
"pitfalls": [
"Run run_drc first: the file carries the board's errors with it."
],
"related": [
"export_manufacturing",
"netlist"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc"
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "export_library_part",
"tier": "native",
"source": "proposed",
"summary": "Export one library part into its own small library files: a symbol library with only its symbol, a footprint library with only its footprint, and its 3D model file.",
"input": {
"part": "the part's symbol name or library id (required)",
"footprint": "a footprint name (default the symbol's own)",
"what": "[symbol, footprint, model] (default all three)",
"outputDir": "folder for the files"
},
"output": {
"exports": "{symbol: path, footprint: path, model: path}",
"missing": "[what]"
},
"hint": "Use it to hand one part to another project or another tool.",
"pitfalls": [
"success is false when any piece asked for is missing; exports still carries what was written."
],
"related": [
"read_symbol",
"read_footprint",
"import_part"
],
"example": {
"part": "IN-S42ATA"
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "export_manufacturing",
"tier": "native",
"source": "altium",
"summary": "A project's manufacturing set in one call: Gerbers, NC drill, pick and place (CSV, mm) and the BOM, from an OutJob the bridge writes beside the project (composed from this Altium's own OutJob templates, every output on one medium that opens nothing).",
"input": {
"bomColumns": "(optional) [column or parameter name] - default Comment, Description, Designator, Footprint, Quantity, MPN, Manufacturer, Mouser/DigiKey/LCSC Part #",
"clean": "bool (default true) - empty the output folder first",
"formats": "[odb, ipc2581] - more fab formats beside the Gerbers (ODB++ folder + .tgz, IPC-2581 .cvg); default Gerbers only",
"pcbPath": "its .PcbDoc",
"projectPath": "the .PrjPcb",
"silkPrep": "bool (default true) - Altium's Silkscreen Preparation first (silk off the pads, text moved where it fits)",
"silkPrepCheck": "bool (default false) - DRC silk counts before/after in silkPrep",
"timeout": "seconds, default 300"
},
"output": {
"dialogs": "[..]",
"elapsedSec": "float",
"files": "[relative paths]",
"outjob": "path",
"outputDir": "path"
},
"hint": "Pull files[] with pull_file and check them against the board (layers, drill hits, every placed part in the pick and place and the BOM) before handing them over. AI Flow's `altium export` does both.",
"pitfalls": [
"The board must be a document of the project.",
"The BOM is the compiled project's (schematic parts); board-only pads are not in it."
],
"related": [
"run_outjob",
"build_schematic",
"routing_state"
],
"example": {
"pcbPath": "C:\\work\\Buck.PcbDoc",
"projectPath": "C:\\work\\Buck.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "export_odb",
"tier": "native",
"source": "proposed",
"summary": "Export the board as ODB++ (copper, drill, stack-up, netlist and parts in one archive) through the tool's own exporter.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"outputDir": "folder for the output (default beside the board)",
"units": "mm|in, default mm",
"compression": "zip|tgz|none, default zip"
},
"output": {
"files": "[path]",
"outputDir": "path"
},
"hint": "Send the archive to a fab that takes ODB++ instead of Gerbers. export_manufacturing makes the Gerber set.",
"pitfalls": [
"Run run_drc first: the file carries the board's errors with it."
],
"related": [
"export_manufacturing",
"export_ipc2581",
"run_drc"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc"
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "export_pdf",
"tier": "native",
"source": "altium",
"summary": "Every sheet of a project as one PDF, plus on request the board's composite print, Altium's assembly drawings (top and bottom, designators on the parts) and its fabrication print, from an OutJob in a throwaway project; the user's project is not touched.",
"input": {
"assembly": "bool, default false - Altium's Assembly Drawings output (needs a board in the project)",
"board": "bool, default false - the composite print",
"fabrication": "bool, default false - Altium's PCB Print fabrication drawing",
"output": "path of the .pdf, default <project>.pdf beside it",
"projectPath": "path to the .PrjPcb (required)",
"timeout": "seconds, default 300"
},
"output": {
"assembly": "bool",
"board": "bool",
"fabrication": "bool",
"outputBytes": "int",
"pdfPath": "path",
"sheets": "int"
},
"hint": "Pull the file with ab's pull_file.",
"pitfalls": [],
"related": [
"run_outjob",
"export_manufacturing"
],
"example": {
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "export_pos",
"tier": "native",
"source": "proposed",
"summary": "Export the pick-and-place (component position, CPL) file of a board, optionally in a fab's assembly format (JLCPCB's columns).",
"input": {
"filePath": "the board (required)",
"side": "both | front | back, default both",
"format": "csv | ascii | gerber, default csv",
"units": "mm | in, default mm",
"smdOnly": "bool",
"excludeDnp": "bool, default true",
"fab": "jlcpcb: also write the fab's own CPL columns",
"outputDir": "folder"
},
"output": {
"files": "[path]",
"parts": "int per side"
},
"hint": "Pair it with a BOM and Gerbers for an assembly order; export_manufacturing writes all three in one call.",
"pitfalls": [
"Rotations follow the tool's convention; a fab may need its own offsets per package.",
"A format the tool cannot write (Altium's pick-and-place generator has no Gerber form) is answered unsupported with the reason."
],
"related": [
"export_manufacturing",
"bom",
"assembly_check"
],
"example": {
"filePath": "C:/proj/board.kicad_pcb",
"fab": "jlcpcb"
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.25.1",
"agreedBy": [
"standard-lane",
"altium-lane",
"fusion-lane"
]
},
{
"name": "export_step",
"tier": "native",
"source": "altium",
"summary": "Headless STEP export of a board. Default lane 'outjob': Altium's own ExportSTEP output run from a throwaway project in %TEMP% that points at the board - no dialog, no click (measured on AD 26.9.1). lane:'extension' is the older AdomBridge .NET extension path.",
"input": {
"componentsOption": "int, Altium ExportComponentOptions, default 0 (all)",
"copperOption": "int, Altium ExportCopperOption, default 0 (no copper)",
"filePath": "path to a .PcbDoc (saved state is exported) - default: the bundled example board",
"folded": "bool, default false",
"holes": "bool, default true (mechanical, electrical and free pad holes)",
"lane": "outjob | extension, default outjob",
"modelsOption": "int, Altium ExportModelsOption, default 2 (template default)",
"nameOccurrences": "bool, default true - name each component occurrence after its designator, as KiCad's STEP does (step2glb --molecule finds MP1-MP4 by it)",
"output": "path - default: <board>.step",
"singlePart": "bool, default false (one merged part)",
"suffix": "string, required with suffixType custom",
"suffixType": "none | board | custom | id, default none - Altium always names parts by DESIGNATOR; this only picks the suffix",
"timeout": "seconds, default 300"
},
"output": {
"elapsedSec": "float",
"lane": "string",
"occurrences": "{named: int} - component occurrences named after their designator",
"output": "path",
"outputBytes": "int",
"outputExists": "bool",
"products": "[string] - STEP PRODUCT names (how parts are named)"
},
"hint": "outputExists and products[] are the proof; then pull the file with ab's pull_file. Save the board first: the export reads the file on disk.",
"pitfalls": [
"Part names are designators (J1, U3...), never the Comment or footprint: Altium has no option for that (suffixType 0-3 measured).",
"Altium leaves every assembly occurrence unnamed; the bridge names each board component's occurrence after its designator (0.2.54), so tools that find parts by occurrence name (step2glb --molecule's MP1-MP4 anchoring) work as on a KiCad STEP.",
"The throwaway project and OutJob are closed afterwards and the temp folder removed; the user's own project is never opened or changed.",
"pcb_not_found / step_not_written / bad_args are named; dialogs from the OutJob come back under outjob.dialogs."
],
"related": [
"run_outjob",
"save",
"show_3d_board"
],
"example": {
"filePath": "C:/proj/board.PcbDoc",
"output": "C:/proj/board.step"
},
"longRunning": false,
"timeoutSeconds": 360
},
{
"name": "import_design",
"tier": "native",
"source": "proposed",
"summary": "Bring a design from another tool into a NEW native design with the parts instantiated: an EAGLE .sch with its paired .brd, a KiCad project, or an Altium project, through the tool's own importer.",
"input": {
"format": "the source tool, an open list (eagle, kicad, altium, pads, orcad, cadstar, fabmaster, pcad, ...); required",
"filePath": "the schematic or project file (required)",
"boardPath": "the paired board file, when the format keeps it separate",
"name": "the new design's name"
},
"output": {
"design": "the new design or project",
"parts": "int",
"nets": "int",
"warnings": "[string]: what the importer could not bring over"
},
"hint": "The import makes a new design and never changes the source files. Check the result with schematic_review and cross_check.",
"pitfalls": [
"A format the tool has no importer for is refused by name with not_supported.",
"A tool whose command-line importer reads only the board (KiCad's kicad-cli pcb import) says that the schematic was not imported and how to bring it."
],
"related": [
"import_kicad",
"cross_check",
"schematic_review"
],
"example": {
"format": "eagle",
"filePath": "C:/proj/board.sch",
"boardPath": "C:/proj/board.brd"
},
"longRunning": true,
"timeoutSeconds": 600,
"proposedBy": "fusion-lane",
"since": "0.28.1",
"agreedBy": [
"standard-lane",
"kicad-lane",
"altium-lane"
]
},
{
"name": "import_step",
"tier": "native",
"source": "proposed",
"summary": "Bring a STEP model in as 3D geometry placed with the board: an enclosure, a bracket or a mating part, for fit and clearance checks. Not a footprint's own model (that is add_body).",
"input": {
"filePath": "the STEP on the tool's machine (required)",
"at": "[x, y, z] mm relative to the board origin, default [0, 0, 0]",
"rotation": "[rx, ry, rz] degrees",
"name": "what to call it"
},
"output": {
"id": "the placed model",
"bboxMm": "[x0, y0, z0, x1, y1, z1]",
"bodies": "int"
},
"hint": "height_check and the bodies companion can then measure the board against it.",
"pitfalls": [
"A tool that can only open the STEP as a separate design answers partial and says so."
],
"related": [
"add_body",
"height_check",
"bodies",
"export_step"
],
"example": {
"filePath": "C:/mech/enclosure.step",
"at": [
0,
0,
-3
]
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "fusion-lane",
"since": "0.28.1",
"agreedBy": [
"standard-lane",
"altium-lane"
]
},
{
"name": "install_library",
"tier": "native",
"source": "altium",
"summary": "Register a library file in Altium's Installed Libraries (IntegratedLibraryManager.InstallLibrary) so its parts appear in the Components panel.",
"input": {
"libraryPath": "path to a .IntLib/.SchLib/.PcbLib/.DbLib (required)",
"timeout": "seconds, default 90"
},
"output": {
"data": "{installed: path}",
"roundtripMs": "int"
},
"hint": "Takes effect live, no restart. For a wiki bundle zip use altium_install_library_bundle (unpack + register + proof).",
"pitfalls": [
"'library not found' = the path must exist on THIS machine.",
"Registers the file where it is: moving or deleting it later leaves a dead entry."
],
"related": [
"install_library_bundle",
"list_library",
"show_library"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib"
},
"longRunning": false,
"timeoutSeconds": 150
},
{
"name": "install_library_bundle",
"tier": "native",
"source": "altium",
"summary": "One-click install of a wiki library bundle (zip of .SchLib/.PcbLib): unpack, register, open the library, prove it with a frame.",
"input": {
"capture": "bool",
"captureMaxWidth": "int",
"installId": "string - echoed in the receipt so a client can match it",
"libraryName": "string",
"zipPath": "string - staged zip"
},
"output": {
"atMs": "int",
"components": "[names]",
"installId": "string",
"phasesMs": "{launch, licence, unpack, register, open, list, panel, capture, agentStop}",
"shot": "{image, ...}",
"shown": "bool",
"symbolCount": "int",
"thumbnailDataUrl": "string",
"totalMs": "int"
},
"hint": "Launches a closed Altium first (up to 240s), then registers and opens the library. Past ab's budget the verb keeps running: poll altium_status until lastInstall.installId matches, then altium_install_receipt for the full receipt.",
"pitfalls": [
"The receipt lives in bridge memory; a bridge restart clears it."
],
"related": [
"install_receipt",
"status",
"install_library"
],
"example": {
"capture": true,
"installId": "Lib-1757350000000",
"libraryName": "Lib",
"zipPath": "C:\\Users\\me\\adom-wiki-libs\\Lib-altium.zip"
},
"longRunning": true,
"timeoutSeconds": 330
},
{
"name": "list_installed_libraries",
"tier": "native",
"source": "altium",
"summary": "Every library in Altium's Installed Libraries list (read-only).",
"input": {},
"output": {
"count": "int",
"libraries": "[path]"
},
"hint": "Check before and after altium_install_library / altium_uninstall_library without a screenshot.",
"pitfalls": [
"Needs the agent (it reads IntegratedLibraryManager inside Altium)."
],
"related": [
"uninstall_library",
"install_library",
"install_library_bundle"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "net_classes",
"tier": "native",
"source": "altium",
"summary": "Net classes on the current board: list them with their nets, or make one (replacing a class of that name) with an optional width and clearance rule scoped to it, or remove one with its rules. Power nets wider, a high-voltage class with more clearance.",
"input": {
"clearance": "mm - optional rule 'Adom <name> clearance' (class to All)",
"filePath": "path to the .PcbDoc - optional, else the current board",
"name": "class name; omit to list",
"nets": "[string] board net names (required to make one)",
"remove": "bool - delete the class and its two rules",
"width": "mm (0.5) or {min, preferred, max} in mm - optional rule 'Adom <name> width'"
},
"output": {
"classes": "[{name, superClass, nets}] (list)",
"members": "int",
"notOnBoard": "[string] nets that were not found",
"rules": "[{kind, success, ..}]",
"scope": "InNetClass('<name>')"
},
"hint": "Rules land first among their kind, so they outrank the board-wide ones. Existing tracks keep their width: re-route the class's nets or check with altium_run_drc. altium_save keeps it.",
"pitfalls": [
"Net names must exist on the board (altium_list_nets); missing ones are reported in notOnBoard, not created.",
"A class made on the board, not in the schematic, can be removed by a later change order if the project's comparator removes board-only classes."
],
"related": [
"add_rule",
"list_nets",
"read_rules",
"diff_pairs",
"set_design_rules"
],
"example": {
"clearance": 0.3,
"name": "Power",
"nets": [
"VIN",
"VOUT",
"GND",
"SW"
],
"width": 0.5
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "netlist",
"tier": "native",
"source": "altium",
"summary": "The compiled netlist of a project: every net with its pins (Designator.Pin) across every sheet, the hierarchy resolved; or one net; or compare with the nets you expect.",
"input": {
"expect": "optional {net: [\"U1.3\", ...]}: compare pin by pin",
"net": "optional: one net",
"projectPath": ".PrjPcb (required)"
},
"output": {
"compileErrors": "[messages]",
"mismatches": "[{net, missing, extra} | {net, unexpected}] (expect)",
"netCount": "int",
"nets": "{net: [pin]}"
},
"hint": "Use it to check a schematic the AI drew or edited before altium_update_pcb: expect the nets you meant and read mismatches.",
"pitfalls": [
"Unnamed nets read as Altium names them (NetU2_3).",
"Compiles the project first: the reply is the design as Altium sees it now."
],
"related": [
"compile",
"schematic_data",
"sch_connect",
"sch_sheet_symbol",
"update_pcb"
],
"example": {
"expect": {
"GND": [
"U1.4",
"U10.4"
],
"VBUS": [
"U1.1",
"U10.1"
]
},
"projectPath": "C:\\\\work\\\\Board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "panelize",
"tier": "native",
"source": "altium",
"summary": "Step and repeat a board into a manufacturing panel: a new .PcbDoc holding Altium's own embedded board array of the board (rows x cols), with rails, the panel frame on the outline layer, three tooling holes and three fiducials; boards separated by JLCPCB-style V-score lines or mouse-bite tabs, with JLCPCB's rules checked. The array stays linked to the board.",
"input": {
"cols": "default 2",
"gapMm": "between boards, default 2 (vscore: 0)",
"overwrite": "bool - replace an existing panelPath (closed in Altium unsaved first); without it an existing file is refused",
"panelPath": "the new panel .PcbDoc",
"pcbPath": "the board's .PcbDoc",
"projectPath": "a .PrjPcb the panel joins (so altium_export_manufacturing can make its Gerbers)",
"railMm": "rail width, default 5 (0 for none)",
"rows": "default 1",
"separation": "none (default) | vscore (boards edge to edge, V-CUT lines across the panel on Mechanical 1 with 'V-CUT' written at both ends, as JLCPCB asks) | tabs (mouse bites: 0.6 mm holes five to a tab, the rout path drawn on Mechanical 1)",
"toolingHoles": "default true: 2 mm unplated holes and 1 mm fiducials when rails are 5 mm or wider"
},
"output": {
"boardMm": "[w, h] of one board's outline",
"boardsAt": "[[x, y]] each board's outline corner from the panel's corner",
"jlcpcb": "{rules:[{rule, ok (true|false|null = a note), detail}], fits}",
"nearestCopperToEdge": "{mm, at}",
"panelMm": "[w, h]",
"panelPath": "path",
"project": "{path, added}",
"saved": "bool",
"separation": "{kind, cutsX, cutsY | tabs, holes, routLines, applied, failed}",
"warnings": "[{copperOutsideOutline}]"
},
"hint": "Fix what jlcpcb.rules marks false (panel under 70 mm: more rows or wider rails; copper under 0.4 mm from a cut; rounded corners on a V-cut) and run it again with overwrite:true. Then altium_export_manufacturing {projectPath, pcbPath: the panel}.",
"pitfalls": [
"Opens the board, then creates and saves the panel; without projectPath the saved panel is closed (open it with altium_open_document).",
"tabs refuses a board that draws its own outline on a mechanical layer: every copy brings it along closed and a router would cut each board free.",
"JLCPCB's rules as published (V-cut standards and mouse-bite guide, read 2026-10-23): V-cut panels 70 to 475 mm, 0.6 mm boards or thicker, copper 0.4 mm (1.0 recommended) from a cut, at most 25 cuts a side; mouse bites 0.6 mm holes 5 to a set, gaps of 1.2 mm or more."
],
"related": [
"fab_check",
"export_manufacturing",
"board_features",
"set_outline"
],
"example": {
"cols": 3,
"panelPath": "C:/proj/Panel.PcbDoc",
"pcbPath": "C:/proj/Board.PcbDoc",
"projectPath": "C:/proj/Board.PrjPcb",
"railMm": 5,
"rows": 3,
"separation": "vscore"
},
"longRunning": false,
"timeoutSeconds": 240
},
{
"name": "pcb_report",
"tier": "native",
"source": "altium",
"summary": "Numbers instead of pixels: for a PcbLib, every footprint's pads, pad bounding box, primitive census and 3D bodies; for a board, outline, components with nets and bodies, census and tracks.",
"input": {
"name": "string - footprint name filter (library form)",
"path": "path to a .PcbLib or .PcbDoc - optional; opened first",
"timeout": "seconds, default 60",
"want": "'board' - report the focused BOARD even though a PcbLib is also answering"
},
"output": {
"data": "{kind: library, components: [{name, pads, padsBboxMil, census, bodies}], bodyCols} | {kind: board, outlineMil, components: [{.., pads, padsBboxMil, nets, bodies}], census, tracks, bodyCols}",
"roundtripMs": "int"
},
"hint": "bodies[] rows follow bodyCols (layerId,wMil,hMil,leftMil,bottomMil,standoffMil,overallMil,hasModel). A body whose leftMil is ~50000 away from padsBboxMil needs altium_normalize_bodies.",
"pitfalls": [
"Altium's GetCurrentPCBLibrary answers even when a BOARD is focused: pass want:'board' for a .PcbDoc or you get the library report.",
"A footprint with bodies:[] places with no 3D model."
],
"related": [
"footprint_primitives",
"normalize_bodies",
"add_body",
"show_3d_chip"
],
"example": {
"name": "VL53L5CX",
"path": "C:/lib/Adom_ToF.PcbLib"
},
"longRunning": false,
"timeoutSeconds": 60,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "physical_properties",
"tier": "native",
"source": "proposed",
"summary": "Per component: volume, mass, density, surface area and centre of mass, from the tool's own materials. A tool with no materials or part masses answers unsupported with the reason. Read only.",
"input": {
"names": "[component name] (default every component)",
"accuracy": "low|medium|high|veryhigh, default low"
},
"output": {
"count": "int",
"properties": "{name: {volume_cm3, mass_kg, density, area_cm2, center_of_mass}}"
},
"hint": "bodies gives each part's box on the board; this gives what it weighs.",
"pitfalls": [
"Mass is only as good as the material on the part."
],
"related": [
"bodies",
"component_data"
],
"example": {
"names": [
"Enclosure"
]
},
"longRunning": false,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"altium-lane",
"kicad-lane"
]
},
{
"name": "pour_state",
"tier": "native",
"source": "altium",
"summary": "Every polygon pour with the copper it actually poured: filled area per pour and per layer, and the pours that poured nothing.",
"input": {},
"output": {
"filledAreaByLayerMm2": "{layer: mm2}",
"unfilled": "[zone]",
"zones": "[{net, name, layer, pourIndex, outline, filledMm2, islands, filled}]"
},
"hint": "filledMm2 is regions minus holes, computed from Altium's own poured geometry.",
"pitfalls": [
"Needs the board current.",
"A shelved or unpoured polygon reads filledMm2 0."
],
"related": [
"apply_pours",
"repour"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "project_snapshot",
"tier": "native",
"source": "proposed",
"summary": "A dated copy of the project's documents into <project>/snapshots/<stamp>[-label]/, with PDFs of the schematic and the board made by the tool.",
"input": {
"project": "path to the project file (required)",
"label": "string: added to the folder name",
"pdfs": "bool, default true"
},
"output": {
"folder": "path",
"files": "[path]",
"pdfs": "{made: [path], skipped: why}"
},
"hint": "Take one before a risky edit (a rename, a big re-route). Libraries in sub-folders are referenced, not copied.",
"pitfalls": [
"A snapshot of an open project holds what is saved on disk, not unsaved edits: save first."
],
"related": [
"project_rename",
"export_pdf",
"save"
],
"example": {
"project": "C:/proj/Board.PrjPcb",
"label": "before-routing"
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "remove_pours",
"tier": "native",
"source": "altium",
"summary": "Delete polygon pours by net (and layer), or all of them, and the pour keepouts (cutouts) apply_pours made. Tracks and vias are untouched.",
"input": {
"cutouts": "(optional) \"all\" or [{layer}] - only the cutouts apply_pours landed (named Adom...)",
"expectedRevision": "string (optional) - refused with stale_board if the board changed since you read it",
"pours": "(optional) \"all\" or [{net, layer?} | {name} - one pour by the name apply_pours answered]"
},
"output": {
"cutoutsRemoved": "int",
"removed": "int",
"revision": "string",
"rulesRemoved": "int - AdomPC connect rules whose pour is gone"
},
"hint": "Use before re-pouring a changed plan; the connect rules of removed pours go with them. altium_ripup_nets clears copper.",
"pitfalls": [],
"related": [
"apply_pours",
"ripup_nets"
],
"example": {
"pours": [
{
"net": "GND"
}
]
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "render_board",
"tier": "native",
"source": "proposed",
"summary": "A rendered 3D picture (PNG or JPG) of a board from one side, made by the tool's own renderer with no window: optionally framed on parts, turned for an isometric view, raytraced.",
"input": {
"filePath": "the board (required)",
"side": "top | bottom | left | right | front | back, default top",
"width": "px, default 1600",
"height": "px, default 900",
"quality": "basic | high (raytraced)",
"background": "default | transparent | opaque",
"zoom": "float",
"perspective": "bool",
"format": "png | jpg",
"refs": "[ref]: frame these parts (camera on their pads' centre, zoomed to them)",
"marginMm": "mm round framed parts, default 2",
"rotate": "'x,y,z' degrees, e.g. '-45,0,45' for isometric",
"outputDir": "folder for the image"
},
"output": {
"path": "the image",
"framed": "{refs, pivot, zoom} when refs was given"
},
"hint": "One call per side (top and bottom for a review). refs frames parts for a close look; quality high raytraces and takes longer.",
"pitfalls": [
"The picture is of the saved board file: unsaved edits are not in it."
],
"related": [
"zoom_to",
"library_views",
"render_schematic"
],
"example": {
"filePath": "C:/proj/board.kicad_pcb",
"side": "top",
"refs": [
"J1"
],
"rotate": "-45,0,45"
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.25.1",
"agreedBy": [
"standard-lane",
"fusion-lane"
]
},
{
"name": "render_board_3d",
"tier": "native",
"source": "proposed",
"summary": "Render a 3D picture of the board from one side to an image file, through the tool's own renderer, without opening a window.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"side": "top|bottom|left|right|front|back, default top",
"width": "int px, default 1600",
"height": "int px, default 900",
"quality": "basic|high, default basic (high raytraces and is much slower)",
"background": "default|transparent|opaque",
"zoom": "number, default 1.0",
"perspective": "bool, default false",
"format": "png|jpg, default png",
"outputDir": "folder for the output (default beside the board)"
},
"output": {
"image": "path",
"width": "int",
"height": "int",
"side": "string"
},
"hint": "One call per side: top and bottom for a review. A flat image of chosen layers is render_board_layers; show_3d_board opens a window instead.",
"pitfalls": [
"Parts without a 3D model render as bare pads: check them with bodies first."
],
"related": [
"render_board_layers",
"render_schematic",
"bodies",
"show_3d_board"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"side": "top"
},
"longRunning": true,
"timeoutSeconds": 600,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "render_board_layers",
"tier": "native",
"source": "proposed",
"summary": "Render chosen board layers to an image file without opening a window: a preset view (copper, silkscreen, solder mask, paste, outline, drill, assembly or fabrication, of either side) or a list of layers, as png or svg.",
"input": {
"filePath": "path to the board (optional; default the open board)",
"preset": "all | top_copper | bottom_copper | top_silkscreen | bottom_silkscreen | top_soldermask | bottom_soldermask | top_paste | bottom_paste | outline | drill | assembly_top | assembly_bottom | fabrication (default all)",
"layers": "[layer]: copper by its standard name (F.Cu, In1.Cu, B.Cu) or any layer by the tool's own id; overrides preset",
"format": "png | svg (default png)",
"dpi": "int, default 300 (png)",
"mirror": "bool, default false: draw the board as seen from below",
"monochrome": "bool, default false",
"outputPath": "the image file to write (default beside the board)",
"listPresets": "bool: answer the presets and their layers, and make no image"
},
"output": {
"path": "path",
"format": "png | svg",
"widthPx": "int (png)",
"heightPx": "int (png)",
"preset": "string, or custom when layers was given",
"layers": "[layer]: what was drawn",
"presets": "{name: description} (listPresets)"
},
"hint": "Each preset is a fixed set of layers, so two bridges draw the same view. For a 3D picture use render_board_3d. The show_* verbs open a window; this one does not.",
"pitfalls": [
"Mirroring is never automatic: a bottom preset is drawn as seen from the top unless mirror is true.",
"Inner copper layers appear only when listed in layers."
],
"related": [
"render_board_3d",
"render_schematic",
"export_gerber",
"export_pdf"
],
"example": {
"preset": "assembly_top",
"format": "png",
"dpi": 300
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "fusion-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "render_schematic",
"tier": "native",
"source": "proposed",
"summary": "Render a sheet to an image without opening a window, through the tool's own plotter, and keep visual baselines: baseline set stores the image, baseline compare reports the pixel drift, the changed region and a diff image.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"width": "int px, default 2000",
"outputDir": "folder for the image (default beside the project)",
"baseline": "set|compare",
"threshold": "percent of pixels, default 0.5 (compare)",
"drawingSheet": "bool, default true: include the frame and title block"
},
"output": {
"png": "path",
"width": "int",
"height": "int",
"driftPercent": "number (compare)",
"pass": "bool (compare)",
"changedRegionMm": "[x1, y1, x2, y2] (compare)",
"diffPng": "path: the changed pixels in red (compare)",
"rendererChanged": "bool: the tool's plotter changed since the baseline"
},
"hint": "A sub-sheet renders with its real designators. compare renders at the baseline's width and passes when driftPercent <= threshold. show_* verbs open a window; this one does not.",
"pitfalls": [
"Anti-aliasing differs between tool versions: rendererChanged:true means drift may not be a design change.",
"A baseline is per sheet and per width; a paper size change reads as 100 percent drift."
],
"related": [
"sch_page",
"export_pdf"
],
"example": {
"sheet": "C:/proj/Power.SchDoc",
"baseline": "compare"
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "replicate_layout",
"tier": "native",
"source": "altium",
"summary": "Copy one channel's placement to matching channels: each target keeps its anchor part where it is and every other part takes the source's offset and rotation from the anchor (turned by the anchors' rotation difference).",
"input": {
"anchor": "optional ref from source (default the first)",
"filePath": "optional .PcbDoc",
"source": "[refs] of the placed channel (2 or more)",
"targets": "[[refs], ...] - each in the same order as source"
},
"output": {
"footprintMismatches": "[..] parts whose footprint differs from their source part",
"moved": "int",
"moves": "[{ref, x, y, rotation}]"
},
"hint": "Read the channels with altium_selection or altium_component_data; route the targets after (routing is not copied). Check with altium_find_space {check:true}.",
"pitfalls": [
"Routing and pours are not copied."
],
"related": [
"move_parts",
"selection",
"find_space"
],
"example": {
"source": [
"U1",
"R1",
"C1"
],
"targets": [
[
"U2",
"R2",
"C2"
],
[
"U3",
"R3",
"C3"
]
]
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "repour",
"tier": "native",
"source": "altium",
"summary": "Repour every polygon on the board (Altium's Repour All) and answer the copper after. Runs outside the script engine so scoped rules apply.",
"input": {
"inScript": "bool (default false) - repour from inside the agent instead (scoped rules then match nothing)"
},
"output": {
"filledAreaByLayerMm2": "{...}",
"run": "{helperExited, seconds, agentStart}",
"unfilled": "[...]",
"zones": "[...]"
},
"hint": "Run after moving parts or copper that pours flow around. Altium evaluates rule queries through its scripting system, so a repour from inside the resident agent ignores every scoped rule (a pour's own connect style, net-class clearances); this verb stops the agent, repours, and starts it again (a few seconds). apply_pours does the same on its own when it wrote connect rules.",
"pitfalls": [
"Needs the board current.",
"The agent restarts: a verb sent meanwhile waits for it."
],
"related": [
"pour_state",
"apply_pours"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "routing_drc",
"tier": "native",
"source": "altium",
"summary": "Design-rule violations on the current board WITH locations, plus the unrouted (ratsnest) count, as one clean/not-clean answer.",
"input": {
"full": "bool (default false) - run Altium's batch DRC on this board first"
},
"output": {
"clean": "bool - no violations and nothing unrouted",
"errors": "int",
"unconnected": "int",
"violations": "[{rule, description, at{x,y} mm}]"
},
"hint": "Without full, this reads online DRC's live violations (fast). full:true runs the batch check through Altium's DRC dialog first.",
"pitfalls": [
"Needs the board current.",
"violations[] is capped at 500; errors is the real count."
],
"related": [
"routing_state",
"run_drc"
],
"example": {
"full": true
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "run_drc",
"tier": "native",
"source": "altium",
"summary": "Run the design rule check on a board and read the violation markers back. PCB:DesignRuleCheck opens a MODAL; the bridge clicks 'Run Design Rule Check' through UIA in the background, waits for the agent, re-activates the board and reads the violations.",
"input": {
"filePath": "path to a .PcbDoc - default: the bundled Bluetooth Sentinel board",
"limit": "int, default 200 violations",
"timeout": "seconds to wait for the DRC, default 180"
},
"output": {
"board": "path",
"dialogs": "[..]",
"elapsedSec": "float",
"steps": "[..]",
"violationCount": "int",
"violations": "[{rule, description}]",
"windowEtiquette": "background"
},
"hint": "violationCount is the true total; violations[] stops at limit. Altium also opens its HTML DRC report as a new document: altium_state shows it, altium_close_document {path} removes it.",
"pitfalls": [
"ALWAYS pass filePath: the default runs DRC on Altium's example board.",
"drc_dialog_not_found = the DRC dialog never opened; check that a PCB is focused (altium_window_info).",
"Never run PCB:DesignRuleCheck through altium_run_command: the modal freezes the agent with nobody to click it."
],
"related": [
"read_rules",
"rules_by_kind",
"review_board",
"compile"
],
"example": {
"filePath": "C:/proj/board.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "run_erc",
"tier": "native",
"source": "altium",
"summary": "Electrical rules check. Same handler as altium_compile: in Altium, compiling the project IS the ERC.",
"input": {
"limit": "int, default 200 messages",
"objectKind": "string, default 'Project'",
"projectPath": "path to a .PrjPcb (alias: filePath) - default: the bundled Bluetooth Sentinel example",
"timeout": "seconds"
},
"output": {
"byClass": "{class: n}",
"elapsedSec": "float",
"messageCount": "int",
"messages": "[{class, source, document, text}]",
"project": "path",
"windowEtiquette": "background"
},
"hint": "byClass gives the error/warning split; read messages[].text and .document for each. Then altium_run_drc for the layout.",
"pitfalls": [
"ALWAYS pass projectPath: the default compiles Altium's example project.",
"Needs the PROJECT path, not a sheet: a free .SchDoc has no project to compile."
],
"related": [
"compile",
"run_drc",
"review_board"
],
"example": {
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "sch_update_from_library",
"tier": "native",
"source": "proposed",
"summary": "Update the placed symbols on a sheet from their libraries (all, or the listed ones) and report which changed, which already matched and which no library has.",
"input": {
"sheet": "path to the schematic sheet file (required)",
"symbols": "[library symbol name or id, ...] (default all)",
"library": "path to one library to take them all from (with symbols)",
"force": "bool, default false: update even when a placed pin would be dropped",
"dryRun": "bool, default false: answer the plan and change nothing",
"save": "bool, default true: save the sheet after the edit"
},
"output": {
"changed": "[{symbol, pinsAdded, pinsRemoved}]",
"unchanged": "[symbol]",
"notFound": "[symbol]",
"refused": "[{symbol, droppedPins}]",
"saved": "bool"
},
"hint": "Run with dryRun first. A symbol whose new version drops a placed pin is refused unless force:true. Check the sheet afterwards with run_erc.",
"pitfalls": [
"A pin that moved in the library moves off its wire: check with sch_pins or run_erc after an update that reports changes."
],
"related": [
"sch_swap_part",
"schematic_data",
"run_erc"
],
"example": {
"sheet": "C:/proj/Main.SchDoc",
"dryRun": true
},
"longRunning": true,
"timeoutSeconds": 180,
"proposedBy": "kicad-lane",
"since": "0.2.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "set_design_rules",
"tier": "native",
"source": "altium",
"summary": "Write a fab's design rules into the current board: clearance, track width, routing via style, hole size, annular ring, hole-to-hole and board-edge clearance (mm).",
"input": {
"annularRing": "mm",
"clearance": "mm",
"costlier": "with fab: allow JLCPCB's surcharged small vias (0.15/0.25 mm) instead of 0.3/0.5",
"edgeClearance": "mm - copper to the board edge (the rule it creates is scoped OnCopper; silkscreen keeps its own rules)",
"fab": "jlcpcb - fill every value left out from JLCPCB's published limits for this board's layers and copper weight",
"hole": "{min, max?} mm",
"holeToHole": "mm",
"polygonConnect": "the board's catch-all polygon connect style: direct|relief|none, or {style, reliefWidth: mm, reliefEntries: 2|4} (per-pour rules from apply_pours keep theirs)",
"trackWidth": "{min, preferred?, max?} mm",
"via": "{diameter:{min, preferred?, max?}, drill:{min, preferred?, max?}} mm"
},
"output": {
"failed": "[{kind, error}]",
"landed": "[{kind, rulesWritten}]",
"rules": "the board's rules after"
},
"hint": "AI Flow's `rules use` calls this with the fab pack's numbers (adom/pcb-design-rules). Each kind is written separately, so one this Altium build lacks fails alone.",
"pitfalls": [
"Needs the board current.",
"Every existing rule of a kind gets the values; rule scopes are kept, except an Adom edge rule an earlier bridge scoped to All, which becomes OnCopper (#26)."
],
"related": [
"read_rules",
"rules_by_kind",
"build_board"
],
"example": {
"clearance": 0.15,
"edgeClearance": 0.3,
"hole": {
"min": 0.2
},
"trackWidth": {
"min": 0.15
},
"via": {
"diameter": {
"min": 0.45
},
"drill": {
"min": 0.2
}
}
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "silkscreen_prep",
"tier": "native",
"source": "altium",
"summary": "Clean the silkscreen off the copper with Altium's own Tools > Silkscreen Preparation: silk clipped clear of every mask opening (pad) by the board's silk rule, designators moved off pads where they fit, silk outside the board deleted; the silkscreen DRC hits counted before and after.",
"input": {
"check": "bool, default true: DRC before and after",
"clipLocked": "bool, default false",
"deleteOutsideBoard": "bool, default true",
"filePath": "the .PcbDoc (opened first)",
"minRemainingMil": "shortest silk segment kept (Altium's default 5.9 mil)",
"moveText": "bool, default true: move text off pads (within Altium's Max Distance) instead of clipping it",
"save": "bool, default true",
"selectedOnly": "bool, default false"
},
"output": {
"after": "{same}",
"before": "{silkToSolderMask, silkToSilk, silkToBoardRegion, maskSliver}",
"dialogsLeft": "[anything Altium asked]",
"silkOffCopper": "bool",
"steps": "[toggles, OK]"
},
"hint": "Run it before fab outputs and before 3D or screenshot renders: fabs trim silk off pads anyway, but a board that shows ink on copper looks wrong.",
"pitfalls": [
"It uses the board's SilkToSolderMaskClearance rule (Use Design Rules stays on).",
"Text that cannot move within Max Distance stays and is counted in after.silkToSolderMask."
],
"related": [
"silk_state",
"apply_silkscreen",
"run_drc",
"export_manufacturing"
],
"example": {
"filePath": "C:\\\\work\\\\Board.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 600,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "symbol_mode",
"tier": "native",
"source": "altium",
"summary": "Show one display mode (0 = Normal, 1.. = alternates) of the CURRENT SchLib component in the editor and capture a frame. Drives the editor's own mode toggle, because setting DisplayMode alone does not repaint.",
"input": {
"libraryPath": "path to a .SchLib - optional; opened first",
"mode": "int, default 0",
"timeout": "seconds, default 60"
},
"output": {
"data": "{mode, displayModeCount, libref}",
"shot": "{image: base64 png, width, height}",
"windowEtiquette": "background"
},
"hint": "Select the component first with altium_show_symbol {libraryPath, symbolName}, then one call per mode up to displayModeCount-1.",
"pitfalls": [
"There is no symbolName argument: it acts on the component current in the editor.",
"Leave it on mode 0 when done: the editor keeps showing the last mode to the user."
],
"related": [
"show_symbol",
"build_symbol_modes",
"read_symbol"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib",
"mode": 1
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "teardrops",
"tier": "native",
"source": "altium",
"summary": "Add (or remove) teardrops with Altium's own Tools > Teardrops: on vias and through-hole pads, SMD pads, track width changes and T-junctions, for the whole board or the selection; teardrops counted before and after.",
"input": {
"filePath": "the .PcbDoc (opened first)",
"force": "bool, default false: add even where a teardrop breaks a rule",
"remove": "bool, default false (add)",
"save": "bool, default true",
"selectedOnly": "bool, default false (all)",
"smdPads": "bool, default true",
"tJunctions": "bool, default true",
"tracks": "bool, default true",
"vias": "bool, default true"
},
"output": {
"dialogsLeft": "[anything Altium asked]",
"steps": "[mode, objects, toggles, OK]",
"teardropsAfter": "int",
"teardropsBefore": "int"
},
"hint": "Add teardrops after routing and before the final pour and DRC: altium_repour, then altium_run_drc.",
"pitfalls": [
"Altium's own sizes are used (via 70% width / 30% length, pads 200% / 100%, curved).",
"force:true places teardrops that violate clearance: leave it off unless the user asks."
],
"related": [
"repour",
"run_drc",
"routing_state",
"selection"
],
"example": {
"filePath": "C:\\\\work\\\\Board.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "uninstall_library",
"tier": "native",
"source": "altium",
"summary": "Remove libraries from Altium's Installed Libraries: the inverse of install_library / install_library_bundle. Library files are never touched.",
"input": {
"dryRun": "bool",
"libraryName": "file stem: matches X.SchLib AND X.PcbLib",
"libraryPath": "exact registered path"
},
"output": {
"closedDocuments": "[path]",
"notInstalled": "bool",
"remaining": "int",
"removed": "[path]"
},
"hint": "Any open document for a removed library is closed first. Close Altium with a plain altium_close afterwards: a close that discards changes can drop the unregistration.",
"pitfalls": [
"Nothing matching answers notInstalled:true (success), so a cleanup can run twice.",
"discardChanges:true on altium_close can bring the removed library back on the next launch."
],
"related": [
"list_installed_libraries",
"install_library",
"close"
],
"example": {
"libraryName": "Adom_ToF"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "update_pcb",
"tier": "native",
"source": "altium",
"summary": "Design > Update PCB Document from the schematic (the engineering change order): parts added, removed or renamed, nets and footprints updated on the board. Previews by default; execute:true runs it (Execute Changes, Close), refusing to delete board parts unless allowRemovals:true.",
"input": {
"allowRemovals": "bool, default false - let the change order delete board parts that are on no sheet",
"execute": "bool, default false - false only previews",
"projectPath": "path to the .PrjPcb (required)",
"timeout": "seconds, default 300"
},
"output": {
"afterExecute": "[string]",
"board": "path",
"changeOrder": "[string] - the dialog's first page (groups carry counts)",
"dialogs": "[..] - anything Altium asked",
"executed": "bool",
"preview": "{addParts, removeParts, sheetParts, boardParts}",
"steps": "[..]"
},
"hint": "Preview first (the default): removeParts are board parts on no sheet (test pads, fiducials, mounting holes) that the change order would DELETE; it refuses them unless allowRemovals:true. New parts land beside the board outline: place them (altium_move_parts) and check with altium_routing_drc.",
"pitfalls": [
"Save the sheets first (the sch_* verbs save by default).",
"The project must contain a .PcbDoc."
],
"related": [
"annotate",
"sch_place_part",
"move_parts",
"routing_drc"
],
"example": {
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "variants",
"tier": "native",
"source": "altium",
"summary": "Assembly variants of a project (which parts are fitted on which build): list them, make or change one with not-fitted parts (or put parts back), or remove one. Altium's script API cannot create variants, so the bridge writes them into the .PrjPcb, reloads the project and reads back what Altium holds.",
"input": {
"fitted": "[designators] to put back (their variation is dropped)",
"name": "variant name; omit to list",
"notFitted": "[designators] to mark Not Fitted (alias dnp)",
"projectPath": "path to the .PrjPcb (required)",
"remove": "bool - delete the variant"
},
"output": {
"altium": "{variants:[{name, variations:[{designator, kind}]}]} as Altium reads them (kind 1 = not fitted, 2 = alternate)",
"variants": "[{name, notFitted, alternates}]"
},
"hint": "altium_bom {variant} then gives that build's BOM (not-fitted parts dropped). Saves the project's documents, closes and reopens the project to load the change.",
"pitfalls": [
"Variants with parameter variations are refused (edit those in Altium's Variant Management).",
"Parts are named by their sheet's unique id: on a multi-channel (repeated) sheet every channel gets the same variation.",
"Alternate parts are listed but not created here."
],
"related": [
"bom",
"export_manufacturing",
"run_outjob"
],
"example": {
"name": "Lite",
"notFitted": [
"R5",
"C9",
"J2"
],
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "assembly_check",
"tier": "checks",
"source": "altium",
"summary": "Ready for JLCPCB assembly? The board against both JLCPCB PCBA tiers as published (Economic and Standard): board or panel size, thickness and layers, parts on one or both sides, the smallest package and the finest pin pitch, fiducials, and the parts with no LCSC number; answers the cheapest tier every rule allows.",
"input": {
"filePath": "the .PcbDoc (opened first; else the current board)",
"panelMm": "[w, h] when it ships in a panel (altium_panelize's panelMm)",
"projectPath": "the .PrjPcb - checks every purchased BOM line has an LCSC number (altium_bom)"
},
"output": {
"board": "{parts, bottomSideParts, finestPitch, smallestChip, tinyFootprints, fiducials, throughHoleParts}",
"economic": "{ok, rules:[{rule, ok, detail}]}",
"linesWithoutLcsc": "[..]",
"service": "economic | standard | null",
"standard": "{ok, rules}"
},
"hint": "Fix what the rules mark false: panelize a small board (altium_panelize, then panelMm), add fiducials (altium_board_features), find LCSC numbers (adom-parts-search). Then altium_bom (JLCPCB BOM) and altium_export_manufacturing (pick and place), and check every part's rotation in JLCPCB's preview.",
"pitfalls": [
"Pitch is the closest pad centres within one part of 3 or more SMD pads; package size is read from footprint names and two-pad parts' pad spacing.",
"Rotations are not checked: JLCPCB's preview is the authority on orientation."
],
"related": [
"bom",
"export_manufacturing",
"panelize",
"board_features",
"fab_check"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"projectPath": "C:/proj/Board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "auto_classes",
"tier": "checks",
"source": "altium",
"summary": "Net classes from the nets' own names: GND, Power (VCC, VDD, 3V3, VBAT...), Clock, HighSpeed (USB, Ethernet, HDMI, PCIe, DDR, MIPI, LVDS, SATA...) and the differential pairs their _P/_N, +/-, DP/DN names spell; a proposal first, written as Altium net classes (Power with a width rule) and pairs with apply.",
"input": {
"apply": "bool - write the classes and pairs (default: propose only)",
"filePath": "the .PcbDoc (opened first; else the current board)",
"powerWidthMm": "the Power class's width rule, default 0.5"
},
"output": {
"applied": "bool",
"proposal": "{classes:{GND, Power, Clock, HighSpeed}, pairs:[{name, pos, neg}], unclassified}",
"written": "[{class|pair, success}]"
},
"hint": "Then scope rules to them (InNetClass('Power')), size the pairs with altium_impedance {apply}, and check power with altium_current_capacity.",
"pitfalls": [
"Names only: a net called N1 stays unclassified. Read the proposal before apply."
],
"related": [
"net_classes",
"diff_pairs",
"impedance",
"add_rule",
"current_capacity"
],
"example": {
"apply": true,
"powerWidthMm": 0.6
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "board_features",
"tier": "checks",
"source": "altium",
"summary": "Add the furniture every real board needs in one undo step: mounting holes (at points or the four corners), fiducials, keepout areas, and a stitching-via grid on a net that keeps clear of every other net's copper, every pad and the board edge.",
"input": {
"dryRun": "bool - plan only",
"expectPath": "optional",
"expectedRevision": "optional",
"fiducials": "[{x, y, size?: 1, opening?: 2 (mask opening diameter), side?: top|bottom}]",
"filePath": "the .PcbDoc (opened first; expectPath is opened too)",
"keepouts": "[{rect: [x1, y1, x2, y2] mm, layer?: all (the Keep-Out layer, default) | F.Cu | B.Cu | In<n>.Cu}] - stitching in the same call keeps out of them",
"mountingHoles": "[{x, y, drill?: 3.2, plated?: false, pad?: drill+2.8 when plated, net?}] or {corners: {inset: 4}, drill?, plated?, net?}",
"stitching": "{net (required), pitch?: 5, size?: 0.6, drill?: 0.3, clearance?: 0.3, edge?: 1 (from the outline), region?: [[x,y],..], max?: 400, underParts?: false (vias stay out of each part's pad box)}"
},
"output": {
"applied": "int",
"planned": "{mountingHoles, fiducials, stitching:{count, points}}",
"results": "[ok|err:..] per item",
"state": "routing_state after"
},
"hint": "dryRun first to see the stitching grid. After stitching, altium_repour so the net's pours join through the vias, then altium_run_drc.",
"pitfalls": [
"Stitching keeps the pad clearance conservative (a pad's circumscribed circle) and does not look at pours: pours of other nets repour around the vias.",
"Unplated holes are bare holes (pad = drill); plated holes take a ring and can join a net (e.g. GND)."
],
"related": [
"place_vias",
"repour",
"run_drc",
"routing_state"
],
"example": {
"fiducials": [
{
"x": 5,
"y": 5
},
{
"x": 45,
"y": 25
}
],
"mountingHoles": {
"corners": {
"inset": 4
},
"drill": 3.2
},
"stitching": {
"net": "GND",
"pitch": 4
}
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "board_report",
"tier": "checks",
"source": "altium",
"summary": "One shareable page per board: every check run against the live board and its project (Altium's DRC, JLCPCB fab limits and assembly tiers, the schematic review, symbols against footprints, impedance widths, return paths, copper balance, 3D heights) with a picture of the board, written as a single HTML file.",
"input": {
"out": "the .html to write (default '<board> report.html' beside the project)",
"pcbPath": "its .PcbDoc",
"projectPath": "the .PrjPcb"
},
"output": {
"elapsedSec": "number",
"needsWork": "int",
"pass": "int",
"picture": "bool",
"report": "path",
"sections": "[{title, ok (true|false|null = info), summary}]"
},
"hint": "Open the file in a browser or send it; each section names the verb to run for its full detail.",
"pitfalls": [
"Runs Altium's full batch DRC and frames the board in Altium's window for the picture (no focus taken).",
"Takes about a minute on a small board."
],
"related": [
"fab_check",
"assembly_check",
"schematic_review",
"pin_pad_check",
"return_path",
"copper_balance",
"height_check",
"routing_drc"
],
"example": {
"pcbPath": "C:/proj/Board.PcbDoc",
"projectPath": "C:/proj/Board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 900
},
{
"name": "bom",
"tier": "checks",
"source": "altium",
"summary": "The project's bill of materials read straight from Altium: every schematic sheet the .PrjPcb lists (placed parts and their parameters) merged with the board (footprint, position, side), a variant applied, grouped one line per manufacturer part number, checked for what an order needs, and written as bom.csv, bom-jlcpcb.csv + cpl-jlcpcb.csv, bom-mouser.csv and bom-digikey.csv (+ bom.json).",
"input": {
"boards": "int, default 1 - multiplies the quantities in the Mouser/DigiKey files",
"outputDir": "path - default <project folder>\\BOM",
"pcbPath": "path - optional, default the project's board",
"projectPath": "path to the .PrjPcb (required)",
"timeout": "seconds per sheet read, default 120",
"variant": "string - optional, a project variant's description (Not Fitted parts become DNP, alternates are listed)",
"write": "bool, default true"
},
"output": {
"alternates": "[{designator, alternatePart}]",
"checks": "{missingMpn, missingManufacturer, missingPartNumbers{mouser, digikey, lcsc}, inconsistent[{field, designators, values}], dnp, excludedKinds, sheetNotOnBoard, boardNotOnSheet}",
"files": "[path]",
"fittedParts": "int",
"lines": "[{quantity, designators, value, comment, description, footprint, package, mpn, manufacturer, mouser, digikey, lcsc, libReference}]",
"variants": "[string]"
},
"hint": "Parameter names are matched across libraries (MPN = Manufacturer Part Number = Mfr Part #; Mouser Part # / Digi-Key Part Number; LCSC Part # / JLCPCB Part #). Missing numbers: look them up (adom-parts-search search <MPN>) and write them back with altium_sheet_params, then run this again.",
"pitfalls": [
"Graphical, Net Tie (no BOM) and Standard (no BOM) components are left out (checks.excludedKinds).",
"DNP: a variant's Not Fitted parts, or a DNP / Do Not Populate / Fitted=false parameter.",
"Variants are read from the .PrjPcb text; alternate parts are listed, not substituted.",
"CPL rotations are Altium's: JLCPCB's preview may need per-footprint corrections.",
"A multi-channel (repeated) sheet is read once: its copies' designators land in checks.boardNotOnSheet.",
"Only the parameters a BOM needs are read (some libraries carry huge blob parameters); a workspace-managed part's description comes from a Description parameter, never its vault."
],
"related": [
"sheet_params",
"export_manufacturing",
"read_schematic"
],
"example": {
"boards": 10,
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "build_board",
"tier": "checks",
"source": "altium",
"summary": "Build a NEW board from a parts list and a netlist: outline (rounded corners allowed), every footprint from one PcbLib placed by its own origin, pad nets assigned, saved; then read back pin by pin.",
"input": {
"libraryPath": "string (required) - the .PcbLib holding every footprint",
"nets": "{net: [\"R1.1\", \"U1.3\", ...]}",
"outline": "{rect:[x0,y0,w,h], cornerRadius?} or {points:[[x,y]...]} (mm)",
"parts": "[{ref, footprint, x, y, rotation, comment?}] (mm, degrees; x,y is the footprint's own origin)",
"pcbPath": "string (required) - the .PcbDoc to write"
},
"output": {
"counts": "{...}",
"missingParts": "[ref]",
"padsWired": "int",
"placed": "int",
"revision": "string",
"unconnected": "int - the ratsnest to route",
"wrongPins": "[{pin, want, got}]"
},
"hint": "The board AI Flow's Altium project builds from its netlist. Footprint pad names must match the netlist's pin numbers (R1.1 = pad 1 of R1). Coordinates are Altium's frame (y up).",
"pitfalls": [
"The library must open in this Altium; a footprint missing from it refuses the whole build (footprint_not_found).",
"A new board each call: pcbPath is overwritten."
],
"related": [
"routing_state",
"set_outline",
"install_library"
],
"example": {
"libraryPath": "C:/designs/buck/Buck.PcbLib",
"nets": {
"GND": [
"U1.1"
]
},
"outline": {
"cornerRadius": 1,
"rect": [
0,
0,
28,
20
]
},
"parts": [
{
"footprint": "SOT-23-6",
"ref": "U1",
"rotation": 0,
"x": 12,
"y": 10
}
],
"pcbPath": "C:/designs/buck/buck.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 900
},
{
"name": "build_footprint",
"tier": "checks",
"source": "altium",
"summary": "Build a complete footprint (pads, silkscreen, courtyard, arcs) in a PcbLib from a kicad2altium spec file on this machine, and return a proof frame.",
"input": {
"libraryPath": "path to a .PcbLib (required; created if missing)",
"spec": "Windows path to the spec (tools/kicad2altium.py output; mm, Y up) (required)",
"timeout": "seconds, default 240"
},
"output": {
"data": "{footprint, description, library, libraryState, pads, throughHolePads, drawingPrimitives}",
"shot": "{image: base64 png, width, height}",
"windowEtiquette": "background"
},
"hint": "Stage the spec with ab's send_files first. Then altium_add_body {step}, altium_plate_vias for thermal vias, altium_save. altium_import_part does all of it in one call.",
"pitfalls": [
"The footprint name comes from the spec's META line, not from an argument.",
"Pads with a repeated designator are legal and all map to that pin (the heatsink-via convention).",
"Library is left UNSAVED."
],
"related": [
"import_part",
"add_body",
"plate_vias",
"show_footprint"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.PcbLib",
"spec": "C:/lib/specs/VL53L5CX.fp.txt"
},
"longRunning": false,
"timeoutSeconds": 240
},
{
"name": "build_schematic",
"tier": "checks",
"source": "altium",
"summary": "Draw a design's schematic from its netlist with the project library's symbols, inside a new project (.PrjPcb with the board and libraries), compile it, and check its netlist pin by pin.",
"input": {
"drawnBy": "optional",
"libraryPath": "string - the project .SchLib",
"nets": "{net: [\"U1.3\", ...]} - pins of parts not on the sheet are ignored",
"number": "optional",
"parts": "[{ref, symbol: LibReference in the SchLib, block?: column name (input, core, output...), comment?: value, footprint?: its footprint in pcbLibPath (the part's PCB model link)}]",
"pcbLibPath": "(optional)",
"pcbPath": "(optional) the board, listed in the project",
"projectPath": "(optional) .PrjPcb, default beside the sheet",
"revision": "optional",
"schPath": "string - the .SchDoc to write",
"title": "optional"
},
"output": {
"compileErrors": "[..]",
"labels": "int",
"mismatches": "[{net, missing, extra}]",
"pinsWithoutNet": "ref.pin;...",
"placed": "int",
"project": "path",
"sch": "path",
"wires": "int"
},
"hint": "One column per block, each part with a wire stub and a net label on every connected pin; designator above, value below; title block filled. The compiled netlist is the proof: success means it matches the given nets.",
"pitfalls": [
"The SchLib must hold every symbol (altium_import_part).",
"Parts are placed unrotated."
],
"related": [
"schematic_data",
"compile",
"build_board"
],
"example": {
"libraryPath": "C:\\work\\library\\Buck.SchLib",
"nets": {
"VIN": [
"U1.3"
]
},
"parts": [
{
"block": "core",
"comment": "TPS54202",
"ref": "U1",
"symbol": "TPS54202DDCR"
}
],
"schPath": "C:\\work\\Buck.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 900
},
{
"name": "check_clearance",
"tier": "checks",
"source": "proposed",
"summary": "Measure the gaps between parts, courtyard to courtyard or pad copper to pad copper, for the listed parts or the whole board, and report every pair under a threshold, closest first.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"refs": "[\"U1\", \"C3\"]: keep pairs that involve one of these (default every part)",
"mode": "courtyard|pads, default courtyard",
"thresholdMm": "number, default 0.25 (courtyard) or 0.2 (pads)",
"includeSameNet": "bool, default false (pads)",
"maxPairs": "int, default 200"
},
"output": {
"pairs": "[{a, b, distanceMm, overlapping: bool, touching: bool}]",
"clean": "bool",
"thresholdMm": "number",
"measuredOn": "courtyard outline|courtyard box|pads"
},
"hint": "Computed from the board model: courtyards compare only parts on the same side, pads only copper that shares a side.",
"pitfalls": [
"Rounded pads may be measured as their full rectangle, so a gap can read a little small: the tool's DRC (run_drc) is the authority."
],
"related": [
"placement_check",
"run_drc",
"align_parts"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"refs": [
"U1"
],
"mode": "pads",
"thresholdMm": 0.2
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "check_orientation",
"tier": "checks",
"source": "altium",
"summary": "Advisory: 2-pad parts whose rotation could be better. Each orthogonal rotation is scored in place by airline length (a routable net's MST with the pad there; a plane-like net's distance to its nearest pad); parts whose best rotation saves minImprovementMm are listed. Nothing is moved.",
"input": {
"filePath": "optional .PcbDoc",
"minImprovementMm": "default 0.6",
"parts": "[refs] - optional, default every 2-pad part",
"planeNetPads": "a net with more pads than this is treated as a plane (nearest-pad distance), default 12"
},
"output": {
"checked": "int",
"suggestions": "[{ref, rotation, suggested, airlineNowMm, airlineThenMm, savesMm}]"
},
"hint": "Rotate with altium_move_parts {parts:[{ref, rotation}]} (position kept).",
"pitfalls": [
"Routed copper is not considered: on a routed board these are hints."
],
"related": [
"move_parts",
"find_space",
"routing_state"
],
"example": {
"minImprovementMm": 0.5
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "copper_balance",
"tier": "checks",
"source": "altium",
"summary": "How much of each copper layer is copper (tracks, pads, vias and what Altium actually poured, inside the outline; a plane counts full), and how far apart each mirrored pair of layers is: the copper balance a fab asks about because an unbalanced stack bows and twists in reflow.",
"input": {
"filePath": "the .PcbDoc (opened first; else the current board)",
"resolutionMm": "raster cell, default 0.1"
},
"output": {
"balanced": "bool",
"boardMm2": "number",
"layers": "[{layer, copperMm2, percent, plane?}]",
"pairs": "[{layers, percent, differencePoints, ok}] - layer 1 with n, 2 with n-1...",
"poursWithoutRegions": "[{net, layer}] - pours not poured, or hatched from tracks (counted through their tracks)"
},
"hint": "Pour the lighter layer of an unbalanced pair (altium_apply_pours: a GND pour, or copper thieving) or ask the fab for thieving; then run it again.",
"pitfalls": [
"A raster of the live board's copper: within a cell of the true area (0.1 mm default).",
"A pour counts only once poured (regions); a hatched pour built from tracks is counted through its tracks only when the board lists them."
],
"related": [
"apply_pours",
"pour_state",
"layer_stack",
"fab_check"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "cross_check",
"tier": "checks",
"source": "altium",
"summary": "Compare one schematic sheet's designators with a board's. Altium holds ONE current document, so the verb activates the board, reads it, then activates the sheet and reads that.",
"input": {
"board": "path to the .PcbDoc - optional, else the current board (with projectPath: the project's board)",
"projectPath": "a .PrjPcb: every sheet it lists against its board instead of one sheet, through the standard's engine (parts kept out of the BOM by kind are not counted missing)",
"sheet": "path to the .SchDoc - optional, else the current sheet",
"timeout": "seconds per step, default 45"
},
"output": {
"board": "path",
"boardComponents": "int",
"matched": "int",
"onBoardNotOnSheet": "[designator]",
"onSheetNotOnBoard": "[designator]",
"sameProject": "bool | null - same folder",
"schematicComponents": "int",
"sheet": "string"
},
"hint": "Pass BOTH paths: with neither, one of the two reads has no current document and the call fails at stage board or sheet. Follow differences with altium_component_data / altium_schematic_data.",
"pitfalls": [
"The schematic side is ONE sheet: on a hierarchical design run it per leaf sheet before calling anything missing.",
"_warning means sheet and board sit in different folders, probably different projects: every difference is then meaningless.",
"With paths given it leaves the SHEET current; altium_activate_document the board again before board verbs."
],
"related": [
"read_board",
"read_schematic",
"review_board"
],
"example": {
"board": "C:/proj/board.PcbDoc",
"sheet": "C:/proj/main.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "current_capacity",
"tier": "checks",
"source": "altium",
"summary": "Will this trace carry the current? For each power net and its current: the narrowest track on every layer it is routed on against the width IPC-2221 needs for the allowed temperature rise (with each layer's real copper weight), and what one of its vias carries.",
"input": {
"filePath": "the .PcbDoc (opened first; else the current board)",
"nets": "{net: amps}, e.g. {VIN: 3, GND: 3}",
"platingUm": "via barrel plating, default 25",
"riseC": "allowed temperature rise, default 10"
},
"output": {
"nets": "[{net, amps, layers:[{layer, copperUm, narrowestMm, at, neededMm, ok}], shortOn, ok, vias:{count, smallestDrillMm, ampsEach, neededPerLayerChange}, poursOn}]",
"ok": "bool"
},
"hint": "Widen what shortOn names (altium_set_track_width, altium_add_rule kind width) or pour the net (altium_apply_pours); a layer change needs neededPerLayerChange vias side by side (altium_place_vias).",
"pitfalls": [
"IPC-2221 (conservative, the chart fabs quote); IPC-2152 allows more on inner layers next to planes.",
"Reads tracks and arcs: a pour on the same layer (poursOn) may already carry the current."
],
"related": [
"routing_state",
"layer_stack",
"set_track_width",
"add_rule",
"apply_pours",
"place_vias"
],
"example": {
"nets": {
"GND": 3,
"SW": 3,
"VIN": 3
},
"riseC": 10
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "estimate_cost",
"tier": "checks",
"source": "proposed",
"summary": "The board's numbers a fab quote needs (size, layers, thickness, smallest track, gap and drill, holes, SMD and through-hole parts and joints, unique parts) and a rough price table at the quantities asked, with every assumption stated and the price source named with the date it was read.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"quantities": "[5, 10, 30, 100] (default)",
"assembly": "bool, default false: add an assembly estimate",
"fab": "the price list to use, default jlcpcb"
},
"output": {
"board": "{sizeMm, layers, thicknessMm, minTrackMm, minGapMm, minDrillMm, holes, smdParts, thtParts, smdJoints, thtJoints, uniqueParts}",
"prices": "[{quantity, board, assembly, total, currency}]",
"assumptions": "[string]",
"source": "{name, url, read: date}"
},
"hint": "An order of magnitude, not a quote: parts, shipping and options are left out. For a real quote send the manufacturing files to the fab.",
"pitfalls": [
"Prices change: source names the price list and the date it was read; an old date means an old price."
],
"related": [
"fab_check",
"export_manufacturing",
"bom"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"quantities": [
5,
50
]
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "fab_check",
"tier": "checks",
"source": "altium",
"summary": "Before ordering: the board's fab-relevant minimums measured from the live board (narrowest track, smallest via drill, diameter and annular ring, smallest pad hole and ring, smallest SMD pad, clearance rule, copper layers, board size), each with where it is; with a fab's limits, which ones fall short.",
"input": {
"copperOz": "outer copper weight for the preset (default: read from the stack)",
"fab": "a vendor adom/pcb-design-rules covers (jlcpcb, pcbway, osh-park, eurocircuits, aisler, allpcb, elecrow, nextpcb, seeed-fusion, advanced-circuits-4pcb, sierra-circuits, macrofab, adom-3rdpartyfab): its record for this board's layer count (source page and date read in the reply); or a record object from that page",
"filePath": "the .PcbDoc (opened first)",
"limits": "{minTrack, minClearance, minViaDrill, minViaDiameter, minViaAnnularRing, minPadHole, minPadAnnularRing, minSmdPad, minEdgeClearance, minHoleToHoleVia, minHoleToHolePad, maxDrill, minSilkLine, minSilkText, maxLayers, minBoardMm:[w,h], maxBoardMm:[w,h]} in mm - any fab's numbers; with fab, these override the preset",
"process": "the record's process (default standard)"
},
"output": {
"costlierOrBelowRecommended": "[{feature, boardMm, note}]",
"fab": "{name, service, copperOz, source, read, notes} | null",
"fits": "bool | null",
"measured": "{track, viaDrill, viaDiameter, viaAnnularRing, padHole, padAnnularRing, smdPad, edgeClearance, holeToHoleVia, holeToHolePad, largestDrill, silkText, silkLine: {mm, at}, clearanceRule, copperLayers, boardSize, counts}",
"outsideLimits": "[{limit, limitMm, boardMm, at}]"
},
"hint": "Computed by the EDA Bridge Standard's shared engine (adom-eda-checks). Fab limits come from adom/pcb-design-rules' records, bundled with the bridge: each finding names the vendor's page and the date it was read. limits adds or overrides any limit. The measured values are what a fab's order form asks for.",
"pitfalls": [
"Measures the board as it is now, from the live document: routed copper, vias and pads.",
"Board size is the outline's bounding box."
],
"related": [
"routing_state",
"read_rules",
"layer_stack",
"export_manufacturing",
"run_drc"
],
"example": {
"fab": "jlcpcb"
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "find_space",
"tier": "checks",
"source": "altium",
"summary": "Free spots on the board for a part near another (clear of every other part on that side, of that side's tracks and vias, and inside the outline), nearest first; or check:true lists parts that already overlap or leave the outline.",
"input": {
"check": "bool - report overlaps instead",
"clearanceMm": "default 0.25",
"copper": "bool, default true - avoid that side's tracks and vias",
"count": "default 5",
"edgeMm": "from the outline, default 0.3",
"near": "designator to place beside (or at: {x, y} mm)",
"part": "designator of the part to place (its own size and origin), or sizeMm: [w, h]",
"precise": "bool, with check - also run Altium's batch DRC and list its Component Clearance violations (primitive to primitive)",
"radiusMm": "search radius, default 10",
"side": "top | bottom (default the part's)"
},
"output": {
"outsideOutline": "[designator] (check)",
"overlaps": "[[a, b]] (check)",
"spots": "[{x, y (the part origin, for move_parts), distanceMm, extent}]"
},
"hint": "Move the part with altium_move_parts {parts:[{ref, x, y, rotation}]} to a spot, then altium_routing_drc. Extents follow Altium's Component Clearance rule: 3D bodies and pads, or every primitive but text for a part with no body.",
"pitfalls": [
"A part with no 3D body is measured by its silkscreen outline too, as Altium does: dense boards report silk-to-silk overlaps.",
"Rotations are kept: rotate first if the part should sit another way."
],
"related": [
"move_parts",
"routing_state",
"routing_drc"
],
"example": {
"clearanceMm": 0.3,
"near": "U1",
"part": "C10"
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "footprint_from_land_pattern",
"tier": "checks",
"source": "altium",
"summary": "Build a complete footprint from the land pattern a datasheet prints: pads numbered the standard way (chip, dual SOIC/TSSOP/DFN, SOT, quad QFP/QFN, BGA), an exposed pad, the courtyard, silkscreen kept clear of the copper with a pin-1 dot, a fab outline with a pin-1 chamfer, and an extruded 3D body when the height is given.",
"input": {
"ballPad": "bga pad diameter mm",
"body": "{w, l, height?, standoff?} mm - silkscreen, fab, courtyard, 3D",
"cols": "bga",
"courtyard": "margin mm, default 0.25",
"description": "optional",
"dryRun": "bool - return the pad table and spec only",
"exposedPad": "{w, h, x?, y?, number?}",
"family": "chip | dual | sot | quad | bga",
"leftPins": "sot",
"libraryPath": ".PcbLib (required unless dryRun; created if missing)",
"missing": "bga ['B2', ...]",
"name": "footprint name (required)",
"padLength": "mm, along the lead (across the row)",
"padShape": "roundrect (default) | rect | round | oval",
"padWidth": "mm, along the row",
"pins": "dual/quad total",
"pinsPerSideX": "quad, top/bottom",
"pinsPerSideY": "quad, left/right",
"pitch": "mm",
"polarized": "chip: add the pin-1 dot",
"rightPins": "sot",
"rows": "bga",
"silkClearance": "default 0.2",
"silkWidth": "default 0.15",
"span": "mm, pad centre to pad centre across the rows (quad: left-right)",
"spanY": "quad, top-bottom (default span)"
},
"output": {
"body3d": "{success}",
"shot": "{image}",
"spec": "the staged spec path",
"summary": "{pads, courtyardMm, silkLines, padTable:[[name, x, y, w, h]]}"
},
"hint": "dryRun first and compare padTable with the datasheet drawing; then build, check shot.image, altium_save the library and link it with altium_set_models.",
"pitfalls": [
"The numbers are the datasheet's RECOMMENDED LAND PATTERN, not the package outline: pad size and the pad-centre span.",
"Pin 1 is top-left (Y up), counter-clockwise, the IPC convention."
],
"related": [
"build_footprint",
"create_footprint",
"add_body",
"set_models",
"save",
"show_footprint"
],
"example": {
"body": {
"height": 1.75,
"l": 4.9,
"w": 3.9
},
"family": "dual",
"libraryPath": "C:\\\\lib\\\\Parts.PcbLib",
"name": "SOIC-8_3.9x4.9mm_P1.27mm",
"padLength": 1.55,
"padWidth": 0.6,
"pins": 8,
"pitch": 1.27,
"span": 5.4
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "height_check",
"tier": "checks",
"source": "altium",
"summary": "Will it fit the enclosure? Each part's height from its 3D bodies (top and bottom side), the parts over a height limit board-wide or under a lid feature in a region, and part bodies that collide or come closer than a gap.",
"input": {
"filePath": "the .PcbDoc (opened first; else the current board)",
"limit": "how many of the tallest parts to list (default 25)",
"maxBottomMm": "limit below the bottom side",
"maxTopMm": "height limit above the top side",
"minGapMm": "report bodies closer than this (default 0: collisions only)",
"regions": "[{rect:[x1,y1,x2,y2] mm, maxMm, side?: top|bottom, name?}] - lid features over part of the board"
},
"output": {
"collisions": "[{parts, overlapMm, at}]",
"heights": "[{ref, side, heightMm, rect}]",
"noBody": "[ref] - parts with no 3D body (no height)",
"ok": "bool",
"overLimit": "[{ref, side, heightMm, limitMm, overByMm}]",
"regionHits": "[{region, ref, heightMm, maxMm}]",
"tallest": "{top, bottom}",
"tooClose": "[{parts, gapMm, at}]"
},
"hint": "Move or swap what overLimit and regionHits name (altium_move_parts, altium_swap_footprint); separate colliding parts. Parts in noBody need a body (altium_add_body) before the check means anything for them.",
"pitfalls": [
"Bodies are compared as boxes, each body its own box; Altium's Component Clearance DRC checks the real shapes.",
"A height is the body's top above the surface its part sits on; the board's own thickness is not included."
],
"related": [
"add_body",
"move_parts",
"find_space",
"run_drc",
"show_3d_board"
],
"example": {
"maxBottomMm": 2,
"maxTopMm": 8,
"minGapMm": 0.25,
"regions": [
{
"maxMm": 3,
"name": "display boss",
"rect": [
10,
10,
30,
25
]
}
]
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "impedance",
"tier": "checks",
"source": "altium",
"summary": "Controlled impedance from the board's own stack-up: the track width each copper layer needs for a single-ended target (50 ohm default) and the width and gap for a differential pair (90 ohm USB, 100 ohm Ethernet/LVDS), microstrip outside and stripline inside; optionally written as width or diff-pair rules per layer.",
"input": {
"apply": "{scope: Altium query e.g. InNetClass('RF') or InDifferentialPair('USB'), name?} - one rule per layer at +/-10%",
"diff": "differential ohm, e.g. 90 or 100",
"filePath": "the .PcbDoc (opened first; else the current board)",
"gapMm": "fix the pair gap (default: gap = width)",
"layers": "[layer names] (default every copper layer)",
"z0": "single-ended ohm (default 50 when diff is not given)"
},
"output": {
"applied": "[{layer, rule, success}] | null",
"layers": "[{layer, model, copperUm, dielectricMm:[above, below], width, z0, diffWidth, diffGap, zdiff}]"
},
"hint": "Then altium_add_rule or apply writes the rules; altium_diff_pairs lists the pairs to scope them to. Tell the fab the target impedance: it tunes the stack-up with its own solver.",
"pitfalls": [
"Closed-form models (Hammerstad-Jensen, Wheeler, IPC-2141 coupling): within a few percent of a field solver on FR-4; uncoated (mask lowers outer layers 1 to 3 ohm).",
"Inner layers assume planes on both neighbours."
],
"related": [
"layer_stack",
"add_rule",
"diff_pairs",
"net_classes"
],
"example": {
"apply": {
"name": "USB 90",
"scope": "InDifferentialPair('USB')"
},
"diff": 90,
"z0": 50
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "import_part",
"tier": "checks",
"source": "altium",
"summary": "One call imports a whole part: footprint spec + STEP + symbol modes + models + params + save.",
"input": {
"comment": "string",
"description": "string",
"footprintSpec": "path",
"params": "{}",
"pcbLib": "path",
"schLib": "path",
"step": "path",
"symbolSpec": "path"
},
"output": {
"footprint": "string",
"steps": "[] - the add_body step carries replacedBodies, bodiesNow, sameNameFootprints",
"symbol": "string"
},
"hint": "Check the step counts: models:0 fails the call - a symbol with no footprint model places with nothing attached. Importing again REPLACES the symbol and the footprint's 3D body (add_body step: bodiesNow 1); boards that place the part need PCB:UpdateFootprints.",
"pitfalls": [
"add_models APPENDS on every call (not idempotent) - repair is remove_symbol + re-import.",
"The add_body step's sameNameFootprints > 1 means the library holds stale footprints of that name: the body went to the FIRST only.",
"The first part into a NEW library can silently skip models+params if the bridge restarted mid-flight - verify with read_symbol."
],
"related": [
"read_symbol",
"show_symbol"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "jlcpcb_order",
"tier": "checks",
"source": "altium",
"summary": "A JLCPCB order in one call: the board checked against JLCPCB's fab limits, the Gerbers and drill zipped the way JLCPCB's order page takes them, the JLCPCB BOM and pick-and-place (CPL), the assembly-tier check, and the order-form values, in one folder with every issue in one list.",
"input": {
"outputDir": "the order folder (default 'JLCPCB order <board>' beside the project; emptied first)",
"pcbPath": "its .PcbDoc",
"projectPath": "the .PrjPcb",
"variant": "an assembly variant for the BOM (optional)"
},
"output": {
"assemblyService": "economic | standard | null",
"bomFiles": "[..] incl. bom-jlcpcb.csv, cpl-jlcpcb.csv",
"folder": "path",
"gerberZip": "{path, files}",
"issues": "[{from, what, at?}]",
"orderForm": "{layers, dimensionsMm, outerCopperOz, minTrackSpaceMm, minHoleMm}",
"ready": "bool - fab fits, an assembly tier passes, no issues"
},
"hint": "Fix what issues lists and run it again; when ready, upload the zip, then the BOM and CPL for assembly and check rotations in JLCPCB's preview.",
"pitfalls": [
"Runs Silkscreen Preparation on the board (through export_manufacturing) and writes the order folder fresh each time.",
"Takes a minute or two: the manufacturing export is most of it."
],
"related": [
"fab_check",
"assembly_check",
"export_manufacturing",
"bom",
"panelize"
],
"example": {
"pcbPath": "C:/proj/Board.PcbDoc",
"projectPath": "C:/proj/Board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 900
},
{
"name": "length_tune",
"tier": "checks",
"source": "altium",
"summary": "Lengthen a routed net to a target length, or to match another net (a pair's skew, a DDR byte lane): a serpentine in its longest straight track that has room beside it, the bumps sized to add exactly the length missing, every bump clear of other copper and inside the board.",
"input": {
"clearance": "to other copper, default 0.2",
"dryRun": "bool - plan only",
"expectedRevision": "optional",
"filePath": "the .PcbDoc (opened first; else the current board)",
"matchTo": "or: a net whose length to match",
"maxAmplitudeMm": "bump height limit, default 3",
"net": "the net to lengthen",
"pitchMm": "one bump's length along the track (default 4 x width, at least 4 x clearance + 2 x width)",
"targetMm": "the length it should have"
},
"output": {
"changed": "bool",
"errorMm": "number",
"lengthBeforeMm": "number",
"lengthMm": "number",
"plan": "{layer, replaces, bumps, amplitudeMm, pitchMm, side, addsMm, points}",
"targetMm": "number"
},
"hint": "Then altium_net_lengths (the pair or group), altium_routing_drc. For a matched group, tune each short net to the longest (matchTo).",
"pitfalls": [
"Only lengthens: a net already longer than its target is left alone.",
"One serpentine per call, in one track; call again to add more elsewhere."
],
"related": [
"net_lengths",
"route_pair",
"add_rule",
"routing_drc"
],
"example": {
"matchTo": "DP",
"net": "DN"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "lint_library",
"tier": "checks",
"source": "altium",
"summary": "Check a .PcbLib or .SchLib before it ships: footprints without pads, courtyard, silkscreen or 3D body, with duplicate or missing pad numbers, an origin off the part or no description; symbols without pins or a footprint, with duplicate pin numbers or no part number, and pins that no pad of the linked footprint answers. KiCad's verb of the same name (KiCad's checks that the file parses; an Altium library always does, so this one checks what is in it).",
"input": {
"footprintLibraries": "[.PcbLib] for a SchLib: where the linked footprints are (default the .PcbLibs in the SchLib's folder); footprintLibrary for one",
"libraryPath": "the .PcbLib or .SchLib (required; filePath accepted too)",
"names": "[name] (default every footprint or symbol)"
},
"output": {
"checked": "int",
"errors": "int",
"findings": "[{name, kind: footprint|symbol, rule, severity: error|warning|info, detail}]",
"footprintLibraries": "[path] (SchLib)",
"infos": "int",
"ok": "bool: no errors and every item read",
"unread": "[{name, error}]",
"warnings": "int"
},
"hint": "Rules: no_pads, zero_size_pad, unnumbered_pad, duplicate_pad_number, no_courtyard (Mechanical 15), no_silkscreen, no_3d_body, origin_off_part, no_description; no_pins, unnumbered_pin, duplicate_pin_number, no_part_number, no_footprint, footprint_not_found, pin_without_pad, pad_without_pin. Read-only.",
"pitfalls": [
"Each item is one read (about half a second): a library of hundreds takes minutes; names picks a few.",
"duplicate_pad_number is right for one pin on several pads (a thermal pad): it is a warning, not an error."
],
"related": [
"read_footprint",
"read_symbol",
"edit_footprint",
"pin_pad_check",
"list_library"
],
"example": {
"libraryPath": "C:/lib/Parts.SchLib"
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "model_check",
"tier": "checks",
"source": "proposed",
"summary": "Per part: is there a 3D model, where is it, is the file found, and does it hold geometry. For a library footprint or a whole board. Read only.",
"input": {
"filePath": "a board: every part on it",
"library": "a footprint library (with footprint)",
"footprint": "one footprint's name",
"limit": "int, default 50: parts reported on a board"
},
"output": {
"parts": "[{name, models: [{path, location: embedded|file|cloud, found: bool, hasGeometry: bool}], issues: [string]}]",
"checked": "int",
"ok": "bool: every part has a model that is found and holds geometry"
},
"hint": "Run it before a 3D export or a fab handoff. Whether the body sits in the right place stays with bodies: this verb only says the model is there and usable.",
"pitfalls": [
"A bridge whose models live in the cloud reports found as whether the reference resolves."
],
"related": [
"bodies",
"lint_library",
"export_3d"
],
"example": {
"filePath": "C:/proj/board.kicad_pcb"
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.31.1",
"agreedBy": [
"altium-lane"
]
},
{
"name": "net_lengths",
"tier": "checks",
"source": "altium",
"summary": "Routed length of every net (or the ones named) on the live board, by layer with its vias; the skew inside each differential pair; and the spread of matched-length groups against a tolerance.",
"input": {
"filePath": "the .PcbDoc (opened first)",
"groups": "[{nets:[..], toleranceMm?: 0.5}] - matched-length groups (a DDR byte lane, a parallel bus)",
"nets": "[net] - default every routed net",
"pairs": "[{name?, pos, neg}] - default the board's differential pairs"
},
"output": {
"groups": "[{nets:[{net, lengthMm, shortByMm}], spreadMm, withinTolerance, longest}]",
"groupsOutOfTolerance": "int",
"nets": "[{net, lengthMm, byLayer, vias, segments}]",
"pairs": "[{name, pos, neg, posMm, negMm, skewMm}]"
},
"hint": "Lengthen the short nets of a group with altium_route_net (a detour) until spreadMm is within tolerance; Altium's interactive length tuning is the hand alternative.",
"pitfalls": [
"A net with branches sums every branch: a multi-pin net's length is its total copper, not pin to pin.",
"Vias are counted, not added to the length."
],
"related": [
"routing_state",
"route_net",
"diff_pairs",
"add_rule"
],
"example": {
"groups": [
{
"nets": [
"D0",
"D1",
"D2",
"D3"
],
"toleranceMm": 0.25
}
]
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "pin_pad_check",
"tier": "checks",
"source": "altium",
"summary": "Do the footprints fit their symbols? Part by part, the symbol's pin numbers (from the sheet files) against the footprint's pad names (from the board): pins with no pad, pads with no pin, and parts on only the sheets or only the board.",
"input": {
"pcbPath": "its .PcbDoc",
"projectPath": "the .PrjPcb"
},
"output": {
"matching": "int",
"mismatches": "[{ref, pinsWithoutPad, padsWithoutPin, pins, pads}]",
"ok": "bool - every pin has a pad",
"onBoardOnly": "[ref]",
"onSheetsOnly": "[ref]"
},
"hint": "A pin with no pad is a net that can never reach copper: change the footprint (altium_swap_footprint) or renumber the symbol's pins before routing.",
"pitfalls": [
"Mounting and thermal pads (MH*, MP*, SH*, EP*, PAD*, TAB*, unnamed or 0) are expected to have no pin."
],
"related": [
"schematic_review",
"update_pcb",
"swap_footprint",
"component_pins"
],
"example": {
"pcbPath": "C:/proj/Board.PcbDoc",
"projectPath": "C:/proj/Board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 200
},
{
"name": "place_decoupling",
"tier": "checks",
"source": "proposed",
"summary": "Plan positions for decoupling capacitors beside an IC's power pins (each cap just outside the courtyard, its power pad facing the pin), answered as move_parts arguments; dryRun:false applies them through move_parts.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"ic": "\"U1\" (required)",
"caps": "[\"C1\", \"C2\"] (default every capacitor across ground and one of the IC's power nets)",
"gapMm": "number, default 0.3",
"dryRun": "bool, default TRUE",
"expectedRevision": "string: the revision you last read (routing_state); refused with stale_board if the board changed (to apply)"
},
"output": {
"placements": "[{cap, pin, side, x, y, rotation, padToPinMm}]",
"skipped": "[{cap, why: other_side|no_shared_power_net|no_free_spot}]",
"moveArgs": "move_parts arguments",
"validation": "move_parts' courtyard and outline check of the plan",
"revision": "string, when applied"
},
"hint": "Read the plan, then apply it with dryRun:false and expectedRevision, or send moveArgs to move_parts yourself.",
"pitfalls": [
"Caps on the other side of the board are skipped: move them to the IC's side first (move_parts with side).",
"It places; it does not route: route the stubs with route_net."
],
"related": [
"move_parts",
"route_net",
"placement_check"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"ic": "U1"
},
"longRunning": true,
"timeoutSeconds": 130,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "placement_check",
"tier": "checks",
"source": "altium",
"summary": "Review the placement before routing: parts whose courtyards (pads and body, grown by a margin) overlap on the same side, parts off the board or over its edge, pads too close to the edge for assembly and depanelling, and parts on a mounting hole.",
"input": {
"edgeMm": "pad to board edge, default 0.5",
"filePath": "the .PcbDoc (opened first; else the current board)",
"marginMm": "courtyard margin round each part, default 0.1 (parts closer than 0.2 mm are flagged)"
},
"output": {
"courtyardOverlaps": "[{parts, side, overlapMm}]",
"nearEdge": "[{ref, padToEdgeMm}]",
"offOrOverEdge": "[{ref, where}]",
"ok": "bool",
"onMountingHoles": "[{ref, hole}]",
"parts": "int"
},
"hint": "Move what it names (altium_move_parts, altium_find_space for a clear spot), then route.",
"pitfalls": [
"A part's box is its pads and its 3D body, so an L-shaped part reads as its bounding box; on or off the board is judged by its pads."
],
"related": [
"move_parts",
"find_space",
"height_check",
"board_features"
],
"example": {
"marginMm": 0.25
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "plan_fanout",
"tier": "checks",
"source": "proposed",
"summary": "Plan the fanout of a BGA or QFN/QFP: the pad pitch, dogbone or via-in-pad per pad, the escape layer, surface stubs for the outer ring and a via grid for an exposed pad, answered as route_net arguments, one call per net.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"ref": "\"U3\" (required)",
"style": "auto|dogbone|via-in-pad, default auto",
"escapeLayer": "a layer name (default the first inner layer, else the opposite side)",
"viaMm": "via diameter",
"viaDrillMm": "via drill",
"widthMm": "track width",
"clearanceMm": "number, default 0.1",
"pitchMm": "override the detected pitch",
"stubMm": "number, default 0.4",
"surfaceOuterRing": "bool, default true"
},
"output": {
"package": "bga|perimeter",
"pitchMm": "number",
"style": "string",
"pads": "[{pad, net, action: surface|dogbone|via-in-pad|stub+via|thermal-via-grid|skip}]",
"calls": "[route_net arguments]",
"minViaToPadMm": "number"
},
"hint": "auto picks dogbone when a via fits between four pads with the clearance, else via-in-pad. Send each call to route_net with filePath and expectedRevision, dry run first.",
"pitfalls": [
"Via-in-pad needs filled and capped vias (IPC-4761 type VII): tell the user before committing it.",
"The plan does not check stubs against other parts' copper; route_net checks each call before it commits."
],
"related": [
"route_net",
"place_vias",
"fab_check"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"ref": "U3"
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "plan_route",
"tier": "checks",
"source": "proposed",
"summary": "Plan a path for one net between two pads without changing the board: a grid search around the existing copper that keeps the clearance rules, on the allowed copper layers, with vias where they help. Answered as route_net's arguments.",
"input": {
"filePath": "path to the board (optional; default the open board)",
"net": "string (required)",
"from": "the start pad as Ref.Pad (required)",
"to": "the end pad as Ref.Pad (required)",
"widthMm": "track width (default the net's rule width)",
"layers": "[F.Cu, B.Cu, ...]: the layers it may use (default the outer layers)",
"allowVias": "bool, default true",
"viaSizeMm": "default 0.6",
"viaDrillMm": "default 0.3",
"gridMm": "search grid, default 0.5",
"viaCost": "a via costs as much as this many mm of track, default 5",
"expectedRevision": "the revision the plan is for"
},
"output": {
"found": "bool",
"routeNet": "{net, layer, width, viaSize, viaDrill, paths}: pass it to route_net unchanged",
"lengthMm": "number",
"vias": "int",
"reason": "string when found is false: no path within the search limits, a pad not on the net",
"revision": "string: the board the plan was made on"
},
"hint": "Read only. Pass routeNet to route_net with expectedRevision set to revision; run_drc after the route is still the proof.",
"pitfalls": [
"Between dense pads a finer grid can find a path the default 0.5 mm grid misses, at a cost in time.",
"The plan holds for the revision it read: route_net refuses it with stale_board once the board changes."
],
"related": [
"route_net",
"route_pair",
"run_drc",
"routing_state"
],
"example": {
"net": "SDA",
"from": "U1.12",
"to": "J3.4",
"layers": [
"F.Cu",
"B.Cu"
]
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "fusion-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "read_sheet_file",
"tier": "checks",
"source": "altium",
"summary": "Read a schematic sheet straight from its .SchDoc file, without Altium (it need not be installed or running): every part with its designator, library reference, comment, UniqueID, part number, position, parameters and pins, in milliseconds.",
"input": {
"params": "bool, default false - every parameter with its value",
"path": "the .SchDoc (alias filePath)",
"pins": "bool, default true - each part's own pins plus the shared part 0"
},
"output": {
"components": "[{designator, libReference, comment, description, uniqueId, partId, partCount, xMil, yMil, orientation, sourceLibrary, params?, pins?}]",
"count": "int",
"elapsedMs": "int",
"format": "the file header"
},
"hint": "The saved file, not the live sheet: an open Altium's unsaved edits are not in it (altium_schematic_data reads those). Useful when Altium is closed, busy or slow, and to check UniqueIDs before Update PCB.",
"pitfalls": [
"Binary .SchDoc only (Altium's default); an ASCII-format sheet is refused by name.",
"No connectivity: nets come from altium_netlist."
],
"related": [
"schematic_data",
"part_parameters",
"bom",
"netlist"
],
"example": {
"params": true,
"path": "C:\\\\work\\\\Power.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 30,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "return_path",
"tier": "checks",
"source": "altium",
"summary": "Where signal tracks lose their reference: for every signal net, the length of track on each layer that runs over no pour or plane copper on either neighbouring layer (a split, a gap, a void), with where the first gap starts. The return current detours around those gaps: loop area, emissions, crosstalk.",
"input": {
"filePath": "the .PcbDoc (opened first; else the current board)",
"nets": "[net] - only these (default every signal net)",
"referenceNets": "[net] - the reference nets (default: every net that owns a pour or a plane)",
"resolutionMm": "raster cell and sampling step, default 0.1"
},
"output": {
"layersWithNoReferenceCopper": "[layer]",
"nets": "[{net, layer, lengthMm, unreferencedMm, percent, firstGapAt}] worst first",
"ok": "bool",
"referenceNets": "[net]"
},
"hint": "Extend or join the pour under the net (altium_apply_pours), reroute it over solid copper (altium_route_net), or add a stitching via or capacitor where it changes reference.",
"pitfalls": [
"Reference copper is pours, planes, the reference nets' own copper and net-less copper (a hatched pour's tracks): another signal's track under a net is not a reference.",
"Checks the two neighbouring copper layers; a board with no pours or planes has nothing to reference (layersWithNoReferenceCopper)."
],
"related": [
"apply_pours",
"pour_state",
"route_net",
"net_lengths",
"board_features"
],
"example": {
"nets": [
"USB_DP",
"USB_DN",
"CLK"
]
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "review_board",
"tier": "checks",
"source": "altium",
"summary": "Design-review checks (14) over one board read; schematic checks with includeSchematic.",
"input": {
"board": "path - optional",
"checks": "[string] - optional filter",
"includeSchematic": "bool",
"sheet": "path - optional"
},
"output": {
"counts": "{}",
"findings": "[{check, severity, message, ...}]",
"notImplemented": "{}",
"skipped": "{}"
},
"hint": "PARTIAL results by design: skipped says which checks had no data; a clean result means the checks that RAN found nothing.",
"pitfalls": [
"Altium holds ONE current document - the review activates board and sheet in turn."
],
"related": [
"read_board",
"cross_check"
],
"example": {
"includeSchematic": true
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "route_pair",
"tier": "checks",
"source": "altium",
"summary": "Route a differential pair as a pair: one centreline from the source pads' midpoint through waypoints to the destination pads' midpoint, each net offset to its own side at width + gap with mitred corners and a short fan-out from each pad; width and gap given or solved from the stack-up for a target impedance; both lengths and the skew answered.",
"input": {
"clearance": "to other nets' pads when checking the plan, default 0.15",
"diffOhms": "solve width (and gap = width unless given) for this differential impedance on the layer",
"fanMm": "fan-out length at each end, default 1",
"force": "bool - route even when the plan check finds problems",
"from": "{pos: \"U1.3\", neg: \"U1.4\"} the source pads",
"gap": "mm",
"layer": "F.Cu (default) | B.Cu | In<n>.Cu",
"neg": "the negative net",
"pos": "the positive net",
"rule": "bool, default true - add a width rule for the two nets (+/-10%) so the board's own width rule does not flag the pair",
"to": "{pos, neg} the destination pads",
"via": "[[x,y]...] centreline waypoints mm (optional)",
"width": "mm"
},
"output": {
"gapMm": "number",
"lengthsMm": "{pos, neg}",
"revision": "string",
"sizedFor": "the impedance row used | null",
"skewMm": "number",
"widthMm": "number"
},
"hint": "Then altium_net_lengths for the routed skew, altium_add_rule {kind:\"diffpair\"} to hold width and gap, and altium_routing_drc.",
"pitfalls": [
"One layer per call; split a pair that changes layer into two calls at the via pair.",
"The waypoints are the pair's centreline, so keep them clear of other copper by half the pair's width."
],
"related": [
"route_net",
"impedance",
"diff_pairs",
"net_lengths",
"add_rule"
],
"example": {
"diffOhms": 90,
"from": {
"neg": "U1.15",
"pos": "U1.14"
},
"neg": "USB_DN",
"pos": "USB_DP",
"to": {
"neg": "J1.2",
"pos": "J1.3"
},
"via": [
[
20,
10
],
[
30,
10
]
]
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "schematic_review",
"tier": "checks",
"source": "altium",
"summary": "Review the schematic before Update PCB: every placed pin (read from the sheet files, with its electrical type) against Altium's compiled netlist. Errors: power pins on no net, outputs driving each other. Warnings: pins on no net, one-pin nets, inputs nothing drives, IC supplies with no decoupling capacitor to ground.",
"input": {
"drawing": "bool, default true: read each sheet's drawing too, for the drawing checks (dangling wire ends, labels off their wire, overlapping symbols)",
"projectPath": "the .PrjPcb (its sheets are read from file; the netlist is Altium's compile)"
},
"output": {
"decoupling": "[{net, ics, capacitors, ok}]",
"errors": "[{check, pin|net, ...}]",
"nets": "int",
"ok": "bool - no errors",
"pins": "int",
"sheets": "[path]",
"warnings": "[{check, ...}]"
},
"hint": "Fix on the sheets (altium_sch_connect, altium_sch_place_part for a missing capacitor), then altium_update_pcb. altium_run_erc is Altium's own ERC with its rules.",
"pitfalls": [
"Pins named NC, N/C or DNC are expected to float.",
"Ground nets are recognised by name (GND, AGND, DGND, PGND, VSS, 0V, *_GND)."
],
"related": [
"netlist",
"read_sheet_file",
"run_erc",
"sch_connect",
"update_pcb"
],
"example": {
"projectPath": "C:/proj/Board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "silk_designators",
"tier": "checks",
"source": "altium",
"summary": "Place every reference designator the way assembly houses want: one size, upright, beside its own part, clear of every pad (JLCPCB: 0.15 mm), every other part's body and the other designators, inside the board; read back from Altium's own text boxes. Parts with no clear spot are reported, not forced onto pads.",
"input": {
"dryRun": "bool - plan only",
"filePath": "the .PcbDoc (opened first; else the current board)",
"gap": "label to part, mm, default 0.2",
"minSize": "mm - parts with no spot at size step down by 0.1 to this (default: size, no shrinking)",
"padClearance": "label to any pad, mm, default 0.15",
"refs": "[ref] - only these (default every part)",
"size": "text height mm, default 1.0 (JLCPCB's minimum)"
},
"output": {
"onPadsAfter": "[{ref, pad}] - must be empty",
"onPadsBefore": "[{ref, pad}]",
"placed": "int",
"planned": "dryRun: [{ref, x, y, size, rotation, side, at}]",
"unplaced": "[{ref, why}]"
},
"hint": "Then altium_silkscreen_prep (it clips silk off the mask) and altium_fab_check {fab:\"jlcpcb\"} for text height and line width. For unplaced parts try refs with a smaller size, or move the part.",
"pitfalls": [
"Labels are tried above, below, right, left and at the corners of the part's body and pads, big parts first.",
"Bottom-side labels are mirrored by Altium; onPadsAfter checks them with Altium's own boxes."
],
"related": [
"silk_state",
"apply_silkscreen",
"silkscreen_prep",
"fab_check"
],
"example": {
"size": 1.0
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "test_board",
"tier": "checks",
"source": "altium",
"summary": "Place one footprint, or a ';' list, from the open PcbLib on ONE board: a NEW board (wMm x hMm outline) when pcbPath is new or omitted, APPENDED to the existing board when pcbPath already exists (issue 11).",
"input": {
"assigns": "des=NET;...",
"footprintName": "string | 'A;B;C'",
"hMm": "number (new board only)",
"libraryPath": "path (.PcbLib)",
"pcbPath": "path (.PcbDoc) - existing = append, new = create+save",
"stubs": "des=x,y;...",
"wMm": "number (new board only)"
},
"output": {
"appended": "bool",
"bodiesOnComp": "int",
"count": "int",
"existingParts": "int",
"padsOnComp": "int",
"pcb": "path",
"placed": "string",
"saved": "bool (checked on disk)"
},
"hint": "Three parts on one board: footprintName 'VL53L5CX;VL53L7CX;VL53L8CX' + pcbPath, then altium_show_3d_board {filePath: pcbPath}. Run it again with the same pcbPath to ADD parts: they land right of the current ones, designators continue (U4...).",
"pitfalls": [
"assigns/stubs apply to the LAST part placed.",
"pcb is empty when pcbPath is omitted: the board exists only unsaved as PCB<n>.PcbDoc.",
"Appending ignores wMm/hMm and does not grow the outline: parts can land outside it - resize with altium_board_shape if needed.",
"Each part's name is its own Comment (moves with the part) and its Pattern is the footprint name.",
"errorCode not_saved: the board was built but the file did not land; the folder is created automatically."
],
"related": [
"place_on_sch",
"show_3d_board",
"add_body"
],
"example": {
"footprintName": "VL53L5CX;VL53L7CX;VL53L8CX",
"hMm": 14,
"libraryPath": "C:/lib/Adom_ToF.PcbLib",
"pcbPath": "C:/proj/tof.PcbDoc",
"wMm": 39
},
"longRunning": false,
"timeoutSeconds": 240
},
{
"name": "thermal_vias",
"tier": "checks",
"source": "altium",
"summary": "A thermal via grid in a part's exposed pad (the ground or thermal pad under a QFN, DFN, PowerPAD or regulator): centred, inset from the pad's edge, sized by the board's Routing Via rule, on the pad's net.",
"input": {
"drill": "mm (default the board's via rule)",
"dryRun": "bool - plan only",
"expectedRevision": "optional",
"filePath": "the .PcbDoc (opened first; else the current board)",
"insetMm": "from the pad's edge, default 0.1",
"pad": "the pad's name (default the part's largest pad)",
"pitchMm": "default via size + 0.5, at least 1.0",
"ref": "the part (e.g. U3)",
"size": "via diameter mm (default the board's via rule)"
},
"output": {
"applied": "int",
"failed": "int",
"planned": "{part, pad, net, padMm, vias, pitchMm, via, points}"
},
"hint": "Pour the pad's net on the far side (altium_apply_pours) so the heat has somewhere to go, ask the fab to tent or plug vias in pads, then altium_routing_drc. adom-fields solves the heat itself.",
"pitfalls": [
"Open vias in a pad wick solder away from it during reflow: tent or plug them, or keep drills at 0.3 mm or smaller."
],
"related": [
"apply_pours",
"board_features",
"routing_drc",
"current_capacity"
],
"example": {
"pitchMm": 1.1,
"ref": "U3"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "via_fence",
"tier": "checks",
"source": "altium",
"summary": "A via fence for EMC: a row of ground vias on both sides of RF or fast nets' tracks, and/or round the board edge, at a pitch from the frequency (lambda/20) or given; each via clear of other copper and pads, the same net's vias and the edge.",
"input": {
"clearance": "to other copper, mm, default 0.2",
"drill": "mm, default 0.3",
"dryRun": "bool - plan only",
"edge": "bool - a fence round the board edge too",
"edgeInsetMm": "edge fence: distance in from the edge (default via radius + 0.5)",
"expectedRevision": "optional",
"filePath": "the .PcbDoc (opened first; else the current board)",
"freqGHz": "the highest frequency: pitch = lambda/20 in FR-4",
"nets": "[net] - the tracks to fence (e.g. [ANT_RF])",
"offsetMm": "track centreline to via centre (default half the widest track + clearance + via radius + 0.1)",
"pitchMm": "pitch, default 2 (a cap when freqGHz is given)",
"size": "via diameter mm, default 0.6",
"viaNet": "the net the vias tie to (usually GND), required"
},
"output": {
"applied": "int",
"failed": "int",
"planned": "{vias, candidates, pitchMm, offsetMm, points}"
},
"hint": "Then altium_repour so the pours join the vias, and altium_run_drc. altium_return_path shows where a net still runs over a gap.",
"pitfalls": [
"Vias go through (top to bottom); a pour on viaNet should exist on the layers they join.",
"Spots too close to other copper, pads or the edge are skipped, not forced."
],
"related": [
"return_path",
"board_features",
"repour",
"run_drc",
"apply_pours"
],
"example": {
"edge": true,
"freqGHz": 2.4,
"nets": [
"ANT_RF"
],
"viaNet": "GND"
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "activate_document",
"tier": "app",
"source": "altium",
"summary": "Make a document current - the quiet lane (one in-process agent call, no cursor, no OS foreground). Board and schematic read verbs act on the CURRENT document.",
"input": {
"path": "full path of the document (aliases: document, name)",
"timeout": "seconds; the wait is capped at 45"
},
"output": {
"data": "{path, objectKind, kind, shown}",
"lane": "agent",
"status": "'in_progress' when still opening",
"windowEtiquette": "background"
},
"hint": "Activate the .PcbDoc, then altium_read_board; activate the .SchDoc, then altium_read_schematic. After a demo or a show_* call, activate the user's own document again.",
"pitfalls": [
"Needs the FULL path with a supported extension; a bare document name is refused.",
"It is the same agent 'open': a path that is not open yet gets opened."
],
"related": [
"open_document",
"state",
"read_board",
"read_schematic"
],
"example": {
"path": "C:/proj/board.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "agent_recover",
"tier": "app",
"source": "altium",
"summary": "Un-halt the script engine: clear the PCB transaction, press OK on open Altium dialogs, send EditScript:Stop, reap the busy notice and delete stale request files.",
"input": {
"reason": "string - optional, recorded in steps"
},
"output": {
"engineFree": "bool - verified by starting a fresh agent",
"steps": "[{reason} | {dialog, pressed} | {editScriptStop, exited, sec} | busy-notice reap]"
},
"hint": "Use after agent_timeout / no_heartbeat / instance_busy, or when Altium sits on AdomAgent_*.pas in its debugger. Then call your verb again: it restarts the agent. Never ask the user to click.",
"pitfalls": [
"A modal orphan (main window disabled, no dialog on screen) answers nothing: recover refuses with altium_modal_orphan instead of firing -R hand-offs that all bounce off 'another instance is busy'. Escape it with altium_close {discardChanges:true}.",
"It presses OK only on the script Error box (a lone OK titled Error or X2). Any other dialog, a save prompt included, stops it with blocked_by_dialog: read it with altium_check_dialogs.",
"An agent_script_error reply was ALREADY recovered by the bridge (autoRecovered): do not recover again, and do not resend the same command - it will halt again.",
"agent_halts_on_start = the engine was freed, but the agent stops on its first command every time it starts, so agent verbs cannot run on this Altium: report it with steps[].errorShot. recover never loops on it (#30)."
],
"related": [
"check_dialogs",
"agent_start",
"dialog_log",
"selftest_script_error"
],
"example": {
"reason": "agent_timeout on read_board"
},
"longRunning": false,
"timeoutSeconds": 240
},
{
"name": "agent_start",
"tier": "app",
"source": "altium",
"summary": "Bootstrap the resident DelphiScript agent inside Altium (renders the script, runs it through the -R lane, waits for the heartbeat). Optional: every agent-backed verb does this on demand.",
"input": {
"waitSec": "int, default 45 - how long to wait for the first heartbeat"
},
"output": {
"alreadyRunning": "bool",
"generation": "string - AdomAgent_<digest>",
"install": "object - the rendered script",
"parkedLoopStopped": "[step] - an earlier loop was parked in the debugger and was stopped first",
"startedInSec": "float",
"strayHelpersKilled": "[pid]"
},
"hint": "After success altium_eval / altium_run_command / altium_state go through the agent in milliseconds. Do NOT use altium_run_script while it is up.",
"pitfalls": [
"The bootstrap ACTIVATES Altium for a moment (it opens the .PrjScr in the script editor); the bridge hands the user's foreground window back.",
"no_heartbeat = the engine halted behind a script Error modal: altium_check_dialogs, then altium_agent_recover.",
"agent_halted_after_start = the agent came up and stopped on its first command (errorShot is Altium's box). The bridge already stopped the script, so Altium is not left parked; it is a bug in the agent on this Altium build: report it with errorShot (#30).",
"An earlier loop parked in Altium's script debugger (engineParked) is stopped first, so the new one can run: parkedLoopStopped lists what was done.",
"If the bridge itself ever ends during a verb, the next bridge process writes which verb and its last steps to altium-bridge-crash.log beside the bridge exe (with Rust's own message for a stack overflow). Attach that file to a report.",
"The loop exits by itself 15 s after the last request (while it runs Altium ignores the user's clicks, #27); the next verb restarts it in 2.5-4 s. Call altium_agent_stop when you hand Altium back to the user."
],
"related": [
"agent_status",
"agent_stop",
"agent_recover",
"eval"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "agent_status",
"tier": "app",
"source": "altium",
"summary": "Is the agent loop alive and responsive, in which workspace, and is any loop resident anywhere? Read-only; never starts the agent.",
"input": {},
"output": {
"alive": "bool - selected instance",
"engineParked": "bool",
"heartbeat": "{ageSec, tick, ...} | null",
"liveWorkspaces": "[{workspace, heartbeatAgeSec}]",
"parkedWorkspaces": "[path] - when parked",
"residentAnywhere": "bool",
"responsive": "bool",
"workspace": "path"
},
"hint": "alive with responsive:false = the loop is busy inside a long Altium process: wait, do not start a second agent. Not alive: call the verb you need, it bootstraps.",
"pitfalls": [
"residentAnywhere:true with alive:false is a freeze-on-close hazard: altium_close tears every loop down before the app exits.",
"engineParked:true = a loop started in this Altium and stopped in its script debugger without exiting, whatever document is in front (read from the agent's own files, not the window title). alive is false then, even within a minute of its last heartbeat. altium_agent_recover, or the next agent verb, stops it."
],
"related": [
"agent_start",
"agent_recover",
"readiness"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 10
},
{
"name": "agent_stop",
"tier": "app",
"source": "altium",
"summary": "Stop the selected instance's resident agent loop (drops a stop file and waits up to 12 s for the heartbeat to go stale).",
"input": {},
"output": {
"stoppedInSec": "float",
"wasRunning": "bool"
},
"hint": "Call it when you hand Altium back to the user: while the loop is resident Altium ignores their clicks (it also stops by itself 15 s after the last verb). Needed before altium_run_script (the -R lanes refuse while a loop is resident). altium_close stops every workspace's loop itself. The next agent-backed verb restarts the agent. Clears the 'Adom is driving' taskbar badge.",
"pitfalls": [
"'the loop did not exit' -> altium_agent_recover.",
"With several Altiums running pass instance: to stop the right loop."
],
"related": [
"agent_start",
"agent_status",
"run_script",
"close"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 20
},
{
"name": "animate_view",
"tier": "app",
"source": "altium",
"summary": "Camera/zoom choreography on the current document - native Altium camera commands, animated by Altium itself.",
"input": {
"lane": "pcb (default) | sch",
"pauseMs": "int default per-step pause",
"preset": "punch_in|showcase3d|orbit|flip|finale",
"steps": "[string | {step, pauseMs}]"
},
"output": {
"elapsedSec": "float",
"stepsRun": "int"
},
"hint": "Runs IN-BRIDGE (~40ms per step to the agent) so timing is tight enough to narrate over. Steps: zoom_all/in/out, view_2d/3d, isometric, top/bottom/front/back/left/right, rotate90, ortho, orbit_left/right/up/down, rolls, pans, flip.",
"pitfalls": [
"Driving camera steps one-by-one from a container adds ~1.4s of jitter per step - that is what this verb exists to avoid.",
"sch lane supports zoom steps only; everything else needs a PCB document current."
],
"related": [
"demo",
"foreground",
"run_command"
],
"example": {
"preset": "showcase3d"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "cancel_run",
"tier": "app",
"source": "proposed",
"summary": "Stop the bridge's own long job, between steps, keeping what is done. With nothing to stop it answers cancelRequested:false and a reason. It never claims to interrupt the tool itself.",
"input": {
"runId": "str (default the latest run in flight)"
},
"output": {
"cancelRequested": "bool",
"reason": "str (when false)",
"runId": "str",
"stage": "str at the time of the request"
},
"hint": "Poll the job's own status verb to see it stop.",
"pitfalls": [
"Which jobs can stop differs per bridge: Fusion's library imports, KiCad's autoroute, Altium's multi-step verbs between steps."
],
"related": [
"status"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"altium-lane",
"kicad-lane"
]
},
{
"name": "check_dialogs",
"tier": "app",
"source": "altium",
"summary": "List every Altium dialog currently open, classified, each with a screenshot (the only way to READ one: Altium paints its dialog text).",
"input": {
"screenshots": "bool, default true"
},
"output": {
"dialogs": "[{hwnd, pid, title, className, body, buttons, category, safeAction, meaning, ownedByMainInstance, rect, shot: base64 png}]",
"dialogsDetected": "int",
"engineParked": "bool - no dialog, but the agent's script is stopped in Altium's debugger: altium_agent_recover"
},
"hint": "READ dialogs[].shot, decide, then altium_dismiss_dialogs {button, titles:[..]}. A script 'Error' box: altium_agent_recover. A save prompt on close: see altium_close discardChanges.",
"pitfalls": [
"category and safeAction are suggestions. A save_prompt is never auto-answered: it names documents that may belong to the user or another AI thread.",
"Known nuisance boxes are pressed by the standing reaper before you ever see them; altium_dialog_log lists those."
],
"related": [
"dismiss_dialogs",
"dialog_log",
"agent_recover",
"window_info"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "close",
"tier": "app",
"source": "altium",
"summary": "Polite close (releases the licence seat). Frees a script engine parked on a breakpoint first (Altium refuses to close over one). discardChanges:true answers Altium's save prompts with Save None for callers whose modified documents are ALL their own; force needs acceptSeatLoss.",
"input": {
"acceptSeatLoss": "bool",
"discardChanges": "bool, default false: press Save None + confirm on 'Confirm Save Locally'",
"force": "bool",
"instance": "pid, when several Altiums run",
"waitSec": "float, default 20"
},
"output": {
"closedInSec": "float",
"engineFreed": "object|null",
"errorCode": "unsaved_changes | close_blocked_by_dialog | altium_modal_orphan | modal_orphan_survived_quit | close_timeout",
"stuckModalOrphan": "{pid,tid,hwnd} when Altium was wedged in a modal loop and the bridge ended it gracefully"
},
"hint": "A save prompt on close NAMES the documents - read it; on a shared machine one may belong to another AI thread. Never defaulted.",
"pitfalls": [
"force:true without acceptSeatLoss is refused: a kill strands the On-Demand seat.",
"errorCode altium_modal_orphan = Altium is stuck inside a modal loop whose dialog is GONE (its main window is disabled, nothing on screen to answer). No menu, keystroke or -R reaches it and it still holds the seat. With discardChanges:true the bridge ends it by posting WM_QUIT - Altium's own shutdown, which RELEASES the seat. Never reach for force/taskkill first."
],
"related": [
"license",
"launch"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "close_all_documents",
"tier": "app",
"source": "proposed",
"summary": "Close every open document without a save dialog. Unsaved work is never lost by default: a document with unsaved changes stays open and is listed, unless save or discardUnsaved says what to do with it.",
"input": {
"save": "bool, default false: save each changed document, then close it",
"discardUnsaved": "bool, default false: close changed documents without saving (their changes are lost)",
"includeScratch": "bool, default false: also close never-saved scratch documents"
},
"output": {
"closed": "[name]",
"saved": "[name]",
"keptOpen": "[{name, why: unsaved changes | scratch}]"
},
"hint": "Use it to start from a clean editor. keptOpen tells you what still needs a decision.",
"pitfalls": [
"discardUnsaved loses changes that exist nowhere else: ask the person first.",
"A scratch document was never saved, so closing one with unsaved changes loses it entirely."
],
"related": [
"close_document",
"save",
"document_info"
],
"example": {
"save": true
},
"longRunning": false,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "close_document",
"tier": "app",
"source": "altium",
"summary": "Close ONE open document by path through its document handle. Never saves.",
"input": {
"path": "absolute path of the open document (required)"
},
"output": {
"data": "{closed: bool, path} | {closed: false, note: 'not open: <path>'}",
"roundtripMs": "int"
},
"hint": "altium_save {filePath} first if anything is worth keeping. After re-running altium_place_on_sch / altium_test_board to the same path, close the stale document before altium_show_*.",
"pitfalls": [
"Unsaved edits are DISCARDED without a prompt.",
"success:true with closed:false means the document was not open."
],
"related": [
"save",
"open_document",
"state"
],
"example": {
"path": "C:/proj/tof.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "connect_workspace",
"tier": "app",
"source": "altium",
"summary": "Open Altium's workspace picker (the 'Not Connected' menu) and return a screenshot with a coordMap. The list is a custom control with no UIA children, so the caller clicks the row.",
"input": {},
"output": {
"picker": "{hwnd, title, className: TWorkspacesForm, rect}",
"shot": "ab desktop_screenshot_window reply: image + coordMap/shotId",
"windowEtiquette": "background"
},
"hint": "Click the wanted row with ab's desktop_click {space:'image', shotId, x, y} straight away, then altium_signin_status to confirm.",
"pitfalls": [
"picker_not_open usually means Altium is ALREADY connected (the menu shows the workspace name).",
"The picker is a popup: it closes on focus loss, so click before doing anything else.",
"A workspace with no free Author seat connects view-only: new documents then fail with view_only_no_author_seat."
],
"related": [
"signin_status",
"a365_status",
"license"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "cross_probe",
"tier": "app",
"source": "proposed",
"summary": "From a schematic part to the board part linked to it, and back, by designator, the schematic symbol's id or its sheet path; optionally select them in the tool.",
"input": {
"filePath": "path to the board file (default: the board open in the tool)",
"ref": "\"U1\"",
"symbolId": "the schematic symbol's id",
"path": "the symbol's sheet path",
"schematic": "path to a sheet of the project (default the project's)",
"select": "bool, default false: also select the matches in the tool"
},
"output": {
"matches": "[{board: {ref, id, side, x, y, rotation}, schematic: {sheet, id, ref, symbol, value}, linked: bool}]",
"symbolWithoutPart": "[ref]"
},
"hint": "Reads the open board when the tool serves it, else the file.",
"pitfalls": [
"linked:false means the board part has no link to a symbol: placed by hand, or update_pcb never ran."
],
"related": [
"selection",
"update_pcb",
"component_data"
],
"example": {
"filePath": "C:/proj/Board.PcbDoc",
"ref": "U3"
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "kicad-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "demo",
"tier": "app",
"source": "altium",
"summary": "The tour. Default: one background beat per call with a screenshot. live:true = the narrated FOREGROUND show: ab caption + document + in-bridge camera choreography per stop, returning the narration text for YOUR TTS.",
"input": {
"live": "bool",
"stage": "int 0-5"
},
"output": {
"done": "bool",
"narrate": "string - speak this",
"nextCall": "{verb, args}",
"nextNarrate": "string"
},
"hint": "live SYNC MODEL: pre-cache narration with `adom-tts load` (one marker per stop), then per stop fire `adom-tts cue <id> <n> --confirm` in the background and IMMEDIATELY make nextCall - the prefetched cue starts instantly and the ~5-17s of on-screen motion runs under the voice; advance when BOTH finish. If Altium is cold, the first call answers status:launching with a narrate line - speak it, poll again in ~20s.",
"pitfalls": [
"The caller owns the VOICE (adom-tts) - the bridge never synthesizes speech.",
"After done:true, restore the user's own document (altium_activate_document)."
],
"related": [
"animate_view",
"foreground",
"show_symbol"
],
"example": {
"live": true,
"stage": 0
},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "describe",
"tier": "app",
"source": "altium",
"summary": "This list - the bridge's verbs and schemas for ab's Verbs tab.",
"input": {},
"output": {
"verbs": "[{name, summary, input, output, ...}]"
},
"hint": "Static; safe to call any time.",
"pitfalls": [],
"related": [
"status"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 5
},
{
"name": "diagnostics",
"tier": "app",
"source": "altium",
"summary": "Bridge-side facts for a bug report: environment variables, every Altium install found, Altium's windows, the agent status block and the cache directory.",
"input": {},
"output": {
"agent": "the altium_agent_status reply",
"cacheDir": "path",
"env": "{LOCALAPPDATA, APPDATA, USERPROFILE, ProgramFiles, ADOM_BIND_HOST, ADOM_DIRECT_API_URL}",
"installs": "[{base_dir, exe, system_dir, major}] newest major first",
"windows": "[{hwnd, title, kind, className, pid, rect}]"
},
"hint": "installs:[] means Altium is not installed (altium_install). Otherwise altium_readiness for the verdict and altium_instances when several Altiums run.",
"pitfalls": [
"Instance-exempt: it runs with no instance selected, so agent.alive reads the legacy workspace; agent.liveWorkspaces is the union that counts."
],
"related": [
"readiness",
"agent_status",
"instances"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 15
},
{
"name": "dialog_log",
"tier": "app",
"source": "altium",
"summary": "What the standing dialog reaper (and the bridge's own recoveries) pressed, newest last: nuisance boxes, script-error boxes, discarded save prompts, silent engine halts cleared.",
"input": {
"limit": "int, default 25"
},
"output": {
"reaped": "[{title, category, pressed, ok, note, at}]",
"running": "bool"
},
"hint": "Read it after a surprise: enginePreviouslyParked on a reply, an agent_script_error, or an open that failed view-only ('Workspace Unavailable' shows here). A dialog that reached the user and is NOT listed is a catalog gap: report it.",
"pitfalls": [
"An in-memory ring of the last 200 events: a bridge restart clears it.",
"Save prompts and unknown dialogs never appear here as pressed: the reaper does not touch them."
],
"related": [
"check_dialogs",
"status",
"agent_recover"
],
"example": {
"limit": 10
},
"longRunning": false,
"timeoutSeconds": 10
},
{
"name": "dismiss_dialogs",
"tier": "app",
"source": "altium",
"summary": "Press one named button (default OK) on the detected Altium dialogs through UIA - no cursor, no focus steal. titles narrows it to dialogs whose title contains one of the strings.",
"input": {
"button": "string, default 'OK' - the button's accessible name",
"titles": "[string] - optional title substrings; only matching dialogs are pressed"
},
"output": {
"detected": "int",
"pressed": "[{title, hwnd, button, ok}]"
},
"hint": "ALWAYS pass titles. Then altium_check_dialogs to confirm nothing is left, and repeat the verb that was blocked.",
"pitfalls": [
"Without titles the button is pressed on EVERY detected Altium dialog, save prompts included.",
"hwnd is NOT read by this verb, although other verbs' hints say {hwnd, button}: target a dialog with titles.",
"success is true even when nothing was pressed or the click failed: check pressed[].ok."
],
"related": [
"check_dialogs",
"close",
"agent_recover"
],
"example": {
"button": "OK",
"titles": [
"Error"
]
},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "document_info",
"tier": "app",
"source": "proposed",
"summary": "The active document: its name, what kind it is, whether it has unsaved changes, where it is saved and which version it is. Read only; opens nothing.",
"input": {},
"output": {
"name": "string",
"kind": "project | schematic | board | library | model | other",
"saved": "bool: it exists as a file or a cloud item",
"modified": "bool: it has unsaved changes",
"path": "file path or cloud location | null",
"version": "int | null: the saved version, where the tool keeps versions",
"project": "string | null"
},
"hint": "Cheap. Call it before an edit verb to make sure the right document is in front.",
"pitfalls": [
"A schematic and a board of one design are separate documents in some tools: kind says which one is in front."
],
"related": [
"open_document",
"close_document",
"save",
"status"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 20,
"proposedBy": "fusion-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "ensure_licensed",
"tier": "app",
"source": "altium",
"summary": "One call to get a usable Altium: launch if needed, then claim a seat (Use License via UIA). Optional escalations: sign out to force a seat release, or start the free-trial flow.",
"input": {
"allowSignInReset": "bool - if no seat is free, Sign Out (the human must sign back in)",
"allowTrial": "bool - if no seat is free, open the trial flow in the browser",
"launchWaitSec": "int, default 240"
},
"output": {
"alreadyLicensed": "bool",
"licenceState": "string",
"needsHuman": "string - only for browser sign-in / trial activation / a licence the account lacks",
"page": "{notUsingLicence, requestAccessBanner, viewerOnly} read off the licence page",
"seatStuck": "bool",
"shot": "{..}",
"steps": "[..]",
"summary": "string"
},
"hint": "success -> drive. errorCode no_seat_available: find the Altium holding the seat (altium_instances here, or another machine) and altium_close it, then call again. errorCode no_licence_on_account: the account has only the Viewer; ask the user (admin assigns a licence, trial, or the other Altium build). errorCode no_author_seat (Develop): every workspace Author seat is taken; ask the user.",
"pitfalls": [
"One On-Demand seat serves EVERY Altium on the account. A KILLED Altium strands the seat (page shows Seats 0/1 while every claim fails): altium_close releases it, waiting does not.",
"allowSignInReset:true signs the user OUT and ends with needsHuman (browser sign-in). Use it only when nothing else holds the seat.",
"It may launch Altium, which raises Altium over the user's work once."
],
"related": [
"license",
"license_status",
"instances",
"close"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "eval",
"tier": "app",
"source": "altium",
"summary": "Run a DelphiScript snippet inside Altium (optional Var block, then Begin ... End;) on the CURRENT document, or on filePath opened first.",
"input": {
"filePath": "optional: the document to make current first (a .PcbDoc for PCBServer.GetCurrentPCBBoard)",
"text": "string - [Var X : Integer;] Begin ... End;",
"timeout": "int seconds"
},
"output": {
"errorCode": "script_error",
"errorShot": "PNG of Altium's error box",
"success": "bool (false + errorShot when Altium raised an error box)"
},
"hint": "Single quotes only (no double quotes). A Var block before Begin is allowed. Capture output by writing a file, not by returning a value. Pass filePath: after an export the OutJob is current and GetCurrentPCBBoard is Nil.",
"pitfalls": [
"An undeclared identifier HALTS the engine with a modal that Try/Except cannot catch.",
"ShowMessage blocks the loop behind a modal - never use it."
],
"related": [
"run_command"
],
"example": {
"text": "Begin PCBServer.GetCurrentPCBBoard.ViewManager_FullUpdate; End;"
},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "export_spice",
"tier": "app",
"source": "proposed",
"summary": "Write the design's SPICE netlist with the tool's own exporter, and say what it holds.",
"input": {
"schematic": "the design or sheet (required)",
"outputPath": "path for the netlist (default beside the design)"
},
"output": {
"path": "the netlist file",
"dialect": "ngspice | pspice | ltspice | xspice",
"elements": "int: parts in the netlist",
"analyses": "[the analysis lines the design carries]",
"includes": "[the model files it includes]"
},
"hint": "A part without a simulation model is left out or becomes a comment: give it one before simulating.",
"pitfalls": [
"Model files are included by the path the part's model field gives: keep them where every machine finds them."
],
"related": [
"simulate"
],
"example": {
"schematic": "C:/proj/filter.kicad_sch"
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.14.0",
"agreedBy": [
"standard-lane",
"altium-lane",
"fusion-lane"
]
},
{
"name": "extension_ping",
"tier": "app",
"source": "altium",
"summary": "Does the AdomBridge .NET extension answer? Sends AdomBridge:Ping through the -R lane and waits up to 30 s for its result file.",
"input": {},
"output": {
"elapsedSec": "float",
"installedOnDisk": "bool",
"result": "string"
},
"hint": "success -> altium_export_step / altium_import_kicad will work. installedOnDisk:true with extension_timeout = installed but not loading on this Altium build.",
"pitfalls": [
"It spawns an X2 -R helper against the running instance: do not loop it."
],
"related": [
"install_extension",
"export_step",
"import_kicad"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "extensions",
"tier": "app",
"source": "proposed",
"summary": "The tool's own plugins and add-ons: list what is installed, install one, remove one. Not install_extension, which is the bridge's own helper inside the tool.",
"input": {
"action": "list|install|remove, default list",
"id": "the package's identifier (install, remove)",
"source": "a repository URL or a local package file (install)",
"version": "optional (install)",
"checkUpdates": "bool, default true (list)"
},
"output": {
"extensions": "[{id, name, version, kind, updateAvailable?, latestVersion?}]",
"count": "int",
"installed": "{id, version} after install",
"removed": "id after remove"
},
"hint": "Read the list before installing, and restart the tool if the reply says the plugin loads at startup.",
"pitfalls": [
"Altium and Fusion list, and refuse install and remove by name: their pages can't be driven."
],
"related": [
"install_extension",
"extension_ping",
"state"
],
"example": {
"action": "list"
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.31.1",
"agreedBy": [
"altium-lane"
]
},
{
"name": "foreground",
"tier": "app",
"source": "altium",
"summary": "Bring Altium in front of the user - the sanctioned exception to the never-foreground rule.",
"input": {
"reason": "string >=10 chars, written for the HUMAN (required)"
},
"output": {
"windowEtiquette": "foreground"
},
"hint": "For a human who asked to WATCH (a live demo, a walkthrough). Everything else stays background.",
"pitfalls": [
"Refused without a real reason - same rule as ab's desktop_caption."
],
"related": [
"demo",
"animate_view"
],
"example": {
"reason": "John asked to watch the import live"
},
"longRunning": false,
"timeoutSeconds": 15
},
{
"name": "install",
"tier": "app",
"source": "altium",
"summary": "Install Altium Designer on this machine, STAGED, with the rules in the verb (from 0.2.29). stage: preflight | get_installer | launch | wait | license, or omit it and 'auto' picks the stage from the machine's state. The verb looks before it asks, verifies the installer's Authenticode signature (Valid, CN=Altium LLC) before anything runs, refuses to launch into an empty room, toasts the human itself and says truthfully whether the toast displayed, and does the licensing clicks (Refresh / Use License) ITSELF.",
"input": {
"humanIsPresent": "bool, REQUIRED true for stage launch: the UAC prompt auto-denies in ~2 minutes",
"installerPath": "optional path; default = newest AltiumDesignerSetup*.exe in Downloads",
"stage": "auto (default) | preflight | get_installer | launch | wait | license"
},
"output": {
"_next": "[string]",
"licensed": "bool",
"needsHuman": "[string] - only ever a password, the UAC prompt, or clicks in an elevated window",
"stage": "string",
"toast": "{displayed, _hint}"
},
"hint": "Call it with no args and follow _next. The human's part ENDS at the installer's Finish button; licensing is yours.",
"pitfalls": [
"needsHuman may only name a password/2FA, the UAC prompt, or clicks inside an ELEVATED window. Release, Assign, Use License, Refresh and save prompts are ordinary clicks: do them.",
"LOOK before you ask: 'Sign Out' on the licence page means the user is ALREADY signed in (the installer's browser sign-in carries over).",
"'There are no seats available' means another running Altium holds the account's single On-Demand seat: altium_close it there, then stage license again.",
"Never use the installer's unattended switches: they take the account password on the command line.",
"A toast only reaches the machine it is shown on. Check toast.displayed and ALSO tell the user in chat."
],
"related": [
"ensure_licensed",
"license",
"launch",
"readiness"
],
"example": {
"humanIsPresent": true,
"stage": "launch"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "install_extension",
"tier": "app",
"source": "altium",
"summary": "Install, update or remove the AdomBridge .NET extension (the PowerShell installer shipped beside the bridge). Altium must be CLOSED.",
"input": {
"remove": "bool, default false - uninstall instead"
},
"output": {
"output": "string - installer stdout tail",
"removed": "bool",
"stderr": "string"
},
"hint": "Sequence: altium_close, altium_install_extension, altium_launch, altium_extension_ping. Only altium_export_step and altium_import_kicad need it.",
"pitfalls": [
"Refused with altium_running while any Altium is up (it holds AdomBridge.dll open); remove:true is allowed while running.",
"A failed extension load can stop Altium starting: put extension/REMOVE-AdomBridge.cmd on the Desktop first.",
"It was unregistered on AD 26.9.1 after coinciding with a 'Could not start Vault Explorer' warning: install only when you need those two verbs."
],
"related": [
"extension_ping",
"export_step",
"import_kicad",
"close"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 200
},
{
"name": "install_receipt",
"tier": "app",
"source": "altium",
"summary": "The last bundle install's full receipt (proof frame included), for a client whose install call outlived ab's budget.",
"input": {},
"output": {
"receipt": "object|null - the install_library_bundle reply"
},
"hint": "Read after altium_status shows lastInstall with your installId.",
"pitfalls": [],
"related": [
"install_library_bundle",
"status"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 10
},
{
"name": "instances",
"tier": "app",
"source": "altium",
"summary": "Every running Altium (Designer + Designer Develop can run together).",
"input": {},
"output": {
"count": "int",
"instances": "[{pid, key, edition, licensed, agentAlive, ...}]"
},
"hint": "With several running, other verbs REFUSE without instance:<pid|key|word> - guessing means acting inside another AI thread's Altium.",
"pitfalls": [
"Develop writes NO licence tail when it HOLDS the seat - blank licenceState there means licensed."
],
"related": [
"status"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 15
},
{
"name": "launch",
"tier": "app",
"source": "altium",
"summary": "Start Altium (the newest numbered install, or the one install names) and wait for its main window, then hand the user's own window back. Answers alreadyRunning when one is up.",
"input": {
"background": "bool, default TRUE: remember the user's foreground window and restore it once Altium is up. Pass false only when the user asked to SEE Altium come up.",
"install": "optional: develop | designer | a folder name (AD26, ADDevelop) | a path, when several Altiums are installed",
"waitSec": "number, default 180"
},
"output": {
"alreadyRunning": "bool",
"foregroundReturnedTo": "hwnd|null",
"licence": "{running, licensed, state, adVersion, edition, hwnd, pid}",
"startedInSec": "float",
"windowEtiquette": "background once the user's window is handed back; foreground only with background:false"
},
"hint": "Cold start is about 60 s. Next: altium_readiness; licensed:false -> altium_ensure_licensed. Most verbs need this first (errorCode altium_not_running).",
"pitfalls": [
"Altium foregrounds ITSELF at startup and offers no switch for it, so the window jumps over the user's work for a few seconds even with background:true \u2014 the bridge can only hand the focus back afterwards. Call it once; never in a retry loop.",
"errorCode host_app_not_installed -> altium_install. launch_timeout = no main window after waitSec.",
"A 'Workspace Unavailable' box at launch (altium_dialog_log) means another running Altium holds the seat: this one is view-only and opens fail with view_only_no_author_seat."
],
"related": [
"readiness",
"ensure_licensed",
"close",
"install"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 240
},
{
"name": "library_views",
"tier": "app",
"source": "proposed",
"summary": "Pictures of library parts for review, each as an image file: the schematic symbol, the footprint (pads and layers), the 3D body seated on the footprint, and the device view that maps symbol pins to pads.",
"input": {
"libraryPath": "path to the library (required)",
"parts": "[part name] (required)",
"views": "[symbol, footprint, 3d, device] (default all four)",
"outputDir": "folder for the images (default beside the library)"
},
"output": {
"captured": "[{part, view, path, ok, error?}]"
},
"hint": "The four pictures a reviewer checks before a part is used: the pin names on the symbol, the pad shapes, the body on its pads, and every pin mapped to a pad.",
"pitfalls": [
"The 3d view needs a body on the part (add_body): a part without one is reported with ok false, not drawn empty."
],
"related": [
"add_body",
"show_3d_chip",
"read_symbol",
"footprint_primitives",
"list_library"
],
"example": {
"libraryPath": "C:/libs/power.lbr",
"parts": [
"TPS54202"
],
"views": [
"symbol",
"footprint",
"3d"
]
},
"longRunning": true,
"timeoutSeconds": 300,
"proposedBy": "fusion-lane",
"since": "0.3.0",
"agreedBy": [
"altium-lane"
]
},
{
"name": "license",
"tier": "app",
"source": "altium",
"summary": "Drive the License Management page (UIA first - no cursor, no foreground).",
"input": {
"action": "show|refresh|use_license|release|start_trial|sign_out",
"product": "use_license, release: part of the licence's name (default the first that isn't the free Viewer)"
},
"output": {
"shot": "{image: base64 png, width, height}",
"success": "bool",
"windowEtiquette": "background"
},
"hint": "One On-Demand seat serves EVERY Altium app on this machine. use_license claims a free seat, and inUse says what the page then marks In Use. release gives it back, and released says the page confirms it. Altium falls back to Viewer and stops running scripts, so the bridge's verbs answer not_licensed until a licence is claimed again.",
"pitfalls": [
"NEVER kill an Altium holding the seat: the lease strands, the page shows Seats 0/1 while every claim fails. altium_close releases it.",
"Altium Designer Develop has no licence page the bridge can reach: every action but show and refresh answers licence_page_not_open. altium_close releases its seat."
],
"related": [
"ensure_licensed",
"license_status",
"close"
],
"example": {
"action": "use_license"
},
"longRunning": false,
"timeoutSeconds": 90
},
{
"name": "license_status",
"tier": "app",
"source": "altium",
"summary": "Plain-language answer to 'what Altium licence am I on?': the state from the window title plus a capture of the License Management page.",
"input": {},
"output": {
"licenceState": "string",
"licensed": "bool | null",
"running": "bool",
"seatStuck": "'possible' | null",
"shot": "{image: base64 png, ...}",
"summary": "string"
},
"hint": "Read shot.image for the product row (Trial/Full, days left, seat n/n): that lives ONLY on the page. Not licensed -> altium_ensure_licensed.",
"pitfalls": [
"It brings up the License Management page inside Altium (when the agent is resident), replacing the view the user had.",
"One On-Demand seat serves every Altium on the account: 'no seats available' usually means ANOTHER running Altium holds it - altium_close that one."
],
"related": [
"ensure_licensed",
"license",
"instances"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "list_commands",
"tier": "app",
"source": "altium",
"summary": "Search Altium's process-launcher catalog (about 1,100 Server:Command entries parsed from the install's System/*.rcs files) by text and/or server.",
"input": {
"limit": "int, default 50",
"query": "string - substring over command, captions, descriptions and params",
"server": "string - e.g. PCB, Sch, WorkspaceManager"
},
"output": {
"count": "int",
"hits": "[{command, server, captions, shortcuts, params, descriptions}]",
"servers": "{server: count}",
"total": "int - distinct commands"
},
"hint": "Run a hit with altium_run_command {command, params}; hits[].params shows the Name=Value pairs Altium's own menus pass.",
"pitfalls": [
"Reads files, not Altium: works with Altium closed but answers host_app_not_installed without an install.",
"Being listed does not make a process safe: some open a modal that blocks the agent (PCB:DesignRuleCheck - use altium_run_drc)."
],
"related": [
"run_command",
"eval"
],
"example": {
"query": "zoom",
"server": "PCB"
},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "log_tail",
"tier": "app",
"source": "proposed",
"summary": "What the tool said about itself since an offset: its own log lines and alerts (warnings and errors), so a verb that looks successful while the tool complains is caught.",
"input": {
"sinceOffset": "int, default 0: where the last call stopped (its next)",
"maxBytes": "int, default 200000",
"errorsOnly": "bool: only errors and warnings"
},
"output": {
"entries": "[{level, text}] newest last",
"next": "the offset to pass as sinceOffset next time",
"truncated": "bool"
},
"hint": "Carry next from call to call to see only what is new. Read it after a verb that succeeded but left the tool looking unhappy.",
"pitfalls": [
"A tool that writes no log of its own answers what the bridge captured from the instances it launched."
],
"related": [
"dialog_log",
"state",
"diagnostics"
],
"example": {
"sinceOffset": 0,
"errorsOnly": true
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.26.4",
"agreedBy": [
"standard-lane",
"fusion-lane"
]
},
{
"name": "open_document",
"tier": "app",
"source": "altium",
"summary": "Open a document or project by path through the agent and show it without focusing it. An already-open document is activated, not reloaded.",
"input": {
"filePath": "absolute Windows path (alias: path)",
"timeout": "seconds; the wait is capped at 45"
},
"output": {
"data": "{path, objectKind, kind, shown: bool, lane}",
"roundtripMs": "int",
"status": "'in_progress' when Altium is still opening it",
"windowEtiquette": "background"
},
"hint": "Then the verb for that document: altium_read_board / altium_read_schematic / altium_list_library. status:in_progress -> poll altium_status or altium_window_info until it is current.",
"pitfalls": [
"Only .PcbDoc .SchDoc .PcbLib .SchLib .OutJob .Pcb3DLib .Prj* .LibPkg .txt .pas .rep are accepted; anything else is refused as unsupported_document (Altium would raise a 'File type not recognised' modal).",
"success:true with data.shown:false on a non-project means the document did NOT open (this verb does not turn that into an error). In a view-only Altium that is every new document: see view_only_no_author_seat."
],
"related": [
"activate_document",
"close_document",
"state",
"show_2d_board"
],
"example": {
"filePath": "C:/proj/board.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "open_project",
"tier": "app",
"source": "altium",
"summary": "Open a project (.PrjPcb / .PrjScr / .PrjMbd / .PrjHar / .LibPkg) by path. Same handler as altium_open_document.",
"input": {
"filePath": "absolute Windows path (alias: path)",
"timeout": "seconds; the wait is capped at 45"
},
"output": {
"data": "{path, objectKind: 'Project', shown: false, note}",
"roundtripMs": "int",
"windowEtiquette": "background"
},
"hint": "Then altium_compile {projectPath} for ERC, or altium_open_document one of its sheets. altium_state lists the project's documents.",
"pitfalls": [
"data.shown:false is NORMAL for a project: projects have no document view."
],
"related": [
"open_document",
"compile",
"show_project",
"state"
],
"example": {
"filePath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "panel",
"tier": "app",
"source": "altium",
"summary": "Activate a docked panel TAB (SCH Library, PCB Library, Components, Projects, Properties) in the BACKGROUND - the 'ganged-up view' needs the right panels in front, and no Altium server process switches a tab.",
"input": {
"ensureId": "string optional - panel ID for Client:CustomizeResources (e.g. TSchLibPanel) when the panel may not exist yet",
"name": "string - the tab caption exactly as painted, e.g. 'SCH Library'"
},
"output": {
"elapsedSec": "float",
"lane": "already | ui_select | ui_select_raised",
"selected": "bool",
"verified": "bool (false when the tab exposes no selection state)"
},
"hint": "One UIA search reads the tab's existence AND selection, then at most one SelectionItemPattern select and one verify, all inside a 24 s budget: every exit is a named answer (panel_not_found, panel_search_timeout, ui_select_gated, panel_not_selected), never ab's generic timeout.",
"pitfalls": [
"ab gates desktop_ui_select behind the shell approval grant; without it the verb reports ui_select_gated instead of pretending.",
"A plain click does not switch panel tabs - that is why this verb exists.",
"On Altium Designer Develop the UI Automation search does not finish in time (panel_search_timeout, measured 2026-10-15); opening a library document already brings its library panel to the front.",
"lane ui_select_raised means ab fell back to a synthetic click that foregrounded Altium; the dispatch wrapper hands the user's window back."
],
"related": [
"show_symbol",
"show_footprint",
"run_command"
],
"example": {
"name": "SCH Library"
},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "preferences",
"tier": "app",
"source": "proposed",
"summary": "Read the tool's own settings (all, or one by key), or change them with set. Reports per key what was applied. A tool that rewrites its settings on exit refuses set while running, with reason: \"tool_running\".",
"input": {
"key": "dotted path of one setting (default all)",
"set": "{key: value} (omit to read)"
},
"output": {
"current": "{key: value}",
"applied": "{key: {ok, requested}} (with set)"
},
"hint": "Read first: the keys differ per tool.",
"pitfalls": [
"Keys differ per tool: read first.",
"A tool that rewrites its settings on exit needs to be closed for set (reason: tool_running)."
],
"related": [
"tool_update"
],
"example": {
"set": {
"lengthUnit": "mm"
}
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"altium-lane",
"kicad-lane"
]
},
{
"name": "prewarm",
"tier": "app",
"source": "proposed",
"summary": "Get this machine ready for a fast first call: detect the tool, seed its first-run settings, dismiss first-run wizards and repair what the first real call would otherwise do slowly. Idempotent.",
"input": {},
"output": {
"steps": "[{step, done, skipped?, why?}]",
"ready": "bool"
},
"hint": "The bridge host may run it once after an install or update; running it again changes nothing. Everything it does is what the first real verb would otherwise do in the user's face.",
"pitfalls": [
"It never opens a document or takes the foreground."
],
"related": [
"verb_times"
],
"example": {},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.25.1",
"agreedBy": [
"standard-lane",
"fusion-lane"
]
},
{
"name": "progress",
"tier": "app",
"source": "altium",
"summary": "The bridge's timing book: phases in flight right now (percent/ETA blocks ab paints on the taskbar), measured phase history and per-verb run statistics.",
"input": {},
"output": {
"active": "[progress blocks of phases in flight]",
"history": "{phase: {warm|cold: {samples, p50, p90}}}",
"verbTimes": "{verb: {count, p50, p90, max, failures}} - p90 descending, top 40"
},
"hint": "Use verbTimes.p90 to choose a timeout for a slow verb on THIS machine, and active[] to see what a long call is doing. Never touches Altium.",
"pitfalls": [],
"related": [
"status",
"describe"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 10
},
{
"name": "readiness",
"tier": "app",
"source": "altium",
"summary": "The one-call gate: is Altium installed, running, licensed, and is the resident agent alive? Answers with Altium closed and never touches the script engine.",
"input": {},
"output": {
"adVersion": "string | null",
"agentAlive": "bool - the selected instance",
"agentLiveWorkspaces": "[{workspace, heartbeatAgeSec}] - only when a loop lives outside the selection",
"agentResidentAnywhere": "bool - any workspace",
"engineParked": "bool - the agent's script is stopped in Altium's debugger",
"install": "{base_dir, exe, system_dir, major} | null",
"installed": "bool",
"licenceState": "string",
"licensed": "bool | null",
"ready": "bool - all four true",
"running": "bool"
},
"hint": "Follow _hint: not installed -> altium_install; not running -> altium_launch; licensed:false -> altium_ensure_licensed; agent down -> just call the verb you need (it bootstraps the agent) or altium_agent_start. ready:true -> altium_state.",
"pitfalls": [
"agentAlive is the SELECTED instance's view. agentResidentAnywhere:true beside agentAlive:false means a loop lives in another workspace: close through altium_close, never the window X.",
"engineParked:true = the agent's script is stopped on a breakpoint in Altium's debugger, with no dialog: nothing agent-backed runs and Altium refuses to close. altium_agent_recover stops it (#30)."
],
"related": [
"status",
"launch",
"ensure_licensed",
"agent_start"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 15
},
{
"name": "run_command",
"tier": "app",
"source": "altium",
"summary": "Run an Altium process (Server:Command) through the agent, on the CURRENT document or on filePath opened first.",
"input": {
"command": "string - e.g. PCB:Zoom",
"filePath": "optional: the document to make current first (PCB: processes need a board current)",
"params": "string or object"
},
"output": {
"success": "bool"
},
"hint": "Params are pipe-joined key=value pairs. altium_list_commands searches the catalog.",
"pitfalls": [
"Some processes open a modal dialog and block the loop until it is answered."
],
"related": [
"eval",
"list_commands"
],
"example": {
"command": "PCB:Zoom",
"params": {
"Action": "All"
}
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "run_script",
"tier": "app",
"source": "altium",
"summary": "One shot: run a procedure of YOUR OWN .PrjScr through Altium's -R command line. Only for when the agent is NOT resident.",
"input": {
"prjscr": "absolute path to a .PrjScr on this machine (required)",
"proc": "string, default 'Main'",
"timeout": "seconds, default 60"
},
"output": {
"arg": "string - the -R argument sent",
"helperSec": "float",
"modalsPreempted": "[{title, body}] - bridge-caused boxes cleared in flight"
},
"hint": "While the agent is resident use altium_eval / altium_run_command instead (or altium_agent_stop first). Scripts return nothing: have yours write a file and read that.",
"pitfalls": [
"Refused with agent_resident while ANY agent loop is alive: a second script raises 'Another script executing now' on the user's screen.",
"ONE SHOT: instance_busy means the running instance did not accept the request. Do not retry in a loop; each attempt costs the user a busy notice."
],
"related": [
"eval",
"run_command",
"agent_stop",
"agent_recover"
],
"example": {
"prjscr": "C:/scripts/MyTool.PrjScr",
"proc": "Main"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "save",
"tier": "app",
"source": "altium",
"summary": "Save the focused document, or the document at filePath (opened first if need be, saved by its path, never whatever happens to have focus).",
"input": {
"filePath": "path - optional; opened and made current before the save"
},
"output": {
"data": "{process, params}",
"roundtripMs": "int"
},
"hint": "Pass filePath every time: every library authoring verb leaves the library UNSAVED. Then altium_check_dialogs - a 'Save As' box means the document never had a path.",
"pitfalls": [
"Without filePath it saves whatever has focus, which may be the user's document rather than yours.",
"success only means the save process was dispatched; a Save As dialog blocks the engine until answered."
],
"related": [
"close_document",
"check_dialogs",
"close"
],
"example": {
"filePath": "C:/lib/Adom_ToF.SchLib"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "sch_zoom",
"tier": "app",
"source": "altium",
"summary": "Find parts on a sheet: select them (everything else deselected), frame the view on them and return a proof frame. The schematic half of cross-probing (the board half: altium_zoom_to).",
"input": {
"designators": "[string] or 'R1,U2' (required)",
"sheet": "path to the .SchDoc (required)",
"shot": "bool, default true"
},
"output": {
"notOnSheet": "[string]",
"parts": "[{designator, xMil, yMil}]",
"shot": "frame of Altium's main window"
},
"hint": "To find which sheet holds a part, altium_bom (or altium_schematic_data per sheet) lists every designator with its sheet.",
"pitfalls": [],
"related": [
"zoom_to",
"schematic_data",
"sch_edit"
],
"example": {
"designators": [
"U1",
"L1"
],
"sheet": "C:/proj/Main.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 60,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "select_items",
"tier": "app",
"source": "proposed",
"summary": "Select parts by designator on the board or the sheet, or clear the selection. A bridge that cannot select on one of them refuses it by name. verified says whether the selection was read back.",
"input": {
"refs": "[designator]",
"clear": "bool",
"where": "board (default) | sheet"
},
"output": {
"selected": "[ref]",
"failed": "[{ref, error}]",
"verified": "bool"
},
"hint": "select_net selects one net; sch_zoom also frames the view; selection reads what the user selected.",
"pitfalls": [
"A tool that cannot report its selection answers verified:false: look at the view."
],
"related": [
"select_net",
"sch_zoom",
"selection"
],
"example": {
"refs": [
"R1",
"R2"
]
},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"altium-lane",
"kicad-lane"
]
},
{
"name": "select_net",
"tier": "app",
"source": "altium",
"summary": "Select one net as a whole on the current board (tracks, arcs, vias, pads, pours) and nothing else, optionally framing it; no net clears the selection.",
"input": {
"margin": "mm, default 1",
"net": "string (optional) - empty or absent clears",
"zoom": "bool - frame the net (altium_zoom_to)"
},
"output": {
"byKind": "{tracks, arcs, vias, pads, pours, other}",
"net": "string",
"selected": "int",
"zoom": "[l, b, r, t] mm when zoom"
},
"hint": "AI Flow's net walkthrough lights each loaded net in turn. Altium draws a selection in its highlight colour.",
"pitfalls": [
"Needs the board current.",
"Pour regions are counted once, as their polygon."
],
"related": [
"zoom_to",
"routing_state",
"list_nets"
],
"example": {
"net": "SW",
"zoom": true
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "selection",
"tier": "app",
"source": "altium",
"summary": "What the user has selected in the current board (components with position mm, rotation, side, footprint, size) or sheet (components with location mils and orientation).",
"input": {
"filePath": "optional: the document to make current first",
"select": "[refs] - optional: select exactly these first (everything else deselected), to show the user which parts you mean"
},
"output": {
"kind": "board | sheet",
"selected": "[{ref, x, y, rotation, side, footprint, widthMm, heightMm}] or [{designator, xMil, yMil, orientation, libReference, comment}]"
},
"hint": "Lets the user point at parts in Altium and say 'these': move them with altium_move_parts {ref, dx, dy}, replicate them with altium_replicate_layout.",
"pitfalls": [
"Only components are reported (selected tracks and vias are not)."
],
"related": [
"move_parts",
"replicate_layout",
"zoom_to"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "selftest_script_error",
"tier": "app",
"source": "altium",
"summary": "Regression test for the script-error safety net (from 0.2.23): makes the agent raise a REAL DelphiScript runtime error on purpose and checks that the bridge photographs Altium's Error box, stops the halted script itself and leaves no dialog behind. Flashes one error box for under a second. Run it after any change to agent.rs / dialogs.rs and once on every new Altium build.",
"input": {},
"output": {
"autoRecovered": "bool",
"dialogsLeft": "int",
"errorShot": "base64 png (halted outcome only)",
"netWorks": "bool",
"outcome": "halted_and_recovered | contained_by_agent | unhandled"
},
"hint": "netWorks:true is the pass. The agent is stopped afterwards by design; the next verb restarts it.",
"pitfalls": [
"It really does halt the engine for a moment: do not run it while a user is mid-edit in Altium.",
"By design this is the SLOWEST verb in the catalog: it halts the engine, waits for the halt to be seen, recovers it and verifies by restarting the agent. Altium Designer Develop parks SILENTLY (no Error box), so the halt is only seen when the wait expires \u2014 measured 18 s to over 60 s on the same machine. Its budget is 180 s for that reason; a timeout here means the safety net is broken, not that it was slow."
],
"related": [
"agent_recover",
"dialog_log",
"agent_status"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 180
},
{
"name": "set_layer_visibility",
"tier": "app",
"source": "altium",
"summary": "Show or hide one layer of the current board (by layer id) and refresh the view and the layer tabs.",
"input": {
"displayed": "bool, default true",
"layerId": "int (required) - an id from altium_layers"
},
"output": {
"data": "{layerId, name, displayed}",
"roundtripMs": "int"
},
"hint": "Then altium_show_2d_board {filePath} for a frame of the result. Restore what you hid: visibility is view state the user keeps seeing.",
"pitfalls": [
"Needs a .PcbDoc current.",
"Only pass ids that altium_layers returned: the id is not range-checked before the layer object is read."
],
"related": [
"layers",
"layers_in_use",
"show_2d_board"
],
"example": {
"displayed": false,
"layerId": 1
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "setup_trial",
"tier": "app",
"source": "altium",
"summary": "Onboarding state machine: from nothing to a working trial. Each call reports the stage it found (install | launch | signin | done) and the ONE next action; human steps are named, not faked.",
"input": {},
"output": {
"licenceState": "string",
"needsHuman": "string - when a person must act",
"nextAction": "string",
"stage": "install | launch | signin | done",
"summary": "string"
},
"hint": "Follow nextAction and call again until stage is done. Not installed -> altium_install (the staged install verb; its licence stage does the clicks itself).",
"pitfalls": [
"Signed in but unlicensed, it starts the free-trial flow in the BROWSER and answers trial_needs_browser: a person names the workspace, accepts terms and clicks Activate.",
"stage launch answers success:true without launching anything: call altium_launch yourself."
],
"related": [
"install",
"ensure_licensed",
"signin_status",
"launch"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "show_2d_board",
"tier": "app",
"source": "altium",
"summary": "Open a .PcbDoc, switch to 2D, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel board.",
"input": {
"filePath": "path to a .PcbDoc - default: the bundled example board",
"timeout": "seconds, default 120"
},
"output": {
"dialogs": "[..]",
"dialogsDetected": "int",
"document": "string",
"elapsedSec": "float",
"path": "string",
"shot": "{image: base64 png, width, height}",
"steps": "[{open | process, ...}]",
"surface": "2d_board",
"title": "string",
"windowEtiquette": "background"
},
"hint": "It also makes the board the CURRENT document, so altium_read_board / altium_board_summary work right after. altium_show_3d_board for the 3D frame.",
"pitfalls": [
"ALWAYS pass filePath: the default opens Altium's example board in the user's session.",
"Measured live 2026-09-20: it RAISES Altium over the user's work. One call per proof; never loop it."
],
"related": [
"show_3d_board",
"read_board",
"set_layer_visibility",
"animate_view"
],
"example": {
"filePath": "C:/proj/tof.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "show_3d_board",
"tier": "app",
"source": "altium",
"summary": "Open a .PcbDoc, switch to 3D, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel board.",
"input": {
"filePath": "path to a .PcbDoc - default: the bundled example board",
"timeout": "seconds, default 120"
},
"output": {
"dialogs": "[..]",
"dialogsDetected": "int",
"document": "string",
"elapsedSec": "float",
"path": "string",
"shot": "{image: base64 png, width, height}",
"steps": "[{open | process, ...}]",
"surface": "3d_board",
"title": "string",
"windowEtiquette": "background"
},
"hint": "The proof for altium_test_board {pcbPath}: check every part shows a body. Missing body = the footprint has none (altium_add_body). altium_animate_view {preset:'showcase3d'} for motion.",
"pitfalls": [
"ALWAYS pass filePath: the default opens Altium's example board in the user's session.",
"Measured live 2026-09-20: it RAISES Altium over the user's work. One call per proof; never loop it.",
"It leaves the board in 3D mode for the user; altium_show_2d_board switches back."
],
"related": [
"show_2d_board",
"test_board",
"add_body",
"animate_view"
],
"example": {
"filePath": "C:/proj/tof.PcbDoc"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "show_3d_chip",
"tier": "app",
"source": "altium",
"summary": "Open a PcbLib member in the footprint editor in 3D, zoom to fit, and capture a proof frame of the part's 3D body.",
"input": {
"footprintName": "string (alias: name) - default: the first footprint of YOUR library, SO-G3 in the demo library",
"libraryPath": "path to a .PcbLib (alias: filePath) - default: the bundled SpiritLevel PcbLib",
"timeout": "seconds, default 60"
},
"output": {
"available": "[string] - when the name was not found",
"dialogs": "[..]",
"path": "string",
"selected": "string",
"shot": "{image: base64 png, width, height}",
"steps": "[..]",
"surface": "3d_chip",
"windowEtiquette": "background"
},
"hint": "The proof after altium_add_body / altium_import_part {step}. Pads with no body in the frame: altium_pcb_report to see whether a body exists, altium_normalize_bodies if it sits off the pads.",
"pitfalls": [
"Measured live 2026-09-20: it RAISES Altium over the user's work. One call per proof; never loop it.",
"It leaves the library editor in 3D mode; altium_show_footprint switches back to 2D."
],
"related": [
"show_footprint",
"add_body",
"normalize_bodies",
"pcb_report"
],
"example": {
"footprintName": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.PcbLib"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "show_footprint",
"tier": "app",
"source": "altium",
"summary": "Open a PcbLib member in the footprint editor in 2D, zoom to fit, and capture a proof frame.",
"input": {
"footprintName": "string (alias: name) - default: the first footprint of YOUR library, SO-G3 in the demo library",
"libraryPath": "path to a .PcbLib (alias: filePath) - default: the bundled SpiritLevel PcbLib",
"timeout": "seconds, default 60"
},
"output": {
"available": "[string] - when the name was not found",
"dialogs": "[..]",
"path": "string",
"selected": "string",
"shot": "{image: base64 png, width, height}",
"steps": "[..]",
"surface": "footprint",
"windowEtiquette": "background"
},
"hint": "Check pads, silkscreen and courtyard in shot.image; altium_pcb_report {path, name} gives the numbers. altium_show_3d_chip for the body.",
"pitfalls": [
"Measured live 2026-09-20: it RAISES Altium over the user's work. One call per proof; never loop it.",
"A wrong footprintName fails with available[] (up to 50 names): pick from it.",
"An empty-looking canvas usually means a 3D body sits 50000 mil from the pads: altium_normalize_bodies."
],
"related": [
"show_3d_chip",
"pcb_report",
"build_footprint",
"list_library"
],
"example": {
"footprintName": "VL53L5CX",
"libraryPath": "C:/lib/Adom_ToF.PcbLib"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "show_library",
"tier": "app",
"source": "altium",
"summary": "Open a .SchLib or .PcbLib (kind taken from the extension), select its first component, return a proof frame and the component names.",
"input": {
"libraryPath": "path to a .SchLib/.PcbLib (alias: filePath) - default: the bundled SpiritLevel SchLib",
"timeout": "seconds, default 60"
},
"output": {
"componentCount": "int",
"components": "[string] up to 200",
"dialogs": "[..]",
"path": "string",
"selected": "string",
"shot": "{image: base64 png, width, height}",
"steps": "[..]",
"surface": "library",
"windowEtiquette": "background"
},
"hint": "Then altium_show_symbol / altium_show_footprint / altium_show_3d_chip {libraryPath, name} for one member. altium_list_library gives the names without a frame.",
"pitfalls": [
"ALWAYS pass libraryPath: the default opens Altium's example library in the user's session.",
"Measured live 2026-09-20: it RAISES Altium over the user's work. One call per proof; never loop it.",
"errorCode proof_unavailable = opened and selected correctly, only the capture failed (window minimized)."
],
"related": [
"list_library",
"show_symbol",
"show_footprint",
"show_3d_chip"
],
"example": {
"libraryPath": "C:/lib/Adom_ToF.SchLib"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "show_project",
"tier": "app",
"source": "altium",
"summary": "Open a project (.PrjPcb) through the agent and return a proof frame of Altium's main window. With no filePath it opens Altium's bundled example project (Bluetooth Sentinel).",
"input": {
"filePath": "path to a .PrjPcb - default: the bundled Bluetooth Sentinel example",
"timeout": "seconds, default 60"
},
"output": {
"dialogs": "[..]",
"dialogsDetected": "int",
"document": "string",
"elapsedSec": "float",
"path": "string",
"shot": "{image: base64 png, width, height}",
"steps": "[{open, result, ms}]",
"surface": "project",
"title": "string",
"windowEtiquette": "background"
},
"hint": "A project has no document view of its own: follow with altium_show_schematic / altium_show_2d_board {filePath} for something to look at, or altium_compile {projectPath}.",
"pitfalls": [
"ALWAYS pass filePath for the user's work: the default opens Altium's example project in their session.",
"Measured live 2026-09-20: opening documents RAISES Altium over the user's work even though the reply says background. One call per proof; never loop show_* verbs.",
"success:false with dialogs[] means a box came up during the open: read it before anything else."
],
"related": [
"show_schematic",
"show_2d_board",
"compile",
"open_project"
],
"example": {
"filePath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "show_schematic",
"tier": "app",
"source": "altium",
"summary": "Open a .SchDoc, zoom to fit, and return a proof frame. With no filePath it opens the bundled Bluetooth Sentinel top sheet.",
"input": {
"filePath": "path to a .SchDoc - default: the bundled example sheet",
"timeout": "seconds, default 60"
},
"output": {
"dialogs": "[..]",
"dialogsDetected": "int",
"document": "string",
"elapsedSec": "float",
"path": "string",
"shot": "{image: base64 png, width, height}",
"steps": "[{open | process, ...}]",
"surface": "schematic",
"title": "string",
"windowEtiquette": "background"
},
"hint": "LOOK at shot.image before claiming anything. Then altium_read_schematic for the data, or altium_animate_view {lane:'sch'} for zoom moves.",
"pitfalls": [
"ALWAYS pass filePath: the default opens Altium's example design in the user's session.",
"Measured live 2026-09-20: it RAISES Altium over the user's work. One call per proof; never loop it.",
"After re-generating a sheet at the same path, altium_close_document the stale one first or the frame shows the OLD document."
],
"related": [
"read_schematic",
"place_on_sch",
"animate_view",
"show_2d_board"
],
"example": {
"filePath": "C:/proj/tof.SchDoc"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "show_symbol",
"tier": "app",
"source": "altium",
"summary": "Open a SchLib member in the Symbol editor and capture a background proof.",
"input": {
"libraryPath": "path",
"symbolName": "string"
},
"output": {
"shot": "{image: base64 png, width, height}",
"success": "bool",
"windowEtiquette": "background"
},
"hint": "Never foregrounds: a minimized Altium is restored INTO THE BACKGROUND and the user's window handed straight back.",
"pitfalls": [
"A capture under 400px wide is refused as proof_unavailable - a title-bar sliver is not evidence."
],
"related": [
"show_footprint",
"show_3d_chip",
"show_library"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "signin",
"tier": "app",
"source": "altium",
"summary": "Report-only alias of altium_signin_status: it does NOT sign anyone in. Signing in to Altium is a browser flow only the human can complete.",
"input": {},
"output": {
"currentUserProcess": "object - only when the agent is resident",
"licenceState": "string",
"licensed": "bool | null",
"running": "bool",
"workspaceConnected": "bool",
"workspaceMenu": "string"
},
"hint": "To see WHO is signed in: altium_license {action:'show'} and read the page ('Sign Out' visible = already signed in). Not connected to a workspace -> altium_connect_workspace.",
"pitfalls": [
"Despite the name there are no credential arguments and nothing is typed or clicked.",
"Never ask the user for their Altium password: the browser flow is theirs."
],
"related": [
"signin_status",
"license",
"connect_workspace",
"install"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "signin_status",
"tier": "app",
"source": "altium",
"summary": "Account and Altium 365 workspace connection as Altium's own UI reports it: licence state from the title, and whether the workspace menu reads 'Not Connected'.",
"input": {},
"output": {
"currentUserProcess": "object - only when the agent is resident",
"licenceState": "string",
"licensed": "bool | null",
"running": "bool",
"workspace": "null - the name is not read",
"workspaceConnected": "bool",
"workspaceMenu": "string"
},
"hint": "workspaceConnected:false -> altium_connect_workspace opens the picker. The signed-in account name is on the License Management page: altium_license {action:'show'}.",
"pitfalls": [
"workspaceConnected is inferred from the ABSENCE of a 'Not Connected' menu item: a UIA miss reads as connected."
],
"related": [
"connect_workspace",
"license",
"license_status"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "simulate",
"tier": "app",
"source": "proposed",
"summary": "Run a circuit simulation of the design's schematic and return the signals as data: an operating point, a DC sweep, an AC sweep or a transient, with the nets and source currents asked for.",
"input": {
"schematic": "the design or sheet to simulate (the bridge's own path or id) (required)",
"analysis": "{type: op} | {type: dc, source, start, stop, step} | {type: ac, sweep: dec|oct|lin, points, start, stop} (Hz) | {type: tran, step, stop, start?} (s) | {type: noise, source, output, reference?, sweep: dec|oct|lin, points, start, stop} (Hz: the output and input-referred noise of output against reference, driven from source) | {type: raw, text: \".ac dec 20 10 1meg\"} (a bridge that cannot run raw SPICE refuses it with not_supported); default the analysis the design carries",
"probes": "[{net: \"OUT\"} | {current: \"V1\"}]; default every net (a bridge may cap the count)",
"sweep": "{parameter, start, stop, step, scale?: \"lin\" | \"dec\" | \"oct\"}: optional; steps a part's value (\"R4\") or a model parameter (\"Q1.BF\"), one run per value; for lin, step is the increment, for dec and oct the points per decade or octave; a bridge may cap the number of runs",
"temperatures": "{start, stop, step} (\u00b0C): optional; one run per temperature",
"monteCarlo": "{runs, distribution?: \"uniform\" | \"gaussian\", seed?, tolerances: {resistor?, capacitor?, inductor?, transistor?, dcSource?, digital?} (%)}: optional; the analysis runs again with every part drawn within its kind's tolerance, each run its own signal; the same seed draws the same values",
"points": "int, default 200: a ceiling on the points returned per signal; decimation keeps the first and last points and every extremum (the run itself is not coarsened)"
},
"output": {
"signals": "[{signal: \"V(OUT)\", x: [..], y: [..], xUnit: s|Hz|V, yUnit: V|A|dB, phase?: [..] (AC, degrees, unwrapped)}]; an op gives one point per signal; with sweep or temperatures each run is its own signal, with step saying which run it is (\"R4 = 300\", \"T = 85\"), so a reader groups runs by signal + step; a Monte Carlo run's step lists the values drawn (\"R3 = 9038.1, C6 = 1.0004e-10\"), so any run can be reproduced; a noise analysis answers onoise and inoise (yUnit V/rtHz) over frequency",
"totals": "noise analysis: {onoise, inoise}, the integrated output and input-referred noise in V",
"missing": "[probe]: probes the run did not have",
"notSimulated": "[ref]: parts the run left out for want of a simulation model, when the sheet is only partly modelled, so a reader knows the result covers only part of the circuit (empty when every part was simulated)",
"available": "[signal name]",
"engine": "the simulator and its version, e.g. \"ngspice 46 (KiCad 10.0.7)\""
},
"hint": "AC signals are the magnitude in dB with phase in degrees beside it. Every part needs a simulation model: passives work from their values, sources come from the tool's simulation library, ICs need a model file.",
"pitfalls": [
"simulation_failed carries the simulator's own message: a part without a model, a node with no DC path to ground, or a bad analysis.",
"points thins the reply, not the run: a long transient with a tiny step still takes its time.",
"A partly modelled sheet still runs and names the parts it left out in notSimulated; a sheet with no modelled parts refuses with no_model.",
"A bridge that cannot sweep refuses sweep or temperatures with not_supported; it never runs once and returns a single trace as if it were the sweep (ngspice has no .step: loop with alter per value).",
"A bridge that cannot run a noise analysis or a Monte Carlo (or draw one of its tolerance kinds) refuses with not_supported; it never answers something else in its place."
],
"related": [
"export_spice",
"run_erc",
"sch_place_part"
],
"example": {
"schematic": "C:/proj/filter.kicad_sch",
"analysis": {
"type": "ac",
"sweep": "dec",
"points": 20,
"start": 10,
"stop": 1000000
},
"probes": [
{
"net": "OUT"
}
]
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.14.0",
"agreedBy": [
"standard-lane",
"altium-lane",
"fusion-lane"
]
},
{
"name": "state",
"tier": "app",
"source": "altium",
"summary": "The whole picture in one call: licence state, windows, dialogs, a screenshot of every main/dialog window, and the agent's logical state (focused document, focused project, open documents).",
"input": {
"screenshots": "bool, default true"
},
"output": {
"agentAlive": "bool - union over every workspace",
"agentWorkspace": "path | null - where logical came from",
"dialogs": "[..]",
"drivingBadge": "{active}",
"licence": "{running, licensed, state, adVersion, edition, document, hwnd, pid}",
"liveWorkspaces": "[{workspace, heartbeatAgeSec}]",
"logical": "agent reply; data = {focusedDocument, focusedProject, documents:[{path, kind, project, open}]} | null when no agent is alive",
"shots": "[{title, hwnd, kind, image: base64 png, width, height}]",
"windows": "[..]"
},
"hint": "Look before acting: logical.data.focusedDocument is what the board/schematic read verbs would read; altium_activate_document {path} changes it. Poll with screenshots:false.",
"pitfalls": [
"logical is null when no agent is resident: state never bootstraps one. Call any agent-backed verb or altium_agent_start first.",
"shots[] are full-size base64 PNGs of every main and dialog window; pass screenshots:false when you only need the data."
],
"related": [
"status",
"window_info",
"activate_document",
"agent_start"
],
"example": {
"screenshots": false
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "status",
"tier": "app",
"source": "altium",
"summary": "Is Altium running, licensed, and is the resident agent alive?",
"input": {},
"output": {
"agentAlive": "bool",
"licenceState": "string",
"licensed": "bool",
"running": "bool"
},
"hint": "Cheapest health call - answers from ab's window list plus the agent heartbeat; never touches the script engine.",
"pitfalls": [
"'running' can be true while 'licensed' is false - a trial lease can be stranded by a crash."
],
"related": [
"readiness",
"agent_status",
"instances"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 15
},
{
"name": "tool_update",
"tier": "app",
"source": "proposed",
"summary": "The tool's own updates: check whether one is offered, apply it in the background when no work would be lost, or read or set automatic updating.",
"input": {
"action": "check | apply | auto (required)",
"on": "bool (auto): turn automatic updating on or off; omitted, the setting is read"
},
"output": {
"current": "the installed version",
"offered": "the version offered, or null",
"applied": "bool",
"auto": "bool",
"needsRestart": "bool"
},
"hint": "apply never closes unsaved work: it refuses with the documents that need saving. Updating the tool is the user's machine changing, so say so before apply.",
"pitfalls": [
"An update offered only through the tool's own dialog is read from that dialog and answered in the background, never left open.",
"apply refuses while documents are unsaved, and an installer that needs a person at the Windows UAC prompt answers needs_user with what to approve."
],
"related": [
"readiness",
"diagnostics",
"install"
],
"example": {
"action": "check"
},
"longRunning": true,
"timeoutSeconds": 600,
"proposedBy": "fusion-lane",
"since": "0.28.1",
"agreedBy": [
"standard-lane",
"altium-lane"
]
},
{
"name": "uninstall",
"tier": "app",
"source": "altium",
"summary": "Remove the bridge's own cache directory (agent workspaces, rendered agent scripts, the Altium 365 token file). Altium Designer and the user's designs are never touched.",
"input": {
"dryRun": "bool - report only, delete nothing"
},
"output": {
"dryRun": "bool",
"note": "string",
"removed": "[path]"
},
"hint": "This is the manifest's uninstall hook; nothing to call afterwards. To revoke the Altium 365 grant remotely call altium_a365_logout BEFORE this.",
"pitfalls": [
"A resident agent is stopped even with dryRun:true; only the delete is skipped."
],
"related": [
"a365_logout",
"agent_stop"
],
"example": {
"dryRun": true
},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "verb_times",
"tier": "app",
"source": "proposed",
"summary": "Measured run times of this bridge's verbs on this machine: per verb the count, p50, p90, max, last and failures, from its own run log, slowest p90 first.",
"input": {
"limit": "int, default 40: how many verbs"
},
"output": {
"verbs": "[{verb, count, p50Sec, p90Sec, maxSec, lastSec, failures}]",
"since": "when the log starts"
},
"hint": "p90 is the headline: a p50 of 15 s next to a p90 of 400 s is two code paths under one name. failures counts runs that returned success:false; a verb that fails fast is a different bug from a slow one.",
"pitfalls": [
"Times are this machine's: a slower box or a bigger board moves them."
],
"related": [
"prewarm"
],
"example": {
"limit": 20
},
"longRunning": false,
"timeoutSeconds": null,
"proposedBy": "kicad-lane",
"since": "0.25.1",
"agreedBy": [
"standard-lane",
"fusion-lane"
]
},
{
"name": "window_info",
"tier": "app",
"source": "altium",
"summary": "Altium's top-level windows plus any open dialogs, without screenshots. The cheap way to ask 'is a modal blocking the engine?'.",
"input": {},
"output": {
"dialogs": "[{hwnd, title, body, buttons, category, safeAction, ownedByMainInstance}]",
"hasModalDialogs": "bool - a dialog owned by the main instance",
"windows": "[{hwnd, title, kind, className, pid, rect}]"
},
"hint": "hasModalDialogs:true means the agent loop and every -R request are frozen behind it: altium_check_dialogs for the pictures, then altium_dismiss_dialogs {button, titles}. Otherwise the main window's title names the current document.",
"pitfalls": [
"Altium PAINTS its dialog text, so body is often empty here; altium_check_dialogs attaches a PNG per dialog."
],
"related": [
"check_dialogs",
"dismiss_dialogs",
"state"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 15
},
{
"name": "zoom_to",
"tier": "app",
"source": "altium",
"summary": "Frame the PCB view on a rectangle, a part (or several) or a whole net, with a margin.",
"input": {
"margin": "mm (default 1)",
"net": "(optional) a net: its pads, tracks and vias",
"rect": "(optional) [x1, y1, x2, y2] mm",
"ref": "(optional) a designator, e.g. U1",
"refs": "(optional) [designator]"
},
"output": {
"rect": "[left, bottom, right, top] mm framed"
},
"hint": "For a close look at a joint or a camera shot of one part or net; altium_run_command PCB:Zoom Action=All frames the whole board.",
"pitfalls": [
"Needs the board current.",
"Coordinates are Altium's (y up), as routing_state reports them."
],
"related": [
"routing_state",
"run_command",
"animate_view"
],
"example": {
"margin": 0.5,
"net": "SW"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "a365_configure",
"tier": "platform",
"source": "altium",
"summary": "Store the Altium 365 workspace domain and, optionally, a Bearer token created by hand in the workspace web UI (Admin - Developer). Local-only; tokens never appear in replies.",
"input": {
"token": "string - optional developer token",
"workspace": "string - e.g. acme.365.altium.com (required unless already stored)"
},
"output": {
"hasToken": "bool",
"workspace": "string"
},
"hint": "Then altium_a365_status to prove the token is live. Preferred over a manual token: altium_a365_oauth_begin {clientId, workspace}.",
"pitfalls": [
"The token is written to a365.json in the bridge cache: altium_uninstall deletes it, altium_a365_logout removes it.",
"Never echo a token back to the user or into a log."
],
"related": [
"a365_status",
"a365_oauth_begin",
"a365_query"
],
"example": {
"workspace": "acme.365.altium.com"
},
"longRunning": false,
"timeoutSeconds": 15
},
{
"name": "a365_files_upload",
"tier": "platform",
"source": "altium",
"summary": "Upload one local file to the workspace's Files Service and get a temporary opaque file id to pass to a library mutation.",
"input": {
"filePath": "path on THIS machine (required)",
"maxBytes": "int, default 104857600 (100 MB)",
"timeout": "int seconds, default 120"
},
"output": {
"expiresAfterHoursInactive": "24",
"fileId": "string - opaque"
},
"hint": "Pass fileId straight into the matching mutation via altium_a365_query {query, variables}. Do not parse or persist it.",
"pitfalls": [
"a365_file_not_found: the path must be on the bridge's machine - stage it with send_files.",
"The id expires after 24 h of inactivity."
],
"related": [
"a365_query",
"a365_library_schema"
],
"example": {
"filePath": "C:/lib/Adom_ToF.SchLib"
},
"longRunning": false,
"timeoutSeconds": 120
},
{
"name": "a365_library_overview",
"tier": "platform",
"source": "altium",
"summary": "One fixed read-only query: the workspace library's name, description, update time, component ids/names and footprint/symbol totals.",
"input": {},
"output": {
"data": "{desLibrary: {name, description, updatedAt, components: {nodes: [{id, name}]}, footprints: {totalCount}, symbols: {totalCount}}}",
"errors": "[..] | null"
},
"hint": "The proof that a fresh OAuth token is workspace-scoped. Then altium_a365_library_schema before attempting any mutation.",
"pitfalls": [
"Same error codes as altium_a365_query (a365_not_configured, a365_graphql_http, a365_network_error)."
],
"related": [
"a365_status",
"a365_library_schema",
"a365_query"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "a365_library_schema",
"tier": "platform",
"source": "altium",
"summary": "Read-only schema map: the GraphQL queries and mutations whose names mention lib, component, symbol, footprint, part or datasheet, with mutation argument types.",
"input": {
"timeout": "int seconds, default 60"
},
"output": {
"mutations": "[{name, description, args: [{name, type}]}]",
"queries": "[{name, description}]"
},
"hint": "Pick the mutation, understand its input types AND its rollback/delete counterpart, upload inputs with altium_a365_files_upload, then altium_a365_query.",
"pitfalls": [
"A name filter over introspection: a relevant field named differently is not listed - the full schema is at https://<workspace>/api/voyager."
],
"related": [
"a365_query",
"a365_files_upload",
"a365_library_overview"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "a365_logout",
"tier": "platform",
"source": "altium",
"summary": "Revoke the refresh grant at Altium and remove every cached OAuth token. Workspace and client id stay configured.",
"input": {},
"output": {
"revoked": "bool - a remote revocation happened",
"workspace": "string"
},
"hint": "altium_a365_status afterwards should read hasToken:false. Sign in again with altium_a365_oauth_begin.",
"pitfalls": [
"If the remote revocation fails (a365_revoke_failed / a365_network_error) the LOCAL tokens are kept on purpose: retry.",
"This is the Altium 365 API grant only; it does not sign Altium Designer out or release a licence seat."
],
"related": [
"a365_status",
"a365_oauth_begin",
"uninstall"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "a365_oauth_begin",
"tier": "platform",
"source": "altium",
"summary": "Start the Altium 365 OAuth (PKCE + ActionWait) sign-in: the bridge starts listening FIRST, then returns the authorize URL for the user's browser. Works with Altium closed.",
"input": {
"clientId": "string - an Altium-issued public OAuth client id (or the stored one)",
"selectWorkspace": "strict (default) | optional | none",
"timeout": "int seconds, default 300 - how long to wait for the consent",
"workspace": "string - e.g. acme.365.altium.com (or the stored one)"
},
"output": {
"authorizeUrl": "string",
"status": "waiting",
"workspace": "string"
},
"hint": "Open authorizeUrl in the user's EXISTING browser only after this returns, then poll altium_a365_oauth_status until status is authorized.",
"pitfalls": [
"a365_client_id_required: OAuth clients come from Altium's Developer Center enrollment. Never reuse a first-party client id.",
"a365_oauth_in_progress: one flow at a time - altium_a365_oauth_cancel the old one first.",
"The consent page is the human's step; tokens never appear in any reply."
],
"related": [
"a365_oauth_status",
"a365_oauth_cancel",
"a365_status"
],
"example": {
"clientId": "<your Altium-issued client id>",
"workspace": "acme.365.altium.com"
},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "a365_oauth_cancel",
"tier": "platform",
"source": "altium",
"summary": "Cancel a waiting OAuth flow.",
"input": {},
"output": {
"alreadyStopped": "bool",
"status": "cancelling | <current status>"
},
"hint": "Poll altium_a365_oauth_status until it reads cancelled, then altium_a365_oauth_begin again if wanted.",
"pitfalls": [
"The worker notices the cancel between long-polls (up to about 75 s)."
],
"related": [
"a365_oauth_begin",
"a365_oauth_status"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 10
},
{
"name": "a365_oauth_status",
"tier": "platform",
"source": "altium",
"summary": "State of the OAuth flow started by altium_a365_oauth_begin: idle | waiting | authorized | cancelled | error.",
"input": {},
"output": {
"claims": "object - unverified token claim summary (authorized)",
"error": "string (error)",
"errorCode": "string (error)",
"status": "idle | waiting | authorized | cancelled | error",
"workspace": "string"
},
"hint": "Poll every few seconds while waiting. authorized -> altium_a365_library_overview proves the workspace-scoped token. error -> read errorCode, then altium_a365_oauth_begin again.",
"pitfalls": [
"success is false only for status error; waiting and idle are success:true.",
"State lives in bridge memory: a bridge restart mid-flow reads idle."
],
"related": [
"a365_oauth_begin",
"a365_oauth_cancel",
"a365_library_overview"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 10
},
{
"name": "a365_query",
"tier": "platform",
"source": "altium",
"summary": "Run one GraphQL query or mutation against the workspace's GraphQL gateway (https://<workspace>/svc/napi/gateway/graphql/) with the stored token.",
"input": {
"query": "string - GraphQL (required)",
"timeout": "int seconds, default 60",
"variables": "object"
},
"output": {
"data": "object | null",
"errors": "[..] | null"
},
"hint": "Discover fields first with altium_a365_library_schema (or https://<workspace>/api/voyager). a365_graphql_http / a365_network_error -> altium_a365_status, then altium_a365_refresh.",
"pitfalls": [
"success is false whenever the reply carries errors[], even with partial data.",
"Mutations change the user's shared workspace for everyone: know the rollback/delete mutation before running one.",
"a365_not_configured = no workspace or token stored."
],
"related": [
"a365_library_schema",
"a365_library_overview",
"a365_refresh",
"a365_files_upload"
],
"example": {
"query": "{ desProjects(first: 10) { nodes { name } } }"
},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "a365_refresh",
"tier": "platform",
"source": "altium",
"summary": "Exchange the stored refresh token for a new access token (and store a rotated refresh token if one comes back).",
"input": {},
"output": {
"claims": "object - unverified token claim summary",
"workspace": "string"
},
"hint": "Call when altium_a365_query answers a365_graphql_http 401 or altium_a365_status shows tokenLive:false, then retry.",
"pitfalls": [
"a365_refresh_not_configured = no OAuth grant stored (a manual developer token cannot be refreshed).",
"a365_refresh_failed usually means the grant was revoked: altium_a365_oauth_begin again."
],
"related": [
"a365_status",
"a365_query",
"a365_oauth_begin"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "a365_status",
"tier": "platform",
"source": "altium",
"summary": "Is the Altium 365 lane configured, is there a token, and is it LIVE (probed with a one-row GraphQL query)?",
"input": {},
"output": {
"clientConfigured": "bool",
"configured": "bool",
"endpoint": "string - the GraphQL URL",
"hasRefreshToken": "bool",
"hasToken": "bool",
"probe": "object - probe data or error",
"tokenLive": "bool",
"workspace": "string | null"
},
"hint": "hasToken:false -> altium_a365_oauth_begin (or altium_a365_configure {token}). tokenLive:false with hasRefreshToken -> altium_a365_refresh. Live -> altium_a365_library_overview / altium_a365_query.",
"pitfalls": [
"Independent of Altium Designer: this lane works while X2.exe is closed and says nothing about the desktop licence seat."
],
"related": [
"a365_oauth_begin",
"a365_refresh",
"a365_query",
"a365_configure"
],
"example": {},
"longRunning": false,
"timeoutSeconds": 60
},
{
"name": "aps_browse",
"tier": "platform",
"source": "proposed",
"summary": "Browse hubs/projects/folders without launching Fusion.",
"input": {
"folderId": "optional str",
"hubId": "optional str",
"projectId": "optional str"
},
"output": {
"items": "[{name,type,id}]"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_create_folder",
"tier": "platform",
"source": "proposed",
"summary": "Create a subfolder in a project (free; needs data:create scope). Use this to make an 'Adom AI Workspace' folder + per-task subfolders so the bridge never dumps loose files in the shared project root. See fusion-cloud-hygiene.",
"input": {
"name": "required str",
"parentFolderId": "required str",
"projectId": "required str"
},
"output": {
"folderId": "str"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"name": "Adom AI Workspace",
"parentFolderId": "urn:...",
"projectId": "a.YnVz..."
},
"longRunning": false,
"timeoutSeconds": 50,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_download",
"tier": "platform",
"source": "proposed",
"summary": "Download a cloud file to the local machine (no Fusion needed).",
"input": {
"fileName": "optional str",
"query": "str OR projectId+urn",
"saveDir": "optional str"
},
"output": {
"bytes": "int",
"path": "str"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"query": "BME690 Molecule"
},
"longRunning": false,
"timeoutSeconds": 90,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_file_info",
"tier": "platform",
"source": "proposed",
"summary": "Version history + who/when/size for a file (tip + recent versions).",
"input": {
"query": "str OR projectId+urn"
},
"output": {
"tip": "{...}",
"versionCount": "int",
"versions": "[...]"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"query": "BME690 Molecule"
},
"longRunning": false,
"timeoutSeconds": 40,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_open",
"tier": "platform",
"source": "proposed",
"summary": "Find a cloud design by name and open it in Fusion (any folder depth). Fire-and-poll.",
"input": {
"query": "required str",
"wait": "optional bool"
},
"output": {
"match": "{name}",
"opening": "bool",
"statusVerb": "str"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"query": "BME690 Molecule"
},
"longRunning": true,
"timeoutSeconds": 60,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_recent",
"tier": "platform",
"source": "proposed",
"summary": "Most-recently-modified designs across the team hub, newest first.",
"input": {
"limit": "optional int (default 25)"
},
"output": {
"count": "int",
"results": "[...]"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"limit": 25
},
"longRunning": false,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_search",
"tier": "platform",
"source": "proposed",
"summary": "Server-indexed search across the whole team hub: about 20-30 s hub-wide, a few seconds with projectId (not a 30-min folder walk). Budget 120 s. A ZERO from the server index is not absence: the reply then carries data.fallback (a name scan of the newest 400 items), data.completeness, and a hint to fusion_aps_browse a known sibling's folder (issue #85).",
"input": {
"hubId": "optional str",
"limit": "optional int (default 50)",
"projectId": "optional str",
"query": "required str"
},
"output": {
"count": "int",
"results": "[{name,id,projectName,lastModified}]"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"limit": 10,
"query": "Molecule"
},
"longRunning": false,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_set_client_id",
"tier": "platform",
"source": "proposed",
"summary": "Set the org's APS (PKCE) client id used for cloud search. Get it from your org's members-only wiki settings: adom-wiki settings get <org> autodesk-aps (never from another machine's config file). When the org has none yet, the reply's hint gives the adom-wiki settings set command that shares it, so every other box adopts it in two calls (fusion-aps-org-setup skill). Public identifier, no secret.",
"input": {
"clientId": "required str"
},
"output": {
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"clientId": "D5nn...EPAq"
},
"longRunning": false,
"timeoutSeconds": 20,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_signin",
"tier": "platform",
"source": "proposed",
"summary": "Open the Autodesk sign-in in the REMEMBERED browser+profile (not the OS default); a background listener captures the token. Pass {exe,profileDir,name} to use+remember a specific browser, or {allowDefaultBrowser:true} to fall back to the OS default. If nothing is remembered, returns needsExtensionOpen so the caller opens authUrl in the user's real browser via nbrowser_open_window.",
"input": {
"allowDefaultBrowser": "optional bool",
"exe": "optional str (browser binary to launch+remember)",
"name": "optional str",
"profileDir": "optional str (e.g. 'Default','Profile 2')"
},
"output": {
"authUrl": "str",
"needsExtensionOpen": "bool",
"openedVia": "str",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": false,
"timeoutSeconds": 30,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_status",
"tier": "platform",
"source": "proposed",
"summary": "APS state: configured, signed in, token live, never-charge meter. When configured:false the hint sends you to your org's shared app ID on the wiki (adom-wiki settings get <org> autodesk-aps) before anything else; the fusion-aps-org-setup skill covers new boxes and first-time orgs.",
"input": {},
"output": {
"configured": "bool",
"neverCharge": "bool",
"signedIn": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": false,
"timeoutSeconds": 20,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_upload",
"tier": "platform",
"source": "proposed",
"summary": "Upload a local file as a NEW cloud file (free Data Management; needs data:write scope). \u26d4 FOLDER HYGIENE: NEVER pass a project ROOT folderId - the bridge REFUSES it (refused_root_upload). Loose files in a shared root clutter the team's cloud. Create/choose a real subfolder first (fusion_aps_create_folder under an 'Adom AI Workspace' folder), or just use fusion_make_3d_package / fusion_build_library_3d which auto-target a non-root workspace. To RELOCATE an existing file, MOVE it (preserves its urn) - do NOT delete + re-upload (mints a new urn, breaks 3D bindings). See the fusion-cloud-hygiene skill.",
"input": {
"fileName": "optional str",
"folderId": "required str (NON-ROOT subfolder)",
"localPath": "required str",
"projectId": "required str"
},
"output": {
"bytes": "int",
"itemUrn": "str"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"folderId": "urn:...",
"localPath": "C:/x.f3d",
"projectId": "a.YnVz..."
},
"longRunning": false,
"timeoutSeconds": 90,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "aps_versions",
"tier": "platform",
"source": "proposed",
"summary": "Full (uncapped) version history of a file.",
"input": {
"query": "str OR projectId+urn"
},
"output": {
"versionCount": "int",
"versions": "[...]"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"query": "BME690 Molecule"
},
"longRunning": false,
"timeoutSeconds": 40,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "cleanup_cloud_files",
"tier": "platform",
"source": "proposed",
"summary": "PRECISELY delete a list of cloud files by lineage urn - SAFE cleanup of AI-created clutter. Deletes ONLY the exact fileIds given (never name-guessing), so it can't touch a teammate's file in a shared folder. Loops server-side. Get the ids from fusion_aps_browse (item .id). Use this to remove f3d files the bridge created. A big list takes minutes (relay may time out at ~60s while deletes continue server-side - re-browse to confirm).",
"input": {
"fileIds": "required [<lineage urn>]",
"folderPath": "optional str (default root - where the files live)",
"projectName": "optional str (default active project)"
},
"output": {
"deletedCount": "int",
"failed": "[{fileId,error}]",
"failedCount": "int",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"fileIds": [
"urn:adsk.wipprod:dm.lineage:abc123"
],
"projectName": "Adom"
},
"longRunning": true,
"timeoutSeconds": 1800,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "compile_intlib",
"tier": "platform",
"source": "altium",
"summary": "Compile a .LibPkg into an integrated library (.IntLib).",
"input": {
"libpkgPath": "path to a .LibPkg (required)",
"output": "destination directory",
"timeout": "seconds, default 300"
},
"output": {
"data": "{libpkg, outputDir}",
"roundtripMs": "int"
},
"hint": "Then altium_install_library {libraryPath: <the .IntLib>}. Check the file exists: the reply does not verify it was written.",
"pitfalls": [
"The LibPkg is opened as a project in the user's workspace and stays open.",
"success only means the compile was dispatched; verify the .IntLib on disk."
],
"related": [
"extract_intlib",
"install_library"
],
"example": {
"libpkgPath": "C:/lib/Adom_ToF.LibPkg",
"output": "C:/lib/out"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "create_cloud_folder",
"tier": "platform",
"source": "proposed",
"summary": "Create a subfolder in a cloud project through the signed-in Fusion session's Data API (no APS needed). Idempotent: an existing folder of that name is returned with alreadyExisted:true instead of a duplicate. Folder names are matched case-insensitively. For an APS-side create without Fusion running, use fusion_aps_create_folder.",
"input": {
"folderName": "required str",
"parentPath": "optional str (parent folder path; default the project root)",
"projectName": "optional str (default the active project)"
},
"output": {
"alreadyExisted": "bool (only when it already existed)",
"folderId": "str",
"folderName": "str",
"parentFolder": "str",
"project": "str",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"folderName": "AI-Scratch",
"projectName": "Main"
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "delete_cloud_file",
"tier": "platform",
"source": "proposed",
"summary": "DESTRUCTIVE: delete ONE cloud file through the signed-in Fusion session's Data API. Looks in exactly one folder (projectName + folderPath, no recursion) for an exact case-insensitive name match, or for the lineage urn when fileId is given (the precise form; prefer it in shared folders). Refuses without fileName or fileId. Large folders time out on the scan; give a precise folderPath. Use fusion_cleanup_cloud_files to delete a LIST of urns with dryRun support.",
"input": {
"fileId": "optional str (lineage urn for a precise delete; lineageUrn is accepted as an alias)",
"fileName": "required str unless fileId is given (exact name match in one folder)",
"folderPath": "optional str (default the project root)",
"projectName": "optional str (default the active project)"
},
"output": {
"fileId": "str",
"fileName": "str",
"folder": "str",
"project": "str",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"fileName": "verbtest-scratch",
"folderPath": "AI-Scratch",
"projectName": "Main"
},
"longRunning": false,
"timeoutSeconds": 60,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "extract_intlib",
"tier": "platform",
"source": "altium",
"summary": "Extract the editable .SchLib/.PcbLib sources from a compiled .IntLib (Altium writes them next to the IntLib and opens them).",
"input": {
"intlibPath": "path to an .IntLib (required)",
"timeout": "seconds, default 300"
},
"output": {
"data": "{intlib, sources: [path]}",
"roundtripMs": "int"
},
"hint": "Then altium_list_library / altium_read_symbol on the extracted sources.",
"pitfalls": [
"sources[] lists EVERY .SchLib/.PcbLib in any open project, not only the ones this call extracted."
],
"related": [
"compile_intlib",
"list_library",
"install_library"
],
"example": {
"intlibPath": "C:/lib/Vendor.IntLib"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "import_kicad",
"tier": "platform",
"source": "altium",
"summary": "Import a KiCad file with Altium's own KiCad importer, driven through the AdomBridge .NET extension.",
"input": {
"filePath": "path to a .kicad_sym / .kicad_sch / .kicad_pcb (required)",
"mode": "string, default 'Import'",
"timeout": "seconds, default 300"
},
"output": {
"elapsedSec": "float",
"result": "string - the extension's result file"
},
"hint": "Output lands in 'Imported <stem>' beside the source. Then link footprints with altium_set_params {footprint}. For Adom parts prefer altium_import_part, which needs no extension.",
"pitfalls": [
"Footprints are NOT imported by Altium's KiCad importer.",
"Same extension caveat as altium_export_step: on AD 26.9.1 it answered extension_timeout."
],
"related": [
"extension_ping",
"install_extension",
"import_part",
"set_params"
],
"example": {
"filePath": "C:/lib/VL53L5CX.kicad_sym"
},
"longRunning": false,
"timeoutSeconds": 300
},
{
"name": "list_cloud_files",
"tier": "platform",
"source": "proposed",
"summary": "List files/folders in a cloud project (optionally a subfolder).",
"input": {
"folderPath": "optional str",
"projectName": "optional str (defaults to active project)"
},
"output": {
"files": "list",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {
"projectName": "Main"
},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "list_cloud_projects",
"tier": "platform",
"source": "proposed",
"summary": "List the cloud PROJECTS visible to the signed-in Fusion session (hub walk - slow on big teams; prefer fusion_aps_search for finding files).",
"input": {},
"output": {
"projects": "list",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": true,
"timeoutSeconds": 120,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "managed_library_create",
"tier": "platform",
"source": "proposed",
"summary": "Create a NEW managed library on library.io FROM the library in front (which must already be saved in a Fusion Hub). Drives MANAGE > LIBRARY.IO > Push, then completes Fusion's Create Managed Library dialog. PITFALL: a managed library created under one Autodesk account is NOT visible to another account until its managed FOLDER is shared on library.io - proven live, so do not assume hub membership shares it.",
"input": {
"description": "optional str",
"name": "optional str (defaults to the library's own name)"
},
"output": {
"alerts": "[...]",
"library": "str",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": true,
"timeoutSeconds": 240,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "managed_library_link",
"tier": "platform",
"source": "proposed",
"summary": "Link the library IN FRONT to an existing managed library on library.io. With no name, opens Fusion's Select Managed Library picker, returns its rows as records (name/type/version/managedFolder/description) and CANCELS - a safe read-only listing of what this Autodesk account can reach. With name, selects that row and confirms. SAFETY: after linking, Fusion offers to force-update your library FROM the managed one; 'Replace Local Library' would destroy your parts, so this verb answers CANCEL by default - pass onUpdatePrompt to choose deliberately. A managed library owned by ANOTHER Autodesk account does NOT appear until its managed FOLDER is shared with this account on library.io; being in the same Fusion hub is not enough.",
"input": {
"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)"
},
"output": {
"alerts": "[...]",
"linkedTo": "str?",
"listedOnly": "bool?",
"managedLibraries": "[{name,type,version,managedFolder,description}]",
"success": "bool",
"updatePrompt": "obj?"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": true,
"timeoutSeconds": 180,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "managed_library_pull",
"tier": "platform",
"source": "proposed",
"summary": "Pull the newest version FROM library.io into the linked library in front. A pull ends in ONE of two CEF dialogs and BOTH block the add-in until answered: the force-update prompt when content differs (answered MERGE by default, since pull is an explicit request for the managed content - pass onUpdatePrompt:'replace' to overwrite local parts entirely, or 'cancel' to back out), or 'Up to Date' when already current. If neither appears, nothing was pulled and this reports failure rather than a false pass - Fusion greys Pull out on a library that was never linked.",
"input": {
"onUpdatePrompt": "optional str merge|replace|cancel (default merge)"
},
"output": {
"alerts": "[...]",
"library": "str",
"success": "bool",
"upToDate": "bool",
"updatePrompt": "obj?"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": true,
"timeoutSeconds": 240,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "managed_library_push",
"tier": "platform",
"source": "proposed",
"summary": "Push a NEW VERSION of the library in front up to its linked managed library on library.io. Clicking the menu item alone does NOT push: Fusion raises a CEF 'Create New Version' confirmation and THAT is what creates the version, so this verb completes it and fails with confirm_missing rather than reporting a false pass. On a library that is not linked yet, Fusion offers Create Managed Library instead and this reports not_linked_yet - use fusion_managed_library_create. NOTE: Library Manager keeps showing the IMPORTED version number after a push, so the row gains an update-available badge instead of incrementing.",
"input": {
"onConfirm": "optional str create|cancel (default create)"
},
"output": {
"alerts": "[...]",
"confirmed": "obj",
"library": "str",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": true,
"timeoutSeconds": 240,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "managed_library_unlink",
"tier": "platform",
"source": "proposed",
"summary": "Unlink the library in front from its managed library on library.io. Fusion greys this out on a library that was never linked, so a silent no-op there is expected.",
"input": {},
"output": {
"alerts": "[...]",
"library": "str",
"success": "bool"
},
"hint": "Fusion's cloud (the Autodesk hub, library.io), the counterpart of Altium 365's a365_* verbs.",
"pitfalls": [],
"related": [],
"example": {},
"longRunning": true,
"timeoutSeconds": 180,
"proposedBy": "fusion-lane",
"since": "0.31.0",
"agreedBy": [
"standard-lane"
]
},
{
"name": "outjob_info",
"tier": "platform",
"source": "altium",
"summary": "An OutJob's containers (output media), the outputs in each, and their key settings (units, decimals, plotted layer count), read from the .OutJob file: Altium need not be running.",
"input": {
"outjobPath": "path to the .OutJob (required)"
},
"output": {
"groups": "[{name, variant, containers: [{name, type, outputs}], outputs: [{type, name, document, enabled, inMedia, settings}]}]"
},
"hint": "Run a container with altium_run_outjob {outjobPath, projectPath, medium:'<container name>'}.",
"pitfalls": [
"Reads the saved file: an OutJob open in Altium with unsaved edits is read as saved."
],
"related": [
"run_outjob",
"export_manufacturing"
],
"example": {
"outjobPath": "C:/proj/board.OutJob"
},
"longRunning": false,
"timeoutSeconds": 30
},
{
"name": "run_outjob",
"tier": "platform",
"source": "altium",
"summary": "Run one output medium of an .OutJob (gerbers, drill, BOM, PDFs...) and list what it wrote under 'Project Outputs for <project>'.",
"input": {
"medium": "string, default 'Folder Structure' - the OutputMedium name inside the OutJob",
"objectKind": "string, default 'OutputBatch'",
"outjobPath": "path to an .OutJob (alias: filePath) - default: the bundled example Fabrication.OutJob",
"projectPath": "path to the .PrjPcb the OutJob belongs to; opened first",
"timeout": "seconds, default 300"
},
"output": {
"agent": "{outjob, medium, objectKind}",
"dialogs": "[..]",
"elapsedSec": "float",
"files": "[relative paths] up to 60",
"medium": "string",
"outjob": "path",
"outputDir": "path | null",
"windowEtiquette": "background"
},
"hint": "files[] is the proof. Pull what you need with ab's pull_file. OutJobs OPEN what they generate (CAMtastic, PDFs): altium_state afterwards and altium_close_document the viewers.",
"pitfalls": [
"Pass projectPath with your own OutJob: outputDir/files are looked up beside the PROJECT, and without it beside the OutJob.",
"medium must be the name of an output medium inside the OutJob. The agent cannot tell whether it ran: files[] is the only proof.",
"A dialog in dialogs[] means a medium needed a decision (printer, PDF path): read dialogs[].shot."
],
"related": [
"export_gerber",
"export_bom",
"export_step",
"check_dialogs"
],
"example": {
"medium": "Folder Structure",
"outjobPath": "C:/proj/Fabrication.OutJob",
"projectPath": "C:/proj/board.PrjPcb"
},
"longRunning": false,
"timeoutSeconds": 600
},
{
"name": "workspace_place",
"tier": "platform",
"source": "altium",
"summary": "Put a part from the Altium 365 workspace on a sheet: search, pick a result, place it (Altium's own placement, so the part keeps its workspace link, parameters and footprint), move it to x,y and name it.",
"input": {
"designator": "optional, else Altium's ('C?')",
"pick": "result index (0-based) or text its name contains; default the first",
"query": "the search (required; an MPN finds one part)",
"save": "bool, default true",
"sheet": "path to the .SchDoc (required)",
"x": "mils",
"y": "mils"
},
"output": {
"picked": "{name, description, footprint}",
"placed": "{designator, libReference, comment, itemGuid, sourceLibrary, xMil, yMil}"
},
"hint": "Then altium_annotate (for a '?'), altium_sch_connect, altium_update_pcb. A part from a local .SchLib goes on with altium_sch_place_part instead.",
"pitfalls": [
"Takes 15-70 s. Uses real clicks (double-click the result, click the sheet): Altium comes to the front.",
"The part lands near the view's lower-left corner first, then moves to x,y: wires do not follow, so connect it after."
],
"related": [
"workspace_search",
"sch_place_part",
"annotate",
"sch_connect",
"update_pcb"
],
"example": {
"query": "100nF 0402 50V",
"sheet": "C:/proj/Main.SchDoc",
"x": 3000,
"y": 2000
},
"longRunning": false,
"timeoutSeconds": 300,
"unitsNote": "The reference bridge answers this verb in mils (xMil). A bridge following the standard answers in mm under Mm names (xMm)."
},
{
"name": "workspace_search",
"tier": "platform",
"source": "altium",
"summary": "Search the Altium 365 workspace's components (the shared cloud library Altium is signed in to) through Altium's own Components panel: name, description and footprint per result.",
"input": {
"limit": "int, default 25",
"query": "text: an MPN, a value and package ('100nF 0402'), a part name (required)"
},
"output": {
"count": "int",
"results": "[{index, name, description, footprint}]"
},
"hint": "Then altium_workspace_place {sheet, query, pick} puts one on a sheet. Altium's 365 API is a closed beta; the signed-in Altium reaches the workspace itself (altium_signin_status).",
"pitfalls": [
"Takes 5-40 s (Altium's WPF panel answers UI Automation slowly; slower when the panel must first be opened).",
"It types into the panel's search box: Altium comes to the front."
],
"related": [
"workspace_place",
"signin_status",
"bom"
],
"example": {
"query": "100nF 0402"
},
"longRunning": false,
"timeoutSeconds": 180
}
]
}