Skip to main content

Overview

KiCad provides multiple plugin mechanisms for extending functionality:
  1. Python Scripting: Action plugins and automation via Python API
  2. 3D Model Plugins: Import various 3D formats
  3. I/O Plugins: Support additional file formats
  4. IPC API: External tool integration via protocol buffers

Python Scripting

Architecture

KiCad uses SWIG (Simplified Wrapper and Interface Generator) to expose C++ classes to Python. Key files:
  • scripting/kicadplugins.i - SWIG interface definition
  • scripting/python_scripting.cpp - Python integration layer
  • scripting/python_manager.cpp - Plugin lifecycle management

Python API Exposure

SWIG Interface

// From kicadplugins.i
%module pcbnew

%{
#include <board.h>
#include <footprint.h>
#include <pcb_track.h>
%}

%include <board.h>
%include <footprint.h>
%include <pcb_track.h>
Generated bindings:
  • pcbnew.py - PCB editor API
  • Python wrapper for C++ classes
  • Automatic memory management via SWIG

Plugin Types

Action Plugins

Location: Loaded from standard plugin directories
  • Linux: ~/.local/share/kicad/scripting/plugins/
  • Windows: %APPDATA%/kicad/scripting/plugins/
  • macOS: ~/Library/Application Support/kicad/scripting/plugins/
Plugin structure:
import pcbnew

class MyPlugin(pcbnew.ActionPlugin):
    def defaults(self):
        self.name = "My Plugin"
        self.category = "Modify PCB"
        self.description = "Does something useful"
        self.show_toolbar_button = True
        self.icon_file_name = "icon.png"
    
    def Run(self):
        board = pcbnew.GetBoard()
        # Manipulate board...
        pcbnew.Refresh()

MyPlugin().register()
Capabilities:
  • Access full board data structure
  • Create/modify footprints, tracks, zones
  • Read design rules
  • Generate manufacturing outputs
  • UI integration via toolbar buttons

Footprint Wizards

Purpose: Parametric footprint generation
import pcbnew
import FootprintWizardBase

class ConnectorWizard(FootprintWizardBase.FootprintWizard):
    def GetName(self):
        return "Connector"
    
    def GetDescription(self):
        return "Generates pin header footprints"
    
    def GetValue(self):
        pins = self.parameters["Pads"]["count"]
        return f"CONN_{pins}"
    
    def GenerateParameterList(self):
        self.AddParam("Pads", "count", self.uNatural, 10)
        self.AddParam("Pads", "pitch", self.uMM, 2.54)
    
    def BuildFootprint(self):
        footprint = pcbnew.FOOTPRINT(None)
        # Build parametric footprint...
        return footprint

ConnectorWizard().register()

Python Shell Integration

Interactive console: Built into Pcbnew (if KICAD_SCRIPTING_WXPYTHON enabled)
# Access current board
board = pcbnew.GetBoard()

# Iterate over footprints
for fp in board.GetFootprints():
    print(f"{fp.GetReference()}: {fp.GetValue()}")

# Modify properties
for track in board.GetTracks():
    track.SetWidth(pcbnew.FromMM(0.25))

pcbnew.Refresh()

Python API Examples

Board manipulation

import pcbnew

board = pcbnew.LoadBoard("project.kicad_pcb")

# Get board properties
print(f"Board size: {board.GetBoundingBox()}")
print(f"Layer count: {board.GetCopperLayerCount()}")

# Add a trace
track = pcbnew.PCB_TRACK(board)
track.SetStart(pcbnew.VECTOR2I(pcbnew.FromMM(10), pcbnew.FromMM(20)))
track.SetEnd(pcbnew.VECTOR2I(pcbnew.FromMM(30), pcbnew.FromMM(20)))
track.SetWidth(pcbnew.FromMM(0.2))
track.SetLayer(pcbnew.F_Cu)
board.Add(track)

pcbnew.SaveBoard("modified.kicad_pcb", board)

Netlist processing

def update_component_values(board, reference_map):
    """Update component values based on mapping"""
    for fp in board.GetFootprints():
        ref = fp.GetReference()
        if ref in reference_map:
            fp.SetValue(reference_map[ref])

values = {"R1": "10k", "R2": "22k", "C1": "100nF"}
update_component_values(board, values)

wxPython Integration

Requires: KICAD_SCRIPTING_WXPYTHON=ON (default) Purpose: Create custom UI dialogs
import wx
import pcbnew

class ConfigDialog(wx.Dialog):
    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, title="Plugin Config")
        
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        
        self.text = wx.TextCtrl(panel)
        sizer.Add(self.text, 0, wx.EXPAND | wx.ALL, 5)
        
        btn = wx.Button(panel, label="OK")
        btn.Bind(wx.EVT_BUTTON, self.OnOK)
        sizer.Add(btn, 0, wx.ALL, 5)
        
        panel.SetSizer(sizer)
    
    def OnOK(self, event):
        self.EndModal(wx.ID_OK)

class UIPlugin(pcbnew.ActionPlugin):
    def Run(self):
        dlg = ConfigDialog(None)
        if dlg.ShowModal() == wx.ID_OK:
            # Use dlg.text.GetValue()
            pass
        dlg.Destroy()

3D Model Plugins

Overview

3D plugins enable importing various 3D model formats into KiCad’s 3D viewer. Location: plugins/3d/

Supported Formats

STEP (via OpenCASCADE)

Plugin: plugins/3d/oce/ Features:
  • Industry-standard CAD format
  • Precise geometry
  • Assembly support
  • Color and material properties
Implementation:
class PLUGIN_3D_OCC : public SCENEGRAPH
{
    bool Load( const wxString& filename );
    void ProcessShape( const TopoDS_Shape& shape );
};
Capabilities:
  • Solid modeling
  • Surface geometry
  • Assembly hierarchies
  • Compound shapes

VRML (Virtual Reality Modeling Language)

Plugin: plugins/3d/vrml/ Versions supported:
  • VRML 1.0 (v1/)
  • VRML 2.0/VRML97 (v2/)
  • X3D (partial)
Features:
  • Mesh-based models
  • Materials and textures
  • Transformations
  • Hierarchical scenes
Parser structure:
class VRML1_BASE
{
    virtual bool Read( WRLPROC& proc );
    virtual void TranslateToSG( SCENEGRAPH* scene );
};

class VRML1_SEPARATOR : public VRML1_BASE { };
class VRML1_MATERIAL : public VRML1_BASE { };
class VRML1_COORDINATE : public VRML1_BASE { };

IDF (Intermediate Data Format)

Plugin: plugins/3d/idf/ Purpose:
  • Board outline exchange
  • Component placement
  • Mechanical CAD integration
Format versions:
  • IDF 2.0
  • IDF 3.0 (most common)
  • IDF 4.0

Plugin Architecture

Base class:
class S3D_PLUGIN
{
    virtual SCENEGRAPH* Load( const wxString& filename ) = 0;
    virtual wxString GetFileExtension() const = 0;
    virtual wxString GetFilesFilter() const = 0;
};
Scene graph:
class SCENEGRAPH
{
    std::vector<SCENEGRAPH*> children;
    std::vector<SGCOLOR> colors;
    std::vector<VECTOR3D> vertices;
    std::vector<int> indices;
    
    void AddNode( SCENEGRAPH* node );
    void SetColor( float r, float g, float b, float a );
};
Registration: Plugins are dynamically loaded at runtime based on file extension.

I/O Plugins

Purpose

Enable import/export of various EDA file formats.

Plugin Interface

class IO_BASE
{
    virtual void Save( const wxString& filename, 
                       BOARD* board,
                       const STRING_UTF8_MAP* props = nullptr );
                       
    virtual BOARD* Load( const wxString& filename,
                         BOARD* board,
                         const STRING_UTF8_MAP* props = nullptr );
                         
    virtual void FootprintEnumerate( wxArrayString& list,
                                     const wxString& libPath );
                                     
    virtual FOOTPRINT* FootprintLoad( const wxString& libPath,
                                      const wxString& name );
};

Supported Formats

Altium

Plugin: common/io/altium/ Formats:
  • .PcbDoc - PCB files
  • .SchDoc - Schematic files
  • .PcbLib - Footprint libraries
  • .SchLib - Symbol libraries
Parsers:
  • altium_binary_parser.cpp - OLE compound documents
  • altium_ascii_parser.cpp - ASCII sections
  • altium_props_utils.cpp - Property extraction

EAGLE

Plugin: common/io/eagle/ Formats:
  • .brd - Board files (XML)
  • .sch - Schematic files (XML)
  • .lbr - Libraries (XML)
Parser: XML-based using TinyXML2

EasyEDA

Plugin: common/io/easyeda/, common/io/easyedapro/ Formats:
  • JSON-based project files
  • Embedded libraries
  • Cloud project exports
Variants:
  • EasyEDA Standard
  • EasyEDA Pro

CADSTAR

Plugin: common/io/cadstar/ Formats:
  • Archive-based projects
  • Parts library database
Features:
  • Complex hierarchical designs
  • Custom attributes
  • Net classes

Plugin Registration

IO_MGR handles plugin discovery:
class IO_MGR
{
    static IO_BASE* PluginFind( IO_FILE_TYPE fileType );
    
    enum IO_FILE_TYPE {
        KICAD_SEXP,
        LEGACY,
        ALTIUM_DESIGNER,
        EAGLE,
        EASYEDA,
        CADSTAR_PCB_ARCHIVE,
        // ...
    };
};

IPC API

Overview

Modern external tool integration via Protocol Buffers and NNG transport. Introduced: KiCad 8.0 Location: api/

Architecture

Protocol Buffers

Definitions: api/proto/ Message structure:
// From common/envelope.proto
message ApiRequest {
    ApiRequestHeader header = 1;
    google.protobuf.Any message = 2;
}

message ApiResponse {
    ApiResponseHeader header = 1;
    ApiResponseStatus status = 2;
    google.protobuf.Any message = 3;
}

enum ApiStatusCode {
    AS_OK = 1;
    AS_BAD_REQUEST = 3;
    AS_NOT_READY = 4;
    AS_UNHANDLED = 5;
    AS_BUSY = 7;
}

Message Types

Board commands (board/board_commands.proto):
message GetOpenBoardsRequest {}

message GetOpenBoardsResponse {
    repeated BoardHeader boards = 1;
}

message RunDrcRequest {
    string board_id = 1;
}
Common commands (common/commands/):
  • base_commands.proto - Basic operations
  • editor_commands.proto - Editor control
  • project_commands.proto - Project management

Transport Layer

NNG (nanomsg-next-gen): Message queue system Endpoint: ipc:///tmp/kicad-api.sock (Unix) or named pipe (Windows) Patterns:
  • Request/Reply - Synchronous commands
  • Publish/Subscribe - Event notifications

Client Integration

Python example

import pynng
from api.board import board_pb2
from api.common import envelope_pb2

# Connect to KiCad API
sock = pynng.Req0()
sock.dial("ipc:///tmp/kicad-api.sock")

# Create request
request = envelope_pb2.ApiRequest()
request.message.Pack(board_pb2.GetOpenBoardsRequest())

# Send and receive
sock.send(request.SerializeToString())
response_data = sock.recv()
response = envelope_pb2.ApiResponse()
response.ParseFromString(response_data)

if response.status.status == envelope_pb2.AS_OK:
    boards = board_pb2.GetOpenBoardsResponse()
    response.message.Unpack(boards)
    for board in boards.boards:
        print(f"Open board: {board.name}")

Use Cases

Automation:
  • CI/CD integration
  • Batch processing
  • Design validation
  • Report generation
External tools:
  • Custom DRC checks
  • Advanced routing algorithms
  • Library management
  • Manufacturing preparation
Testing:
  • Automated testing
  • Regression validation
  • Performance benchmarking

Security

Token validation: Prevents unauthorized access
message ApiRequestHeader {
    string kicad_token = 1;  // Must match running instance
    string client_name = 2;  // Client identification
}
Limitations:
  • Local-only by default (IPC sockets)
  • No authentication (relies on OS permissions)
  • Trusted client assumption

Plugin Development Guidelines

Python Plugins

Best practices:
  1. Handle exceptions gracefully
  2. Validate board state before modifications
  3. Use transactions for multiple operations
  4. Refresh UI after changes
  5. Provide meaningful error messages
Testing:
class TestPlugin(unittest.TestCase):
    def setUp(self):
        self.board = pcbnew.CreateEmptyBoard()
    
    def test_plugin_operation(self):
        plugin = MyPlugin()
        plugin.Run()
        self.assertEqual(len(self.board.GetFootprints()), 10)

I/O Plugins

Requirements:
  1. Inherit from IO_BASE
  2. Register with IO_MGR
  3. Handle malformed input
  4. Preserve as much data as possible
  5. Document format limitations

3D Plugins

Requirements:
  1. Implement S3D_PLUGIN interface
  2. Build scene graph efficiently
  3. Handle materials/colors
  4. Support coordinate transformations
  5. Validate geometry

See Also

Build docs developers (and LLMs) love