Introduction
kicad-ipc-rs is an async-first Rust client for KiCad IPC.
Project goals:
- Rust-native API for KiCad IPC commands.
- Typed models for common board/editor operations.
- Blocking wrapper parity via
feature = "blocking". - Maintainer-friendly release and proto-regeneration flow.
Current scope:
- KiCad API proto snapshot pinned in repo (
src/proto/generated/). - 56/56 wrapped command families from the current snapshot.
- Runtime compatibility verified against KiCad
10.0.0-rc1.
Core entrypoints:
- Async:
kicad_ipc_rs::KiCadClient - Blocking:
kicad_ipc_rs::KiCadClientBlocking(blockingfeature) - Error type:
kicad_ipc_rs::KiCadError
Related docs:
- Crate README: README.md
- CLI runbook: docs/TEST_CLI.md
- API docs: docs.rs/kicad-ipc-rs
Quickstart
Prereqs
- KiCad running on the same machine.
- IPC socket available (default discovery, or
KICAD_API_SOCKET). - Optional auth token in
KICAD_API_TOKENif your setup requires it.
Async API (default)
Cargo.toml:
[dependencies]
kicad-ipc-rs = "0.3.1"
tokio = { version = "1", features = ["macros", "rt"] }
use kicad_ipc_rs::KiCadClient;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), kicad_ipc_rs::KiCadError> {
let client = KiCadClient::builder()
.client_name("quickstart-async")
.connect()
.await?;
client.ping().await?;
let version = client.get_version().await?;
println!("KiCad: {}", version.full_version);
Ok(())
}
Blocking API
Cargo.toml:
[dependencies]
kicad-ipc-rs = { version = "0.3.1", features = ["blocking"] }
use kicad_ipc_rs::KiCadClientBlocking;
fn main() -> Result<(), kicad_ipc_rs::KiCadError> {
let client = KiCadClientBlocking::builder()
.client_name("quickstart-blocking")
.connect()?;
client.ping()?;
let version = client.get_version()?;
println!("KiCad: {}", version.full_version);
Ok(())
}
Environment Variables
| Variable | Purpose | Used by |
|---|---|---|
KICAD_API_SOCKET | Explicit IPC socket URI/path override | async + blocking |
KICAD_API_TOKEN | IPC auth token | async + blocking |
Next Steps
- Use
kicad-ipc-clifor rapid command checks. - Follow Validation and Testing before CI/release.
Usage Patterns
This chapter targets repeatable integration patterns for tool builders and code generators.
Pattern: Cheap Health Check
Use at process startup to validate socket + auth + server liveness.
use kicad_ipc_rs::KiCadClient;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), kicad_ipc_rs::KiCadError> {
let client = KiCadClient::connect().await?;
client.ping().await?;
Ok(())
}
Pattern: Read-only Query Pipeline
Recommended order for board-aware reads:
get_open_documents()get_nets()get_items_by_net(...)orget_items_by_type_codes(...)
Reason: fail fast on document state before expensive item traversal.
Pattern: Safe Write Session
Use begin/end commit around mutating commands.
begin_commit(...)create_items(...)/update_items(...)/delete_items(...)end_commit(..., CommitAction::Commit, ...)
If errors mid-flight: close with CommitAction::Abort/Drop per flow.
Common Pitfalls
| Pitfall | Symptom | Avoidance |
|---|---|---|
| Assume KiCad always running | connect errors at startup | explicit prereq check + ping() |
| Skip open-document check | downstream command failures | call get_open_documents() first |
| Mix sync + async API unintentionally | duplicate runtime ownership | pick one surface per process |
| Fire write commands without commit session | partial or rejected mutations | always bracket writes with commit APIs |
| Hardcode unsupported commands | AS_UNHANDLED at runtime | map/handle RunActionStatus and runtime flags |
Async vs Blocking Selection
| Requirement | Preferred API |
|---|---|
| Tokio app / async daemon | KiCadClient |
| Existing sync binary | KiCadClientBlocking |
| Lowest integration friction for scripts | KiCadClientBlocking + CLI |
Reliability Checklist
- Set explicit
client_namefor traceability. - Keep request timeout defaults unless measured need.
- Handle transport + protocol errors as recoverable boundary.
- Use typed wrappers when available; drop to raw only when needed.
Examples
Quick Version Probe (Async)
use kicad_ipc_rs::KiCadClient;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), kicad_ipc_rs::KiCadError> {
let client = KiCadClient::connect().await?;
let version = client.get_version().await?;
println!("{:?}", version);
Ok(())
}
Open Board Detection (Blocking)
use kicad_ipc_rs::KiCadClientBlocking;
fn main() -> Result<(), kicad_ipc_rs::KiCadError> {
let client = KiCadClientBlocking::connect()?;
let has_board = client.has_open_board()?;
println!("open board: {}", has_board);
Ok(())
}
CLI-first Smoke Testing
Runbook commands:
cargo run --features blocking --bin kicad-ipc-cli -- ping
cargo run --features blocking --bin kicad-ipc-cli -- version
cargo run --features blocking --bin kicad-ipc-cli -- board-open
Full command catalog: docs/TEST_CLI.md
Validation and Testing
Before handoff or release:
cargo fmt --all
cargo test
cargo test --features blocking
Evidence Pointers
- Unit tests across client/model/blocking/CLI parser paths:
- Runtime command coverage matrix:
- Runtime CLI verification flow:
CI Notes
- API/release pipeline:
.github/workflows/release-plz.yml - Book deploy pipeline:
.github/workflows/mdbook.yml
API Reference
Primary API docs live on docs.rs:
Key items:
KiCadClient(async)KiCadClientBlocking(blockingfeature)KiCadError- Typed models under
model::*