Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 (blocking feature)
  • Error type: kicad_ipc_rs::KiCadError

Related docs:

Quickstart

Prereqs

  1. KiCad running on the same machine.
  2. IPC socket available (default discovery, or KICAD_API_SOCKET).
  3. Optional auth token in KICAD_API_TOKEN if 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

VariablePurposeUsed by
KICAD_API_SOCKETExplicit IPC socket URI/path overrideasync + blocking
KICAD_API_TOKENIPC auth tokenasync + blocking

Next Steps

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:

  1. get_open_documents()
  2. get_nets()
  3. get_items_by_net(...) or get_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.

  1. begin_commit(...)
  2. create_items(...) / update_items(...) / delete_items(...)
  3. end_commit(..., CommitAction::Commit, ...)

If errors mid-flight: close with CommitAction::Abort/Drop per flow.

Common Pitfalls

PitfallSymptomAvoidance
Assume KiCad always runningconnect errors at startupexplicit prereq check + ping()
Skip open-document checkdownstream command failurescall get_open_documents() first
Mix sync + async API unintentionallyduplicate runtime ownershippick one surface per process
Fire write commands without commit sessionpartial or rejected mutationsalways bracket writes with commit APIs
Hardcode unsupported commandsAS_UNHANDLED at runtimemap/handle RunActionStatus and runtime flags

Async vs Blocking Selection

RequirementPreferred API
Tokio app / async daemonKiCadClient
Existing sync binaryKiCadClientBlocking
Lowest integration friction for scriptsKiCadClientBlocking + CLI

Reliability Checklist

  • Set explicit client_name for 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

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 (blocking feature)
  • KiCadError
  • Typed models under model::*