app
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 + footprint + 3D + pin↔pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.
← Commit history
Publish 1.7.0
8 files changed
+119−18
Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "adom-lbr"-version = "1.6.2"+version = "1.7.0" dependencies = [ "anyhow", "clap",
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-lbr"-version = "1.6.2"+version = "1.7.0" edition = "2021" description = "EAGLE .lbr generator, linter, and validator for Fusion 360 Electronics. Converts KiCad symbols + footprints to complete EAGLE libraries."
SKILL.md+7−3@@ -106,9 +106,13 @@ the real footprint, and the chip outline are identical across them: - **OrCAD** — shells the **adom-orcad** converter to emit EDIF 2.0.0 (`.edn`), which Capture imports to a native `.olb`. If adom-orcad isn't installed it writes an `ORCAD-README.md` with the exact command instead of failing.-- **Altium** — the `.lbr` (Altium's Import Wizard reads EAGLE directly) **plus**- the staged KiCad sources + `ALTIUM-README.md` for the **Altium bridge**, which- drives a real Altium to native `.SchLib/.PcbLib` (Altium has no headless mode).+- **Altium** — a bridge-ready import package: **`<part>.altium.json`** (manifest,+ schema `adom-lbr.altium/1` — part, BOM part numbers incl. `LCSC Part #`, staged+ sources, target `.SchLib/.PcbLib`, mode) — the Altium analog of `fusion3d.json`.+ The orchestrating AI hands it to the **Altium bridge** (`adom/adom-desktop-altium-bridge`+ / `altium-part-importer`) on the Altium machine to build native libraries.+ `--altium-lib <base>` / `--altium-mode create|append|reuse` set the target. The+ staged `.lbr` is also Altium-Import-Wizard-ready as a no-tooling fallback. `--targets` limits the set (e.g. `--targets kicad,fusion`). This is still a pure exporter: it writes files and hands off; the orchestrating AI does any
VERSION+1−1@@ -1 +1 @@-1.6.2+1.7.0
bin/adom-lbr⋯ 1 unchanged line ⋯
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-lbr",- "version": "1.6.2",+ "version": "1.7.0", "type": "app", "description": "One KiCad part \u2192 every major EDA tool. `adom-lbr export` writes a folder per tool: native KiCad, Fusion 360 (.lbr + 3D handoff), OrCAD (EDIF via adom-orcad), and an Altium bridge hand-off \u2014 real-footprint accurate. Bidirectional KiCad converter + 8-check linter + a live library viewer. Includes a focused fusion-export sub-skill.", "dependencies": {},
page.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-lbr",- "version": "1.6.2",+ "version": "1.7.0", "type": "app", "description": "One KiCad part → every major EDA tool. `adom-lbr export` writes a folder per tool: native KiCad, Fusion 360 (.lbr + 3D handoff), OrCAD (EDIF via adom-orcad), and an Altium bridge hand-off — real-footprint accurate. Bidirectional KiCad converter + 8-check linter + a live library viewer. Includes a focused fusion-export sub-skill.", "dependencies": {},
src/main.rs+107−10@@ -179,6 +179,14 @@ enum Commands { /// Any of: kicad,fusion,orcad,altium #[arg(long)] targets: Option<String>,+ /// Altium destination library base name → `<base>.SchLib`/`<base>.PcbLib`+ /// in the Altium import manifest (the bridge surveys existing libs if omitted).+ #[arg(long)]+ altium_lib: Option<String>,+ /// Altium import mode hint for the bridge: create | append | reuse+ /// (default: survey — let the importer `--list-libs` and decide).+ #[arg(long)]+ altium_mode: Option<String>, }, /// Export a Fusion-style 3-column INTERACTIVE HTML package — symbol | footprint /// | 3D, each pan/zoomable, with a pin→pad mapping table carrying the datasheet@@ -1806,6 +1814,8 @@ fn run_export( mouser: Option<String>, digikey: Option<String>, lcsc: Option<String>,+ altium_lib: Option<String>,+ altium_mode: Option<String>, ) { use std::process::Command; @@ -1958,14 +1968,23 @@ fn run_export( if let Some(fc) = &fp_content { let _ = fs::write(adir.join(format!("{part}.kicad_mod")), fc); }+ let mut model_ext: Option<String> = None; if let Some(mp) = &model { if let Ok(b) = fs::read(mp) {- let ext = mp.extension().and_then(|e| e.to_str()).unwrap_or("step");+ let ext = mp.extension().and_then(|e| e.to_str()).unwrap_or("step").to_string(); let _ = fs::write(adir.join(format!("{part}.{ext}")), b);+ model_ext = Some(ext); } }+ // The bridge-ready import manifest (the Altium analog of fusion3d.json).+ let _ = write_altium_manifest(+ &adir.join(format!("{part}.altium.json")),+ &part, &parsed.description, &attrs,+ fp_content.is_some(), model_ext.as_deref(),+ altium_lib.as_deref(), altium_mode.as_deref(),+ ); let _ = fs::write(adir.join("ALTIUM-README.md"), altium_readme(&part, fp_content.is_some(), model.is_some()));- status.push(("Altium".into(), "ok".into(), format!("{part}.lbr (direct import) + sources + ALTIUM-README.md")));+ status.push(("Altium".into(), "ok".into(), format!("{part}.altium.json (bridge manifest) + {part}.lbr (direct import) + sources"))); } // ── index + summary ──@@ -1989,13 +2008,89 @@ fn run_export( } } +// The Altium import manifest — the Altium analog of fusion3d.json. adom-lbr is a+// pure exporter, so it can't write binary .SchLib/.PcbLib itself; instead it+// emits this machine-readable package describing the part + BOM + target library+// so the **altium bridge** (altium-part-importer / adom-desktop-altium-bridge,+// on the machine running Altium) can drive Altium to create native libraries.+#[allow(clippy::too_many_arguments)]+fn write_altium_manifest(+ path: &std::path::Path,+ part: &str,+ desc: &str,+ attrs: &PartAttrs,+ has_fp: bool,+ model_ext: Option<&str>,+ lib: Option<&str>,+ mode: Option<&str>,+) -> std::io::Result<()> {+ // BOM parameters under Altium's own field names; the importer keys off+ // "LCSC Part #" so JLCPCB BOM + pick-and-place exports carry it.+ let mut params = serde_json::Map::new();+ let mut put = |k: &str, v: &Option<String>| {+ if let Some(s) = v { if !s.trim().is_empty() {+ params.insert(k.to_string(), serde_json::Value::String(s.trim().to_string()));+ } }+ };+ put("Manufacturer", &attrs.mfr);+ put("Manufacturer Part Number", &attrs.mpn);+ put("Mouser Part Number", &attrs.mouser);+ put("Digi-Key Part Number", &attrs.digikey);+ put("LCSC Part #", &attrs.lcsc);++ let model = model_ext.map(|e| serde_json::json!(format!("{part}.{e}"))).unwrap_or(serde_json::Value::Null);+ let footprint = if has_fp { serde_json::json!(format!("{part}.kicad_mod")) } else { serde_json::Value::Null };+ let (schlib, pcblib) = match lib {+ Some(b) => (+ serde_json::json!(format!("{b}.SchLib")),+ if has_fp { serde_json::json!(format!("{b}.PcbLib")) } else { serde_json::Value::Null },+ ),+ None => (serde_json::Value::Null, serde_json::Value::Null),+ };++ let manifest = serde_json::json!({+ "schema": "adom-lbr.altium/1",+ "generated_by": format!("adom-lbr {}", VERSION.trim()),+ "part": { "name": part, "value": part, "description": desc },+ // Everything the bridge needs as input — all relative to this manifest's dir.+ "sources": {+ "symbol_kicad_sym": format!("{part}.kicad_sym"),+ "footprint_kicad_mod": footprint,+ "eagle_lbr": format!("{part}.lbr"),+ "model_3d": model+ },+ "parameters": serde_json::Value::Object(params),+ "target": {+ "schlib": schlib,+ "pcblib": pcblib,+ "intlib": serde_json::Value::Null,+ "mode": mode.unwrap_or("survey")+ },+ "import": {+ "preferred": "bridge",+ "bridge": {+ "importer_skill": "barrett-land/altium-part-importer",+ "desktop_bridge": "adom/adom-desktop-altium-bridge",+ "verb_prefix": "altium_",+ "note": "Run on the machine with Altium + Adom Desktop. The importer surveys existing libraries (--list-libs) before creating, attaches the LCSC Part #, and builds symbol + footprint (+3D) natively."+ },+ "fallback_import_wizard": format!("Altium ▸ File ▸ Import Wizard ▸ EAGLE Projects and Libraries ▸ {part}.lbr")+ },+ "status": "pending-altium-bridge"+ });+ std::fs::write(path, serde_json::to_string_pretty(&manifest)?)+}+ fn altium_readme(part: &str, has_fp: bool, has_model: bool) -> String { let mut s = String::new();- s.push_str(&format!("# {part} → Altium\n\nTwo paths — pick one.\n\n"));- s.push_str("## 1. Direct (nothing else needed)\n\n");- s.push_str(&format!("Altium imports EAGLE libraries: **File ▸ Import Wizard ▸ EAGLE Projects and Libraries** ▸ select `{part}.lbr`. You get a schematic symbol + PCB footprint in an integrated library.\n\n"));- s.push_str("## 2. Native .SchLib / .PcbLib (Altium bridge)\n\n");- s.push_str("adom-lbr is a pure exporter — it does **not** drive Altium. For true native\nAltium libraries, the orchestrating AI runs the **Altium bridge** on the machine\nrunning Altium + Adom Desktop (Altium has no headless mode, so the bridge drives\na real Altium via DelphiScript). The KiCad sources are staged here for it:\n\n");+ s.push_str(&format!("# {part} → Altium\n\n"));+ s.push_str(&format!("**Primary input: `{part}.altium.json`** — a machine-readable import manifest\n(schema `adom-lbr.altium/1`) describing the part, its BOM part numbers, the staged\nsources, and the target library. Hand it to the Altium bridge (path 1). It's the\nAltium analog of the Fusion `fusion3d.json` sidecar.\n\nTwo paths to get a library:\n\n"));+ s.push_str("## 1. Native .SchLib / .PcbLib (Altium bridge) — recommended\n\n");+ s.push_str(&format!("adom-lbr is a pure exporter — it does **not** drive Altium. The orchestrating AI\nfeeds `{part}.altium.json` to the **Altium bridge** on the machine running Altium\n+ Adom Desktop (Altium has no headless mode, so the bridge drives a real Altium\nvia DelphiScript). The manifest points at the staged sources:\n\n"));+ s.push_str(&format!("- `{part}.kicad_sym` — schematic symbol\n"));+ if has_fp { s.push_str(&format!("- `{part}.kicad_mod` — PCB footprint\n")); }+ if has_model { s.push_str("- the 3D model (`*.step` / `*.glb`) — 3D body\n"); }+ s.push_str("\nThe shipped tools that consume it (install on the Altium machine):\n\n"); s.push_str(&format!("- `{part}.kicad_sym` — schematic symbol\n")); if has_fp { s.push_str(&format!("- `{part}.kicad_mod` — PCB footprint\n")); } if has_model { s.push_str("- the 3D model (`*.step` / `*.glb`) — 3D body\n"); }@@ -2003,6 +2098,8 @@ fn altium_readme(part: &str, has_fp: bool, has_model: bool) -> String { s.push_str("- **`adom/adom-desktop-altium-bridge`** — the Adom Desktop bridge that drives\n Altium via DelphiScript to add symbols + footprints (with 3D) to a file-based\n library:\n ```\n adompkg install adom/adom-desktop-altium-bridge\n ```\n"); s.push_str("- **`altium-part-importer`** — adds a catalog part to an Altium library;\n CREATE a new `.IntLib`, APPEND to an existing one, or REUSE existing symbols:\n ```\n adompkg install altium-part-importer\n ```\n"); s.push_str("- **`adom/adom-altium-library-importer`** — one-command install of pre-converted\n `.SchLib` + `.PcbLib` (with linked 3D) into Altium.\n\n");+ s.push_str("## 2. Direct (nothing else needed)\n\n");+ s.push_str(&format!("No bridge handy? Altium imports EAGLE libraries directly: **File ▸ Import Wizard\n▸ EAGLE Projects and Libraries** ▸ select `{part}.lbr`. You get a schematic symbol\n+ PCB footprint. (The Import Wizard may re-place the designator at its default —\nthe bridge path preserves the exact placement.)\n\n")); s.push_str("## Reverse (Altium → KiCad)\n\n"); s.push_str("Already have an Altium library? Convert it natively (no Altium, no KiCad install):\n\n"); s.push_str("```\nadompkg install adom/adom-sfconvert # .SchLib/.PcbLib/.IntLib → .kicad_sym/.kicad_mod\n# parsers: adom/adom-altium-schlib (symbols), adom/altium-pcblib (footprints)\n```\n");@@ -2023,7 +2120,7 @@ fn export_index(part: &str, status: &[(String, String, String)], has_fp: bool, h let fnote = if has_model { " Then the bridge attaches the 3D body (Create3DPackage → FINISH → Save)." } else { "" }; s.push_str(&format!("| **Fusion 360** | `fusion/{part}.lbr`{fsc} | Open the `.lbr` as an Electronics library.{fnote} |\n")); s.push_str(&format!("| **OrCAD** | `orcad/{part}.edn` | Capture ▸ Accessories/Import ▸ EDIF 2.0.0 ▸ select the `.edn` → native `.olb`. (Falls back to a README if adom-orcad isn't installed.) |\n"));- s.push_str(&format!("| **Altium** | `altium/{part}.lbr` + sources | Direct: Import Wizard (EAGLE). Native `.SchLib/.PcbLib`: see `altium/ALTIUM-README.md`. |\n\n"));+ s.push_str(&format!("| **Altium** | `altium/{part}.altium.json` + `.lbr` + sources | Hand `{part}.altium.json` (bridge manifest) to the Altium bridge for native `.SchLib/.PcbLib`; or Import Wizard the `.lbr` directly. See `altium/ALTIUM-README.md`. |\n\n")); let _ = status; s.push_str("adom-lbr is a pure exporter: it writes these files and hands off. The orchestrating AI does any app-driving (Fusion bridge, Altium bridge).\n"); s@@ -2155,8 +2252,8 @@ fn main() { } } - Commands::Export { sym, fp, model, symbol_art, symbol_art_scale, name, out, targets, mfr, mpn, mouser, digikey, lcsc } => {- run_export(sym, fp, model, symbol_art, symbol_art_scale, name, out, targets, mfr, mpn, mouser, digikey, lcsc);+ Commands::Export { sym, fp, model, symbol_art, symbol_art_scale, name, out, targets, mfr, mpn, mouser, digikey, lcsc, altium_lib, altium_mode } => {+ run_export(sym, fp, model, symbol_art, symbol_art_scale, name, out, targets, mfr, mpn, mouser, digikey, lcsc, altium_lib, altium_mode); } Commands::Bind3d { lbr, wip_urn, urn, lineage_urn, record_only, package, output, sidecar } => {