API Referenceο
Complete reference for kicad-sch-api. For practical examples, see RECIPES.md.
Table of Contentsο
Creating Schematicsο
create_schematic(name: str) β Schematicο
Create a new blank schematic.
import kicad_sch_api as ksa
sch = ksa.create_schematic("My Circuit")
Parameters:
name(str): Schematic name (appears in title block)
Returns: Schematic object
load_schematic(filepath: str) β Schematicο
Load an existing KiCAD schematic file.
sch = ksa.load_schematic("existing.kicad_sch")
Parameters:
filepath(str): Path to .kicad_sch file
Returns: Schematic object
Raises:
FileNotFoundError: If file doesnβt existValueError: If file is not valid KiCAD format
Component Operationsο
Schematic.componentsο
ComponentCollection object providing access to all components.
components.add(lib_id, reference, value, position, **kwargs) β Componentο
Add a component to the schematic.
resistor = sch.components.add(
lib_id="Device:R",
reference="R1",
value="10k",
position=(100, 100),
footprint="Resistor_SMD:R_0805_2012Metric"
)
Parameters:
lib_id(str): Library and component name (e.g., βDevice:Rβ)reference(str, optional): Component reference (e.g., βR1β). Auto-generated if None.value(str): Component value (e.g., β10kβ, β100nFβ)position(tuple or Point, optional): (x, y) position in mm. Auto-placed if None.footprint(str, optional): PCB footprintunit(int, optional): Unit number for multi-unit components. Default: 1component_uuid(str, optional): Specific UUID. Auto-generated if None.**properties: Additional properties as keyword arguments
Returns: Component object
Raises:
ValidationError: If lib_id invalid or reference already exists
Example:
# Minimal
r = sch.components.add("Device:R", "R1", "10k", (100, 100))
# With all options
r = sch.components.add(
lib_id="Device:R",
reference="R1",
value="10k",
position=(100, 100),
footprint="Resistor_SMD:R_0805_2012Metric",
unit=1,
Tolerance="1%",
Power="0.125W",
MPN="RC0805FR-0710KL"
)
components.get(reference: str) β Optional[Component]ο
Get component by reference.
resistor = sch.components.get("R1")
if resistor:
print(f"R1 value: {resistor.value}")
Parameters:
reference(str): Component reference
Returns: Component object or None if not found
Component Removalο
Three methods for removing components:
components.remove(reference: str) β boolο
Remove component by reference (primary method).
# Remove by reference
removed = sch.components.remove("R1")
print(f"Removed: {removed}") # True if removed, False if not found
Parameters:
reference(str): Component reference
Returns: True if removed, False if not found
Raises: TypeError if reference is not a string
components.remove_by_uuid(uuid: str) β boolο
Remove component by UUID.
# When you have the UUID
component_uuid = resistor.uuid
removed = sch.components.remove_by_uuid(component_uuid)
Parameters:
uuid(str): Component UUID
Returns: True if removed, False if not found
Use When: You have the UUID but not the reference, or working with UUIDs directly.
components.remove_component(component: Component) β boolο
Remove component object directly.
# When you have the component object
resistor = sch.components.get("R1")
if resistor:
removed = sch.components.remove_component(resistor)
Parameters:
component(Component): Component object to remove
Returns: True if removed, False if not found
Raises: TypeError if argument is not a Component instance
Use When: You have the Component object from iteration or search.
Note: When the last component of a specific lib_id is removed, the associated lib_symbol is automatically cleaned up from the schematic file.
components.filter(**criteria) β List[Component]ο
Filter components by criteria.
# By library
resistors = sch.components.filter(lib_id="Device:R")
# By value
ten_k_resistors = sch.components.filter(value="10k")
# By footprint
smd_parts = sch.components.filter(footprint="*SMD*")
# Multiple criteria
ten_k_smd_resistors = sch.components.filter(
lib_id="Device:R",
value="10k",
footprint="*SMD*"
)
Parameters:
lib_id(str, optional): Library ID to matchvalue(str, optional): Value to match (exact)value_pattern(str, optional): Value pattern (substring)reference_pattern(str, optional): Reference regex patternfootprint(str, optional): Footprint to matchin_area(tuple, optional): (x1, y1, x2, y2) bounding boxhas_property(str, optional): Must have this property
Returns: List of matching components
components.bulk_update(criteria: Dict, updates: Dict) β intο
Update multiple components at once.
# Update all resistors
count = sch.components.bulk_update(
criteria={'lib_id': 'Device:R'},
updates={'properties': {'Tolerance': '1%', 'Power': '0.125W'}}
)
print(f"Updated {count} resistors")
Parameters:
criteria(dict): Selection criteriaupdates(dict): Updates to apply
Returns: Number of components updated
Component Objectο
Represents a single component.
Propertiesο
comp = sch.components.get("R1")
# Read/write properties
comp.reference # str: "R1"
comp.value # str: "10k"
comp.footprint # Optional[str]: "Resistor_SMD:R_0805_2012Metric"
comp.position # Point: Point(x=100, y=100)
comp.rotation # float: Rotation in degrees
comp.lib_id # str: "Device:R"
comp.uuid # str: UUID
comp.properties # Dict[str, str]: All properties
# Read-only properties
comp.library # str: "Device"
comp.symbol_name # str: "R"
comp.pins # List[SchematicPin]: Pin information
Methodsο
# Property management
comp.set_property("MPN", "RC0805FR-0710KL")
comp.get_property("MPN", default="")
"MPN" in comp.properties # Check if property exists
comp.remove_property("MPN")
# Pin operations
pin = comp.get_pin("1") # Get pin by number
pin_pos = comp.get_pin_position("1") # Get absolute position
# Text effects (formatting, colors, fonts)
effects = comp.get_property_effects("Reference") # Get all effects
comp.set_property_effects("Reference", {"bold": True, "color": (255, 0, 0, 1.0)})
# Validation
issues = comp.validate() # List[ValidationIssue]
# Conversion
comp_dict = comp.to_dict() # Convert to dictionary
Text Effectsο
Get and modify text effects for component properties (Reference, Value, Footprint).
comp = sch.components.get("R1")
# Get all effects for a property
effects = comp.get_property_effects("Reference")
# Returns dictionary with:
# {
# 'position': (x, y), # Position relative to component
# 'rotation': float, # Rotation in degrees
# 'font_face': str, # Font name (e.g., 'Arial')
# 'font_size': (h, w), # Font size (height, width) in mm
# 'font_thickness': float, # Line thickness
# 'bold': bool, # Bold flag
# 'italic': bool, # Italic flag
# 'color': (r, g, b, a), # RGBA color (0-255, 0-1 alpha)
# 'justify_h': str, # 'left', 'right', 'center'
# 'justify_v': str, # 'top', 'bottom'
# 'visible': bool, # True = visible, False = hidden
# }
# Modify effects (partial updates - preserves other effects)
comp.set_property_effects("Reference", {
"color": (0, 255, 0, 1.0), # Green
"bold": True,
"font_size": (2.0, 2.0)
})
# Hide a property
comp.set_property_effects("Footprint", {"visible": False})
# Rotate and style value
comp.set_property_effects("Value", {
"rotation": 90.0,
"italic": True,
"justify_h": "left",
"color": (160, 32, 240, 1.0) # Purple
})
Supported Properties:
Reference,Value,Footprint(standard properties)Any custom property that exists in the component
Effect Properties:
position(tuple): (x, y) position relative to componentrotation(float): Rotation angle in degrees (stored in(at x y rotation)section)font_face(str): Font name (e.g., βArialβ, βCourier Newβ)font_size(tuple): (height, width) in mmfont_thickness(float): Line thickness for textbold(bool): Bold text flagitalic(bool): Italic text flagcolor(tuple): (r, g, b, alpha) - RGB 0-255, alpha 0.0-1.0justify_h(str): Horizontal justification - βleftβ, βrightβ, βcenterβjustify_v(str): Vertical justification - βtopβ, βbottomβvisible(bool): Visibility flag (False = hidden)
Notes:
Effects are merged - only specified properties are changed, others preserved
Works on both loaded components (preserves existing) and newly created components (creates defaults)
Format preservation - exact KiCAD S-expression format maintained
Wire Operationsο
Schematic.wiresο
WireCollection object providing access to all wires.
wires.add(start=None, end=None, points=None, **kwargs) β strο
Add a wire.
# Simple 2-point wire
wire_uuid = sch.wires.add(start=(100, 100), end=(150, 100))
# Multi-point wire (L-shaped)
wire_uuid = sch.wires.add(
points=[
(100, 100),
(100, 120),
(150, 120)
]
)
Parameters:
start(tuple or Point, optional): Start point for 2-point wireend(tuple or Point, optional): End point for 2-point wirepoints(List[tuple or Point], optional): List of points for multi-point wirewire_type(WireType, optional): Wire type. Default: WireType.WIREstroke_width(float, optional): Line width. Default: 0.0uuid(str, optional): Specific UUID
Returns: Wire UUID (string)
Raises:
ValueError: If neither start/end nor points provided
add_wire_between_pins(from_ref, from_pin, to_ref, to_pin) β Optional[str]ο
Connect two component pins automatically.
# Connect R1 pin 2 to R2 pin 1
wire_uuid = sch.add_wire_between_pins("R1", "2", "R2", "1")
Parameters:
from_ref(str): Source component referencefrom_pin(str): Source pin numberto_ref(str): Destination component referenceto_pin(str): Destination pin number
Returns: Wire UUID or None if components/pins not found
add_wire_to_pin(point, component_ref, pin) β Optional[str]ο
Connect a point to a component pin.
# Connect external point to R1 pin 1
sch.add_wire_to_pin((50, 100), "R1", "1")
# Using Point object
from kicad_sch_api.core.types import Point
sch.add_wire_to_pin(Point(50, 100), "R1", "1")
Parameters:
point(tuple or Point): External point coordinatescomponent_ref(str): Component referencepin(str): Pin number
Returns: Wire UUID or None if component/pin not found
wires.get(uuid: str) β Optional[Wire]ο
Get wire by UUID.
wire = sch.wires.get(wire_uuid)
wires.remove(uuid: str) β boolο
Remove wire by UUID.
removed = sch.wires.remove(wire_uuid)
wires.get_by_point(point, tolerance=None) β List[Wire]ο
Find wires near a point.
wires = sch.wires.get_by_point((100, 100), tolerance=1.0)
Connectivity Analysisο
NEW in v0.5.0 - Comprehensive electrical connectivity analysis.
are_pins_connected(ref1, pin1, ref2, pin2) β boolο
Check if two component pins are electrically connected.
# Check direct or indirect connection
if sch.are_pins_connected("R1", "2", "R2", "1"):
print("Pins are connected!")
Traces through:
Direct wire connections
Connections through junctions
Local labels (same sheet)
Global labels (cross-sheet)
Hierarchical labels (parent-child)
Power symbols (VCC, GND, etc.)
Sheet pins
Parameters:
ref1(str): First component reference (e.g., βR1β)pin1(str): First pin number (e.g., β2β)ref2(str): Second component referencepin2(str): Second pin number
Returns: True if pins are electrically connected, False otherwise
Implementation Notes:
Uses lazy-initialized connectivity analyzer
Automatically caches results
Cache invalidates on schematic changes (add/remove wires)
Always uses hierarchical mode for multi-sheet designs
get_net_for_pin(component_ref, pin_number) β Optional[Net]ο
Get the electrical net connected to a specific pin.
# Get net information
net = sch.get_net_for_pin("R1", "2")
if net:
print(f"Net name: {net.name}")
print(f"Total pins: {len(net.pins)}")
# Iterate pins on this net
for pin in net.pins:
print(f" {pin.reference}.{pin.pin_number}")
Parameters:
component_ref(str): Component referencepin_number(str): Pin number
Returns: Net object or None if pin not connected
Net Object Attributes:
name(str): Net name (from label or auto-generated)pins(Set[PinConnection]): All pins on this netlabels(Set[str]): All label names on this netis_power(bool): Whether net is a power net
PinConnection Attributes:
reference(str): Component referencepin_number(str): Pin numberposition(Point): Absolute pin position
get_connected_pins(component_ref, pin_number) β List[Tuple[str, str]]ο
Get all pins electrically connected to a specific pin.
# Get list of connected pins
connected = sch.get_connected_pins("R1", "2")
for ref, pin in connected:
print(f"Connected to: {ref}.{pin}")
Parameters:
component_ref(str): Component referencepin_number(str): Pin number
Returns: List of (reference, pin_number) tuples
Note: Does not include the queried pin itself in results.
Example - Finding All Components on a Net:
# Find all components connected to VCC
vcc_net = sch.get_net_for_pin("U1", "VCC")
if vcc_net:
components = {pin.reference for pin in vcc_net.pins}
print(f"Components on VCC: {components}")
Connectivity Cache Managementο
Connectivity analysis is automatically cached for performance:
# First query: Builds connectivity graph (slow on large schematics)
result1 = sch.are_pins_connected("R1", "2", "R2", "1")
# Subsequent queries: Use cached graph (fast)
result2 = sch.get_net_for_pin("R1", "2")
result3 = sch.get_connected_pins("R1", "2")
# Cache invalidates automatically when schematic changes
sch.wires.add((100, 100), (150, 100)) # Cache now invalid
# Next query: Rebuilds connectivity graph
result4 = sch.are_pins_connected("R1", "1", "R3", "1")
Cache Invalidation Triggers:
Adding wires
Removing wires
Adding components
Removing components
Modifying labels
Any schematic changes affecting connectivity
Hierarchy Managementο
NEW in v0.5.0 - Advanced hierarchical schematic management.
For complete documentation, see HIERARCHY_FEATURES.md.
hierarchy.build_hierarchy_tree(root_schematic, root_path) β HierarchyNodeο
Build complete hierarchy tree from root schematic.
from pathlib import Path
# Build tree
schematic_path = Path("my_project.kicad_sch")
tree = sch.hierarchy.build_hierarchy_tree(sch, schematic_path)
# Access tree
print(f"Root: {tree.name}")
for child in tree.children:
print(f" Child: {child.name} ({child.filename})")
Parameters:
root_schematic: Root Schematic objectroot_path(Path, optional): Path to root schematic file (required for loading child sheets)
Returns: HierarchyNode object representing the root
HierarchyNode Attributes:
path(str): Hierarchical path (e.g., β/β, β/sheet_uuid/β)name(str): Sheet namefilename(str): Schematic filenameschematic: Loaded Schematic objectparent(HierarchyNode): Parent nodechildren(List[HierarchyNode]): Child nodesis_root(bool): Whether this is the root node
hierarchy.find_reused_sheets() β Dict[str, List[SheetInstance]]ο
Find sheets that are used multiple times.
# Find reused sheets
reused = sch.hierarchy.find_reused_sheets()
for filename, instances in reused.items():
print(f"{filename} used {len(instances)} times:")
for instance in instances:
print(f" Path: {instance.path}")
Returns: Dictionary mapping filename β list of SheetInstance objects
SheetInstance Attributes:
sheet_uuid(str): Sheet UUID in parentsheet_name(str): Sheet namefilename(str): Referenced schematic filepath(str): Hierarchical pathschematic: Loaded Schematic objectsheet_pins(List[Dict]): Sheet pin definitions
hierarchy.validate_sheet_pins() β List[SheetPinConnection]ο
Validate sheet pin connections against hierarchical labels.
# Validate all sheet connections
connections = sch.hierarchy.validate_sheet_pins()
# Check for errors
errors = sch.hierarchy.get_validation_errors()
for error in errors:
print(f"Error: {error['pin_name']} - {error['error']}")
Returns: List of SheetPinConnection objects
SheetPinConnection Attributes:
sheet_path(str): Path to sheet instancesheet_pin_name(str): Pin namesheet_pin_type(str): Pin type (input/output/bidirectional)hierarchical_label_name(str): Matching label in childvalidated(bool): Whether connection is validvalidation_errors(List[str]): Error messages
Validation Checks:
Sheet pins have matching hierarchical labels
Pin types are compatible
Pin names match exactly
No duplicate pins
hierarchy.trace_signal_path(signal_name, start_path=None) β List[SignalPath]ο
Trace signal through hierarchical boundaries.
# Trace VCC through hierarchy
paths = sch.hierarchy.trace_signal_path("VCC")
for path in paths:
print(f"Signal: {path.signal_name}")
print(f"From: {path.start_path}")
print(f"To: {path.end_path}")
print(f"Sheet crossings: {path.sheet_crossings}")
Parameters:
signal_name(str): Signal/label name to tracestart_path(str, optional): Starting hierarchical path
Returns: List of SignalPath objects
SignalPath Attributes:
signal_name(str): Signal namestart_path(str): Starting hierarchical pathend_path(str): Ending hierarchical pathconnections(List[str]): Connection pointssheet_crossings(int): Number of sheet boundaries crossed
hierarchy.flatten_hierarchy(prefix_references=False) β Dictο
Flatten hierarchical design into single-level representation.
# Flatten design
flattened = sch.hierarchy.flatten_hierarchy(prefix_references=True)
print(f"Components: {len(flattened['components'])}")
print(f"Wires: {len(flattened['wires'])}")
# Check original locations
for ref, path in flattened['hierarchy_map'].items():
print(f"{ref} was in {path}")
Parameters:
prefix_references(bool): Whether to prefix references with sheet path
Returns: Dictionary with keys:
components(List): All componentswires(List): All wireslabels(List): All labelshierarchy_map(Dict): Mapping reference β original path
Example - Prefixed References:
# Without prefix: R1, R2, R3
# With prefix: /R1, /sheet_uuid/R2, /sheet_uuid/R3
hierarchy.visualize_hierarchy(include_stats=False) β strο
Generate text-based hierarchy tree visualization.
# Visualize tree
viz = sch.hierarchy.visualize_hierarchy(include_stats=True)
print(viz)
# Output:
# βββ Main Board (5 components, 8 wires)
# β βββ PowerSupply [power.kicad_sch] (3 components)
# β βββ MCU [mcu.kicad_sch] (12 components)
Parameters:
include_stats(bool): Include component/wire counts
Returns: String with tree visualization
Label Operationsο
Schematic.labelsο
LabelCollection object providing access to all labels.
add_label(text, position, **kwargs) β strο
Add a label (net name).
label_uuid = sch.add_label("VCC", position=(100, 50))
# With options
label_uuid = sch.add_label(
text="SDA",
position=(150, 100),
rotation=0.0,
size=1.27
)
Parameters:
text(str): Label textposition(tuple or Point): Positionrotation(float, optional): Rotation in degrees. Default: 0.0size(float, optional): Text size. Default: 1.27label_uuid(str, optional): Specific UUID
Returns: Label UUID
labels.find_by_text(text, exact=True) β List[LabelElement]ο
Find labels by text.
# Exact match
vcc_labels = sch.labels.find_by_text("VCC", exact=True)
# Substring match
power_labels = sch.labels.find_by_text("VCC", exact=False)
labels.remove(uuid: str) β boolο
Remove label by UUID.
removed = sch.labels.remove(label_uuid)
Collections APIο
All collections (components, wires, labels, etc.) inherit from BaseCollection.
Common Methodsο
# Length
count = len(sch.components)
# Iteration
for comp in sch.components:
print(comp.reference)
# Indexing by UUID
comp = sch.components[uuid]
# Indexing by position
first_comp = sch.components[0]
# Contains check
if "R1" in sch.components: # Checks reference for ComponentCollection
print("R1 exists")
# Get by UUID
comp = sch.components.get(uuid)
# Find with predicate
matching = sch.components.find(lambda c: c.value == "10k")
# Remove
removed = sch.components.remove(uuid)
# Clear all
sch.components.clear()
# Statistics
stats = sch.components.get_statistics()
Modification Trackingο
# Check if modified
if sch.components.is_modified():
print("Components have been modified")
# Reset flag (usually after save)
sch.components.reset_modified_flag()
Configurationο
Global configuration accessible via ksa.config.
Property Positioningο
# Adjust label positions
ksa.config.properties.reference_y = -2.0 # Reference label offset
ksa.config.properties.value_y = 2.0 # Value label offset
ksa.config.properties.footprint_y = 4.0 # Footprint label offset
Tolerancesο
# Position matching tolerance
ksa.config.tolerance.position_tolerance = 0.01 # mm
# Wire segment minimum length
ksa.config.tolerance.wire_segment_min = 0.005 # mm
Defaultsο
# Default values for new elements
ksa.config.defaults.project_name = "My Project"
ksa.config.defaults.stroke_width = 0.1
ksa.config.defaults.text_size = 1.27
Grid and Spacingο
# Grid settings
ksa.config.grid.size = 2.54 # KiCAD grid size (0.1 inch)
ksa.config.grid.unit_spacing = 10.0 # Multi-unit IC spacing
ksa.config.grid.component_spacing = 5.0 # Component spacing
Sheet Settingsο
# Hierarchical sheet settings
ksa.config.sheet.name_offset_y = -1.0
ksa.config.sheet.file_offset_y = 1.0
File Operationsο
Schematic.save(filepath: str = None)ο
Save schematic to file.
# Save to original path (if loaded)
sch.save()
# Save to new path
sch.save("new_circuit.kicad_sch")
Parameters:
filepath(str, optional): Save path. Uses original if None.
Raises:
ValueError: If filepath is None and schematic wasnβt loaded from file
Hierarchical Sheetsο
add_hierarchical_sheet(name, filename, position, size, **kwargs)ο
Add a hierarchical sheet.
sheet_uuid = sch.add_hierarchical_sheet(
name="Power Supply",
filename="power.kicad_sch",
position=(100, 100),
size=(80, 60)
)
Parameters:
name(str): Sheet name/titlefilename(str): Referenced schematic filenameposition(tuple or Point): Top-left corner positionsize(tuple or Point): (width, height)project_name(str, optional): Project namepage_number(str, optional): Page numberuuid(str, optional): Specific UUID
Returns: Sheet UUID
add_hierarchical_label(text, label_type, position, **kwargs)ο
Add a hierarchical label (sheet connector).
label_uuid = sch.add_hierarchical_label(
text="VIN",
label_type="input",
position=(50, 25)
)
Parameters:
text(str): Label textlabel_type(str): Type: βinputβ, βoutputβ, βbidirectionalβ, βtri_stateβ, βpassiveβposition(tuple or Point): Positionshape(str, optional): Shape styleuuid(str, optional): Specific UUID
Returns: Label UUID
Junctionsο
junctions.add(position, **kwargs) β strο
Add a junction (connection point).
junction_uuid = sch.junctions.add(position=(100, 100))
No-Connect Symbolsο
no_connects.add(position, **kwargs) β NoConnectElementο
Add a no-connect symbol.
nc = sch.no_connects.add(position=(100, 100))
Text Elementsο
texts.add(text, position, **kwargs) β TextElementο
Add text annotation.
text = sch.texts.add(
text="Important Note",
position=(100, 100),
size=2.0,
rotation=0.0
)
Validationο
Schematic.validate() β List[ValidationIssue]ο
Validate entire schematic.
issues = sch.validate()
for issue in issues:
print(f"{issue.severity}: {issue.message}")
Utilitiesο
Point Classο
from kicad_sch_api.core.types import Point
p1 = Point(100, 100)
p2 = Point(150, 150)
# Distance
dist = p1.distance_to(p2)
# Addition
p3 = p1 + p2 # Component-wise addition
# Access
x = p1.x
y = p1.y
Type Hintsο
Library provides full type hints:
from kicad_sch_api import Schematic, Component
from kicad_sch_api.core.types import Point
from typing import Optional, List
def process_schematic(sch: Schematic) -> List[str]:
"""Process schematic and return component references."""
references: List[str] = []
comp: Component
for comp in sch.components:
references.append(comp.reference)
return references
Error Handlingο
from kicad_sch_api.utils.validation import ValidationError
try:
sch.components.add("InvalidLib:Part", "R1", "10k", (100, 100))
except ValidationError as e:
print(f"Validation error: {e}")
try:
sch = ksa.load_schematic("missing.kicad_sch")
except FileNotFoundError:
print("File not found")
except ValueError as e:
print(f"Invalid file format: {e}")
Complete Exampleο
import kicad_sch_api as ksa
# Create schematic
sch = ksa.create_schematic("Complete Example")
# Add components
r1 = sch.components.add("Device:R", "R1", "10k", (100, 100))
r2 = sch.components.add("Device:R", "R2", "5k", (100, 120))
c1 = sch.components.add("Device:C", "C1", "100nF", (150, 110))
# Set properties
r1.set_property("Tolerance", "1%")
r1.set_property("Power", "0.125W")
# Connect components
sch.add_wire_between_pins("R1", "2", "R2", "1")
sch.add_wire_between_pins("R2", "2", "C1", "1")
# Add labels
sch.add_label("VIN", (100, 90))
sch.add_label("VOUT", (125, 110))
sch.add_label("GND", (150, 130))
# Add junction at connection point
sch.junctions.add((125, 110))
# Validate
issues = sch.validate()
if issues:
for issue in issues:
print(f"Warning: {issue.message}")
# Save
sch.save("complete_example.kicad_sch")
print("Schematic created successfully!")
For more examples, see:
GETTING_STARTED.md - Beginner guide
RECIPES.md - Common patterns and solutions
examples/directory - Complete working examples