PCB CAM software for CNC isolation routing, written in Rust.
CopperCrab is a desktop application that takes Gerber and Excellon files as input and generates G-code for CNC machining of PCBs. It handles isolation routing (copper traces), board outline cutting, and drill operations β with a persistent tool library and a real-time PCB preview.
- Import Gerber files (copper top, board outline)
- Real-time 2D PCB preview with zoom and pan
- Persistent tool library (V-Bits, End Mills, Drill Bits) stored as TOML
- Isolation routing toolpath generation with configurable passes and overlap
- Outline toolpath generation
- G-code export (GRBL dialect)
- Multi-pass Z depth support based on tool
max_depth - Integrated log panel
- Inch support β Gerber files in imperial units are parsed but not yet fully handled
- Excellon / drill file support β drill file parsing and G83 peck drilling G-code generation
- i18n / translation files β UI strings are hardcoded in English,
rust-i18nintegration planned - LinuxCNC and Mach3 G-code dialects β currently only GRBL is supported
- App config persistence β window size and last used folder not yet saved between sessions
- Unit tests β parser and toolpath generator need proper test coverage
- CI/CD pipeline β no automated build or test workflow yet
- Nice icons - display nice icon on linux (Is windows/mac ok ?)
- Move to (0, 0) - Move the traces to place the bottom-left PCB vertex to (0, 0).
- Multiple drill - Allow to "map" different drill bit for each hole size.
- Outline tabs - Add tabs when milling the outline (number and thickness)
| Crate | Purpose |
|---|---|
eframe / egui |
Native desktop GUI framework |
egui_extras |
Image loading support for egui |
clipper2 |
Polygon boolean operations and offsetting (toolpath generation) |
lyon |
Polygon tessellation for concave shape rendering |
gerber_parser |
Gerber RS-274X file parsing |
rfd |
Native file dialog (open/save) |
serde + toml |
Tool library and config serialization |
log + env_logger |
Logging facade and console output |
image |
PNG image loading |
directories |
Platform-appropriate config/data directories |
CopperCrab is functional but still in early development. The following limitations are known and some are planned to be addressed in future versions.
- Arc primitives β arcs are parsed and converted to polygons via point approximation. Very tight arcs with few segments may show slight deviation from the original geometry.
- Aperture macros β complex aperture macros (
%AMOC8*%and similar) are not fully supported. Most standard KiCad/Eagle exports work fine, but exotic macros may produce incorrect geometry. - Negative polarity (
%LPD*%/%LPC*%) β layer polarity switching (used for cutouts in copper pours) is not handled. Gerber files using%LPC*%(clear polarity) will render and machine incorrectly. - Step and repeat (
%SR*%) β panelized boards using the step-and-repeat block are not supported.
The Excellon parser is functional for standard KiCad exports but has several limitations:
What is supported:
- Metric unit declaration (
METRIC) - Tool definitions with decimal diameter (
T1C0.800) - Absolute decimal coordinates (
X142.0Y-67.92) - Tool selection between hole sequences
- KiCad attribute comments (
#@! TF.*,#@! TA.*) β silently ignored
What is not supported:
- Inch unit (
INCH) β files in imperial units are not handled - Integer coordinates β some exporters omit the decimal point and use a scale factor (e.g.
X14200Y-6792withFMAT,1). These will be parsed incorrectly. - Routed slots β
G85slot commands andG00/G01moves between holes are ignored; only point drill hits are extracted - Repeat command (
R) βX...Y...R5style repeated holes are not expanded - NPTH files β non-plated through-hole files must be imported separately and are treated identically to PTH files
- Peck drilling cycles (
G81,G82,G83) β drill cycle commands in the body are ignored; only coordinates are read - Coordinate offset (
OFFSET) β global offset declarations are not applied
- Inch Gerber files β files declared as
%MOIN*%are parsed but the unit conversion to mm has not been fully validated. Results may be incorrect for inch-unit boards.
- Bottom copper layer β only the top copper layer is supported. Two-sided PCBs require flipping the board manually and generating a second pass.
- Copper pours / filled zones β large filled copper areas generate a very high number of polygons and may be slow to process or render.
- Toolpath ordering β paths are not optimized for travel distance. The CNC may make unnecessary long rapid moves between cuts. A nearest-neighbor sort is planned.
- No DRC β there is no design rule check. If your isolation depth is too shallow or your tool too wide, CopperCrab will not warn you that traces may be shorted.
- GRBL only β only the GRBL dialect is currently exported. LinuxCNC and Mach3 support is planned.
- No spindle ramp-up β the spindle is started (
M3) and the tool immediately moves to the first cut position. Some machines benefit from a short dwell (G4) after spindle start. - No tool change β isolation, outline, and drill G-code are exported as separate files. Multi-tool workflows with automatic tool changers are not supported.
- Wayland icon β the application icon does not display correctly on KDE Wayland. A
.desktopfile with the icon path is required as a workaround. - macOS notarization β the macOS binary is unsigned. Gatekeeper will show a security warning on first launch. Right-click β Open to bypass it.
- Rust (edition 2024, stable toolchain)
- A C/C++ compiler (required by
clipper2FFI) βgccorclang - On Linux:
libgtk-3-devandlibxdo-devfor native file dialogs
# Arch Linux
sudo pacman -S gcc gtk3 xdotool
# Ubuntu/Debian
sudo apt install build-essential libgtk-3-dev libxdo-devgit clone https://github.com/jnthbdn/CopperCrab.git
cd CopperCrab
cargo run --releaseThe release build is significantly faster for rendering large PCBs. Use cargo run (debug) during development for faster compile times.
RUST_LOG=debug cargo run
RUST_LOG=coppercrab=debug cargo run # only CopperCrab logs- Import files β click the copper Gerber file link in the left panel, then optionally the outline Gerber
- Select tools β pick an isolation tool (V-Bit or End Mill) and an outline tool from the dropdowns
- Adjust parameters β set depth, number of passes, overlap, Z-safe, and Z-finish in the right panel
- Generate toolpaths β click "Run toolpath generation"; toolpaths appear as colored overlays on the canvas
- Select output folder β click the output folder link in the Export section
- Export β toggle which files to export and click "Export files"
Click Tool Library... in the left panel to open the tool manager. You can add, edit, and delete V-Bits, End Mills, and Drill Bits. The library is automatically saved to a tools.toml file in your platform config directory.
- Pan β click and drag
- Zoom β scroll wheel (zooms toward the cursor)
- Layer visibility β toggle layers in the left panel using the eye buttons
Contributions are welcome β bug reports, feature requests, and pull requests alike.
- Fork the repository
- Create a branch:
git checkout -b feat/my-feature - Make your changes, keeping the KISS principle in mind β the
corecrate must stay UI-independent - Open a pull request with a clear description of what changed and why
src/
βββ core/ # Business logic β no UI dependencies
β βββ geometry/ # Primitive types (Segment, Arc, Circle, Rectangle)
β βββ parser/ # Gerber β PcbLayer conversion
β βββ toolpath/ # Clipper2-based toolpath generation + G-code export
β βββ tools/ # CncTool trait, VBit / EndMill / DrillBit, ToolLibrary
βββ ui/ # egui frontend β only depends on core
The core crate exposes no egui types. If you are adding a new feature, implement the logic in core first with no UI, then wire it up in ui.
CopperCrab uses rust-i18n for translations. All strings live in a single YAML file per locale under locales/.
- Copy
locales/en.yamland name it after the BCP 47 language tag β e.g.locales/de.yamlfor German,locales/zh-TW.yamlfor Traditional Chinese. - Translate every value in the file. Leave the keys untouched β only translate the values:
ui.button.cancel:
en: "Cancel"
de: "Abbrechen" # β your translation here- Register the new locale in
src/ui/mod.rsby adding it to theAVAILABLE_LOCALEconstant:
const AVAILABLE_LOCALE: &[(&str, &str)] = &[
("en", "English"),
("fr", "FranΓ§ais"),
("de", "Deutsch"), // β add your language here
];- Build and test:
cargo runβ open Preferences and switch to your language to verify everything looks correct. - Open a pull request with the new
.yamlfile and the updatedAVAILABLE_LOCALE. No Rust knowledge required β translation contributions are very welcome!
Tip: strings using
%{variable}are interpolated at runtime. Keep the%{...}placeholders as-is and only translate the surrounding text.
- Standard
rustfmtformatting (cargo fmt) - Log with the
logfacade (log::info!,log::warn!, etc.) β neverprintln! - English for all code, comments, and log messages
MIT β see LICENSE for details.
