Commit Graph

331 Commits

Author SHA1 Message Date
mixelpixx
d957a22144 Merge pull request #125 from daeng5913-create/fix/windows-kicad10-python-path
fix(windows): support KiCad 10.0 pcbnew path (bin/Lib/site-packages)
2026-04-25 19:59:09 -04:00
mixelpixx
b386bc3be5 Merge pull request #130 from 7tobias/feat/delete-trace-wildcard
feat(routing): support '*' wildcard in delete_trace net_name
2026-04-25 19:58:47 -04:00
mixelpixx
c9a98e44be Merge pull request #132 from 7tobias/fix/connect-to-net-pcb-pad-assignment
fix(connect_to_net): also assign net to PCB pad so save_project persi…
2026-04-25 19:13:28 -04:00
Eugene Mikhantyev
c62a859e0b Merge pull request #134 from vdawger/fix/import-time-logging-crash
fix: prevent import-time crash when ~/.kicad-mcp/ is not writable
2026-04-25 23:31:09 +01:00
Eugene Mikhantyev
0efcd923c1 Merge pull request #133 from johndev7000/fix/pin-locator-y-double-negation
fix: remove duplicate Y-axis negation in PinLocator.get_pin_location
2026-04-25 23:29:43 +01:00
Eugene Mikhantyev
9f932b13ef Merge pull request #127 from matthewellis/fix/jlcpcb-downloader-improvements
fix: improve JLCPCB downloader robustness and disk usage
2026-04-25 23:20:10 +01:00
Eugene Mikhantyev
0d5f5ea8a7 Merge pull request #124 from vdawger/fix/schematic-symbol-lookup-libname-ordering
fix: locate placed symbols when (lib_name) precedes (lib_id)
2026-04-25 23:10:51 +01:00
Eugene Mikhantyev
74990eabdf Merge pull request #119 from thesamprice/fix/add-component-subsheet-project-path
fix: resolve project-local sym-lib-table for schematics in sub-folders
2026-04-25 23:06:31 +01:00
Eugene Mikhantyev
86edc58168 Merge pull request #117 from thesamprice/fix/add-label-subsheet-fallback
fix: add_label falls back gracefully on sub-sheet schematics
2026-04-25 23:00:52 +01:00
William Viana
7f473e06cc fix: prevent import-time crash when ~/.kicad-mcp/ is not writable
Configuring logging at module import time hard-failed in environments
without write access to the user's home directory (sandboxed pytest
runners, restricted CI containers, read-only filesystems). The
unhandled OSError/PermissionError aborted module import and cascaded
into ~100 test failures during collection.

Wrap the FileHandler setup in try/except and fall back to console-only
logging when the log directory cannot be created. Production behavior
is unchanged - file logging in ~/.kicad-mcp/logs is still used
whenever the directory is writable.

Also picks up an isort-driven import reorder applied by the project's
pre-commit hook.
2026-04-23 21:24:54 -07:00
John Dev
1c25c85de0 fix: remove duplicate Y-axis negation in PinLocator.get_pin_location
The symbol-to-schematic y-flip was applied twice in sequence (two identical
negation blocks with matching comments), cancelling out and leaving pin
Y-coordinates mirrored about the placement Y. For symmetric passives the
bug is invisible (pin 1 and pin 2 are electrically interchangeable); for
ICs with non-equivalent pins (power pins, opamp inputs, etc.) this causes
tools that go through PinLocator — connect_to_net, add_schematic_connection,
add_schematic_net_label with componentRef+pinNumber — to place connections
at the mirror-flipped pin. Verified against kicad-cli generate_netlist
ground truth: on a Device:R placed at (111.76, 83.82), pin 1 resolves to
y=80.01 (actual) vs y=87.63 (pre-fix).

This is a regression of PR #103, which originally fixed the y-negation;
the redundant second block was added subsequently.

Includes a regression test with both a straight Device:R and a rotated
Device:C to exercise the y-flip + rotation pipeline.
2026-04-23 19:19:14 +01:00
Tobias Welz
3a172f0448 fix(connect_to_net): also assign net to PCB pad so save_project persists it
connect_to_net and connect_passthrough previously only touched the
schematic: a wire stub plus a net label were added via
ConnectionManager, but the corresponding pad on the .kicad_pcb was
never updated.

pcbnew.SaveBoard() silently drops every net that is not referenced by
at least one board element (pad/track/via/zone). A net that exists
only in the schematic therefore disappears on save, and in KiCad the
board's ratsnest never shows anything.

Fix:
- new _assign_net_to_pad(component_ref, pin_name, net_name):
  ensures the net exists on the board (creates NETINFO_ITEM if not)
  and sets it on the matching pad of the matching footprint.
- _handle_connect_to_net calls it after the schematic op when
  self.board is loaded.
- _handle_connect_passthrough parses ConnectionManager's 'connected'
  entries ('J1/1 <-> J2/1 [PIN_1]') and assigns nets to both pads.
- register 'connect_to_net' in _BOARD_MUTATING_COMMANDS so the
  existing auto-save path persists the pad assignment to disk.
2026-04-23 14:07:59 +02:00
Tobias Welz
b19d341daf feat(routing): support '*' wildcard in delete_trace net_name
Passing net_name='*' now deletes all tracks on the board (respecting
the include_vias flag). Useful for wiping a test layout before
re-routing without having to iterate every net by name.
2026-04-23 14:04:21 +02:00
Matthew Ellis
985fca108e style: add return type hints to all function signatures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 03:04:09 +01:00
Matthew Ellis
7b6d327688 fix: improve JLCPCB downloader robustness and disk usage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 02:56:43 +01:00
mixelpixx
a8684a1f97 Add link to official forum in README 2026-04-22 14:14:24 -04:00
mixelpixx
00c3eb9dd2 Revise forum link and add help section
Updated forum link and added a help section.
2026-04-22 09:18:39 -04:00
mixelpixx
92419dba2e Update README with new forum link
Added a note about the new forum for community discussions.
2026-04-22 09:16:55 -04:00
mixelpixx
a3ee609742 Add announcement for new forum in README 2026-04-22 09:15:30 -04:00
TE603
1a14a45881 fix(windows): add KiCad 10.0 bin/Lib/site-packages to Python path detection
KiCad 10.0 on Windows ships pcbnew.py under bin/Lib/site-packages rather
than the lib/python3/dist-packages path used by KiCad 9.x. Without this
path the MCP server's Python process fails to import pcbnew and exits
immediately with "Failed to import pcbnew module - KiCAD Python API not found".

Changes:
- Prioritise 10.0 in the version list so the newer path is checked first
- Add bin/Lib/site-packages check before the existing lib/python3/dist-packages
  check for every version, so both layouts are supported side-by-side

Note: the pcbnew extension is compiled against KiCad's bundled Python 3.11,
so callers must also set KICAD_PYTHON to the KiCad python.exe
(C:\Program Files\KiCad\10.0\bin\python.exe) to avoid a DLL version
conflict when the system Python differs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 16:00:43 +09:00
William Viana
e96637c6c3 fix: locate placed symbols when (lib_name) precedes (lib_id)
KiCad serialises rescued or locally-customised library entries with an
extra (lib_name "...") child before (lib_id "..."):

    (symbol
      (lib_name "RESISTOR_0603_4")
      (lib_id "MF_Passives:RESISTOR_0603")
      (at 132.08 44.45 90)
      ...)

The block-matching regex in _handle_get_schematic_component,
_handle_edit_schematic_component, and _handle_delete_schematic_component
required (lib_id IMMEDIATELY after (symbol, so any placed component
using this form was silently invisible to lookup. The user-visible
symptom is "Component '<ref>' not found in schematic" even though the
component is plainly present (and reachable through list / IPC paths).
This bug also affected set/remove_schematic_component_property and the
existing footprint/value/reference rewriting paths in edit, since they
all share the same lookup code.

The parent-position lookup used a similarly-strict regex
((symbol (lib_id "...") (at ...))), which silently fell back to (0,0)
on (lib_name)-first symbols and caused new properties added through
the custom-properties path to anchor at the schematic origin instead
of the parent symbol.

Fix: relax the symbol-block opening pattern to (symbol\s+\( — matching
any opening paren after (symbol — and read the symbol's origin from
the first (at ...) inside the block. Library-definition entries inside
(lib_symbols ...) are still excluded by the existing range check
(they use the (symbol "name" ...) form with a quoted string, not a
paren).

Adds 7 regression tests in TestLibNameBeforeLibIdOrdering using a
real-world (lib_name)-first resistor block, covering get / edit /
set-property / remove-property / delete and verifying that newly
added properties anchor to the symbol origin instead of (0, 0).
2026-04-21 10:12:52 -07:00
mixelpixx
28d9f3353e Merge pull request #115 from thesamprice/test/add-schematic-component-unit
test: add unit parameter tests for add_schematic_component
2026-04-21 09:15:59 -04:00
mixelpixx
738f652eab Merge pull request #118 from thesamprice/fix/delete-label-all-types
fix: delete_label matches global_label and hierarchical_label types
2026-04-21 09:01:27 -04:00
mixelpixx
1b2b98fd45 Merge pull request #116 from thesamprice/feat/ipc-annotation-generator
feat: Claude-powered annotation generator for KiCad IPC API tools
2026-04-21 09:00:49 -04:00
mixelpixx
4d8dcf7dbb Merge pull request #103 from tecnovel/main
fix: correct pin location, symbol reference dedup, and ERC violation parsing
2026-04-21 09:00:09 -04:00
mixelpixx
74b4e717f8 Merge pull request #120 from thesamprice/feat/hierarchical-sync
feat: walk all sub-sheets to build hierarchical pad→net map for sync_schematic_to_board
2026-04-21 08:59:39 -04:00
mixelpixx
34feb5dcce Merge pull request #122 from vdawger/feat/multi-sheet-net-connectivity
feat: multi-sheet net connectivity + sexp-based parsing reliability
2026-04-21 08:58:51 -04:00
mixelpixx
cd6f9af366 Merge pull request #123 from vdawger/feat/schematic-component-custom-properties
feat: support arbitrary custom properties on schematic components
2026-04-21 08:58:05 -04:00
William Viana
4d7843c03a feat: support arbitrary custom properties on schematic components
Promotes BOM / sourcing fields (MPN, Manufacturer, DigiKey_PN, LCSC,
JLCPCB_PN, Voltage, Tolerance, Dielectric, ...) to first-class citizens
on placed schematic symbols.

New MCP tools:
- set_schematic_component_property: add or update one custom property
  on a component (convenience wrapper around edit_schematic_component).
- remove_schematic_component_property: delete one custom property.
  The four built-in fields (Reference, Value, Footprint, Datasheet) are
  protected and rejected.

edit_schematic_component enhancements:
- New `properties` parameter: map of property name to either a string
  value or a full spec object { value, x?, y?, angle?, hide?, fontSize? }.
  Adds the property when missing, otherwise updates the existing field
  (and optionally its label position / visibility). Lets a single tool
  call attach an entire BOM payload to a component.
- New `removeProperties` parameter: list of custom property names to
  delete in the same call.
- Property values are now backslash-escaped so descriptions containing
  a double-quote or a backslash no longer corrupt the .kicad_sch file.
- New properties default to (hide yes) so they appear in BOM exports
  without cluttering the schematic canvas.

get_schematic_component description clarified to highlight that it
already returns every field on the symbol, including custom ones.

New MCP prompt component_sourcing_properties guides agents through the
conventional property names recognised by downstream BOM tooling and
the recommended call sequence.

Implementation (python/kicad_interface.py):
- _PROTECTED_PROPERTY_FIELDS frozenset
- _escape_sexpr_string / _find_matching_paren static helpers
- _set_property_in_block / _set_hide_on_property /
  _remove_property_from_block surgical text-level edits that preserve
  formatting and the property's UUID
- _handle_edit_schematic_component rewritten to orchestrate
  add/update/remove and return a per-property summary
- New handlers _handle_set_schematic_component_property and
  _handle_remove_schematic_component_property registered in the
  command dispatch table

Tests (tests/test_schematic_component_properties.py):
32 tests covering escape helper, paren matcher, add/update/remove
(single + batched), full spec dicts, default position, default
(hide yes), special-character escaping, UUID preservation, protected
built-in field rejection, no-op removal, both new convenience tools,
and input validation. All 590 tests in the project still pass.

Docs: README, SCHEMATIC_TOOLS_REFERENCE, TOOL_INVENTORY, CHANGELOG.
2026-04-20 17:36:38 -07:00
William Viana
046f33d876 feat: multi-sheet net connectivity + sexp-based parsing reliability
Adds robust multi-sheet (hierarchical) net connectivity for KiCad
schematics and switches the wire/label parsing to a direct sexpdata
pipeline that bypasses kicad-skip's collection iteration, which was
silently dropping wires, labels, and symbol instances on real-world
schematics.

python/commands/wire_connectivity.py
  - New sexpdata helpers: _load_sexp, _parse_wires_sexp,
    _parse_labels_sexp, _parse_symbol_instances_sexp,
    _parse_hierarchical_labels_sexp, _discover_sub_sheets.
  - _build_adjacency now detects T-junctions (endpoint landing on
    another wire's interior segment) so adjacency captures connections
    KiCad doesn't represent as separate wire segments.
  - _find_connected_wires gains an interior-segment fallback so labels
    placed mid-wire still seed BFS correctly.
  - _parse_virtual_connections gathers label / global_label /
    hierarchical_label and power-symbol pin positions, with a
    kicad-skip fallback for unit tests that mock the schematic.
  - _find_pins_on_net rebuilds pin positions from sexpdata symbol
    instances (with mirror_x/mirror_y/rotation handling) and uses a
    plus/minus 1 IU tolerance for floating-point edge cases.
  - get_connections_for_net walks the top sheet plus every recursively
    discovered sub-sheet, deduping pins across sheets.

python/commands/pin_locator.py
  - lib_id matching now falls back to a bare-name + unit-suffix match
    so instances like "stat-tis-custom:BAT_18650" resolve to
    lib_symbols entries like "BAT_18650_3".
  - Pin position math now y-negates lib_symbols coords, applies
    mirror_x/mirror_y in local coords before rotation, and propagates
    the same transform into get_pin_orientation so downstream callers
    get a correct outward angle for mirrored symbols.

python/commands/connection_schematic.py
  - generate_netlist now collects nets from both label and
    global_label and routes them through get_connections_for_net so
    netlists reflect cross-sheet connectivity instead of single-sheet
    label-only nets.

python/kicad_interface.py
  - list_schematic_nets aggregates net names across the top sheet and
    all sub-sheets via the sexp helpers, then resolves connections
    using get_connections_for_net.
  - get_net_connections delegates to get_connections_for_net for
    consistent multi-sheet results.
2026-04-20 15:59:22 -07:00
Noah Piqué
ef42eb60bb fix: correct pin location calculation and symbol reference dedup in kicad-skip
Three bugs fixed in the schematic component and pin locator pipeline:

1. component_schematic: remove redundant symbol.append() after clone()
   kicad-skip's clone() already inserts the raw element into the schematic
   tree. The subsequent NamedCollection.append() detects the reference as
   already registered (from the elementRename triggered by setting
   property.Reference.value) and renames it "R1_" with a trailing
   underscore, causing all subsequent pin lookups to fail.

2. pin_locator: negate lib y coordinate before rotation
   lib_symbols in .kicad_sch use library y-up convention; schematic
   coordinates use y-down. get_pin_location now negates pin_rel_y before
   applying rotation, matching KiCad's own transform order (same approach
   as _transform_local_point in schematic_analysis.py).

3. pin_locator: add .rstrip("_") guard in all symbol reference lookups
   Defensive guard against any residual cases where kicad-skip writes a
   trailing underscore to the Reference property value.

Also fixes the self-test script to use template_with_symbols.kicad_sch
(which contains placed _TEMPLATE_* symbols) rather than the expanded
template (which only contains lib_symbols definitions and has no cloneable
instances).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 13:10:47 +02:00
Eugene Mikhantyev
5b7434fdef Merge pull request #121 from mixelpixx/feat/schematic-text-tools
feat: add add_schematic_text and list_schematic_texts tools
2026-04-19 23:14:33 +01:00
Eugene Mikhantyev
e5916005a0 feat: add add_schematic_text and list_schematic_texts tools
Adds two new MCP tools for working with free-form text annotations
(SCH_TEXT elements) in KiCad schematics:

- add_schematic_text: place a text note with optional angle, font size,
  bold/italic, and justification
- list_schematic_texts: list all text annotations with optional
  case-insensitive substring filter

Includes WireManager.add_text / list_texts using _text_insert + sexpdata,
handler dispatch in KiCADInterface, TypeScript tool definitions, registry
entry, reference doc updates, and 30 unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 21:26:39 +01:00
Samuel Price
8a4281211e test: add unit tests for _build_hierarchical_pad_net_map
15 tests covering:
- Empty schematic → empty maps
- Global / local / hierarchical labels at pin endpoints
- Net propagation through one and two wire hops
- Unconnected pin stays absent from map
- Power (#PWR) and flag (#FLG) symbols excluded from component map
- Components in sub-sheets collected alongside top-level components
- 90° rotated symbol produces correct absolute pin positions

Uses MagicMock skip.Schematic objects patched in both the walker
import and commands.pin_locator module namespace; lib_symbols are
provided in real on-disk .kicad_sch files so sexpdata parsing runs
without mocking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:52:02 -04:00
Samuel Price
0cff3c749c feat: walk all sub-sheets to build hierarchical pad→net map for sync
Hierarchical KiCad schematics store all components in sub-sheets;
the top-level .kicad_sch only contains sheet references. The previous
sync_schematic_to_board implementation called generate_netlist on the
top-level file only, which has no components, so it always returned
0 pads assigned.

Replace with _build_hierarchical_pad_net_map which:
- rglobs all .kicad_sch files in the project directory
- For each sheet, collects label positions from label, global_label,
  and hierarchical_label via skip.Schematic
- Adds power symbol (#PWR/#FLG) positions using their Value as net name
- Builds a wire adjacency graph and BFS-propagates net names through
  wire segments to reach pins not directly under a label
- Calls PinLocator.get_all_symbol_pins to get absolute pin positions,
  then matches to the propagated net map within 0.5 mm tolerance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:48:01 -04:00
Samuel Price
91f4a05a00 feat: load IPC API annotations at startup to enrich tool descriptions
Adds python/annotations/loader.py (AnnotationLoader) which resolves MCP
tool names to KiCad IPC proto message annotations using three layers:
  1. Explicit TOOL_TO_PROTO mapping for non-obvious name pairs
  2. Automatic snake_case → PascalCase conversion
  3. Suffix-stripped variants (get_nets_list → GetNets)

Integrates into kicad_interface.py tools/list handler:
  - Tools with existing schemas: enrich_schema() adds blocking/interactive
    ToolAnnotations hints and fills description gaps
  - Tools without schemas (fallback): gets a real description from the
    IPC annotation instead of the generic "KiCAD command: <name>" string

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:15:43 -04:00
Samuel Price
8253550715 data: add generated KiCad IPC API tool annotations (master, 73 messages)
Generated by scripts/generate_tool_annotations.py --fetch-from-gitlab --use-cli.
Covers all command messages across board, schematic, and common proto files.
Stored in python/annotations/ (data/ is gitignored for large JLCPCB databases).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:15:43 -04:00
Samuel Price
9142e6700d feat: add --use-cli backend for Claude monthly plan users
Adds a second annotation backend that shells out to the 'claude' CLI
(Claude Code) instead of calling the Anthropic SDK. This allows users
with a Claude.ai monthly subscription to run the annotation script
without needing an API key.

The SDK backend (default) still uses prompt caching on the proto context
block for cheaper repeated/resumed runs. The CLI backend skips caching
but works out of the box with a Claude.ai account.

Usage:
    # Monthly plan (no API key)
    python scripts/generate_tool_annotations.py --fetch-from-gitlab --use-cli

    # API key (with prompt caching)
    python scripts/generate_tool_annotations.py --fetch-from-gitlab

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:15:43 -04:00
Samuel Price
e54721cd7c feat: add generate_tool_annotations.py script for Claude-powered proto annotation
Reads KiCad's IPC API proto definitions and uses the Claude API to generate
rich, user-facing descriptions for MCP tool metadata. The output JSON file
can be loaded by an MCP server at startup to annotate auto-generated tools.

Features:
- Fetches proto files from KiCad GitLab or loads from a local checkout
- Pure-Python proto parser (no protoc dependency)
- Prompt caching on the static proto context block — re-runs are cheap
- --resume to skip already-annotated messages after an interrupted run
- --dry-run to preview what would be annotated without calling the API
- Reports cache hit/write/read token counts after each API call

Usage:
    python scripts/generate_tool_annotations.py --fetch-from-gitlab
    python scripts/generate_tool_annotations.py --proto-dir /path/to/kicad/api/proto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:15:43 -04:00
Samuel Price
c53c188f8d fix: use KICAD_PYTHON env var instead of hardcoded Windows path
The Python executable and PYTHONPATH were hardcoded to Windows paths,
causing the server to fail silently on macOS/Linux. Now reads
KICAD_PYTHON from the environment (set by setup-macos.sh) with
python3 as the fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:15:43 -04:00
Samuel Price
6578667197 fix: resolve project-local sym-lib-table for schematics in sub-folders
When add_schematic_component is called with a schematic that lives in a
sub-folder (e.g. sheets/rs485.kicad_sch), the handler derived the project
path as schematic.parent — which in a hierarchical project is the sheets/
directory, not the project root.  Any project-local symbol library declared
in sym-lib-table (using ${KIPRJMOD}) is invisible to DynamicSymbolLoader
from that directory, causing "Symbol 'X' not found in library 'Y'" even
though the library file and sym-lib-table entry both exist.

Fix: walk the ancestor chain from the schematic file upward until a
directory is found that contains a sym-lib-table file or a .kicad_pro
file, then use that as the project root for library resolution.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:02:54 -04:00
Samuel Price
1767a269b0 fix: delete_label matches global_label and hierarchical_label types
WireManager.delete_label only checked for Symbol("label") when scanning
the schematic s-expression list, so it silently skipped and failed to
delete global_label and hierarchical_label elements — returning False
with "No matching label found" even when a visible label existed at the
given coordinates.

Fix: collect all three label-like symbol types into a set and use `in`
instead of `==` for the type check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:02:30 -04:00
Samuel Price
6e56ccdd59 fix: add_label falls back gracefully on sub-sheet schematics
In hierarchical KiCad designs, sub-sheets (.kicad_sch files referenced
via (sheet ...) blocks) do not have a (sheet_instances) section — that
only appears in the top-level schematic.

WireManager.add_label was returning False with a logged error whenever
no (sheet_instances) marker was found, making it impossible to add any
net label (local, global, or hierarchical) to a sub-sheet.

Fix: fall back to inserting before the final item of the s-expression
list, which is equivalent to appending before the closing ')' of the
outer (kicad_sch ...) block.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 12:02:03 -04:00
Samuel Price
b3940b9331 test: add unit parameter tests for add_schematic_component
Covers create_component_instance and _handle_add_schematic_component:
- default unit=1 behaviour
- explicit unit 2 and 4 written to (unit N) in schematic S-expression
- (instances ...) block also records the correct unit
- multiple units of the same reference placed independently
- handler param validation (missing schematicPath, missing component)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:15:02 -04:00
Samuel Price
78e3b8860a feat: add unit parameter to add_schematic_component for multi-unit symbols
Allows placing a specific unit (A=1, B=2, C=3, …) of a multi-unit KiCad
symbol rather than always defaulting to unit 1. Required for quad
optocouplers, dual op-amps, and other multi-unit parts where each channel
must be placed independently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 10:11:15 -04:00
Tom
c4bcc34894 Merge pull request #113 from thesamprice/fix/mac-python-path
fix: use KICAD_PYTHON env var instead of hardcoded Windows path
2026-04-19 13:55:19 +02:00
Eugene Mikhantyev
e164f12ffa tests: add regression tests for pin location y-axis, reference trailing underscore, and clone dedup
Covers the three bugs fixed in the previous commit:
- TestAddComponentNoTrailingUnderscore (integration): verifies clone() + no extra append()
- TestPinLocatorYAxisNegation (unit): rotation=0 and 90° cases with y-negation
- TestPinLocatorReferenceRstrip (unit): lookup tolerates 'R1_' artifact from kicad-skip

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:42:08 +01:00
Noah Piqué
ab2500fb8d fix: correct pin location calculation and symbol reference dedup in kicad-skip
Three bugs fixed in the schematic component and pin locator pipeline:

1. component_schematic: remove redundant symbol.append() after clone()
   kicad-skip's clone() already inserts the raw element into the schematic
   tree. The subsequent NamedCollection.append() detects the reference as
   already registered (from the elementRename triggered by setting
   property.Reference.value) and renames it "R1_" with a trailing
   underscore, causing all subsequent pin lookups to fail.

2. pin_locator: negate lib y coordinate before rotation
   lib_symbols in .kicad_sch use library y-up convention; schematic
   coordinates use y-down. get_pin_location now negates pin_rel_y before
   applying rotation, matching KiCad's own transform order (same approach
   as _transform_local_point in schematic_analysis.py).

3. pin_locator: add .rstrip("_") guard in all symbol reference lookups
   Defensive guard against any residual cases where kicad-skip writes a
   trailing underscore to the Reference property value.

Also fixes the self-test script to use template_with_symbols.kicad_sch
(which contains placed _TEMPLATE_* symbols) rather than the expanded
template (which only contains lib_symbols definitions and has no cloneable
instances).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:31:14 +01:00
Eugene Mikhantyev
f494f5fb37 chore: untrack CLAUDE.md and add to .gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:24:50 +01:00
Eugene Mikhantyev
c8f6a58116 feat: add move_schematic_net_label tool
Moves a net label (local, global, or hierarchical) to a new position in
place, avoiding the error-prone delete-then-re-add workflow. Supports an
optional currentPosition disambiguator and labelType filter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 23:14:29 +01:00