Plugin to generate all files necessary for JLCPCB board fabrication and assembly
- Gerber files
- Excellon files
- BOM file
- CPL file
Furthermore it lets you search the JLCPCB parts database and assign parts directly to the footprints which result in them being put into the BOM file.
On KiCad 10 boards with named design variants, compare and edit variants side by side and generate separate fabrication outputs.
Add my custom repo to the Plugin and Content Manager, the URL is:
https://raw.githubusercontent.com/Bouni/bouni-kicad-repository/main/repository.jsonFrom there you can install the plugin via the GUI.
Clone this repo into your KiCad scripting/plugins folder.
Tip
You can open the plugins directory directly from KiCad to avoid locating the path manually:
In the PCB Editor, choose Tools → External Plugins → Open Plugin Directory (or Reveal Plugin Folder in Finder on macOS), or open Preferences → PCB Editor → Action Plugins and click the folder icon. From that directory, open a terminal and run git clone https://github.com/Bouni/kicad-jlcpcb-tools.git.
Alternatively, navigate to the folder in your terminal:
Windows (Command Prompt)
cd "%USERPROFILE%\Documents\KiCad\<version>\scripting\plugins"
git clone https://github.com/Bouni/kicad-jlcpcb-tools.gitWindows (PowerShell)
cd "$HOME\Documents\KiCad\<version>\scripting\plugins"
git clone https://github.com/Bouni/kicad-jlcpcb-tools.gitLinux
cd ~/.local/share/kicad/<version>/scripting/plugins
git clone https://github.com/Bouni/kicad-jlcpcb-tools.gitmacOS
cd ~/Documents/KiCad/<version>/scripting/plugins
git clone https://github.com/Bouni/kicad-jlcpcb-tools.gitNote
<version> can be 7.0, 8.0, 9.0, or X.YY depending on the version you use. You may need to create the scripting/plugins folder if it does not exist.
After cloning, choose Tools → External Plugins → Refresh Plugins in the PCB Editor (or restart KiCad) to load the plugin.
The Flatpak installation of KiCAD currently does not ship with pip and requests installed. The later is required for the plugin to work. In order to get it working you can run the following 3 commands:
flatpak run --command=sh org.kicad.KiCadpython -m ensurepip --upgrade/var/data/python/bin/pip3 install requests
See issue #94 for more info.
To access the plugin choose Tools → External Plugins → JLCPCB Tools from the PCB Editor menus
Checkout this screencast, it shows quickly how to use this plugin:
Create named variants in KiCad and transfer them to the PCB to use the variant table. Boards without named variants keep the ordinary parts table.
- Compare variants side by side, with Ref, Footprint, Side, PCB angle, and Correction columns fixed on the left when space permits. Ref stays fixed in narrower windows.
- Spot differences quickly through highlighted settings and yellow outlines around the affected variant’s cells in each component row.
- Focus on differing component settings with Differences only in the toolbar above the table.
- Edit each variant independently: Value, LCSC assignment, and BOM/POS/POP (populated) flags. Select components within one variant for batch assignments, flag changes, and copying.
- Copy and paste selected components between variants: Copy transfers Value, LCSC and BOM/POS/POP settings for every selected component; select the same components in another variant and Paste. Use Copy cell value for an individual value, or Copy to variants… to choose fields and destination variants.
- Drag variant headers to reorder them and bring variants together for comparison.
- Compare price and stock availability using compact indicators and hover details.
- Choose an Output variant to generate its BOM, placement, and fabrication files.
- Review placement corrections for the Output variant in the Correction column. Exact LCSC rules follow that variant's assigned part; pattern rules use Default's reference, Value, and placed footprint.
Assignments and flags are stored in the KiCad board; save the PCB to preserve edits.
The examples below use sample component data in the main JLCPCB Tools window. Pointer and click cues make the actions easier to follow.
Change a setting in one variant to compare it with Default. Here, turning off POP (populated) for R4 in Economy highlights the changed cell and outlines Economy’s cells in that row. The yellow outline remains visible while the row is selected.
Turn POP back on to match Default and clear R4’s difference highlight.
Select Differences only in the toolbar above the table to focus on differing component settings. In this example, enabling the checkbox leaves R1 and R3 visible. Clear it to bring all five rows back.
Drag a variant header to move its entire group of columns. Here, Premium moves before Economy.
The translucent column preview follows the pointer, while the insertion marker and Drop before Economy label show the destination. Release the header to change the order to Default, Premium, Economy.
Windows can be closed with ctrl-w/ctrl-q/command-w/command-w (OS dependent) and escape. Pressing enter in the keyword text box will start a search.
You can easily toggle the exclude from BOM and exclude from CPL attributes of one or multiple footprints.
Select one or multiple footprints, click select part. You can select parts with equal value and footprint using the Select alike button. In the upcoming modal dialog, search for parts, select the one of your choice and click select part. The LCSC number of your selection will then be assigned to the footprints.
To type or paste an LCSC number instead, right-click the selected footprints and choose Enter LCSC…. It accepts a part number such as C25804 or a product link copied from lcsc.com or jlcpcb.com. The number may be one the downloaded parts library does not list: JLC can still assemble LCSC-only parts it buys in through pre-order or global sourcing, and your library may be older than the part. The plugin asks once before assigning such a number. With no library downloaded there is nothing to check against, so it assigns without asking.
The part selector helps the same way: search for one LCSC number, and if the results don't show that exact part, a button beside the result count assigns it with one click.
Closing JLCPCB Tools saves its LCSC assignments and supported BOM settings to the project's schematics. The manual Export to schematic button has been removed. On boards with design variants, this always saves Default; selecting a named variant for fabrication does not change the schematic source.
A missing assignment field preserves the schematic's existing part number; an explicit empty assignment clears it. Invalid or conflicting assignments are preserved and reported while safe assignments still save. Footprints are linked to symbols by KiCad's UUID paths, so changed or duplicate references do not redirect a save. PCB-only footprints need no schematic update. Stale or ambiguous links are preserved and reported. For reused sheets, a shared field is updated only when every instance is linked and agrees on that field. A linked multi-unit component updates all authenticated units together; incomplete or ambiguous component membership is preserved.
Ordinary unassigned parts and PCB-only footprints close quietly. If an unassigned
PCB footprint has a part number in the schematic, use KiCad's Update PCB from
Schematic to transfer it to the board. This is an advisory, not a save failure.
When a conflict, invalid assignment, or unresolved link needs attention, the plugin keeps the complete report
at jlcpcb/schematic-save-report.txt, identifying affected footprints and the
reasons. Interactive closing also shows a warning; forced shutdown saves the
report without a prompt. A later complete save removes an outdated report.
Safe partial saves can complete; they do not authorize archival of active legacy
recovery data.
Projects that already have a jlcpcb/project.db see a one-time notice explaining
that the schematic is now the durable store. Before the first automatic write,
the plugin also keeps a permanent zip at
jlcpcb/schematics-before-plugin-attributes.zip so you can restore the previous
sheets if needed.
The plugin uses the project's associated schematics and preserves an _old
backup for each file it writes. Projects without an associated schematic close
without writing one. If a schematic is locked, the default Cancel keeps the
plugin open so you can close Schematic Editor and retry. Save Anyway approves
only the listed locks; Close without saving leaves the schematic unchanged.
Save errors also let you keep the window open or close without saving the
remaining changes. Earlier sheets may already have been saved if a later write
fails. A forced application shutdown cannot wait for these prompts: locked or
failed saves are logged and the window closes.
This saves schematic files. Use KiCad's PCB save command to persist changes to the PCB itself. An already-open Schematic Editor does not reload exported files automatically and can overwrite them if you choose Save Anyway.
The live KiCad board is the sole source of LCSC assignments, with or without named design variants. Selecting, pasting, or clearing a part updates the native footprint fields or the selected variant's fields. Save the PCB in KiCad to persist these changes. Refreshing the plugin reads the current board, including edits made outside the plugin.
Both table modes recognize LCSC, JLC, and JLCPCB assignment fields,
optionally followed by Part, Part Number, Part Num, Part No, PartNr,
PN, Number, Code, or ID; case, spaces, and punctuation are ignored.
Conflicting or invalid assignments appear unassigned. Selecting or clearing a part updates
all recognized assignment fields together. Other prefixed fields, such as
JLCPCB Rotation or LCSC custom code, remain metadata; move part numbers from
such fields into a recognized assignment field.
Previously, ordinary boards used database or CSV assignments while boards with named variants read native fields. Editing or clearing Default, then removing the last named variant, could therefore restore an obsolete database assignment. Both modes now read and edit the board; the former schematic/database priority setting no longer applies.
On opening, the plugin checks an existing jlcpcb/project.db for recoverable
legacy assignments before applying part preferences or displaying the initial
BOM. It imports a valid LCSC number only when the board assignment field is
missing and the reference, value, footprint, and BOM/POS flags exactly match
the historical row. Every linked schematic unit must also have no assignment or
the same part number. PCB-only footprints and projects confirmed to have no
schematic can recover directly into native fields, even if the PCB retains old
symbol paths. Unreadable project files and missing declared sheets do not count
as an absent schematic. KiCad 10's generated placeholder for a layout-only
project does not require a schematic file. Within a discovered hierarchy, stale
or ambiguous links remain unresolved.
Existing native values, explicit clears, invalid or conflicting
fields, unresolved links, and disagreeing shared instances are preserved.
Recovery imports neither stock nor flags and does not require a parts catalog.
Save the PCB to retain recovered assignments.
Once recovery is durable in the saved schematic or PCB, the active part_info
table is renamed to part_info_retired, preserving its rows and schema. Existing
archives remain intact; later archives use names such as part_info_retired_2.
The plugin rechecks the table's schema and data inside the archive transaction
so another window's changes cannot be archived using an outdated recovery check.
Before archival, the plugin reads the saved current PCB and sibling PCBs in the
same directory. macOS AppleDouble metadata sidecars are excluded. Recovery needed
by another board stays active, including recovery needed by temporary PCB copies.
The migration report names blocking sibling files and repeats only new notices;
acknowledgment does not allow archival. Obsolete rows can
be archived only when those saved boards confirm they are no longer needed;
an unsaved deletion or footprint change is insufficient. Native-only recovery
stays active until you explicitly save the PCB. The plugin never saves it for
you. Cancellation, incomplete saves, unresolved recovery, and unreadable saved
boards retain the recovery table for a later retry.
The durable jlcpcb/legacy-migration-report.json records the source board, old
legacy value, chosen native value or clear, and the reason for each recovery
decision, retaining original provenance and the latest board snapshot without
adding a full snapshot for every session. It survives schematic-report cleanup
and archival. When an existing native value or explicit clear supersedes a
legacy number, an interactive close
shows the previously unseen decisions once. Forced shutdown leaves that notice
pending for the next interactive close. Failed audit writes retain recovery data
and retry later without reapplying imported assignments. If the audit still cannot
be written, keep the plugin open to retry. Explicitly closing without the audit
or forcing shutdown can lose observations that could not be written to disk.
Archived assignments are never imported again, and legacy CSV files are never
automatically imported. Archival preserves generation counters, corrections,
other tables, and CSV files. Reading or refreshing assignments does not create
or modify part_info; the notice acknowledgment and generation counter use
the separate metadata table.
Supplier descriptions and other part details are cached in memory by LCSC number and fetched again as needed. Stock and pricing come from the currently selected parts catalog; they are not persisted as board assignments.
Part preferences remember which LCSC part to use for a value and footprint combination across projects. Two independent settings are enabled by default:
- Remember my part preferences remembers each successful part selection or pasted LCSC assignment. The latest explicit assignment replaces the preference; opening a board does not change preferences.
- Parts preferences fill in empty LCSC assignments fills blank LCSC assignments once each time the plugin window opens. Existing assignments are preserved. DNP parts and parts excluded from BOM or POS are skipped.
Applying part preferences, including automatic filling on opening, writes the native board fields. Save the PCB to keep those assignments.
Clearing an LCSC assignment keeps its part preference, so an eligible blank assignment may fill again on the next opening. Exclude the part or disable automatic filling to keep it blank. The right-click actions Save part preferences and Apply part preferences remain available even when automation is disabled. Use Part preferences to delete, import, or export preferences. Deleting a preference does not remove assignments from your boards.
Generate all necessary assembly files for your board with a simple click.
A new directory called jlcpcb is created, and in there, two separate folders are created, gerber and production_files.
In the gerber folder all necessary *.gbr and *.drl files are generated and zipped into the production_files folder, ready for upload to JLCPCB.
The zipfile is named GERBER-<projectname>.zip
Also in the production_files folder, two files are generated, BOM-<projectname>.csv and CPL-<projectname>.csv.
Footprints are included into the BOM and CPL files according to their exclude from BOM and exclude from POS attributes.
Optional pre/post generation hook scripts can be configured in settings.
- The pre-hook runs before generation and can block generation on failure (with Continue/Cancel prompt).
- The post-hook runs only after successful generation.
See HOOKS.md for configuration details and available environment variables.
Some boards you have manufactured will require additional layers in your Gerber. For example, when manufacturing flex PCBs with a stiffener, JLC requires a layer outlining the stiffener layer (top/bottom), dimensions and the stiffener material properties (material, thickness etc). Export these additional JLC specific layers in your production files with a simple modification.
Additional layers can be exported by creating layers with JLC_ as the prefix of the layer name. You can access and edit the layer names in Board Setup/Board Stackup/Board Editor Layers
This tool will automatically export all additional layers with the JLC_ prefix and add them to the production files in GERBER-<projectname>.zip
JLCPCB seems to need corrected rotation information. @matthewlai implemented that in his JLCKicadTools and I adopted his work in this plugin as well. You can download Matthews file from GitHub and manage your own corrections in the Rotation manager.
See Importing and repairing corrections for supported CSV formats, validation rules, and recovery of invalid records from older versions.
This plugin makes use of a lot of icons from the excellent Material Design Icons
- Fork repo
- Git clone forked repo
- Install pre-commit
pip install pre-commit - Setup pre-commit
pre-commit run - Create feature branch
git switch -c my-awesome-feature - Make your changes
- Commit your changes
git commit -m "Awesome new feature" - Push to GitHub
git push - Create PR
Make sure you make use of pre-commit hooks in order to format everything nicely with black
In the near future I'll add ruff / pylint and possibly other pre-commit-hooks that enforce nice and clean code style.
Report ordinary Python tests, real wx controls, and real KiCad tests separately. A passing test that uses a fake board does not verify KiCad's file handling, project state, or native object cleanup.
python -m pytest -rs -m 'not native_wx and not native_kicad'
python -m pytest -rs --require-native=wx -m 'not native_kicad and not os_input'
python -m pytest -rs --require-native=wx -m os_input
python -m pytest -rs --require-native=kicad -m native_kicadThe required native modes reject missing libraries, empty native selections, and skipped native tests. Run them with Python libraries matching the installed KiCad or wx packages. Mouse/keyboard tests require an isolated desktop with a window manager; Linux native tests can use Xvfb.
To reproduce CI locally, use an Ubuntu 24.04 Docker container with the same CPU architecture, KiCad packages, dependencies, and commands as the test workflow. Copy the tracked source tree so untracked test files cannot change collection. Include the tested revision, Python/wx/KiCad versions, command, and pass/skip/deselection counts when reporting results. A required lane that was not run remains unvalidated.
default_settings.json holds the settings a fresh install starts from and is the only
settings file tracked in git. The plugin writes the settings you actually use to
settings.json beside it, which is git-ignored, so toggling a checkbox while developing
no longer shows up as a change to commit.
On every launch the stored settings are layered over the defaults, so a setting added by
a newer version arrives with its default rather than being missing. Add new settings to
default_settings.json; tests/test_settings_defaults.py fails if a setting the code
reads has no default shipped for it.
The parts database is rebuilt by the update_parts_database.yml GitHub workflow
You can reference the steps in the 'Update database' section for the commands to run locally.
lib/ contains the necessary python packages that may not be a part of the KiCad python distribution.
These packages include:
- packaging
To install a package, such as 'packaging':
pip install packaging --target ./libTo update these packages:
pip install packaging --upgrade --target ./libFuture versions of KiCad may have support for a requires.txt to automate this process.
Allows the plugin UI to be started without KiCAD, enabling debugging with an IDE like pycharm / vscode.
Standalone mode is under development.
- All board / footprint / value data are hardcoded stubs, see standalone_impl.py
To use the plugin in standlone mode you'll need to identify three pieces of information specific to your Kicad version, plugin path, and OS.
The {KiCad python} should be used, this can be found at different locations depending on your system:
| OS | Kicad python |
|---|---|
| Mac | /Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/3.9/bin/python3 |
| Linux | /usr/bin/python3 |
| Windows | C:\Program Files\KiCad\8.0\bin\python.exe |
The {working directory} should be your plugins directory, ie:
| OS | Working dir |
|---|---|
| Mac | ~/Documents/KiCad//scripting/plugins/ |
| Linux | ~/.local/share/kicad//scripting/plugins/ |
| Windows | %USERPROFILE%\Documents\KiCad<version>\scripting\plugins\ |
Note
can be 7.0, 8.0, 9.0, or X.YY depending on the version you use
The {kicad-jlcpcb-tools folder name} should be the name of the kicad-jlcpcb-tools folder.
- For Kicad managed plugins this may be like
com_github_bouni_kicad-jlcpcb-tools
- If you are developing kicad-jlcpcb-tools this is the folder you cloned the kicad-jlcpcb-tools as.
- Change to the working directory as noted above
- Run the python interpreter with the {kicad-jlcpcb-tools folder name} folder as a module.
For example:
cd {working directory}
{kicad_python} -m {kicad-jlcpcb-tools folder name}For example on Mac:
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/3.9/bin/python3 -m kicad-jlcpcb-toolsFor example on Linux:
cd ~/.local/share/kicad/8.0/scripting/plugins/ && python -m kicad-jlcpcb-toolsFor example on Windows:
& 'C:\Program Files\KiCad\8.0\bin\python.exe' -m kicad-jlcpcb-tools- Configure the command line to be '{kicad_python} -m {kicad-jlcpcb-tools folder name}'
- Set the working directory to {working directory}
If using PyCharm or Jetbrains IDEs, set the interpreter to Kicad's python, {Kicad python} and under 'run configuration' select Python.
Click on 'script path' and change instead to 'module name', entering the name of the kicad-jlcpcb-tools folder, {kicad-jlcpcb-tools folder name}.
bouni-kicad-repository contains the files for the latest version of the plugin, in the format KiCAD expects from external plugins.
To release a new version of this plugin:
- In the kicad-jlcpcb-plugin repository:
- Automatically the new release will trigger the 'kicad-pcm' workflow which will:
- Pull the latest plugin tag
- Create the appropriate pcm archive
- Upload the zip as an asset to a new GitHub release
- benc-uk/workflow-dispatch@v1 is used to trigger the 'Rebuild repository' workflow in bouni-kicad-repository
- Automatically in the bouni-kicad-repository, the 'Rebuild repository' (rebuild.yml) workflow runs 'generate.py'
- generate.py updates .json and the latest .zip file using the release assets from the kicad-jlcpcb-plugin repository
- The plugin should now be visible to users via the plugin manager.















