npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@labwired/kicad-monkey

v0.3.1

Published

KiCad schematic netlists, design facts, sheet plots and UUID-keyed property writes from kicad_monkey, compiled to WebAssembly, for Node and browsers.

Readme

@labwired/kicad-monkey

KiCad schematic netlists and design facts, computed by kicad_monkey compiled to WebAssembly. Runs in Node and in browsers, with no KiCad install.

This is a packaging of Wavenumber's engine, not the upstream project. See NOTICE.

Node

import { loadNode } from "@labwired/kicad-monkey/node";

const engine = await loadNode(); // uses the .wasm shipped in this package
const netlist = engine.netlist({
  root: "board.kicad_sch",
  files: [
    { path: "board.kicad_sch", text: boardText },
    { path: "power.kicad_sch", text: powerText },
  ],
});

Load once and reuse the engine. Every loadNode() call creates an independent engine whose memory stays allocated for the life of the process, so call it again only to replace a poisoned engine.

If you bundle your code, mark this package external: the loader finds its .wasm relative to its own module.

Browser

import { loadBrowser } from "@labwired/kicad-monkey/browser";

const engine = await loadBrowser(); // fetches the .wasm next to the module
// loadBrowser(wasmUrl) when your bundler relocates assets

There is one engine per page. Initialisation is async so compiling doesn't block the main thread.

Input

files holds every file the design references: the root, its sub-sheets, and optionally the .kicad_pro. Each file's kind is inferred from its name. The .kicad_pro whose name matches the root becomes the project. Without one, connectivity is the same, but net_classes is empty.

Output

netlist() returns a parsed kicad_monkey.netlist.a0 object. The schema is checked before it is returned.

  • Nets carry a stable uid, terminals with pin_type, and graphical.wires.
  • Components carry parameters.kicad_instance_uuid.
  • Treat all UUIDs as opaque strings. Older KiCad files use ids that aren't RFC-4122, and a wire can have an empty one. Never join on an empty UUID.

Plotting a sheet

const plot = engine.plotSheet(sheetText, { sheet_index: 1, sheet_count: 3 });
// plot.schema === "kicad.plotter_ir.a0"; coordinates in nm, y down

One sheet per call. Records carry the item's KiCad UUID: a wire record's uuid is what the netlist lists under net.graphical.wires, so a viewer maps nets onto drawn wires by lookup. Text comes out as text operations; the plotter still needs real glyph metrics to place symbol fields, so a font is required. In Node the bundled KiCad stroke face (fonts/kicad-stroke.ttf, CC0) is used. In a browser fetch it once and pass it:

import { loadBrowser, fetchStrokeFont } from "@labwired/kicad-monkey/browser";
const [engine, font] = await Promise.all([loadBrowser(), fetchStrokeFont()]);
const plot = engine.plotSheet(sheetText, { font });

Writing properties

writeProperties(bundle, edits) sets symbol fields, keyed by the kicad_instance_uuid the netlist reported, and returns every file of the bundle rewritten plus the list of paths that changed. Only the property's quoted value is replaced (or a new (property ...) form inserted), so every other byte survives. Properties do not change connectivity: the rewritten files re-netlist identically.

const { files, changed } = engine.writeProperties(bundle, [
  { uuid: "2b3c4d5e-0002-4000-8000-000000000012", property: "Value", value: "4k7" },
  { uuid: "2b3c4d5e-0002-4000-8000-000000000012", property: "MPN", value: "RC0805FR-074K7L" },
]);

The batch is all or nothing: an unknown or ambiguous UUID, an empty UUID, or a Reference edit (annotation belongs to KiCad) throws invalid_input naming the edit, and nothing is returned.

Errors

Every failure is a KicadEngineError with a code:

  • invalid_input: the engine rejected the files, or the bundle was malformed. This is safe to report as a problem with the input.
  • internal: anything else, including a WebAssembly trap. It says nothing about the input.

After a trap, engine.poisoned is true and every later call throws internal. Load a new engine.

Verified

Node 20 (tests run against the shipped files) and Chrome 149 (headless). The package is ESM only.