* feat: bump vendored KiCad protos to v10.0.0 * test: add protocol contract tests for board layer name * docs: overhaul README and guide site - Rewrite README with punchy opening, realistic examples, and cleaner structure - Update status to Beta and version numbers to 0.4.1 - Remove redundant sections (roadmap, future work, guide site link) - Simplify API matrix by removing redundant Status column - Add CONTRIBUTING.md header with welcoming message - Expand mdBook examples with real-world patterns: - PCB analysis (unconnected nets, footprints) - Automation (text variables, test points) - CI/CD integration patterns - Net class validation - Selection manipulation - Update mdBook intro with comparison table and clearer goals - Update quickstart version numbers - Suppress missing_docs warnings for internal modules (commands, envelope, transport) - Format code with cargo fmt * docs: complete library assessment report with verified findings - Corrected baseline metrics (5448 LOC client.rs, 7903 non-generated total, 12766 overall) - Added full non-generated source tree with LOC breakdown - Expanded anti-pattern scan from 3 to 6 findings (AP-4 through AP-6) - Added verified clean signals (zero production unwrap/expect/panic) - Added transport architecture, feature flag, and model cross-dependency analysis - Proposed concrete client.rs domain split into 8 modules - Identified 5 new documentation issues (DR-2 through DR-6) - Resolved DR-1 (version drift already fixed) - Expanded risk register from 5 to 9 entries - Updated prioritized action plan with corrected priorities * fix: complete P0 action items from library assessment - Fix clone_on_copy in client.rs map_text_shape (AP-1) - Add clippy::enum_variant_names allow for generated proto code (AP-2) - Fix bool_assert_comparison patterns in test assertions (AP-3) - Fix broken README anchor in validation.md (DR-2) - Remove docs/book/src/https: filesystem artifact (DR-3) * refactor: split monolithic client.rs into domain modules Split src/client.rs (5448 LOC) into src/client/ directory with 11 modules: - mod.rs: core structs, builder, constants, send_command - common.rs: ping, version, paths, documents, text vars, text geometry - board.rs: nets, layers, origin, stackup, graphics, appearance, DRC - selection.rs: get/add/remove/clear selection - items.rs: CRUD, get by type/net/class, commit workflow - document.rs: title block, save, revert, string serialization - geometry.rs: bounding boxes, hit test, pad polygons, padstack, zones - mappers.rs: all proto-to-model and model-to-proto conversions - decode.rs: PCB item type decoding - format.rs: selection detail formatting, debug utilities - tests.rs: all unit tests No public API changes. All existing tests pass. Updated blocking parity test to scan split module files. * refactor: add rpc! dispatch macro to reduce RPC boilerplate Introduce rpc! macro in client/mod.rs that encapsulates the pack → send_command → response_payload_as_any pattern repeated across 57 RPC methods. Demonstrate usage in common.rs with 4 converted _raw methods. * feat: complete P1/P2 action items from library assessment - Add beginner examples: hello_kicad.rs and board_inspector.rs - Add README prerequisites section with KiCad IPC API setup guide - Add README examples section with run commands for all 3 examples - Add protocol-contract tests: CMD/RES prefix validation, PCB types catalog - Add module-level rustdoc to all client submodules - All tests pass (default + blocking features) * docs: update assessment report with completed action items Mark resolved: AP-1/AP-2/AP-3 (clippy), DR-2 (anchor), DR-3 (artifact), ST-1 (client.rs split), DR-5 (examples), DR-6 (prerequisites). Mark mitigated: AP-4 (RPC boilerplate via rpc! macro). Update baseline metrics to reflect 11-module client layout. Update risk register, action plan status, and revision history. * chore: finalize tier-1 API docs and modular client cleanup Document the public client and blocking surfaces so strict rustdoc linting passes, while keeping tier-2/3 internals lightly scoped. Also clean stale modularization references and remove leftover split-refactor dead imports/helpers to reduce maintenance drift. |
||
|---|---|---|
| .github/workflows | ||
| docs | ||
| examples | ||
| kicad@0feeca2a80 | ||
| scripts | ||
| src | ||
| test-scripts | ||
| tools/proto-gen | ||
| .gitignore | ||
| .gitmodules | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CONTRIBUTING.md | ||
| CONTRIBUTIONS.md | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
| release-plz.toml | ||
| slate.json | ||
README.md
kicad-ipc-rs
Control KiCad programmatically from Rust. The most complete, production-ready client for KiCad's IPC API — async-first with full sync support.
- 100% API coverage (57/57 KiCad v10.0.0 commands)
- Type-safe PCB item manipulation with ergonomic Rust models
- Both async and blocking APIs for any application architecture
- Zero protobuf dependencies for consumers — everything is typed Rust
Status
Beta. All KiCad v10.0.0 API commands are implemented and tested.
- Async API (default): production-ready with full feature parity
- Sync/blocking wrapper API (
feature = "blocking"): production-ready, uses dedicated Tokio runtime thread
Prerequisites
- Rust 1.70+ (edition 2021)
- KiCad 10.0.0+ running with the IPC API enabled
- The
nngtransport library is bundled automatically via nng-rs
Enabling the KiCad IPC API
- Open KiCad → Preferences → Plugins
- Check Enable IPC API
- Restart KiCad
The API socket path is auto-detected. Override with KICAD_API_SOCKET if needed.
Usage
Async API (Default)
Add to Cargo.toml:
[dependencies]
kicad-ipc-rs = "0.4.1"
tokio = { version = "1", features = ["macros", "rt"] }
Connect and query KiCad:
use kicad_ipc_rs::KiCadClient;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), kicad_ipc_rs::KiCadError> {
let client = KiCadClient::connect().await?;
// Get KiCad version info
let version = client.get_version().await?;
println!("Connected to KiCad {}", version.full_version);
// Check if a board is open
if client.has_open_board().await? {
// Get all nets in the current board
let nets = client.get_nets().await?;
println!("Found {} nets", nets.len());
// Get all tracks on the board
let tracks = client.get_items_by_type_codes(vec![
kicad_ipc_rs::PcbObjectTypeCode::new_trace()
]).await?;
println!("Found {} tracks", tracks.len());
}
Ok(())
}
Sync API (Blocking)
Enable the blocking feature for synchronous applications:
[dependencies]
kicad-ipc-rs = { version = "0.4.1", features = ["blocking"] }
use kicad_ipc_rs::KiCadClientBlocking;
fn main() -> Result<(), kicad_ipc_rs::KiCadError> {
let client = KiCadClientBlocking::connect()?;
// Get all nets and find unconnected ones
let nets = client.get_nets()?;
let unconnected: Vec<_> = nets
.iter()
.filter(|n| n.name == "unconnected")
.collect();
println!("Found {} unconnected nets", unconnected.len());
Ok(())
}
Making Changes to PCBs
All board modifications use commit sessions for safety:
use kicad_ipc_rs::{KiCadClient, CommitAction};
async fn add_track(client: &KiCadClient) -> Result<(), kicad_ipc_rs::KiCadError> {
// Start a commit session
let commit = client.begin_commit().await?;
// Create items (tracks, vias, footprints, etc.)
let items = vec![/* your PcbItem instances */];
let created_ids = client.create_items(items).await?;
// Commit the changes
client.end_commit(
commit.id,
CommitAction::Commit,
"Added new track"
).await?;
Ok(())
}
Examples
Run the included examples against a running KiCad instance:
# Minimal connection + version check
cargo run --example hello_kicad --features blocking
# Inspect board nets, layers, and origin
cargo run --example board_inspector --features blocking
# Deep-dive into current PCB selection
cargo run --example selection_deep_dump --features blocking
See the examples/ directory for full source.
KiCad Version Compatibility
This crate tracks KiCad releases. When KiCad updates their API, we update within a week. Currently supports KiCad 10.0.0.
KiCad v10.0.0 API Reference
All 57 KiCad v10.0.0 API commands are implemented:
Section Coverage
| Section | Commands | Coverage |
|---|---|---|
| Common (base) | 6 | 100% |
| Common editor/document | 23 | 100% |
| Project manager | 5 | 100% |
| Board editor (PCB) | 23 | 100% |
| Total | 57 | 100% |
Command Reference
Common (base)
| KiCad Command | Rust API |
|---|---|
Ping |
KiCadClient::ping |
GetVersion |
KiCadClient::get_version |
GetKiCadBinaryPath |
KiCadClient::get_kicad_binary_path |
GetTextExtents |
KiCadClient::get_text_extents |
GetTextAsShapes |
KiCadClient::get_text_as_shapes |
GetPluginSettingsPath |
KiCadClient::get_plugin_settings_path |
Common editor/document
| KiCad Command | Rust API |
|---|---|
RefreshEditor |
KiCadClient::refresh_editor |
GetOpenDocuments |
KiCadClient::get_open_documents, get_current_project_path, has_open_board |
SaveDocument |
KiCadClient::save_document |
SaveCopyOfDocument |
KiCadClient::save_copy_of_document |
RevertDocument |
KiCadClient::revert_document |
RunAction |
KiCadClient::run_action |
BeginCommit / EndCommit |
KiCadClient::begin_commit, end_commit |
CreateItems |
KiCadClient::create_items |
GetItems |
KiCadClient::get_items_by_type_codes, get_all_pcb_items, get_pad_netlist |
GetItemsById |
KiCadClient::get_items_by_id |
UpdateItems |
KiCadClient::update_items |
DeleteItems |
KiCadClient::delete_items |
GetBoundingBox |
KiCadClient::get_item_bounding_boxes |
GetSelection |
KiCadClient::get_selection, get_selection_summary, get_selection_details |
AddToSelection / RemoveFromSelection / ClearSelection |
KiCadClient::add_to_selection, remove_from_selection, clear_selection |
HitTest |
KiCadClient::hit_test_item |
GetTitleBlockInfo |
KiCadClient::get_title_block_info |
SaveDocumentToString |
KiCadClient::get_board_as_string |
SaveSelectionToString |
KiCadClient::get_selection_as_string |
ParseAndCreateItemsFromString |
KiCadClient::parse_and_create_items_from_string |
Project manager
| KiCad Command | Rust API |
|---|---|
GetNetClasses / SetNetClasses |
KiCadClient::get_net_classes, set_net_classes |
ExpandTextVariables |
KiCadClient::expand_text_variables |
GetTextVariables / SetTextVariables |
KiCadClient::get_text_variables, set_text_variables |
Board editor (PCB)
| KiCad Command | Rust API |
|---|---|
GetBoardStackup / UpdateBoardStackup |
KiCadClient::get_board_stackup, update_board_stackup |
GetBoardEnabledLayers / SetBoardEnabledLayers |
KiCadClient::get_board_enabled_layers, set_board_enabled_layers |
GetGraphicsDefaults |
KiCadClient::get_graphics_defaults |
GetBoardOrigin / SetBoardOrigin |
KiCadClient::get_board_origin, set_board_origin |
GetNets |
KiCadClient::get_nets |
GetItemsByNet / GetItemsByNetClass |
KiCadClient::get_items_by_net, get_items_by_net_class |
GetNetClassForNets |
KiCadClient::get_netclass_for_nets |
RefillZones |
KiCadClient::refill_zones |
GetPadShapeAsPolygon |
KiCadClient::get_pad_shape_as_polygon |
CheckPadstackPresenceOnLayers |
KiCadClient::check_padstack_presence_on_layers |
InjectDrcError |
KiCadClient::inject_drc_error |
GetVisibleLayers / SetVisibleLayers |
KiCadClient::get_visible_layers, set_visible_layers |
GetActiveLayer / SetActiveLayer |
KiCadClient::get_active_layer, set_active_layer |
GetBoardLayerName |
KiCadClient::get_board_layer_name |
GetBoardEditorAppearanceSettings / SetBoardEditorAppearanceSettings |
KiCadClient::get_board_editor_appearance_settings, set_board_editor_appearance_settings |
InteractiveMoveItems |
KiCadClient::interactive_move_items |
Documentation
- Guide: https://milind220.github.io/kicad-ipc-rs/
- API Reference: docs.rs/kicad-ipc-rs
Protobuf Source
This crate ships checked-in Rust protobuf output under src/proto/generated/.
- Consumers do not need KiCad source checkout or git submodules
- Maintainers regenerate bindings from KiCad upstream via the
kicadgit submodule - Current proto pin: KiCad
10.0.0(KICAD_API_VERSION = 10.0.0-0-g0feeca2a)
Maintainer refresh flow:
git submodule update --init --recursive
./scripts/regenerate-protos.sh
Contributing
See CONTRIBUTING.md for development workflow and commit conventions.
Issues and PRs welcome!
License
MIT