skills/schemdraw-circuit-generator/SKILL.md
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.
npx skillsauth add takazudo/claude-resources schemdraw-circuit-generatorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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()
development
Link Claude Code skill names mentioned in a CodeGrid article (data/{series}/{n}.md) to the author's public claude-resources repo, pinned to the latest commit hash so links don't rot. Use when: (1) user says 'linkify cc resources', 'link the skills', 'link skill names', or invokes /dev-linkify-cc-resources; (2) editing a CodeGrid article that mentions `/commits`, `/pr-complete`, `/skill-creator` or other Claude Code skills and they should point to claude-resources. Only links skills that actually exist in the public repo; skips hypothetical examples and code blocks.
development
Second opinion from Claude Opus on a plan or approach. Use when: (1) Planning phase of /big-plan needs a higher-quality review than /codex-2nd / /gco-2nd / /gcoc-2nd, (2) User says 'opus 2nd' or 'opus opinion', (3) Wanting Anthropic's larger model to critique a plan. Spawns a general-purpose Agent with model: opus that reads the plan file and returns structured feedback. Anthropic quota — not free.
tools
AI-based testing via subagent + a per-task test-flow skill. Use when the user wants to verify something that mechanical assertions can't fully capture — image recognition, visual size/position comparison, animation smoothness, multi-step manual flows that need AI judgment. Triggers: 'AI-based test', 'AI test', 'visual verify', 'image recognition test', 'manual operation test', 'human-eye check', 'verify visually', 'compare screenshots', 'looks the same', 'looks correct'. The skill's job is to (1) author a focused test-flow skill that captures the exact procedure + verdict criteria, then (2) dispatch a verification subagent via the Agent tool that loads BOTH the test-flow skill AND a browser-driving skill (/verify-ui primary, /headless-browser fallback) so the subagent has clear context and consistent verdicts. NEVER uses `claude -p` — subagent dispatch goes through the Agent tool exclusively.
development
End-of-workflow audit of touched GitHub issues, PRs, and branches via a Sonnet subagent. Use when: (1) /big-plan, /x-as-pr, or /x-wt-teams finishes its main work and needs to verify every touched resource is in the right state (closed when done, kept when ongoing, deleted when dead), (2) User says 'cleanup resources', 'audit cleanup', or 'check what should be closed', (3) A long workflow ends and the manager wants a structured paper trail of what it closed/kept/deleted. Auto-execute by default — the Sonnet agent proposes, the manager (you) executes safe actions and prints a final report.