KiKit: scripted panelization, fab exports and stencils for KiCAD boards
Automation tools for KiCAD
At a glance
- What is it?
- KiKit turns a KiCAD board into a panel through a CLI, a Python API and a menu plugin in the KiCAD GUI, then exports Gerbers and stencils from manufacturer presets. The build path is where the friction sits: the repository's own install target leaves all seven runtime dependencies out of the wheel.
- Who is it for?
- Pick KiKit when the same panel is rebuilt after every board revision, or when one design has to reach several fabricators with different presets, because a script is re-run while hand assembly in Pcbnew is redone from scratch. For a single board cut once, stay inside Pcbnew.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Distinct nets per instance are what make panels pass DRC
The feature list makes one claim that hand-built panels struggle with: a panel produced by KiKit passes DRC because tracks belonging to different instances of the same board carry distinct nets. Copy a board into a sheet in Pcbnew and every copy keeps the original net names, so copper that was never meant to touch ends up on one net and the checker objects. KiKit renames nets per instance as part of placement, which is why the project presents panelization as a script rather than a drawing session.
What a user writes is close to plain intent: place board here, add bridge here, separate boards via mouse bites or V-CUTS. Run the same recipe again after a board revision and the sheet comes out the same way, a property hand work cannot promise. A design rule check that passes on the first submission saves a round trip with the fabricator, and that is the concrete payoff the project names.
Bridges and mouse bites define the substrate between boards
Between placed boards there is bare substrate, and KiKit treats that gap as an object you can place. A bridge is a piece of substrate inserted to hold a board section that would otherwise be fragile, and it is positioned with the same scripted instruction as a board itself. Separation can be asked for as mouse bites or as V-CUTS, so one recipe can route a break across a curve and cut a straight line elsewhere without the layout being redrawn by hand.
Boards with arbitrary shapes are supported, so the outline does not have to be a rectangle on a grid. That matters when the shape is curved, follows the edge of an enclosure, or carries a cutout. The same tool also splits a file holding several boards back into individual ones, the inverse operation, and that is the one worth having when a fabricator returns a combined sheet that has to be worked on again.
One CLI entry point and a Python library share the panelizer
setup.py registers two console scripts: `kikit=kikit.ui:cli` for the main command and `kikit-info=kikit.info:cli` for the smaller information command. `packages=setuptools.find_packages()` collects the `kikit` tree whole, so the code the command line reaches is importable from a Python script, and a layout recipe becomes a function call. The KiCAD menu plugin and the shell sit on one core, so a panel drawn interactively and one built inside a Makefile share structure rather than merely looking alike.
Version strings come from versioneer rather than a literal in setup.py, so a checkout and an installed wheel report the same value without anyone editing a constant by hand. The last push was on 2026-09-25 and the newest tagged version is v1.8.1 from 2026-08-05, following v1.8.0 on 2026-04-12, so the plugin and the command line move with one tree instead of being maintained apart.
Manufacturer presets and stencils come out of one pipeline
The second job is output rather than geometry. Gerbers and assembly data are exported from manufacturer presets, so a fab house's rules live in a configuration file instead of a run of dialog clicks repeated for every revision. The same pipeline produces solder paste stencils in two documented forms: a 3D printed self-registering stencil, and a steel stencil with an alignment jig. Stencil generation is where the `solidpython>=1.1.2` requirement earns its place, and the container installs openscad beside it so that geometry can be rendered rather than left as source.
Export and page generation hang off a Makefile, so `make` is the intended entry point once a project is set up. Board presentation pages are produced by the same run, which is what turns a panel job into something a team repeats without a person in the loop.
The Makefile install target skips all seven runtime dependencies
A local build starts from the Makefile. The `package` target clears `dist/*` and runs `python3 setup.py sdist bdist_wheel`, and `install: package` follows it with `pip3 install --no-deps --force dist/*.whl`.
package:
rm -f dist/*
python3 setup.py sdist bdist_wheel
install: package
pip3 install --no-deps --force dist/*.whlRead that flag closely. `--no-deps` means none of the seven entries under `install_requires` arrive with the wheel: numpy, shapely, click, markdown2, pybars3, solidpython and commentjson all have to sit in the environment beforehand, which is why the Dockerfile installs the same names by hand. The README never points at this target; it sends readers to the PyPI package, where pip resolves that list itself. Seven declared dependencies, none of them handled by the command a newcomer runs first.
The declared Python floor and the container's pinned interpreter disagree
setup.py declares `python_requires='>=3.7'`, a floor wide enough to cover a range of interpreters. The container image takes a narrower position and pins itself to exactly one.
ARG REPO=ubuntu
FROM $REPO:24.04 AS base
ARG KICAD_VERSION="10.0"
RUN add-apt-repository --yes ppa:kicad/kicad-$KICAD_VERSION-releases
ENV PYTHONPATH=/usr/lib/kicad/lib/python3/dist-packages:${PYTHONPATH} \
LD_LIBRARY_PATH=/usr/lib/kicad/lib/x86_64-linux-gnu/:${LD_LIBRARY_PATH}
RUN pip3 install --break-system-packages \
"shapely >= 2.0.3" \
"click >= 7.1" \
"solidpython >= 1.1.2"The final stage copies only what the build stage installed, taking a fixed tree from `/usr/local/lib/python3.12/dist-packages` and ignoring the source directories. Two variables make the coupling explicit: `PYTHONPATH` and `LD_LIBRARY_PATH` both point into the KiCAD lib directory, which is the concrete form of the README's warning that some platforms require a specific Python interpreter. If your own KiCAD build exposes its bindings somewhere else, the paths baked into this image are wrong for your machine, and nothing in the repository checks that.
Generated documentation depends on a tool outside the package
Documentation here is built rather than written. The top-level Make target chains the documentation, package, test and plugin bundle steps together, and the documentation step sets `PYTHONPATH="$(pwd):${PYTHONPATH}"` before running `python3 scripts/panelizeDoc.py`, which regenerates `docs/panelization/python_api.md` and `docs/panelization/examples.md` from the tree itself. A docstring change therefore reaches the published pages only when somebody runs the target and commits the result.
One step reaches outside the package entirely. The `conn.png` illustration is produced by `pcbdraw plot`, a separate project by the same author, together with `convert`, supplied in the container through the ImageMagick and GraphicsMagick development packages rather than through `install_requires`. Testing splits along the same seam: `cd build/test && bats ../../test/system` covers behaviour, `cd test/units && pytest` covers units. None of that reaches a user of the wheel, yet it marks where the invariants are actually checked.
Hand assembly in Pcbnew is the alternative this project argues against
The strongest case against the tool sits inside its own feature notes. Everything KiKit does can also be done via Pcbnew by hand, and the project says so, naming Pcbnew's append board function as the route being replaced. The claimed difference is not capability but repetition: manual assembly is described as labour-intensive and error-prone, and it has to be redone whenever the board changes, whereas a script is re-run. For a designer cutting two boards from one sheet who never touches the outline again, the manual route costs nothing extra and adds no files to maintain. For a layout that ships in revision after revision, the scripted route wins from the second run onward.
Two further KiCAD and PCB projects by the same author are linked from the same page, PcbDraw and JlcParts, though nothing in this repository states what either one does. The repository ships a `LICENCE` file and setup.py classifies the package as MIT, so the panel recipes you build around it carry no obligation of their own.
Editorial conclusion
Pick KiKit when the same panel is rebuilt after every board revision, or when one design has to reach several fabricators with different presets, because a script is re-run while hand assembly in Pcbnew is redone from scratch. For a single board cut once, stay inside Pcbnew. Before adopting the container in continuous integration, check which interpreter your KiCAD build exposes, since the image copies a fixed tree from /usr/local/lib/python3.12/dist-packages and expects PYTHONPATH to point inside the KiCAD lib directory.
Frequently asked questions
How do I install KiKit for KiCAD?
The README points to the PyPI package and to a per-platform installation guide, warning that KiCAD's own packaging means some platforms need a specific Python interpreter. The Dockerfile builds from an `ubuntu` base tagged `24.04` and adds KiCAD from `ppa:kicad/kicad-$KICAD_VERSION-releases` with `KICAD_VERSION="10.0"`.
Does KiKit replace Pcbnew for panel design?
No. The feature notes state that everything KiKit does can also be done via Pcbnew, and that append board by hand is labour-intensive and error-prone and has to be repeated after every board change.
What does the install target in the Makefile actually do?
It runs `python3 setup.py sdist bdist_wheel` to build a wheel, then `pip3 install --no-deps --force dist/*.whl`. Because of `--no-deps`, the seven packages listed under `install_requires` are not installed by that command.
Which Python versions does KiKit support?
setup.py declares `python_requires='>=3.7'`. The container image is narrower: its final stage copies the installed tree from `/usr/local/lib/python3.12/dist-packages`, so the image carries a single interpreter.
Can KiKit panelize boards that are not rectangles?
Yes. The feature list names panels of boards with arbitrary shapes, bridges made from pieces of substrate, mouse bites or V-CUTS as separation methods, and splitting a file that holds several boards back into separate ones.
How are the documentation pages produced?
The doc target sets `PYTHONPATH="$(pwd):${PYTHONPATH}"` and runs `python3 scripts/panelizeDoc.py`, which regenerates `docs/panelization/python_api.md` and `docs/panelization/examples.md`. The `conn.png` figure needs `pcbdraw plot` and `convert` on top of that.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/yaqwsx-kikit)