From claude-resources
Generates publication-quality circuit diagrams using schemdraw Python library from natural language descriptions. Supports resistors, capacitors, ICs, logic gates. Outputs SVG/PDF/PNG for schematics and documentation.
npx claudepluginhub takazudo/claude-resourcesThis skill uses the workspace's default tool permissions.
Generate professional, publication-quality circuit diagrams using schemdraw Python library. Outputs to vector formats (SVG, PDF) or raster (PNG).
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Generate professional, publication-quality circuit diagrams using schemdraw Python library. Outputs to vector formats (SVG, PDF) or raster (PNG).
🎯 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:
C. Final Verification - Once all components added:
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:
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
E. Final Confirmation - Trace each signal path from connection list
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.
🚨 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:
This is like HTML+CSS development - requires human eyes to judge visual quality.
Key insight: Users see layout problems AI cannot detect. Trust human feedback over AI assessment.
"Technically connected" ≠ "Visually connected"
For each connection in your connection list:
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:
# ❌ WRONG - line touches IC edge, invisible
elm.Line().at(junction).to(ic.PIN)
# ✅ CORRECT - route away from edge first
elm.Line().at(junction).down(0.5)
elm.Line().left(SMALL_SPACING) # Clear the IC edge
elm.Dot()
elm.Line().down(0.5)
elm.Dot()
elm.Line().right(SMALL_SPACING + 1.0) # Now visible approaching pin
🚨 CRITICAL RULE: Labels must NEVER overlap component symbols
Common overlap zones:
Visual test questions:
Fix priority order:
First: Increase spacing - Most effective, cleanest solution
HORIZONTAL_SPACING = 1.5 # Increase from 1.0
VERTICAL_SPACING = 1.5 # Increase from 1.0
SMALL_SPACING = 0.75 # Increase from 0.5
Second: Adjust label position - Change loc parameter
# R1/R2 overlap example:
elm.Resistor().label('R1\n10kΩ', loc='top', ofst=0.2) # Push up
elm.Resistor().label('R2\n1kΩ', loc='left') # Move to opposite side
Third: Reduce font size - Only if spacing isn't feasible
.label('U2\nLM2596S', fontsize=10) # Reduce from 11
Fourth: Add offset - Fine-tune position
.label('IC', ofst=-0.3) # Shift left by 0.3 units
🚨 CRITICAL RULE: Lines touching IC edges = Connection ambiguity
Problem areas:
Fix rules:
.to(ic.PIN) directly - creates line touching IC edge.at() to position connections explicitlyExample - Correct IC connection:
# ❌ WRONG - line touches IC edge
elm.Line().at(junction).to(ic.VIN)
# ✅ CORRECT - visible gap before IC edge
elm.Line().at(junction).right(1.0) # Stop BEFORE IC edge
# IC connects from current position automatically
A diagram is complete ONLY when:
🚨 CRITICAL: Never claim "complete" without explicit user approval of visual output!
AI cannot reliably assess visual quality. Only human confirmation counts.
Purpose: Generate visual output for HUMAN evaluation, not AI assessment.
Use HTML wrapper + headless browser to create screenshots for user review:
# Generate SVG first
python3 /tmp/circuit.py
# Create HTML wrapper
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 #333;max-width:100%;max-height:90vh;}
</style>
</head><body>
[Paste SVG content here]
</body></html>
EOF
# Capture screenshot
node $HOME/.claude/skills/headless-browser/scripts/headless-check.js \
--url file:///tmp/view_diagram.html \
--screenshot viewport
Then READ the screenshot and perform comprehensive visual assessment.
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:
.at(ic.pinname) to start FROM a specific pin.at(junction) BEFORE routing TO a pin to avoid edge overlapic.VIN, ic.GND, ic.FB, ic.VOUTExample of proper IC connection:
# Create junction BEFORE IC
elm.Dot()
pre_ic_junction = d.here
# IC connects automatically from current position (sequential flow)
ic = elm.Ic(pins=[...])
# Route from junction to IC pin explicitly
elm.Line().at(pre_ic_junction).down(1.0)
elm.Dot()
elm.Line().right(1.0) # Now connects to IC.PIN visibly
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:
Examples:
topic: "opamp operational amplifier circuits"topic: "transistor bjt npn pnp"topic: "wire routing shapes"topic: "seven segment display multiplexer"pip install schemdraw
Dependencies: numpy, pillow (for PNG export), matplotlib (optional backend)
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')
Elements chain sequentially, each picking up where last ended:
elm.Resistor().right().label('R1') # Goes right
elm.Capacitor().down().label('C1') # Goes down from R1's end
elm.Line().left() # Goes left from C1's end
.up(), .down(), .left(), .right() - Cardinal directions.theta(angle) - Arbitrary angle in degrees.up(length=2).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 positionedElements have named connection points:
start, end, centerbase, collector, emitter (BJT) or gate, drain, source (FET)in1, in2, out, vd, vselm.Resistor().label('R1') # Simple label
elm.Resistor().label('$R_1$') # LaTeX math
elm.Resistor().label('1kΩ', loc='bottom') # Position
elm.Capacitor().label(('−', '$V_o$', '+')) # Multiple (polarity)
elm.Dot() - Junction (filled circle)elm.Dot(open=True) - Terminal (open circle)elm.Line() - Straight connectionelm.Wire('shape') - Routed: '-|', '|-', 'N', 'Z'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.
CRITICAL: Build circuit incrementally, one component/connection at a time.
Typical build order:
Example - First iteration (IC only):
import schemdraw
from schemdraw import elements as elm
# Black foreground with transparent background (default)
with schemdraw.Drawing(
font='Arial',
fontsize=11,
color='black',
transparent=True
) as d:
d.config(unit=3)
# Iteration 1: IC only
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')
After EACH iteration:
Run the script:
python3 /tmp/circuit_generator.py
Generate screenshot:
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 #333;max-width:100%;max-height:90vh;}
</style>
</head><body>
EOF
cat /tmp/buck_converter.svg >> /tmp/view.html
echo "</body></html>" >> /tmp/view.html
node $HOME/.claude/skills/headless-browser/scripts/headless-check.js \
--url file:///tmp/view.html --screenshot viewport
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
User guides the process:
You respond with:
Benefits:
Once all components added and user confirms diagram looks complete:
Provide to user:
See references/patterns.md for copy-paste patterns:
Complete component library reference with syntax for all elements:
Copy-paste code for common circuits:
Guidelines for professional diagrams:
Complete working examples:
Solutions to common problems:
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:
# For components going upward
elm.Capacitor().up(2.0).label('C3\n470µF\n25V', loc='bot', ofst=0.5)
elm.Ground().flip() # Flipped ground at top
# For components going downward
elm.Resistor().down().label('R1\n10kΩ', loc='bot', ofst=0.5)
elm.Resistor().down().label('R2\n1kΩ', loc='bot', ofst=0.5)
elm.Ground() # Normal ground at bottom
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.
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, # Wider box prevents label overlap
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.
Problem: Need junction at exact midpoint for symmetrical connections.
Solution: Calculate position mathematically:
# For horizontal rail between two pins
junction_y = (ic.VIN[1] + ic.ON[1]) / 2
# Build entire rail at calculated height
elm.Dot(open=True).at((x_position, junction_y)).label('+15V', loc='left')
elm.Line().right(2.0)
elm.Dot()
# ... all elements at same Y coordinate
Why this works: Calculating exact coordinates ensures straight lines and symmetrical layout. No diagonal connections or misaligned junctions.
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() # Save junction1
# Branch 1
elm.Line().right(1.0)
elm.Dot()
junction2 = d.here
d.push() # Save junction2
# Branch 2
elm.Line().right(1.0)
elm.Dot(open=True)
# Return to junction2
d.pop() # Now at junction2
# Continue from junction2
elm.Line().down(0.5)
elm.Resistor()...
# Return to junction1
d.pop() # Now at junction1
Rule: Every d.push() must have a matching d.pop(). Stack structure: LIFO (Last In, First Out).
Problem: Ground symbols appear upside-down when components go upward.
Solution: Use .flip() for upward-facing components:
# Component going UP - flip ground
elm.Capacitor().up(2.0)
elm.Ground().flip() # Ground symbol at top, points down
# Component going DOWN - normal ground
elm.Resistor().down()
elm.Ground() # Ground symbol at bottom, points down
Rule: Ground always "points down" toward earth. Flip when it's physically above the component.
Problem: User says "NO!" or expresses frustration - you misunderstood the request.
Solution:
loc='right', not loc='left'Example from session:
loc='left' (causes "NO!!!")loc='right' (what they literally requested)Problem: User requests specific spacing changes during build.
Solution: Be responsive to spacing requests:
# User: "halve the line there"
elm.Line().right(1.0) # Changed from 2.0
# User: "change distance 1 -> 0.5 for each line"
elm.Line().down(0.5) # Changed from 1.0
elm.Resistor()...
elm.Line().down(0.5) # All spacing changed consistently
Why this matters: Small spacing adjustments (0.5 vs 1.0) significantly impact readability and label overlap prevention.
font='Arial', color='black', transparent=True for web documentationpatterns.md as starting pointQ1 = elm.BjtNpn().toy() and .tox() for clean linesd.config(unit=3) if too crampedloc='bot', ofst=0.5 for vertical components# SVG (recommended - vector, scalable)
with schemdraw.Drawing(
file='circuit.svg',
font='Arial',
fontsize=11,
color='black',
transparent=True
) as d:
d.config(unit=3)
# ... components ...
# PNG (raster, for compatibility)
# Note: Generate SVG first, then save as PNG
d.save('circuit.png', dpi=300, transparent=True)
# PDF (for print)
with schemdraw.Drawing(
file='circuit.pdf',
font='Arial',
fontsize=11,
color='black',
transparent=True
) as d:
d.config(unit=3)
# ... components ...
All diagrams should use black foreground with transparent background by default:
with schemdraw.Drawing(
font='Arial', # Sans-serif font
fontsize=11,
color='black', # Black foreground
transparent=True # Transparent background
) as d:
d.config(unit=3)
# ... components ...
Why transparent background with black foreground:
Solid background (if specifically requested):
# Dark theme with solid black background and white foreground
with schemdraw.Drawing(
font='Arial',
fontsize=11,
color='white',
bgcolor='black'
) as d:
# ... components ...
# Light theme with solid white background and black foreground
with schemdraw.Drawing(
font='Arial',
fontsize=11,
color='black',
bgcolor='white'
) as d:
# ... components ...
import schemdraw
from schemdraw import elements as elm
# Black foreground with transparent background (default)
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()