Adom Library
Public Made by Adomby adom
adom-lbr — the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad ⇄ Altium ⇄ EAGLE/Fusion) through one canonical adom-lbr JSON — symbol + footp
Fusion 360 library export (and Altium / OrCAD)
Sub-page of adom-lbr. adom-lbr exports to four ECAD tools from one source; this page is the deep dive on the EAGLE
.lbrpath — the one Fusion 360, Altium, and OrCAD all import — including the part most generators get wrong (the real footprint) and the part they skip entirely (the 3D model).
Why one .lbr covers three tools
Fusion 360 Electronics is the modern face of EAGLE, and the EAGLE .lbr
library format is read natively by Fusion 360, Altium Designer, and OrCAD.
So adom-lbr generates the .lbr once and all three import it. KiCad is the
exception — it doesn't read .lbr, so adom-lbr converts to .kicad_sym via
import.
A complete .lbr deviceset has three linked parts:
<symbol> schematic pins + body (layer 94)
<package> the real footprint: <smd>/<pad> + silkscreen outline
<deviceset><device package="…"><connects> pin-name → pad-number map
Miss any one and Fusion shows "No Components." adom-lbr's linter exists to catch exactly that.
The footprint must be real
The single most important flag is --fp. It points at the KiCad
.kicad_mod so the package is built from true pad geometry instead of a
placeholder.
adom-lbr generate --sym ADS8588SIPM.kicad_sym --fp ADS8588SIPM.kicad_mod -o ADS8588SIPM.lbr
What the writer does with each .kicad_mod pad:
KiCad (.kicad_mod, mm, Y-down) |
EAGLE (.lbr, mm, Y-up) |
|---|---|
(pad "17" smd rect (at -3.75 5.738 90) (size 1.475 0.3)) |
<smd name="17" x="-3.75" y="-5.738" dx="1.475" dy="0.3" layer="1" rot="R90"/> |
thru-hole (pad … (at x y) (size …) (drill d)) |
<pad … x drill diameter shape="long"/> |
- Y is negated (KiCad Y-down → EAGLE Y-up).
- Rotation maps the KiCad angle straight to
rot=R90/R180/R270, matching Fusion's own library-export convention (verified by the Fusion bridge against a round-tripped.flbr): a KiCad-90 pad on a QFP/SOIC top/bottom side becomesrot="R90", oriented along the lead. - Silkscreen outline is derived from the footprint body —
F.SilkSlines first, thenF.Fab, then a fallback bounding box of the pads. Eachfp_lineis matched to its own layer (a balanced s-expression parse), so courtyard and body lines never bleed together.
Worked example — ADS8588SIPM (LQFP-64)
| Before (placeholder) | After (--fp) |
|
|---|---|---|
| Pads | 32 at x=−8, 32 at x=+8 (2 columns) | 16 left / 16 right / 16 top / 16 bottom |
| Extent | y only, ±7.5 | X and Y, ±5.74 mm |
| Shape in Fusion | a domino, not the chip | true 4-sided LQFP-64 |

Without --fp you still get a valid .lbr — just a two-column placeholder
package. That's intentional for symbol-only parts. For anything you'll fabricate,
pass --fp.
The 3D model: a Fusion-side attach (not a flat-file write)
This is the part that can't be baked into a flat file. In EAGLE/Fusion a
package's 3D body is not embedded — it's a cloud reference, and the model
only renders once Fusion brings it into a session. So adom-lbr keeps the
.lbr 2D and the Fusion bridge does the attach; the sidecar just points the
bridge at the model and the package.
Verified by the Fusion bridge (round-tripping a bound
.flbrand reading the EAGLE XML). The earlier assumption that Fusion mints anurn:adsk.eagle:package:NNN/Vwas wrong for self-uploaded models — that form is for managed (library.io) parts only.
The real markup — self-uploaded model
A model you upload yourself is linked by wip_urn (the versioned file URN),
with urn left empty and locally_modified="yes":
<packages3d>
<package3d name="ADS8588SIPM" urn="" wip_urn="urn:adsk.wipprod:fs.file:vf.<id>?version=1"
locally_modified="yes" type="model">
<packageinstances><packageinstance name="ADS8588SIPM"/></packageinstances>
</package3d>
</packages3d>
…
<device name="" package="ADS8588SIPM">
<connects>…</connects>
<package3dinstances><package3dinstance package3d_urn="urn:adsk.wipprod:fs.file:vf.<id>?version=1"/></package3dinstances>
<technologies><technology name=""/></technologies>
</device>
Use the ?version=1 file URN (fs.file:vf), not the dm.lineage URN
that an upload returns first. (urn:adsk.eagle:package:NNN/V is managed-only.)
Step 1 — generate the .lbr + a 3D sidecar
adom-lbr generate --sym part.kicad_sym --fp part.kicad_mod --model part.step -o part.lbr
# → part.lbr (2D: symbol + real footprint)
# → part.fusion3d.json (the handoff manifest)
The sidecar (schema: "adom-lbr.fusion3d/2") carries no pre-minted URN — it just
names model.path, package, and the placement:
{
"schema": "adom-lbr.fusion3d/2",
"package": "ADS8588SIPM",
"model": { "path": "part.step", "format": "step", "units": "mm" },
"placement": { "translation_mm": [0,0,0], "rotation_deg": [0,0,0], "note": "…run chipfit before FINISH" },
"binding": { "scheme": "self-hosted", "wip_urn": null, "package3d_attrs": { "urn": "", "wip_urn": "<…vf…?version=1>", "locally_modified": "yes", "type": "model" } },
"status": "pending-fusion-attach",
"bridge_steps": [ "open .lbr (library ACTIVE)", "Create3DPackage → import model → orient → FINISH → Save", "…" ]
}
Step 2 — the bridge attaches the model (this both binds AND renders)
The Fusion bridge: opens the .lbr (library active) → Electron.Create3DPackage
→ imports model.path → auto-orients (your placement is an override for its
"rotate smallest bbox dim to Z" default) → Package3DStop (FINISH) → Save.
The Content Manager tree then shows the 3D nested under the package. (Run
chipfit before FINISH to confirm pin-1 / seat-Z.)
This is the whole job for the normal case — the FINISH step is what makes the body actually render. The in-Fusion library is the runtime source of truth.
Step 3 — record the URN back (provenance)
After Save, the bridge reports the saved version's URN —
fusion_aps_file_info {query:"<package>"} returns the tip
fs.file:vf.<id>?version=N. adom-lbr owns the sidecar record and writes it:
adom-lbr bind-3d --record-only --sidecar part.fusion3d.json \
--wip-urn "urn:adsk.wipprod:fs.file:vf.<id>?version=N" \
--lineage-urn "urn:adsk.wipprod:dm.lineage:<id>" # optional provenance
--record-only writes binding.wip_urn + status: "bound" (and the optional
lineage_urn) without touching the .lbr — bookkeeping for idempotency and
provenance. dm.lineage is kept here only as the stable cross-version id; it is
never written into the .lbr (Fusion pins the versioned fs.file URN).
Optional — pre-write the binding into the .lbr (fast-path)
Once recorded/known-synced, you can bake the binding into the .lbr for a
self-contained library:
adom-lbr bind-3d --lbr part.lbr \
--wip-urn "urn:adsk.wipprod:fs.file:vf.<id>?version=N" --sidecar part.fusion3d.json
# managed/library.io part instead? --urn "urn:adsk.eagle:package:NNN/V"
bind-3d inserts the <packages3d> block + the device <package3dinstance>,
re-lints, and updates the sidecar. It's idempotent, and refuses a dm.lineage
URN for the .lbr. Caveat: a pre-written wip_urn shows a gray placeholder
on a cold open — Fusion renders the body only once the model is brought into a
session via FINISH. So this is for known-synced models, not a substitute for the
bridge attach.
End-to-end
# 1. Generate the 2D .lbr + sidecar from the KiCad part + STEP
adom-lbr generate --sym part.kicad_sym --fp part.kicad_mod --model part.step -o part.lbr
# 2. Hand part.lbr + part.fusion3d.json + the STEP to the Fusion bridge.
# It does Create3DPackage → import → orient → FINISH → Save (binds + renders).
# 3. Record the URN the bridge reports (fusion_aps_file_info) back into the sidecar:
adom-lbr bind-3d --record-only --sidecar part.fusion3d.json --wip-urn "urn:adsk.wipprod:fs.file:vf.<id>?version=N"
# 4. (Optional) bake the binding into the .lbr for a self-contained library:
adom-lbr bind-3d --lbr part.lbr --wip-urn "urn:adsk.wipprod:fs.file:vf.<id>?version=N" --sidecar part.fusion3d.json
# 5. Verify the 2D library
adom-lbr validate part.lbr # complete deviceset, 0 errors
Altium / OrCAD
Both import the same EAGLE .lbr directly — no separate generate step. A desktop
bridge for automated "Send to Altium/OrCAD" isn't built yet; until then, hand
the .lbr over and import it manually. Want that bridge? Build it and contribute
it on the wiki — adom-lbr's "Send to" already routes those targets.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Footprint is two columns / a domino | generated without --fp |
regenerate with --fp part.kicad_mod |
| Fusion: "No Components" | empty <packages> or <connects> |
adom-lbr lint — fix the reported code |
| 3D body is a gray placeholder | binding pre-written but model not in session | let the bridge attach it (Create3DPackage → FINISH); that renders it |
| 3D body offset / wrong pin 1 | placement not aligned | run chipfit, set placement in the sidecar before FINISH |
bind-3d rejected the URN |
wrong URN family | self-uploaded → --wip-urn (fs.file:vf …?version=1); managed → --urn (eagle:package) |
| Outline looks lopsided | (fixed in 1.1) | upgrade — silk lines are now matched per-layer |
# Fusion 360 library export (and Altium / OrCAD)
> Sub-page of [adom-lbr](../README.md). adom-lbr exports to four ECAD tools from
> one source; this page is the deep dive on the **EAGLE `.lbr`** path — the one
> Fusion 360, Altium, and OrCAD all import — including the part most generators
> get wrong (the real footprint) and the part they skip entirely (the 3D model).
## Why one `.lbr` covers three tools
Fusion 360 Electronics is the modern face of EAGLE, and the EAGLE `.lbr`
library format is read natively by **Fusion 360, Altium Designer, and OrCAD**.
So adom-lbr generates the `.lbr` once and all three import it. KiCad is the
exception — it doesn't read `.lbr`, so adom-lbr converts to `.kicad_sym` via
`import`.
A complete `.lbr` deviceset has three linked parts:
```
<symbol> schematic pins + body (layer 94)
<package> the real footprint: <smd>/<pad> + silkscreen outline
<deviceset><device package="…"><connects> pin-name → pad-number map
```
Miss any one and Fusion shows **"No Components."** adom-lbr's linter exists to
catch exactly that.
## The footprint must be real
The single most important flag is **`--fp`**. It points at the KiCad
`.kicad_mod` so the package is built from true pad geometry instead of a
placeholder.
```bash
adom-lbr generate --sym ADS8588SIPM.kicad_sym --fp ADS8588SIPM.kicad_mod -o ADS8588SIPM.lbr
```
What the writer does with each `.kicad_mod` pad:
| KiCad (`.kicad_mod`, mm, Y-down) | EAGLE (`.lbr`, mm, Y-up) |
|---|---|
| `(pad "17" smd rect (at -3.75 5.738 90) (size 1.475 0.3))` | `<smd name="17" x="-3.75" y="-5.738" dx="1.475" dy="0.3" layer="1" rot="R90"/>` |
| thru-hole `(pad … (at x y) (size …) (drill d))` | `<pad … x drill diameter shape="long"/>` |
- **Y is negated** (KiCad Y-down → EAGLE Y-up).
- **Rotation** maps the KiCad angle straight to `rot=R90/R180/R270`, matching
Fusion's own library-export convention (verified by the Fusion bridge against a
round-tripped `.flbr`): a KiCad-90 pad on a QFP/SOIC top/bottom side becomes
`rot="R90"`, oriented along the lead.
- **Silkscreen outline** is derived from the footprint body — `F.SilkS` lines
first, then `F.Fab`, then a fallback bounding box of the pads. Each `fp_line`
is matched to its *own* layer (a balanced s-expression parse), so courtyard
and body lines never bleed together.
### Worked example — ADS8588SIPM (LQFP-64)
| | Before (placeholder) | After (`--fp`) |
|---|---|---|
| Pads | 32 at x=−8, 32 at x=+8 (2 columns) | 16 left / 16 right / 16 top / 16 bottom |
| Extent | y only, ±7.5 | X **and** Y, ±5.74 mm |
| Shape in Fusion | a domino, not the chip | true 4-sided LQFP-64 |

Without `--fp` you still get a *valid* `.lbr` — just a two-column placeholder
package. That's intentional for symbol-only parts. For anything you'll fabricate,
pass `--fp`.
## The 3D model: a Fusion-side attach (not a flat-file write)
This is the part that can't be baked into a flat file. In EAGLE/Fusion a
package's 3D body is **not embedded** — it's a cloud reference, and the model
only **renders once Fusion brings it into a session**. So adom-lbr keeps the
`.lbr` 2D and the **Fusion bridge does the attach**; the sidecar just points the
bridge at the model and the package.
> **Verified by the Fusion bridge** (round-tripping a bound `.flbr` and reading
> the EAGLE XML). The earlier assumption that Fusion mints an
> `urn:adsk.eagle:package:NNN/V` was **wrong for self-uploaded models** — that
> form is for *managed* (library.io) parts only.
### The real markup — self-uploaded model
A model you upload yourself is linked by **`wip_urn`** (the *versioned file* URN),
with `urn` left **empty** and `locally_modified="yes"`:
```xml
<packages3d>
<package3d name="ADS8588SIPM" urn="" wip_urn="urn:adsk.wipprod:fs.file:vf.<id>?version=1"
locally_modified="yes" type="model">
<packageinstances><packageinstance name="ADS8588SIPM"/></packageinstances>
</package3d>
</packages3d>
…
<device name="" package="ADS8588SIPM">
<connects>…</connects>
<package3dinstances><package3dinstance package3d_urn="urn:adsk.wipprod:fs.file:vf.<id>?version=1"/></package3dinstances>
<technologies><technology name=""/></technologies>
</device>
```
Use the `?version=1` **file** URN (`fs.file:vf`), **not** the `dm.lineage` URN
that an upload returns first. (`urn:adsk.eagle:package:NNN/V` is managed-only.)
### Step 1 — generate the `.lbr` + a 3D sidecar
```bash
adom-lbr generate --sym part.kicad_sym --fp part.kicad_mod --model part.step -o part.lbr
# → part.lbr (2D: symbol + real footprint)
# → part.fusion3d.json (the handoff manifest)
```
The sidecar (`schema: "adom-lbr.fusion3d/2"`) carries no pre-minted URN — it just
names `model.path`, `package`, and the placement:
```json
{
"schema": "adom-lbr.fusion3d/2",
"package": "ADS8588SIPM",
"model": { "path": "part.step", "format": "step", "units": "mm" },
"placement": { "translation_mm": [0,0,0], "rotation_deg": [0,0,0], "note": "…run chipfit before FINISH" },
"binding": { "scheme": "self-hosted", "wip_urn": null, "package3d_attrs": { "urn": "", "wip_urn": "<…vf…?version=1>", "locally_modified": "yes", "type": "model" } },
"status": "pending-fusion-attach",
"bridge_steps": [ "open .lbr (library ACTIVE)", "Create3DPackage → import model → orient → FINISH → Save", "…" ]
}
```
### Step 2 — the bridge attaches the model (this both binds AND renders)
The Fusion bridge: opens the `.lbr` (library **active**) → `Electron.Create3DPackage`
→ imports `model.path` → auto-orients (your `placement` is an **override** for its
"rotate smallest bbox dim to Z" default) → `Package3DStop` (**FINISH**) → **Save**.
The Content Manager tree then shows the 3D nested under the package. (Run
[chipfit](../../adom-chipfit) before FINISH to confirm pin-1 / seat-Z.)
This is the whole job for the normal case — the FINISH step is what makes the body
actually render. The **in-Fusion library is the runtime source of truth.**
### Step 3 — record the URN back (provenance)
After Save, the bridge reports the saved version's URN —
`fusion_aps_file_info {query:"<package>"}` returns the tip
`fs.file:vf.<id>?version=N`. adom-lbr **owns the sidecar record** and writes it:
```bash
adom-lbr bind-3d --record-only --sidecar part.fusion3d.json \
--wip-urn "urn:adsk.wipprod:fs.file:vf.<id>?version=N" \
--lineage-urn "urn:adsk.wipprod:dm.lineage:<id>" # optional provenance
```
`--record-only` writes `binding.wip_urn` + `status: "bound"` (and the optional
`lineage_urn`) **without touching the `.lbr`** — bookkeeping for idempotency and
provenance. `dm.lineage` is kept here only as the stable cross-version id; it is
**never** written into the `.lbr` (Fusion pins the versioned `fs.file` URN).
### Optional — pre-write the binding into the `.lbr` (fast-path)
Once recorded/known-synced, you can bake the binding into the `.lbr` for a
self-contained library:
```bash
adom-lbr bind-3d --lbr part.lbr \
--wip-urn "urn:adsk.wipprod:fs.file:vf.<id>?version=N" --sidecar part.fusion3d.json
# managed/library.io part instead? --urn "urn:adsk.eagle:package:NNN/V"
```
`bind-3d` inserts the `<packages3d>` block + the device `<package3dinstance>`,
re-lints, and updates the sidecar. It's **idempotent**, and refuses a `dm.lineage`
URN for the `.lbr`. **Caveat:** a pre-written `wip_urn` shows a **gray placeholder**
on a cold open — Fusion renders the body only once the model is brought into a
session via FINISH. So this is for known-synced models, not a substitute for the
bridge attach.
## End-to-end
```bash
# 1. Generate the 2D .lbr + sidecar from the KiCad part + STEP
adom-lbr generate --sym part.kicad_sym --fp part.kicad_mod --model part.step -o part.lbr
# 2. Hand part.lbr + part.fusion3d.json + the STEP to the Fusion bridge.
# It does Create3DPackage → import → orient → FINISH → Save (binds + renders).
# 3. Record the URN the bridge reports (fusion_aps_file_info) back into the sidecar:
adom-lbr bind-3d --record-only --sidecar part.fusion3d.json --wip-urn "urn:adsk.wipprod:fs.file:vf.<id>?version=N"
# 4. (Optional) bake the binding into the .lbr for a self-contained library:
adom-lbr bind-3d --lbr part.lbr --wip-urn "urn:adsk.wipprod:fs.file:vf.<id>?version=N" --sidecar part.fusion3d.json
# 5. Verify the 2D library
adom-lbr validate part.lbr # complete deviceset, 0 errors
```
## Altium / OrCAD
Both import the same EAGLE `.lbr` directly — no separate generate step. A desktop
**bridge** for automated "Send to Altium/OrCAD" isn't built yet; until then, hand
the `.lbr` over and import it manually. Want that bridge? Build it and contribute
it on the wiki — adom-lbr's "Send to" already routes those targets.
## Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Footprint is two columns / a domino | generated without `--fp` | regenerate with `--fp part.kicad_mod` |
| Fusion: "No Components" | empty `<packages>` or `<connects>` | `adom-lbr lint` — fix the reported code |
| 3D body is a gray placeholder | binding pre-written but model not in session | let the bridge attach it (Create3DPackage → FINISH); that renders it |
| 3D body offset / wrong pin 1 | placement not aligned | run chipfit, set `placement` in the sidecar before FINISH |
| `bind-3d` rejected the URN | wrong URN family | self-uploaded → `--wip-urn` (`fs.file:vf …?version=1`); managed → `--urn` (`eagle:package`) |
| Outline looks lopsided | (fixed in 1.1) | upgrade — silk lines are now matched per-layer |