Skip to content

Fermium/kicad_monkey

 
 

Repository files navigation

KiCad Monkey

            ▓▓▓▓▓▓▓▓▓▓
          ▓▓▓▓▓▓▓▓▓▓▓▓▓▓
        ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
      ▓▓▓▓░░░░░░▓▓░░░░░░▓▓▓▓
  ░░░░▓▓░░░░░░░░░░░░░░░░░░▓▓░░░░
  ░░░░▓▓░░    ░░░░░░    ░░▓▓░░░░
    ░░▓▓░░  ██░░░░░░  ██░░▓▓░░
      ▓▓░░░░░░░░░░░░░░░░░░▓▓
        ▓▓░░░░░░░░░░░░░░▓▓
          ▓▓▓▓░░░░░░▓▓▓▓
  ░░          ▓▓▓▓▓▓
    ▓▓      ▓▓▓▓▓▓▓▓▓▓
    ▓▓▓▓    ▓▓▓▓▓▓▓▓▓▓
      ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
          ▓▓▓▓░░▓▓░░▓▓▓▓

kicad_monkey is a focused Python package for KiCad source-file parsing, round-trip modeling, close-to-format utilities, and IR-backed 2D rendering.

Use it when you need Python code to inspect or modify KiCad files directly:

  • read .kicad_pro, .kicad_sch, .kicad_pcb, .kicad_sym, and .kicad_mod files;
  • query schematic and PCB objects through typed model facades;
  • compile KiCad-native design netlists and design JSON;
  • render schematic, PCB, symbol, and footprint views through plotter IR and SVG;
  • make focused model edits, then write KiCad files back out.

This package is the low-level parser/model/rendering library. Larger workflow commands and application orchestration should live in downstream packages.

Install

For library use inside an existing Python environment:

pip install kicad-monkey

For development:

git clone https://github.com/wavenumber-eng/kicad_monkey.git
cd kicad_monkey
uv sync --extra test

Quick Examples

Load A Design And Inspect Nets

from kicad_monkey import KiCadDesign

design = KiCadDesign.from_project_file("hardware/demo.kicad_pro")
netlist = design.to_netlist()

for net in netlist.nets:
    terminals = ", ".join(
        f"{terminal.designator}.{terminal.pin}"
        for terminal in net.terminals
    )
    print(f"{net.name}: {terminals}")

Save the KiCad-native design JSON used by higher-level review tools:

design.save_json("build/design.json")

Render PCB SVG

from pathlib import Path

from kicad_monkey import KiCadDesign

design = KiCadDesign.from_project_file("hardware/demo.kicad_pro")

out_dir = Path("build/svg")
out_dir.mkdir(parents=True, exist_ok=True)

svg = design.to_pcb_svg(
    layers=["Edge.Cuts", "F.Cu", "F.SilkS"],
    profile="enriched",
)
(out_dir / "front-copper.svg").write_text(svg, encoding="utf-8")

Use profile="oracle" when comparing against KiCad CLI output. Use profile="enriched" when an app needs metadata on SVG elements.

Render Every Schematic Sheet Instance

Hierarchical designs can instantiate one .kicad_sch file more than once. KiCadSchematicInstance represents each concrete sheet view.

from pathlib import Path

from kicad_monkey import KiCadDesign, render_ir_to_svg

design = KiCadDesign.from_project_file("hardware/demo.kicad_pro")

out_dir = Path("build/schematic-svg")
out_dir.mkdir(parents=True, exist_ok=True)

for sheet in design.schematic_instances():
    doc = design.to_schematic_instance_ir(sheet)
    svg = render_ir_to_svg(doc)
    safe_name = sheet.sheet_name.replace("/", "_").replace("\\", "_")
    (out_dir / f"{sheet.instance_index:02d}_{safe_name}.svg").write_text(
        svg,
        encoding="utf-8",
    )

To find where a reused child schematic appears:

for instance in design.schematic_instances_for("hardware/LED_Controller.kicad_sch"):
    print(instance.sheet_name, instance.sheet_path, instance.sheet_instance_path)

Query And Mutate Schematic Objects

The .objects property is a live read-only query view over model-owned objects. Mutate the returned objects, then call save().

from kicad_monkey import KiCadSchematic

schematic = KiCadSchematic.from_file("hardware/demo.kicad_sch")

for symbol in schematic.objects.where("SchSymbol"):
    if symbol.reference.startswith("R"):
        symbol.set_property_value("Value", "10 kOhm")

for label in schematic.objects.where("SchLabel"):
    if label.effects is not None and label.effects.font is not None:
        label.effects.font.size_x = 1.5
        label.effects.font.size_y = 1.5

schematic.save("hardware/demo.edited.kicad_sch")

Query And Mutate PCB Objects

from kicad_monkey import KiCadPcb

board = KiCadPcb.from_file("hardware/demo.kicad_pcb")

for footprint in board.objects.where("Footprint"):
    reference = footprint.get_property_value("Reference")
    if reference.startswith("U"):
        footprint.set_property_value("Reviewed", "yes", create=True)

for text in board.objects.where("GrText", layer="F.SilkS"):
    text.effects.font.size_x = 1.0
    text.effects.font.size_y = 1.0
    text.text = text.text.strip()

board.save("hardware/demo.edited.kicad_pcb")

Object queries also work with class objects when you prefer typed imports:

from kicad_monkey import Footprint, KiCadPcb

board = KiCadPcb.from_file("hardware/demo.kicad_pcb")
connectors = [
    footprint
    for footprint in board.objects.where(Footprint)
    if footprint.get_property_value("Reference").startswith("J")
]

Testing

Rack is the primary public gate:

uv run --extra test python tests/rack.py run L0_foundation
uv run --extra test python tests/rack.py run L99_signoff

L99_signoff checks release metadata, changelog coverage, public API contract resolution, API design-doc ownership, Rack test ownership, corpus archive hygiene, and the current ruff/pyright ratchet state.

The redistributable KiCad corpus is transported as tests/corpus/kicad.zip. The loose mirror is ignored locally; test helpers extract it on demand when no external corpus is configured.

API Shape

Stable package-root exports are recorded in kicad_monkey.kicad_api_contract. Those names are the public API that downstream code should rely on. The broader package __all__ remains a discovery surface while downstream integrations prove which additional symbols should become stable public exports.

The public OOP facade groups and supporting public classes are documented under docs/design/api. L99 fails when a stable public class or major interface is missing design documentation or Rack test ownership.

Typical entrypoints:

from kicad_monkey import KiCadDesign, KiCadFootprint, KiCadPcb, KiCadSchematic
from kicad_monkey import KiCadSymbolLib

schematic = KiCadSchematic.from_file("design.kicad_sch")
board = KiCadPcb.from_file("board.kicad_pcb")
design = KiCadDesign.from_project_file("project.kicad_pro")
symbols = KiCadSymbolLib.from_file("library.kicad_sym")
footprint = KiCadFootprint.from_file("package.kicad_mod")

Fixture Model

Public fixtures should be redistributable and package-local when possible. Broader fixture families should use this shape:

  • input/
  • reference_output/
  • output/

output/ is transient and should stay local or temporary.

Documentation

License

MIT.

About

a python based kicad toolkit for directly interacting with files

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 100.0%