KiCad schematic analysis and connectivity assistant. Parses .kicad_sch files, resolves full net connectivity, and answers questions about components, pins, signal routing, and power rails. Can also apply simple schematic changes (add/remove net labels, add wires). Invoke for: "what connects to X pin Y", "which net is R1 pin 1 on", "trace signal from IN1 to ESP32", "show GND connections", "connect X to Y", "what components are on the 3V3 net", schematic design review questions. Proactively invoke when the user is in a KiCad project directory (contains .kicad_sch) and asks about component connections, nets, or signal paths.
You are analyzing a KiCad schematic. Follow these steps exactly.
Use Glob to find *.kicad_sch in the current directory.
Run the parser (uses the kicad-agent conda environment):
conda run -n kicad-agent python ~/.claude/skills/kicad/kicad_parse.py "<SCHEMATIC_PATH>" summary
This produces a structured text report with:
.kicad_sch files that were merged (hierarchical projects)global_label/GND/3V3SheetName::netDIO::GND1[Sheet::]net_X_Y formatIf the conda env is not available, try:
python3 ~/.claude/skills/kicad/kicad_parse.py "<SCHEMATIC_PATH>" summary
The user's request is: $ARGUMENTS
Print a compact overview:
net_X_Y format): describe them as "internal node — no net label, connects [list the pins]"Example answer format:
R2 (Resistor, Device:R):
Pin 1 → net_180.34_132.08 [internal node, shared with: Q3.2:B (base of Q3)]
Pin 2 → D18 [also on: U1.30:IO18 (ESP32 GPIO18)]
Before applying any change:
To connect a floating pin to a named net (e.g., connect R1 pin 1 at (214.63, 102.87) to GND):
python ~/.claude/skills/kicad/kicad_apply.py "<SCHEMATIC_PATH>" add-label --text GND --x 214.63 --y 102.87
To add a wire between two points:
python ~/.claude/skills/kicad/kicad_apply.py "<SCHEMATIC_PATH>" add-wire --x1 X1 --y1 Y1 --x2 X2 --y2 Y2
kicad_apply.pyuses direct raw-text editing — it does NOT round-trip through kiutils. Run it with the systempython3(notconda run) since it no longer requires kiutils.
After applying: re-run the parser to confirm the pin now shows the expected net name.
Safety rules for changes:
.kicad_sch.bak before writingAdding symbols requires a Python script — kicad_apply.py only handles labels and wires.
Write a dedicated script and apply all changes in one raw-text pass (no kiutils round-trip).
Step-by-step workflow:
1. Look up the actual pin offsets — do NOT assume them. Read the lib_symbols section of the schematic (or /usr/share/kicad/symbols/Device.kicad_sym) to find the exact (pin ... (at X Y angle)) coordinates for each pin. Common ones (confirmed in this project):
Device:R — pins at local (0, +3.81) and (0, −3.81). Placed at angle=90 (horizontal): pin1=(cx−3.81, cy), pin2=(cx+3.81, cy)Device:LED — pin K at local (−3.81, 0), pin A at (+3.81, 0). Placed at angle=180 (reversed): anode=(cx−3.81, cy), cathode=(cx+3.81, cy)world = (cx + px·cosA − py·sinA, cy − (px·sinA + py·cosA))2. Choose placement positions on the 2.54 mm grid (100 mil):
cx / 2.54 and cy / 2.54 must be integers3. Always use a direct wire from the source pin to the new component's pin. Never rely on same-name labels across a gap for connections in the same area — it is confusing for humans reading the schematic.
4. Required fields in every symbol S-expression:
(symbol
(lib_id "Device:R")
(at CX CY ANGLE)
(unit 1)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(dnp no)
(fields_autoplaced yes)
(uuid "...fresh UUID...")
(property "Reference" "R35" ...) ← VISIBLE, no hide
(property "Value" "330R" ...) ← VISIBLE, no hide
(property "Footprint" "..." ...) ← MUST have (hide yes) in effects
(property "Datasheet" "~" ...) ← MUST have (hide yes) in effects
(property "Description" "..." ...) ← MUST have (hide yes) in effects
(pin "1" (uuid "..."))
(pin "2" (uuid "..."))
(instances ← REQUIRED — without this KiCad resets ref to "R?"
(project "Neo"
(path "/PROJECT-UUID"
(reference "R35")
(unit 1)
)
)
)
)
Critical: NEVER use kiutils to_file() after adding symbols.
kiutils round-trips corrupt manually inserted symbols:
R? (missing instances block or kiutils bug)(hide yes) flags are dropped from Footprint/Datasheet properties → clutters schematic(at ...) positions are recalculated and jumbledAll edits (symbols, wires, labels) must be done as raw S-expression text insertions before the final \n) of the file. The kicad_apply.py script already does this safely for labels and wires.
5. Finding the project UUID (needed for the instances block):
import re
m = re.search(r'\(path "(/[0-9a-f-]+)"', content)
project_path = m.group(1) # e.g. "/14ec2205-6f58-47dd-8ab3-c7dcafcac86a"
6. Adding a lib symbol (e.g. Device:LED not yet in the schematic):
Extract it from /usr/share/kicad/symbols/Device.kicad_sym, rename it "Device:LED", and insert it inside the (lib_symbols ...) block before its closing ).
7. Verify after every addition by re-running the parser:
? or an unexpected unlabeled netnet_X_Y in the parser)Edge cases the parser handles automatically:
.kicad_sch, loads every sub-sheet recursively, and merges the results into one flat connectivity modelglobal_label nets (prefix /) and power-symbol nets merge across sheets; local labels and unlabeled nodes are prefixed SheetName:: to avoid false mergesValue property (GND, +3V3, etc.) IS the net name; they don't use wire labelsKnown pin offsets for common KiCad standard library symbols (verified in this project):
Device:R — pins at local (0, ±3.81). Default angle=0 (vertical): pin1 top, pin2 bottom. At angle=90 (horizontal): pin1 left=(cx−3.81,cy), pin2 right=(cx+3.81,cy)Device:LED — K at local (−3.81,0), A at local (+3.81,0). At angle=0: K left, A right. At angle=180: A left=(cx−3.81,cy), K right=(cx+3.81,cy)lib_symbols section of the schematic — embedded copies can differ from the system librarykicad_apply.py implementation notes:
python3 (no conda env required — no kiutils dependency)R?, dropped (hide yes) flags, jumbled property positionsNet naming conventions (Neo project):
/GND, /3V3, /5V, /24V — power rails (cross-sheet global labels)SheetName::GND — a sheet-local GND label NOT wired to the global GND label in that sheet (possible ERC issue)/D18–/D35 — ESP32 GPIO signals (global labels)/IN1–/IN4 — 24V digital inputs via optocouplers/O1–/O4 — ULN2803 output signals[Sheet::]net_X_Y — unlabeled internal node at schematic coordinate (X, Y); these are real connections, not errors