| name | schemdraw-circuit-generator |
| description | Generate professional circuit diagrams using schemdraw Python library. Creates vector graphics (SVG/PDF/PNG) from natural language descriptions. Components: resistors, capacitors, inductors, diodes, transistors, opamps, ICs, logic gates, etc. Use when: (1) User requests circuit diagrams or schematics, (2) User wants publication-quality output, (3) User needs SVG/PDF for documentation, (4) Complex circuits with ICs/opamps/digital logic, (5) User mentions schemdraw or wants alternative to ASCII circuits. |
Schemdraw Circuit Generator
Generate professional, publication-quality circuit diagrams using schemdraw Python library. Outputs to vector formats (SVG, PDF) or raster (PNG).
Quick Start Workflow
🎯 RECOMMENDED: Incremental Conversational Approach
This workflow builds diagrams step-by-step with visual confirmation at each stage. Use this for complex circuits or when starting fresh.
A. Connection List - Write explicit connection list showing all component pins
B. Incremental Build Loop - Build one component/section at a time:
-
Add ONE component or connection (e.g., "IC only", "add GND connection", "add R1")
-
Execute - Run Python script and save SVG
-
Visual Check - Generate screenshot via HTML wrapper + headless browser
-
User Confirmation - Show screenshot, get approval before proceeding
-
REPEAT - Go back to step 1 for next component until circuit complete
Why this works:
- Catches issues immediately when they occur
- Easy to debug single changes
- User can guide spacing, positioning, and layout decisions
- Prevents compound errors that are hard to untangle
C. Final Verification - Once all components added:
- Generate final screenshot
- Trace each connection from Step A connection list
- Verify all component values, labels, pin numbers present
D. Complete - Deliver connection list AND final diagram
⚡ ALTERNATIVE: All-at-Once Approach (Only for simple circuits or experienced users)
Use this workflow ONLY when:
- Circuit is simple (< 5 components)
- You have high confidence in layout
- User explicitly requests complete diagram in one shot
A. Connection List - Write explicit connection list showing all component pins
B. Generate Complete Code - Create schemdraw code implementing ALL connections
C. Execute - Run Python script and save SVG
D. Visual Verification (MANDATORY) - Perform comprehensive visual assessment
- Generate screenshot via HTML wrapper + headless browser
- LIST ALL PROBLEMS FIRST (don't fix one-by-one - you'll forget issues!)
- Apply ALL fixes at once
- Confirm with fresh screenshot
- REPEAT until all problems resolved
E. Final Confirmation - Trace each signal path from connection list
- If violations found: Return to B with fixes
- If clean: Proceed to F
F. Complete - Deliver both connection list AND diagram
⚠️ Warning: All-at-once approach often requires multiple fix iterations for complex circuits. Incremental approach is more reliable.
Visual Verification Checklist (MANDATORY)
🚨 CRITICAL REALITY: Only Human Visual Feedback is Reliable
AI visual assessment is NOT reliable for layout verification. AI may report "all connections traceable" while humans see obvious layout problems. Therefore:
- ✅ Generate screenshots for HUMAN review - Always provide visual output
- ✅ Wait for human feedback - Don't make assumptions about visual quality
- ❌ Don't trust AI visual verification - It misses layout issues humans easily spot
- ❌ Don't claim "complete" without user confirmation - User must see and approve
The Human-Driven Verification Loop
This is like HTML+CSS development - requires human eyes to judge visual quality.
- GENERATE SCREENSHOT - Create visual output for user to review
- SHOW TO USER - Present screenshot and ask for feedback
- LISTEN TO HUMAN FEEDBACK - User will identify spacing, overlap, or clarity issues
- FIX BASED ON USER INPUT - Apply changes user requests
- REPEAT - Generate new screenshot, show to user, iterate until approved
Key insight: Users see layout problems AI cannot detect. Trust human feedback over AI assessment.
Visual Verification Categories
1. Connection Visibility Test
"Technically connected" ≠ "Visually connected"
For each connection in your connection list:
- ✅ Can you visually TRACE the line end-to-end?
- ✅ Are junction dots visible at split points?
- ❌ Are lines overlapping IC edges? (Human can't see the connection!)
- ❌ Are lines hidden behind component bodies?
- ❌ Are connection points ambiguous?
Common failure: Line connects to IC pin at the edge of the IC box → looks disconnected even though code is correct.
Fix: Route connections AWAY from IC edges using Manhattan routing:
elm.Line().at(junction).to(ic.PIN)
elm.Line().at(junction).down(0.5)
elm.Line().left(SMALL_SPACING)
elm.Dot()
elm.Line().down(0.5)
elm.Dot()
elm.Line().right(SMALL_SPACING + 1.0)
2. Label Overlap Detection
🚨 CRITICAL RULE: Labels must NEVER overlap component symbols
Common overlap zones:
- Labels on component symbols - ❌ FORBIDDEN (e.g., "10kΩ" text on resistor zigzag)
- Adjacent components on same signal path (R1 ↔ R2)
- IC center label ↔ pin labels (IC name ↔ VOUT)
- Component labels ↔ value labels
- Labels ↔ junction dots or lines
Visual test questions:
- ❌ Is label text sitting ON TOP of component symbol? (resistor, capacitor, inductor)
- ❌ Are any characters touching between different labels?
- ❌ Is label text crowded or cramped?
- ✅ Can you clearly read each label independently?
- ✅ Can you see the complete component symbol without text obscuring it?
Fix priority order:
-
First: Increase spacing - Most effective, cleanest solution
HORIZONTAL_SPACING = 1.5
VERTICAL_SPACING = 1.5
SMALL_SPACING = 0.75
-
Second: Adjust label position - Change loc parameter
elm.Resistor().label('R1\n10kΩ', loc='top', ofst=0.2)
elm.Resistor().label('R2\n1kΩ', loc='left')
-
Third: Reduce font size - Only if spacing isn't feasible
.label('U2\nLM2596S', fontsize=10)
-
Fourth: Add offset - Fine-tune position
.label('IC', ofst=-0.3)
3. Line Overlap Detection
🚨 CRITICAL RULE: Lines touching IC edges = Connection ambiguity
Problem areas:
- Lines touching/overlapping IC box edges - ❌ FORBIDDEN ("Is this connected?" - impossible to tell!)
- Lines crossing component bodies
- Lines crossing other lines without junction
- Lines crossing ground symbols
Fix rules:
- NEVER use
.to(ic.PIN) directly - creates line touching IC edge
- Use
.at() to position connections explicitly
- Use Manhattan routing (horizontal → vertical → horizontal only)
- Add intermediate junction dots to clarify path
- Route around component bodies, not through them
- Leave visible gap between IC edge and incoming lines
Example - Correct IC connection:
elm.Line().at(junction).to(ic.VIN)
elm.Line().at(junction).right(1.0)
4. Definition of "Complete"
A diagram is complete ONLY when:
- ✅ Code executes without errors
- ✅ SVG generates successfully
- ✅ USER has visually reviewed screenshot and approved (MOST IMPORTANT)
- ✅ USER confirms all connections are traceable
- ✅ USER confirms no visual issues (overlaps, spacing, clarity)
- ✅ Every item from connection list is verified in diagram
🚨 CRITICAL: Never claim "complete" without explicit user approval of visual output!
AI cannot reliably assess visual quality. Only human confirmation counts.
Screenshot Generation for USER Review
Purpose: Generate visual output for HUMAN evaluation, not AI assessment.
Use HTML wrapper + headless browser to create screenshots for user review. The headless-browser skill is an external dependency (installed from Takazudo/zudo-test-wisdom — not part of this repo). If it isn't installed, degrade gracefully with a warning instead of failing the whole workflow:
python3 /tmp/circuit.py
cat > /tmp/view_diagram.html << 'EOF'
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Check</title>
<style>
body{margin:20px;background:white;display:flex;justify-content:center;align-items:center;min-height:100vh;}
svg{border:2px solid
</style>
</head><body>
[Paste SVG content here]
</body></html>
EOF
if [ -f "$HOME/.claude/skills/headless-browser/scripts/headless-check.js" ]; then
node $HOME/.claude/skills/headless-browser/scripts/headless-check.js \
--url file:///tmp/view_diagram.html \
--screenshot viewport
else
echo "headless-browser skill not installed (external: Takazudo/zudo-test-wisdom) — skipping screenshot check"
fi
Then READ the screenshot and perform comprehensive visual assessment (when a screenshot was produced).
Common IC Connection Patterns (Context7 Reference)
When working with ICs, query context7 for proper connection syntax:
topic: "IC integrated circuit pin connection"
topic: "wire routing shapes manhattan"
topic: "element positioning at anchor"
Key IC patterns learned:
- IC connects via sequential flow - current position flows to first left pin automatically
- Use
.at(ic.pinname) to start FROM a specific pin
- Use
.at(junction) BEFORE routing TO a pin to avoid edge overlap
- Pin names are anchors:
ic.VIN, ic.GND, ic.FB, ic.VOUT
Example of proper IC connection:
elm.Dot()
pre_ic_junction = d.here
ic = elm.Ic(pins=[...])
elm.Line().at(pre_ic_junction).down(1.0)
elm.Dot()
elm.Line().right(1.0)
Using Context7 for Documentation
CRITICAL: Schemdraw has extensive features. When you need specific syntax, advanced features, or uncommon components, use context7:
mcp__context7__get-library-docs(
context7CompatibleLibraryID: "/cdelker/schemdraw",
mode: "code",
topic: "your specific topic"
)
When to use context7:
- Uncommon components not in references/components.md
- Advanced features (custom elements, annotations, etc.)
- Specific IC pinout configurations
- Latest API changes or new features
- Troubleshooting unusual errors
Examples:
topic: "opamp operational amplifier circuits"
topic: "transistor bjt npn pnp"
topic: "wire routing shapes"
topic: "seven segment display multiplexer"
Installation
pip install schemdraw
Dependencies: numpy, pillow (for PNG export), matplotlib (optional backend)
Core Concepts
Drawing Context
All diagrams use context manager:
import schemdraw
from schemdraw import elements as elm
with schemdraw.Drawing(file='output.svg') as d:
elm.Resistor().label('1kΩ')
elm.Capacitor().down().label('10µF')
Element Chaining
Elements chain sequentially, each picking up where last ended:
elm.Resistor().right().label('R1')
elm.Capacitor().down().label('C1')
elm.Line().left()
Directional Methods
.up(), .down(), .left(), .right() - Cardinal directions
.theta(angle) - Arbitrary angle in degrees
- Optional length:
.up(length=2)
Positioning
.at(position) - Place at specific location or anchor
.to(position) - Draw to endpoint
.toy(y) / .tox(x) - Manhattan routing
.anchor(name) - Set which part is positioned
Anchors
Elements have named connection points:
- Two-terminal:
start, end, center
- Transistors:
base, collector, emitter (BJT) or gate, drain, source (FET)
- Opamps:
in1, in2, out, vd, vs
- ICs: Custom pin names
Labels
elm.Resistor().label('R1')
elm.Resistor().label('$R_1$')
elm.Resistor().label('1kΩ', loc='bottom')
elm.Capacitor().label(('−', '$V_o$', '+'))
Connections
elm.Dot() - Junction (filled circle)
elm.Dot(open=True) - Terminal (open circle)
elm.Line() - Straight connection
elm.Wire('shape') - Routed: '-|', '|-', 'N', 'Z'
Step-by-Step Workflow (Incremental Approach)
Step A: Create Connection List
CRITICAL: Start with explicit connection list, not the diagram.
Write every connection showing which pin connects to which:
Connections:
- +15V input → U2 (LM2596S) pin 5 (VIN)
- +15V input → C5 (100µF) → GND
- U2 pin 3 (ON) → +15V (always enabled)
- U2 pin 4 (VOUT) → Switching node
- Switching node → L1 (100µH) → +13.5V Output
- Switching node → D1 (SS34 cathode)
- D1 (SS34 anode) → GND
- +13.5V → C3 (470µF) → GND
- U2 pin 2 (FB) → R1 (10kΩ) → Tap
- Tap → R2 (1kΩ) → GND
- Tap → +13.5V (feedback sense)
- U2 pin 1 (GND) → GND
This list serves as the specification. The diagram must satisfy EVERY connection.
Step B: Incremental Build - Start with Foundation
CRITICAL: Build circuit incrementally, one component/connection at a time.
Typical build order:
- Start with IC only (no connections)
- Add power connections (VIN, ON pins to input rail)
- Add ground connection
- Add input decoupling capacitors
- Add output stage (VOUT → switching node → L1 → output)
- Add flyback diode and output capacitor
- Add feedback network
- Connect feedback to FB pin
Example - First iteration (IC only):
import schemdraw
from schemdraw import elements as elm
with schemdraw.Drawing(
font='Arial',
fontsize=11,
color='black',
transparent=True
) as d:
d.config(unit=3)
ic = elm.Ic(
pins=[
elm.IcPin(name='GND', pin='3', side='left', slot='1/3'),
elm.IcPin(name='ON', pin='5', side='left', slot='2/3'),
elm.IcPin(name='VIN', pin='1', side='left', slot='3/3'),
elm.IcPin(name='FB', pin='4', side='right', slot='1/2'),
elm.IcPin(name='VOUT', pin='2', side='right', slot='2/2'),
],
edgepadW=2.5,
edgepadH=0.8,
pinspacing=1.0,
leadlen=1.0
).label('U2\nLM2596S', loc='center', fontsize=10)
d.save('/tmp/buck_converter.svg')
Step C: Execute and Verify
After EACH iteration:
-
Run the script:
python3 /tmp/circuit_generator.py
-
Generate screenshot (requires the external headless-browser skill — Takazudo/zudo-test-wisdom; degrades with a warning if absent):
cat > /tmp/view.html << 'EOF'
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Circuit Check</title>
<style>
body{margin:20px;background:white;display:flex;justify-content:center;align-items:center;min-height:100vh;}
svg{border:2px solid
</style>
</head><body>
EOF
cat /tmp/buck_converter.svg >> /tmp/view.html
echo "</body></html>" >> /tmp/view.html
if [ -f "$HOME/.claude/skills/headless-browser/scripts/headless-check.js" ]; then
node $HOME/.claude/skills/headless-browser/scripts/headless-check.js \
--url file:///tmp/view.html --screenshot viewport
else
echo "headless-browser skill not installed (external: Takazudo/zudo-test-wisdom) — skipping screenshot check"
fi
-
Show user the screenshot
-
Get user confirmation: "Looks good, add next component"
-
Update code for next iteration (e.g., add GND connection)
-
REPEAT steps C1-C5 until circuit complete
Step D: Conversational Build Loop
User guides the process:
- "Add GND connection next"
- "Connect the input rail"
- "Shorten that line by half"
- "Move the label to the right side"
You respond with:
- Code update for requested change
- Execute script
- Generate screenshot
- Show result
- Wait for next instruction
Benefits:
- User can correct spacing/positioning immediately
- Catches label overlaps before they compound
- Easy to adjust layout decisions in real-time
- No need to untangle complex multi-component issues
Step E: Final Verification
Once all components added and user confirms diagram looks complete:
- Visual check: Generate final screenshot
- Connection trace: Verify each connection from Step A list is present
- Component verification: Check all values, labels, pin numbers
- User approval: Get final confirmation
Step F: Deliver
Provide to user:
- Connection list (from Step A)
- Final SVG diagram (verified version)
- Python code (for reproducibility)
- Screenshot (for documentation)
Common Patterns
See references/patterns.md for copy-paste patterns:
- Voltage divider
- RC filter (low-pass, high-pass)
- Inverting/non-inverting opamp
- Transistor switch
- LED driver
- Buck converter
- Comparator
- And more...
Reference Documentation
components.md
Complete component library reference with syntax for all elements:
- Passive: Resistors, capacitors, inductors
- Semiconductors: Diodes, transistors (BJT/FET)
- Sources: Voltage, current, AC, batteries
- ICs: Opamps, logic gates, specialized ICs
- Power/Ground: Various ground and supply symbols
- Connections: Dots, lines, wires
patterns.md
Copy-paste code for common circuits:
- Simple circuits (voltage divider, RC filter, LED)
- Opamp configurations (inverting, non-inverting, buffer, comparator)
- Transistor circuits (switch, amplifier)
- Advanced circuits (H-bridge, oscillators)
best-practices.md
Guidelines for professional diagrams:
- Layout strategies
- Labeling conventions
- Connection techniques
- Readability tips
- Code organization
- Common mistakes to avoid
examples.md
Complete working examples:
- 555 timer LED blinker
- Inverting opamp with power
- Differential amplifier
- Common emitter amplifier
- H-bridge motor driver
- RC oscillator
- Natural language parsing tips
troubleshooting.md
Solutions to common problems:
- Installation and import issues
- Layout and positioning problems
- Label issues (Unicode, LaTeX)
- Connection problems
- Orientation issues
- Output problems
- Advanced issues
Best Practices (Learned from Real Usage)
1. Consistent Label Positioning for Vertical Components
Problem: Labels on vertical components (resistors, capacitors going up/down) need consistent positioning to avoid overlaps and maintain professional appearance.
Solution: Use loc='bot', ofst=0.5 pattern for all vertical components:
elm.Capacitor().up(2.0).label('C3\n470µF\n25V', loc='bot', ofst=0.5)
elm.Ground().flip()
elm.Resistor().down().label('R1\n10kΩ', loc='bot', ofst=0.5)
elm.Resistor().down().label('R2\n1kΩ', loc='bot', ofst=0.5)
elm.Ground()
Why this works: loc='bot' anchors label at component's bottom reference point, ofst=0.5 shifts it right, positioning label cleanly on the right side of the component body without overlapping the symbol or connection lines.
2. IC Edge Padding for Label Clearance
Problem: IC center label (e.g., "U2 LM2596S") overlaps with pin labels on the right side.
Solution: Use adequate edgepadW parameter instead of label offsets:
ic = elm.Ic(
pins=[...],
edgepadW=2.5,
edgepadH=0.8,
pinspacing=1.0,
leadlen=1.0
).label('U2\nLM2596S', loc='center', fontsize=10)
Why this works: Widening the IC box is cleaner than using label offsets. Typical values: edgepadW=2.5 for ICs with 5+ pins.
3. Precise Junction Positioning
Problem: Need junction at exact midpoint for symmetrical connections.
Solution: Calculate position mathematically:
junction_y = (ic.VIN[1] + ic.ON[1]) / 2
elm.Dot(open=True).at((x_position, junction_y)).label('+15V', loc='left')
elm.Line().right(2.0)
elm.Dot()
Why this works: Calculating exact coordinates ensures straight lines and symmetrical layout. No diagonal connections or misaligned junctions.
4. Proper Push/Pop Stack Management
Problem: Multiple branches require careful stack management to return to correct positions.
Solution: Track push/pop pairs systematically:
elm.Dot()
junction1 = d.here
d.push()
elm.Line().right(1.0)
elm.Dot()
junction2 = d.here
d.push()
elm.Line().right(1.0)
elm.Dot(open=True)
d.pop()
elm.Line().down(0.5)
elm.Resistor()...
d.pop()
Rule: Every d.push() must have a matching d.pop(). Stack structure: LIFO (Last In, First Out).
5. Ground Symbol Orientation
Problem: Ground symbols appear upside-down when components go upward.
Solution: Use .flip() for upward-facing components:
elm.Capacitor().up(2.0)
elm.Ground().flip()
elm.Resistor().down()
elm.Ground()
Rule: Ground always "points down" toward earth. Flip when it's physically above the component.
6. User Correction Responsiveness
Problem: User says "NO!" or expresses frustration - you misunderstood the request.
Solution:
- STOP immediately - Don't continue with wrong approach
- Re-read user's EXACT words - What did they literally say?
- Use exact parameters specified - "right side" means
loc='right', not loc='left'
- Show result immediately - Generate screenshot, don't assume it's correct
- Wait for confirmation - Let user verify before proceeding
Example from session:
- User: "the RIGHT side of the capacitor symbol"
- Wrong:
loc='left' (causes "NO!!!")
- Correct:
loc='right' (what they literally requested)
7. Spacing Adjustments
Problem: User requests specific spacing changes during build.
Solution: Be responsive to spacing requests:
elm.Line().right(1.0)
elm.Line().down(0.5)
elm.Resistor()...
elm.Line().down(0.5)
Why this matters: Small spacing adjustments (0.5 vs 1.0) significantly impact readability and label overlap prevention.
Quick Tips
- Black foreground with transparent background - Always use
font='Arial', color='black', transparent=True for web documentation
- Start simple - Use patterns from
patterns.md as starting point
- Query context7 - For components/features not in references
- Save references - Assign elements to variables:
Q1 = elm.BjtNpn()
- Use dots - Always at T-junctions, open dots for terminals
- Check anchors - Use correct anchor names for element type
- Manhattan routing - Use
.toy() and .tox() for clean lines
- Increase spacing -
d.config(unit=3) if too cramped
- SVG format - Best for documentation (vector, scalable)
- Consistent labels - Use
loc='bot', ofst=0.5 for vertical components
- Listen carefully - When user corrects you, use their EXACT words
Output Formats
with schemdraw.Drawing(
file='circuit.svg',
font='Arial',
fontsize=11,
color='black',
transparent=True
) as d:
d.config(unit=3)
d.save('circuit.png', dpi=300, transparent=True)
with schemdraw.Drawing(
file='circuit.pdf',
font='Arial',
fontsize=11,
color='black',
transparent=True
) as d:
d.config(unit=3)
Black Foreground with Transparent Background (Default)
All diagrams should use black foreground with transparent background by default:
with schemdraw.Drawing(
font='Arial',
fontsize=11,
color='black',
transparent=True
) as d:
d.config(unit=3)
Why transparent background with black foreground:
- Allows HTML container background to show through (e.g., custom background colors)
- Black lines and text are visible on light container backgrounds
- Works seamlessly with web-based documentation (Docusaurus, etc.)
- Professional appearance with clean contrast
- Integrates with any light-themed documentation
Solid background (if specifically requested):
with schemdraw.Drawing(
font='Arial',
fontsize=11,
color='white',
bgcolor='black'
) as d:
with schemdraw.Drawing(
font='Arial',
fontsize=11,
color='black',
bgcolor='white'
) as d:
Example: Simple Voltage Divider
import schemdraw
from schemdraw import elements as elm
with schemdraw.Drawing(
file='voltage_divider.svg',
font='Arial',
fontsize=11,
color='black',
transparent=True
) as d:
elm.SourceV().label('12V')
elm.Line().right(d.unit/2)
elm.Resistor().down().label('R1\n10kΩ')
elm.Dot()
d.push()
elm.Line().right(d.unit/2).dot(open=True).label('Vout\n(6V)', 'right')
d.pop()
elm.Resistor().down().label('R2\n10kΩ')
elm.Ground()
When to Use This Skill
- User requests circuit diagrams or schematics
- Publication-quality output needed
- Vector graphics (SVG/PDF) for documentation
- Complex circuits with ICs, opamps, logic
- Alternative to ASCII art diagrams
- Technical papers or presentations
When NOT to Use
- User specifically wants ASCII art (use ascii-circuit-diagram-creator instead)
- Quick sketches where quality doesn't matter
- No Python environment available