Quick start

Installation

pip install 'git+https://github.com/antmicro/askiff.git'

Usage examples

Loading a project from path

A typical entry point for operating on a project is Project, which handles file discovery, lazy loading necessary files as they are used.

from askiff import Project

# Load a KiCad project
project = Project("path/to/project").load()

# Modify a schematic
project.sch[0].title_block.title = "Modified Title"

# Save the project
project.save()

Creating a new PCB

It is also possible to operate directly on a specific KiCad file only.

from askiff.board import Board

# Create a new board
board = Board()

# Save created board to file
board.to_file("path/to/pcb.kicad_pcb")

Adding a footprint to a PCB

Load an existing PCB, add a footprint, and save the updated PCB.

from askiff import Project
from askiff.common import Position
from askiff.footprint import FootprintFile

# Load a KiCad project
project = Project("path/to/project").load()

# Load footprint (from project library)
footprint = project.fp["ResistorLib"]["Resistor0402"]

# OR Load footprint (from file)
footprint = FootprintFile.from_file("path/to/footprint.kicad_mod")

# Add footprint to board
project.pcb[0].add_footprint(footprint, reference="R1", position=Position(15, 20))

# Save the project
project.save()

Getting a bounding box of all shapes on silkscreen layers

askiff also allows operating directly on a specific KiCad file only (without Project).

from askiff.board import Board
from askiff.common_pcb import LayerSilkS
from askiff.common import BBox
from askiff.gritems import GrShapePCB

# Load Board
board = Board.from_file("path/to/pcb.kicad_pcb")

# Get all Silkscreen shapes
silkscreen_items = [
    item for item in board.graphic_items
    if isinstance(item, GrShapePCB) # Filter shapes using base class for all shapes on PCB
        # To get just e.g. rectangles and circles use `isinstance(item, (GrCirclePCB, GrRectPCB))`
        and isinstance(item.layer, LayerSilkS) # filter layers to that inheriting from LayerSilkS (that is Layer.SILKS_F or Layer.SILKS_B)
        # Layer type are also inheritance based, e.g. parent class `LayerTech` can be used to get all technical layers such as SilkS, Fab, Mask, ..
]

# Get bounding box of shapes
bbox = BBox.from_shapes(silkscreen_items)

print(f"Bounding box: ({bbox.start.x},{bbox.start.y}) : ({bbox.end.x},{bbox.end.y})")

Simple DFN footprint generator

A simple DFN footprint generator with configurable pins and pitches.

from askiff.common import LibId, Position, Size
from askiff.common_pcb import Layer, LayerSet
from askiff.footprint import FootprintFile
from askiff.fp_pad import PadShapeRoundrect, PadSMD
from askiff.gritems import GrRectFp

def generate_dfn_footprint(name: str, pins: int, pitch: float, row_spacing: float) -> FootprintFile:
    # Initialize empty footprint
    footprint = FootprintFile(lib_id=LibId(name=name))

    pad_shape = PadShapeRoundrect(size=Size(0.4, 0.2))
    pad_layers = LayerSet(Layer.CU_F, Layer.MASK_F, Layer.PASTE_F)

    # Add pads
    for i in range(pins):
        y = (i % (pins / 2)) * pitch
        x = 0 if i < pins / 2 else row_spacing
        pad = PadSMD(number=str(i+1), shape=pad_shape, position=Position(x, y), layers=pad_layers)
        footprint.pads.append(pad)

    # Add courtyard
    courtyard_rect = GrRectFp(
        start=Position(x=0, y=-pitch * 0.5),
        end=Position(x=row_spacing, y=(pins / 2 - 0.5) * pitch),
        layer=Layer.COURTYARD_F,
    )
    footprint.graphic_items.append(courtyard_rect)

    return footprint

# Create a DFN footprint
dfn = generate_dfn_footprint("DFN16", 16, 0.65, 1.25)
dfn.to_file("path/to/dfn16.kicad_mod")

Last update: 2026-05-05