Add Starlight docs site with full tool reference

Astro/Starlight documentation at docs/ with 21 pages:
- Getting started (prerequisites, Claude Code setup, first simulation)
- Tutorials (filter design, Monte Carlo yield)
- Reference (all 37 tools, 5 resources, 7 prompts)
- Concepts (LTspice on Linux, simulation types)

Docker infrastructure with dev/prod compose overlays, Caddy
reverse proxy for mcltspice.warehack.ing, and Makefile targets.

Includes patch for Starlight 0.37 head schema default bug.
This commit is contained in:
Ryan Malloy 2026-02-13 01:06:17 -07:00
parent f608fe5421
commit f2c18982ae
36 changed files with 11461 additions and 0 deletions

5
.gitignore vendored
View File

@ -5,3 +5,8 @@ __pycache__/
dist/
*.egg-info/
.ruff_cache/
# Docs site build artifacts
docs/node_modules/
docs/dist/
docs/.astro/

6
docs/.dockerignore Normal file
View File

@ -0,0 +1,6 @@
node_modules
dist
.astro
.env
.git
*.md

10
docs/.env Normal file
View File

@ -0,0 +1,10 @@
# docs environment configuration
COMPOSE_PROJECT_NAME=mcltspice-docs
# MODE: dev | prod
MODE=dev
# Domain configuration
SITE_DOMAIN=mcltspice.l.warehack.ing
# Production: mcltspice.warehack.ing
# Dev (local): mcltspice.l.warehack.ing

63
docs/Dockerfile Normal file
View File

@ -0,0 +1,63 @@
# ── Dev target ────────────────────────────────────────────────
FROM node:22-slim AS dev
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 4321
CMD ["npm", "run", "dev"]
# ── Prod build stage ─────────────────────────────────────────
FROM node:22-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ── Prod serve stage ─────────────────────────────────────────
FROM caddy:2-alpine AS prod
# Non-root user
RUN addgroup -g 1001 -S app && \
adduser -S app -u 1001 -G app
COPY --from=build /app/dist /srv
COPY <<'CADDYFILE' /etc/caddy/Caddyfile
:8080 {
root * /srv
file_server
encode gzip zstd
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy strict-origin-when-cross-origin
Cache-Control "public, max-age=31536000, immutable"
}
handle_errors {
rewrite * /404.html
file_server
}
}
CADDYFILE
RUN chown -R app:app /srv
USER app
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget -qO- http://127.0.0.1:8080/ || exit 1
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]

47
docs/Makefile Normal file
View File

@ -0,0 +1,47 @@
include .env
export
COMPOSE_BASE := docker compose -f docker-compose.yml -f docker-compose.$(MODE).yml
.PHONY: dev prod build logs stop clean restart status help
## dev: start in dev mode with HMR and follow logs
dev:
@echo "Starting dev on $(SITE_DOMAIN) ..."
MODE=dev docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build -d
MODE=dev docker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f
## prod: build and start in production mode
prod:
@echo "Deploying prod on $(SITE_DOMAIN) ..."
MODE=prod docker compose -f docker-compose.yml -f docker-compose.prod.yml up --build -d
MODE=prod docker compose -f docker-compose.yml -f docker-compose.prod.yml logs --tail=40
## build: build containers using current MODE from .env
build:
$(COMPOSE_BASE) build
## logs: follow container logs
logs:
$(COMPOSE_BASE) logs -f
## stop: stop containers
stop:
$(COMPOSE_BASE) down
## restart: rebuild and restart
restart: stop
$(COMPOSE_BASE) up --build -d
$(COMPOSE_BASE) logs --tail=20
## clean: stop, remove volumes and local images
clean:
$(COMPOSE_BASE) down -v --rmi local
## status: show running container status
status:
$(COMPOSE_BASE) ps
## help: show available targets
help:
@grep '^## ' Makefile | sed 's/^## //' | column -t -s ':'

80
docs/astro.config.mjs Normal file
View File

@ -0,0 +1,80 @@
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
site: 'https://mcltspice.warehack.ing',
telemetry: false,
devToolbar: { enabled: false },
integrations: [
starlight({
title: 'mcltspice',
tagline: 'LTspice circuit simulation via MCP',
social: [
{ icon: 'external', label: 'Gitea', href: 'https://git.supported.systems/MCP/mcltspice' },
{ icon: 'external', label: 'PyPI', href: 'https://pypi.org/project/mcltspice/' },
],
editLink: {
baseUrl: 'https://git.supported.systems/MCP/mcltspice/_edit/main/docs/',
},
customCss: ['./src/styles/custom.css'],
sidebar: [
{
label: 'Getting Started',
items: [
{ label: 'Overview', slug: 'getting-started' },
{ label: 'Prerequisites', slug: 'getting-started/prerequisites' },
{ label: 'Claude Code Setup', slug: 'getting-started/claude-code' },
{ label: 'First Simulation', slug: 'getting-started/first-simulation' },
],
},
{
label: 'Tutorials',
badge: { text: 'Learn', variant: 'tip' },
items: [
{ label: 'Overview', slug: 'tutorials' },
{ label: 'Design a Filter', slug: 'tutorials/design-a-filter' },
{ label: 'Monte Carlo Yield', slug: 'tutorials/monte-carlo-yield' },
],
},
{
label: 'Reference',
collapsed: false,
items: [
{ label: 'Overview', slug: 'reference' },
{ label: 'Simulation', slug: 'reference/simulation' },
{ label: 'Waveform', slug: 'reference/waveform' },
{ label: 'Signal Analysis', slug: 'reference/signal-analysis' },
{ label: 'Noise', slug: 'reference/noise' },
{ label: 'Stability & Power', slug: 'reference/stability-power' },
{ label: 'Schematic & Netlist', slug: 'reference/schematic-netlist' },
{ label: 'Library & Templates', slug: 'reference/library-templates' },
{ label: 'Resources', slug: 'reference/resources' },
{ label: 'Prompts', slug: 'reference/prompts' },
],
},
{
label: 'Concepts',
collapsed: true,
items: [
{ label: 'LTspice on Linux', slug: 'concepts/ltspice-on-linux' },
{ label: 'Simulation Types', slug: 'concepts/simulation-types' },
],
},
],
}),
],
vite: {
plugins: [tailwindcss()],
server: {
host: '0.0.0.0',
...(process.env.VITE_HMR_HOST && {
hmr: {
host: process.env.VITE_HMR_HOST,
protocol: 'wss',
clientPort: 443,
},
}),
},
},
});

View File

@ -0,0 +1,19 @@
services:
docs:
environment:
- VITE_HMR_HOST=${SITE_DOMAIN}
volumes:
- ./src:/app/src
- ./public:/app/public
- ./astro.config.mjs:/app/astro.config.mjs
labels:
caddy.reverse_proxy: "{{upstreams 4321}}"
# HMR WebSocket support -- keeps Vite hot-reload alive through Caddy
caddy.reverse_proxy.flush_interval: "-1"
caddy.reverse_proxy.transport: http
caddy.reverse_proxy.transport.read_timeout: "0"
caddy.reverse_proxy.transport.write_timeout: "0"
caddy.reverse_proxy.transport.keepalive: "5m"
caddy.reverse_proxy.transport.keepalive_idle_conns: "10"
caddy.reverse_proxy.stream_timeout: "24h"
caddy.reverse_proxy.stream_close_delay: "5s"

View File

@ -0,0 +1,15 @@
services:
docs:
labels:
caddy.reverse_proxy: "{{upstreams 8080}}"
caddy.header.Cache-Control: "public, max-age=31536000, immutable"
caddy.header.X-Content-Type-Options: nosniff
caddy.header.X-Frame-Options: DENY
caddy.header.Referrer-Policy: strict-origin-when-cross-origin
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=50m
- /config/caddy:size=10m
- /data/caddy:size=10m

24
docs/docker-compose.yml Normal file
View File

@ -0,0 +1,24 @@
services:
docs:
build:
context: .
dockerfile: Dockerfile
target: ${MODE:-dev}
container_name: mcltspice-docs
restart: unless-stopped
environment:
- ASTRO_TELEMETRY_DISABLED=1
networks:
- caddy
labels:
caddy: ${SITE_DOMAIN}
caddy.encode: gzip
logging:
driver: json-file
options:
max-size: "5m"
max-file: "3"
networks:
caddy:
external: true

7997
docs/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

20
docs/package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "mcltspice-docs",
"type": "module",
"private": true,
"scripts": {
"postinstall": "node patches/fix-starlight-head.mjs",
"dev": "astro dev --host 0.0.0.0",
"build": "astro build",
"preview": "astro preview --host 0.0.0.0"
},
"dependencies": {
"astro": "^5.17.2",
"@astrojs/starlight": "^0.37.6",
"@astrojs/starlight-tailwind": "^4.0.2",
"@tailwindcss/vite": "^4.1.0",
"tailwindcss": "^4.1.0",
"@lucide/astro": "^0.563.0",
"sharp": "^0.33.0"
}
}

View File

@ -0,0 +1,35 @@
/**
* Patches @astrojs/starlight to handle undefined `data.head` in frontmatter.
*
* Starlight 0.37.x assumes docsSchema() defaults `head` to [] via Zod, but
* the content loader doesn't always apply this default, causing:
* "Cannot read properties of undefined (reading 'some')"
*
* This adds a nullish coalescing fallback: `data.head ?? []`
*/
import { readFileSync, writeFileSync } from 'node:fs';
const file = 'node_modules/@astrojs/starlight/utils/head.ts';
try {
let src = readFileSync(file, 'utf8');
const target = 'config.head, data.head)';
const replacement = 'config.head, data.head ?? [])';
if (src.includes(replacement)) {
console.log('[patch] head.ts already patched, skipping.');
process.exit(0);
}
if (!src.includes(target)) {
console.warn('[patch] Could not find target string in head.ts — Starlight may have been updated.');
process.exit(0);
}
src = src.replace(target, replacement);
writeFileSync(file, src, 'utf8');
console.log('[patch] Patched head.ts: data.head ?? []');
} catch (err) {
console.warn('[patch] Could not patch head.ts:', err.message);
}

4
docs/public/favicon.svg Normal file
View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" rx="4" fill="#18181b"/>
<path d="M4 16 L8 16 L10 6 L14 26 L18 10 L22 22 L24 16 L28 16" fill="none" stroke="#2dd4bf" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 285 B

View File

@ -0,0 +1,7 @@
import { defineCollection } from 'astro:content';
import { docsLoader } from '@astrojs/starlight/loaders';
import { docsSchema } from '@astrojs/starlight/schema';
export const collections = {
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
};

View File

@ -0,0 +1,92 @@
---
title: LTspice on Linux
description: How mcltspice drives a Windows application via Wine.
---
import { Aside } from '@astrojs/starlight/components';
LTspice is a Windows application. There is no official Linux build. mcltspice solves this by running LTspice through Wine in headless batch mode --- no GUI, no display server, no X11 forwarding required. This page explains the key pieces of the stack and how they fit together.
## Wine and batch mode
Wine is a compatibility layer that runs Windows executables on Linux. mcltspice invokes LTspice through Wine with the `-b` (batch) flag:
```bash
wine XVIIx64.exe -b circuit.cir
```
The `-b` flag tells LTspice to run the simulation, write the results to a `.raw` file, and exit. No GUI window is created. This works in headless environments --- SSH sessions, containers, CI pipelines --- anywhere you can run a shell command.
<Aside type="note">
Wine's batch mode performance is nearly identical to native Windows execution. The translation overhead is in the Win32 API layer, not in the SPICE solver math, which dominates simulation time.
</Aside>
## The WINEPREFIX
Every Wine installation operates within a "prefix" --- a directory that acts as a virtual Windows filesystem. It contains the registry, drive letter mappings (the `C:\` drive), and any DLLs the application needs.
mcltspice auto-detects the Wine prefix from the `LTSPICE_DIR` path. If your LTspice files are at `/home/user/ltspice/extracted/ltspice`, the prefix is expected at `/home/user/ltspice/extracted/ltspice/.wine`.
You create the prefix once during setup:
```bash
export WINEPREFIX=/path/to/ltspice/.wine
export WINEARCH=win64
wineboot --init
```
After that, mcltspice sets `WINEPREFIX` automatically before each simulation run. You do not need to manage it.
<Aside type="tip">
The prefix only needs the bare minimum Wine runtime. LTspice does not depend on .NET, Visual C++ redistributables, or any other Windows components for batch simulation.
</Aside>
## Binary .raw files
LTspice writes simulation results to binary `.raw` files. These are not human-readable --- they use a compact binary format specific to LTspice.
mcltspice's `raw_parser` module reads these files by parsing:
1. **The header** --- plain text at the top of the file containing the title, simulation type, variable names, variable types (voltage, current, frequency), and the total number of data points.
2. **The binary data block** --- IEEE 754 double-precision floats packed contiguously after the header. The parser reads the correct number of bytes based on the variable count and point count from the header.
For AC analysis, each data point is a complex number (real + imaginary parts stored as two consecutive doubles). The parser converts these to magnitude and phase automatically when you call `get_waveform`.
For transient analysis, values are real-valued doubles. The independent variable (time) may use a compressed encoding where LTspice only stores points where the waveform changes significantly, but the parser handles this transparently.
<Aside type="note">
Raw files can be large for long transient simulations with many saved signals. A 10ms transient with 100k points and 10 signals produces roughly 8 MB of binary data. The parser streams this efficiently without loading the entire file into memory at once.
</Aside>
## Simulation types
LTspice supports several simulation types, each producing different data in the `.raw` file:
- **.tran** (transient) --- Time-domain simulation. The independent variable is time; dependent variables are instantaneous voltages and currents. Used for oscillators, step response, switching converters.
- **.ac** (AC analysis) --- Small-signal frequency response. The independent variable is frequency; dependent variables are complex-valued (magnitude and phase). Used for filter design, amplifier bandwidth, stability analysis.
- **.dc** (DC sweep) --- Sweeps a source value and records the DC operating point at each step. Used for transfer characteristics and I-V curves.
- **.op** (operating point) --- A single DC bias calculation with no sweep. Returns one set of node voltages and branch currents. Used to verify quiescent conditions.
- **.tf** (transfer function) --- Computes small-signal gain, input impedance, and output impedance at DC. Returns scalar values, not waveforms.
- **.noise** (noise analysis) --- Computes noise spectral density at each frequency point. The independent variable is frequency; dependent variables are noise voltage or current densities (V/sqrt(Hz) or A/sqrt(Hz)).
See [Simulation Types](/concepts/simulation-types/) for detailed coverage of each type, including directive syntax and which mcltspice tools work with each one.
## Performance
Typical simulation times:
| Circuit complexity | Simulation type | Approximate time |
|---|---|---|
| Simple RC filter | .ac (800 points) | 0.1 -- 0.5 seconds |
| Op-amp circuit (10 components) | .tran (1ms) | 0.5 -- 2 seconds |
| Switching converter | .tran (10ms, 100k steps) | 2 -- 5 seconds |
| Monte Carlo (100 runs) | .tran or .ac | 10 -- 60 seconds |
Wine overhead is minimal for batch mode. LTspice launches, runs the solver, writes the `.raw` file, and exits. The startup cost is roughly 50-100ms per invocation. For Monte Carlo or parameter sweeps, mcltspice runs LTspice once with stepped parameters rather than launching it repeatedly, which eliminates the startup overhead for multi-run analyses.
The main bottleneck is always the SPICE solver itself --- the matrix factorization and Newton-Raphson iterations that compute circuit behavior at each time step or frequency point.

View File

@ -0,0 +1,244 @@
---
title: Simulation Types
description: When to use .tran, .ac, .dc, .op, .noise, and .tf analyses.
---
import { Aside, Code } from '@astrojs/starlight/components';
LTspice supports six simulation types. Each one solves a different question about your circuit --- time-domain behavior, frequency response, DC characteristics, bias conditions, noise performance, or small-signal transfer function. This page covers what each type computes, its SPICE directive syntax, when to reach for it, and which mcltspice tools process its output.
## Summary
<table class="param-table">
<thead>
<tr><th>Type</th><th>Directive</th><th>Independent variable</th><th>Primary mcltspice tools</th></tr>
</thead>
<tbody>
<tr><td>.tran</td><td><code>.tran 0 10m 0 1u</code></td><td>Time</td><td><code>get_waveform</code>, <code>analyze_waveform</code>, <code>analyze_power</code></td></tr>
<tr><td>.ac</td><td><code>.ac dec 100 1 1meg</code></td><td>Frequency</td><td><code>get_waveform</code>, <code>measure_bandwidth</code>, <code>analyze_stability</code></td></tr>
<tr><td>.dc</td><td><code>.dc V1 0 5 0.1</code></td><td>Swept source value</td><td><code>get_waveform</code></td></tr>
<tr><td>.op</td><td><code>.op</code></td><td>None (single point)</td><td><code>get_operating_point</code></td></tr>
<tr><td>.tf</td><td><code>.tf V(out) V1</code></td><td>None (single point)</td><td><code>get_transfer_function</code></td></tr>
<tr><td>.noise</td><td><code>.noise V(out) V1 dec 100 1 1meg</code></td><td>Frequency</td><td><code>analyze_noise</code>, <code>get_spot_noise</code>, <code>get_total_noise</code></td></tr>
</tbody>
</table>
---
## .tran --- Transient analysis
**What it computes:** The circuit's behavior over time, solving the full nonlinear differential equations at each time step. Voltages and currents are recorded as functions of time.
**Directive syntax:**
```
.tran <Tstep> <Tstop> [Tstart] [Tmaxstep] [options]
```
- `Tstep` -- Suggested output time step (LTspice may use smaller internal steps)
- `Tstop` -- End time of the simulation
- `Tstart` -- When to start saving data (default: 0)
- `Tmaxstep` -- Maximum internal time step (controls accuracy)
**Examples:**
```
.tran 10m ; Run for 10ms, auto timestep
.tran 0 10m 0 1u ; 10ms, max 1us steps
.tran 0 1 0 10u startup ; 1 second, include startup transients
```
**When to use it:**
- Oscillator startup and steady-state waveforms
- Step response and settling time
- Switching converter operation (duty cycle, ripple)
- Any circuit where time-domain behavior matters
**mcltspice tools for .tran data:**
- `get_waveform` -- Extract voltage/current traces vs. time
- `analyze_waveform` -- Compute RMS, peak-to-peak, rise time, settling time, FFT, THD
- `analyze_power` -- Power dissipation and efficiency from V(t) and I(t) products
- `plot_waveform` -- Generate time-domain SVG plots
<Aside type="tip">
For switching converters, set `Tmaxstep` small enough to capture the switching edges. A good rule of thumb: Tmaxstep should be at most 1/20th of the switching period.
</Aside>
---
## .ac --- AC analysis
**What it computes:** The small-signal frequency response. LTspice linearizes the circuit around its DC operating point, then sweeps frequency and computes the complex transfer function. Results are complex-valued: magnitude and phase at each frequency point.
**Directive syntax:**
```
.ac <variation> <Npoints> <Fstart> <Fstop>
```
- `variation` -- `dec` (points per decade), `oct` (per octave), or `lin` (linear)
- `Npoints` -- Number of points per decade/octave, or total for linear
- `Fstart` -- Starting frequency (Hz)
- `Fstop` -- Ending frequency (Hz)
**Examples:**
```
.ac dec 100 1 1meg ; 100 pts/decade, 1 Hz to 1 MHz
.ac dec 50 10 10G ; 50 pts/decade, 10 Hz to 10 GHz
.ac lin 1000 1k 100k ; 1000 linear points, 1 kHz to 100 kHz
```
**When to use it:**
- Filter design (frequency response, cutoff, rolloff)
- Amplifier bandwidth and gain
- Stability analysis (loop gain, gain and phase margins)
- Impedance vs. frequency
**mcltspice tools for .ac data:**
- `get_waveform` -- Returns magnitude (dB) and phase (degrees) vs. frequency
- `measure_bandwidth` -- Finds the -3dB cutoff frequency
- `analyze_stability` -- Computes gain margin and phase margin from loop gain
- `plot_waveform` -- Generates Bode plots (magnitude + phase)
<Aside type="note">
AC analysis requires at least one AC source in the circuit. Set it with <code>AC 1</code> on a voltage source to get a unity-amplitude stimulus. The source's DC value sets the bias point; the AC amplitude sets the stimulus level.
</Aside>
---
## .dc --- DC sweep
**What it computes:** The DC operating point of the circuit at each value of a swept source. The independent variable is the source value (voltage or current), and the dependent variables are node voltages and branch currents at each sweep step.
**Directive syntax:**
```
.dc <Source1> <Start1> <Stop1> <Step1> [Source2 Start2 Stop2 Step2]
```
A second source can be swept as a nested loop for 2D parameter exploration.
**Examples:**
```
.dc V1 0 5 0.1 ; Sweep V1 from 0 to 5V in 0.1V steps
.dc I1 0 10m 100u ; Sweep I1 from 0 to 10mA in 100uA steps
.dc V1 0 5 0.1 V2 0 3 1 ; 2D sweep: V1 and V2
```
**When to use it:**
- Transfer characteristics (Vout vs. Vin)
- I-V curves of transistors and diodes
- Voltage regulator load/line regulation
- Finding threshold voltages
**mcltspice tools for .dc data:**
- `get_waveform` -- Extract output voltage/current vs. swept source value
---
## .op --- Operating point
**What it computes:** A single DC operating point. LTspice solves the circuit with all capacitors open and all inductors shorted, finding the steady-state DC voltages and currents. No sweep, no time variation --- just one set of numbers.
**Directive syntax:**
```
.op
```
No parameters. The result is a single snapshot of every node voltage and branch current.
**When to use it:**
- Verifying bias conditions before running .ac or .tran
- Checking quiescent power dissipation
- Debugging: confirming that DC voltages are where you expect
**mcltspice tools for .op data:**
- `get_operating_point` -- Returns all node voltages and branch currents as a flat dictionary
<Aside type="tip">
Run <code>.op</code> as the first analysis on any new circuit. If the DC bias point is wrong, all other analyses will produce meaningless results. It takes milliseconds.
</Aside>
---
## .tf --- Transfer function
**What it computes:** The small-signal DC transfer function: voltage gain (or transconductance), input resistance, and output resistance. This is a single-point linearization at DC --- no frequency sweep.
**Directive syntax:**
```
.tf <output> <input_source>
```
- `output` -- An output voltage expression, e.g. `V(out)` or `V(out, in)`
- `input_source` -- The input source name, e.g. `V1` or `I1`
**Examples:**
```
.tf V(out) V1 ; Voltage gain from V1 to V(out)
.tf I(R_load) V1 ; Transconductance
```
**When to use it:**
- Quick gain check without running a full AC sweep
- Input and output impedance measurement
- Verifying amplifier topology before detailed analysis
**mcltspice tools for .tf data:**
- `get_transfer_function` -- Returns gain, input resistance, and output resistance
---
## .noise --- Noise analysis
**What it computes:** The noise spectral density at an output node, referred to an input source. LTspice computes the noise contribution of every component (resistor thermal noise, transistor shot noise, 1/f noise) and sums them. The result is noise voltage (or current) spectral density in V/sqrt(Hz) at each frequency point.
**Directive syntax:**
```
.noise V(<output>) <input_source> <variation> <Npoints> <Fstart> <Fstop>
```
The frequency sweep parameters follow the same format as `.ac`.
**Examples:**
```
.noise V(out) V1 dec 100 1 1meg ; Noise at V(out), referred to V1
.noise V(out,inn) V1 dec 50 10 100k ; Differential output noise
```
**When to use it:**
- Amplifier noise floor characterization
- Noise figure calculation
- Identifying dominant noise sources (1/f corner frequency)
- Signal-to-noise ratio estimation
**mcltspice tools for .noise data:**
- `analyze_noise` -- Full noise analysis: spectral density, RMS, noise figure, 1/f corner, per-component breakdown
- `get_spot_noise` -- Noise spectral density at a single frequency
- `get_total_noise` -- Integrated RMS noise over a frequency band
<Aside type="note">
Noise analysis runs a linearized AC simulation under the hood. The circuit must have a valid DC operating point. If <code>.op</code> fails, noise analysis will also fail.
</Aside>
---
## Choosing the right analysis
A practical decision tree:
- **"What does the output look like over time?"** --- Use `.tran`
- **"What is the frequency response?"** --- Use `.ac`
- **"How does the output change as I vary an input?"** --- Use `.dc`
- **"Are the DC bias voltages correct?"** --- Use `.op`
- **"What is the gain and impedance at DC?"** --- Use `.tf`
- **"What is the noise floor?"** --- Use `.noise`
For a thorough characterization, run them in this order: `.op` first (verify bias), then `.tf` (quick gain check), then `.ac` (full frequency response), then `.tran` (time-domain behavior), and `.noise` if noise matters. Each analysis builds confidence that the circuit is behaving correctly before moving to the next.

View File

@ -0,0 +1,102 @@
---
title: Claude Code Setup
description: Add mcltspice to Claude Code or other MCP clients.
---
import { Tabs, TabItem, Aside, Code } from '@astrojs/starlight/components';
mcltspice communicates over standard MCP stdio transport. The examples below show the three main ways to configure it.
## Add to Claude Code
<Tabs>
<TabItem label="From PyPI">
The quickest option. This pulls the latest published version from PyPI and runs it with `uvx`:
```bash
claude mcp add mcltspice -- uvx mcltspice
```
If you need to pin a specific version:
```bash
claude mcp add mcltspice -- uvx mcltspice==2026.2.10
```
</TabItem>
<TabItem label="Local development">
For working on mcltspice itself, point at your local checkout:
```bash
claude mcp add mcltspice -- uv run --directory /path/to/mcltspice mcltspice
```
This uses `uv run` to resolve dependencies from the local `pyproject.toml` and run the entry point. Changes to the source take effect on the next server restart.
</TabItem>
<TabItem label="Manual .mcp.json">
Create or edit `.mcp.json` in your project root (or `~/.mcp.json` for global scope):
```json
{
"mcpServers": {
"mcltspice": {
"command": "uvx",
"args": ["mcltspice"],
"env": {
"LTSPICE_DIR": "/home/you/ltspice/extracted/ltspice"
}
}
}
}
```
The `env` block is optional. Include it only if your LTspice files are not at the default path.
For local development, swap the command:
```json
{
"mcpServers": {
"mcltspice": {
"command": "uv",
"args": ["run", "--directory", "/path/to/mcltspice", "mcltspice"]
}
}
}
```
</TabItem>
</Tabs>
## Other MCP clients
Any MCP client that supports stdio transport can use mcltspice. The generic configuration is:
| Field | Value |
|-------|-------|
| **Transport** | stdio |
| **Command** | `uvx` |
| **Arguments** | `["mcltspice"]` |
| **Environment** | `LTSPICE_DIR` (optional) |
The server reads from stdin and writes to stdout using JSON-RPC over the MCP protocol. No HTTP server, no ports to configure.
<Aside type="note">
mcltspice uses stdin/stdout for MCP transport. It never prints diagnostics to stdout --- any startup messages go to stderr to keep the protocol stream clean.
</Aside>
## Passing environment variables
If your LTspice installation is not at the default path, set `LTSPICE_DIR` in whichever way your client supports:
- **Claude Code CLI**: Pass it through the `env` field in `.mcp.json` (shown above).
- **Shell**: `export LTSPICE_DIR=/path/to/ltspice` before launching the client.
- **Docker**: Add `-e LTSPICE_DIR=/path/to/ltspice` to your `docker run` command.
## Verify the connection
After adding the server, ask your MCP client to call the `check_installation` tool:
```
check_installation()
```
If the server is connected and LTspice is found, you will get a status report confirming the Wine version, LTspice binary path, and library availability. If anything is missing, see [Prerequisites](/getting-started/prerequisites/).

View File

@ -0,0 +1,141 @@
---
title: First Simulation
description: Run an end-to-end circuit simulation in under a minute.
---
import { Steps, Aside } from '@astrojs/starlight/components';
This walkthrough takes you from zero to a plotted frequency response using five tool calls. We will create an RC low-pass filter from a built-in template, simulate it, extract the output waveform, measure the bandwidth, and generate a plot.
<Aside type="tip">
Every tool call below is something your MCP client sends on your behalf. In Claude Code, you describe what you want in plain language and the assistant selects the right tools automatically.
</Aside>
<Steps>
1. **Create a circuit from a template**
The `create_from_template` tool generates a ready-to-simulate netlist from one of the built-in circuit templates.
```
create_from_template("rc_lowpass")
```
This writes an RC low-pass filter netlist to `/tmp/rc_lowpass.cir` with default component values (R=1k, C=100n) and an AC analysis directive.
```json
// Response
{
"netlist_path": "/tmp/rc_lowpass.cir",
"template": "rc_lowpass",
"parameters": { "R1": "1k", "C1": "100n" },
"description": "RC low-pass filter, fc ~ 1.59 kHz"
}
```
2. **Run the simulation**
Pass the netlist to `simulate_netlist`. LTspice runs via Wine in batch mode and produces a binary `.raw` file with the results.
```
simulate_netlist("/tmp/rc_lowpass.cir")
```
```json
// Response
{
"raw_file": "/tmp/rc_lowpass.raw",
"log_file": "/tmp/rc_lowpass.log",
"simulation_type": "AC Analysis",
"variables": ["frequency", "V(out)", "V(in)", "I(R1)"],
"points": 801,
"elapsed_seconds": 0.42
}
```
3. **Extract the output waveform**
Use `get_waveform` to pull signal data out of the `.raw` file. For AC analysis, this returns complex-valued data (magnitude and phase at each frequency point).
```
get_waveform("/tmp/rc_lowpass.raw", ["V(out)"])
```
```json
// Response (truncated)
{
"variables": {
"frequency": [1.0, 1.26, 1.58, "...801 points..."],
"V(out)": {
"magnitude": [1.0, 0.9999, 0.9998, "..."],
"phase_deg": [-0.036, -0.045, -0.057, "..."]
}
},
"simulation_type": "AC Analysis",
"num_points": 801
}
```
4. **Measure the bandwidth**
The `measure_bandwidth` tool finds the -3dB cutoff frequency from the AC analysis results.
```
measure_bandwidth("/tmp/rc_lowpass.raw", "V(out)")
```
```json
// Response
{
"f_3dB_hz": 1591.5,
"dc_gain_dB": 0.0,
"gain_at_cutoff_dB": -3.01,
"signal": "V(out)"
}
```
The measured cutoff of 1591.5 Hz matches the theoretical value of 1/(2 * pi * R * C) = 1/(2 * pi * 1000 * 100e-9) = 1592 Hz.
5. **Plot the results**
Generate an SVG plot of the frequency response with `plot_waveform`.
```
plot_waveform("/tmp/rc_lowpass.raw", "V(out)")
```
```json
// Response
{
"svg_path": "/tmp/rc_lowpass_V(out).svg",
"plot_type": "bode",
"signals": ["V(out)"],
"format": "SVG"
}
```
The SVG contains a Bode plot with magnitude and phase traces --- suitable for embedding in reports or viewing in a browser.
</Steps>
## What just happened
In five tool calls, you:
- Generated a complete SPICE netlist from a template
- Ran an AC analysis through LTspice (via Wine, in batch mode, with no GUI)
- Extracted complex-valued frequency-domain data from the binary `.raw` file
- Measured the -3dB bandwidth automatically
- Produced a publication-ready Bode plot
All of this happened without writing a single line of SPICE, opening a GUI, or parsing binary files manually.
## Next steps
Try modifying the circuit. You can change component values with the template parameters:
```
create_from_template("rc_lowpass", parameters={"R1": "10k", "C1": "10n"})
```
This shifts the cutoff frequency to ~1.59 kHz (same frequency, different impedance) --- or pick entirely different values to explore the design space. See the [tool reference](/reference/) for the full list of available operations.

View File

@ -0,0 +1,69 @@
---
title: Getting Started
description: Install mcltspice and run your first circuit simulation.
---
import { Steps, Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
mcltspice is an MCP server that drives LTspice on Linux via Wine. It exposes 37 tools for circuit simulation, waveform extraction, signal analysis, and design automation --- all accessible from Claude Code or any MCP client.
## Setup at a glance
<Steps>
1. **Install prerequisites**
You need Wine and an extracted copy of LTspice. Wine runs the LTspice binary in batch mode; no GUI required.
[Prerequisites details](/getting-started/prerequisites/)
2. **Install mcltspice**
```bash
uvx mcltspice
```
Or install from source with `uv pip install -e .` for development.
3. **Add to your MCP client**
```bash
claude mcp add mcltspice -- uvx mcltspice
```
Works with Claude Code out of the box. Other MCP clients use standard stdio transport.
[Claude Code setup details](/getting-started/claude-code/)
4. **Run your first simulation**
Create a circuit from a template, simulate it, and extract waveforms --- all through tool calls.
[First simulation walkthrough](/getting-started/first-simulation/)
</Steps>
## What you can do
Once installed, mcltspice gives your MCP client the ability to:
<CardGrid>
<Card title="Simulate circuits" icon="seti:config">
Run `.asc` schematics and `.cir` netlists through LTspice. Sweep parameters, vary temperature, run Monte Carlo.
</Card>
<Card title="Analyze results" icon="seti:notebook">
Extract waveforms, measure bandwidth, compute FFT and THD, analyze noise, check stability margins.
</Card>
<Card title="Edit and generate" icon="seti:zig">
Read and modify schematics, build netlists from scratch, generate circuits from templates, run design rule checks.
</Card>
<Card title="Browse the library" icon="seti:folder">
Search 6500+ component symbols, 4000+ example circuits, and SPICE model/subcircuit definitions.
</Card>
</CardGrid>
## Next steps
<LinkCard title="Prerequisites" description="Set up Wine and LTspice on your system." href="/getting-started/prerequisites/" />
<LinkCard title="Claude Code Setup" description="Configure mcltspice in Claude Code or other MCP clients." href="/getting-started/claude-code/" />
<LinkCard title="First Simulation" description="Walk through an end-to-end simulation workflow." href="/getting-started/first-simulation/" />

View File

@ -0,0 +1,109 @@
---
title: Prerequisites
description: Set up LTspice and Wine on Linux.
---
import { Steps, Tabs, TabItem, Aside, Code } from '@astrojs/starlight/components';
mcltspice drives LTspice through Wine in headless batch mode. You need two things: a working Wine installation and the LTspice application files extracted from the Windows installer.
## Install Wine
<Tabs>
<TabItem label="Arch Linux">
```bash
sudo pacman -S wine
```
</TabItem>
<TabItem label="Debian / Ubuntu">
```bash
sudo dpkg --add-architecture i386
sudo apt update
sudo apt install wine64
```
</TabItem>
<TabItem label="Fedora">
```bash
sudo dnf install wine
```
</TabItem>
</Tabs>
Verify the installation:
```bash
wine --version
```
<Aside type="tip">
mcltspice uses Wine in batch mode only. No display server or GUI is needed --- it works fine in headless environments, containers, and SSH sessions.
</Aside>
## Extract LTspice
LTspice is distributed as a Windows `.msi` installer. Rather than running it through Wine's installer, extract the files directly with `7z`.
<Steps>
1. **Download LTspice**
Get `LTspice64.msi` from [analog.com/ltspice](https://www.analog.com/en/resources/design-tools-and-calculators/ltspice-simulator-software.html).
2. **Extract the MSI**
```bash
7z x LTspice64.msi -oltspice
cd ltspice
7z x disk1.cab
```
3. **Initialize a Wine prefix**
```bash
export WINEPREFIX=$PWD/.wine
export WINEARCH=win64
wineboot --init
```
This creates a minimal Wine prefix in the same directory. LTspice does not need a full Windows environment --- the prefix just provides the runtime.
</Steps>
<Aside type="note">
You need `p7zip` (or `7zip`) installed to extract the MSI. On Arch: `sudo pacman -S p7zip`. On Debian/Ubuntu: `sudo apt install p7zip-full`.
</Aside>
## Set the LTspice directory
mcltspice looks for LTspice in this order:
1. The `LTSPICE_DIR` environment variable
2. The default path: `~/claude/ltspice/extracted/ltspice`
If your extracted files are elsewhere, set the environment variable:
```bash
export LTSPICE_DIR=/path/to/your/extracted/ltspice
```
For persistent configuration, add it to your shell profile (`~/.bashrc`, `~/.zshrc`, etc.) or pass it through your MCP client configuration.
<Aside type="tip">
The directory should contain the `XVIIx64.exe` binary and the `lib/` folder with component libraries. If you see those files, the extraction worked correctly.
</Aside>
## Verify the setup
Once Wine and LTspice are in place, use the `check_installation` tool to confirm everything is working:
```
check_installation()
```
This checks for:
- Wine availability and version
- LTspice binary presence
- Library and symbol directories
- Write permissions for output files
If any check fails, the tool reports exactly what is missing and how to fix it.

View File

@ -0,0 +1,63 @@
---
title: mcltspice
description: Drive LTspice from any MCP client. 37 tools for circuit simulation, analysis, and design automation.
template: splash
hero:
tagline: Drive LTspice from any MCP client. 37 tools for circuit simulation, analysis, and design automation.
actions:
- text: Get Started
link: /getting-started/
icon: right-arrow
- text: Tool Reference
link: /reference/
variant: minimal
---
import { Card, CardGrid } from '@astrojs/starlight/components';
## Documentation
<CardGrid>
<Card title="Getting Started" icon="rocket">
Install mcltspice and run your first simulation in under a minute.
[Start here](/getting-started/)
</Card>
<Card title="Tutorials" icon="open-book">
Step-by-step circuit design walkthroughs, from filters to Monte Carlo yield analysis.
[Browse tutorials](/tutorials/)
</Card>
<Card title="Tutorials" icon="list-format">
Task-specific walkthroughs --- filter design, Monte Carlo yield, parameter sweeps.
[Browse tutorials](/tutorials/)
</Card>
<Card title="Reference" icon="setting">
Every tool, resource, and prompt documented with parameters, types, and examples.
[Full reference](/reference/)
</Card>
</CardGrid>
## What's inside
<CardGrid stagger>
<Card title="Simulation" icon="seti:config">
7 tools --- run schematics and netlists, sweep parameters, Monte Carlo analysis, optimization, and tuning.
</Card>
<Card title="Waveform" icon="seti:audio">
5 tools --- extract signals from `.raw` files, evaluate expressions, export to CSV, and generate SVG plots.
</Card>
<Card title="Signal Analysis" icon="seti:notebook">
4 tools --- FFT, THD, bandwidth measurement, operating point extraction, and transfer functions.
</Card>
<Card title="Noise Analysis" icon="random">
3 tools --- full noise analysis, spot noise at a frequency, and integrated RMS noise over a band.
</Card>
<Card title="Stability and Power" icon="seti:log">
3 tools --- gain and phase margin, power dissipation metrics, and efficiency calculations.
</Card>
<Card title="Schematic and Netlist" icon="seti:zig">
8 tools --- read, edit, diff, and DRC schematics. Build netlists, generate from templates, parse Touchstone files.
</Card>
<Card title="Library and Templates" icon="seti:folder">
7 tools --- browse 6500+ symbols, 4000+ examples, search SPICE models and subcircuits, verify installation.
</Card>
</CardGrid>

View File

@ -0,0 +1,66 @@
---
title: Reference
description: Complete reference for all mcltspice tools, resources, and prompts.
---
import { LinkCard } from '@astrojs/starlight/components';
mcltspice exposes 37 tools, 5 resources, and 7 prompts. This section documents every one of them with parameter types, defaults, return values, and usage notes.
## Tools by category
<LinkCard
title="Simulation (7 tools)"
description="Run schematics and netlists, sweep parameters, vary temperature, run Monte Carlo analysis, optimize and tune component values."
href="/reference/simulation/"
/>
<LinkCard
title="Waveform (5 tools)"
description="Extract signals from .raw files, evaluate math expressions, export data to CSV, and generate SVG Bode and time-domain plots."
href="/reference/waveform/"
/>
<LinkCard
title="Signal Analysis (4 tools)"
description="FFT, THD, bandwidth measurement, operating point extraction, and transfer function queries."
href="/reference/signal-analysis/"
/>
<LinkCard
title="Noise (3 tools)"
description="Full noise spectral density analysis, spot noise at a frequency, and integrated RMS noise over a band."
href="/reference/noise/"
/>
<LinkCard
title="Stability and Power (3 tools)"
description="Gain and phase margin from loop gain data, power dissipation metrics, and efficiency calculations."
href="/reference/stability-power/"
/>
<LinkCard
title="Schematic and Netlist (8 tools)"
description="Read, edit, diff, and DRC schematics. Build netlists programmatically, generate from templates, parse Touchstone files."
href="/reference/schematic-netlist/"
/>
<LinkCard
title="Library and Templates (7 tools)"
description="Browse 6500+ symbols, 4000+ example circuits, search SPICE models and subcircuits, list templates, verify installation."
href="/reference/library-templates/"
/>
## Resources and prompts
<LinkCard
title="Resources (5 URIs)"
description="Read-only data sources exposed via MCP resource URIs --- symbols, examples, status, templates, and template detail."
href="/reference/resources/"
/>
<LinkCard
title="Prompts (7 prompts)"
description="Guided workflows for filter design, power supply analysis, debugging, optimization, Monte Carlo, circuit creation, and troubleshooting."
href="/reference/prompts/"
/>

View File

@ -0,0 +1,249 @@
---
title: Library and Template Tools
description: Browse components, search models, and use circuit templates.
---
import { Aside } from '@astrojs/starlight/components';
mcltspice ships 7 tools for browsing LTspice's component library, searching SPICE model and subcircuit definitions, managing circuit templates, and verifying your installation. These tools never modify anything on disk --- they are read-only queries against the LTspice library files.
<Aside type="tip">
Use `list_templates` first to see what is available, then `create_from_template` or `generate_schematic` to build circuits. See the [Schematic and Netlist reference](/reference/schematic-netlist/) for those creation tools.
</Aside>
---
## list_templates
List all available circuit templates with their parameters and default values.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td colspan="4"><em>No parameters.</em></td></tr>
</tbody>
</table>
**Returns:** `dict` with `templates` (list of name, description, and params for each) and `total_count`.
```json
// Example response
{
"templates": [
{
"name": "rc_lowpass",
"description": "RC low-pass filter, fc ~ 1.59 kHz",
"params": { "r": "1k", "c": "100n", "f_start": "1", "f_stop": "1meg" }
},
{
"name": "voltage_divider",
"description": "Resistive voltage divider",
"params": { "v_in": "5", "r1": "10k", "r2": "10k", "sim_type": "dc" }
}
],
"total_count": 15
}
```
---
## list_symbols
Browse LTspice's 6500+ component symbols. Filter by category or search by name.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>category</td><td><code>str | None</code></td><td><code>None</code></td><td>Filter by category folder (e.g. <code>"Opamps"</code>, <code>"Comparators"</code>, <code>"Misc"</code>).</td></tr>
<tr><td>search</td><td><code>str | None</code></td><td><code>None</code></td><td>Case-insensitive search term matched against symbol name.</td></tr>
<tr><td>limit</td><td><code>int</code></td><td><code>50</code></td><td>Maximum number of results to return.</td></tr>
</tbody>
</table>
**Returns:** `dict` with `symbols` (list of name, category, path), `total_count`, and `returned_count`.
```json
// Example response (search='LT1')
{
"symbols": [
{ "name": "LT1001", "category": "Opamps", "path": "/home/user/ltspice/lib/sym/Opamps/LT1001.asy" },
{ "name": "LT1006", "category": "Opamps", "path": "/home/user/ltspice/lib/sym/Opamps/LT1006.asy" },
{ "name": "LT1010", "category": "Misc", "path": "/home/user/ltspice/lib/sym/Misc/LT1010.asy" }
],
"total_count": 342,
"returned_count": 50
}
```
---
## list_examples
Browse 4000+ example circuits from the LTspice installation. Filter by category folder or search by name.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>category</td><td><code>str | None</code></td><td><code>None</code></td><td>Filter by category folder name.</td></tr>
<tr><td>search</td><td><code>str | None</code></td><td><code>None</code></td><td>Case-insensitive search term matched against example name.</td></tr>
<tr><td>limit</td><td><code>int</code></td><td><code>50</code></td><td>Maximum number of results to return.</td></tr>
</tbody>
</table>
**Returns:** `dict` with `examples` (list of name, category, path), `total_count`, and `returned_count`.
```json
// Example response (search='buck')
{
"examples": [
{ "name": "Buck", "category": "Educational", "path": "/home/user/ltspice/examples/Educational/Buck.asc" },
{ "name": "LT3800_Buck", "category": "jigs", "path": "/home/user/ltspice/examples/jigs/LT3800_Buck.asc" }
],
"total_count": 37,
"returned_count": 37
}
```
---
## get_symbol_info
Get pin names, attributes, and description from a `.asy` symbol file.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>symbol_path</td><td><code>str</code></td><td><em>required</em></td><td>Absolute path to a <code>.asy</code> symbol file.</td></tr>
</tbody>
</table>
**Returns:** `dict` with `name`, `pins` (list of pin names), `attributes` (key-value pairs), `description`, `prefix`, and `spice_prefix`.
```json
// Example response
{
"name": "LT1001",
"pins": ["IN+", "IN-", "V+", "V-", "OUT"],
"attributes": {
"Prefix": "X",
"SpiceModel": "LT1001",
"Value": "LT1001"
},
"description": "Low Offset, Low Drift Op Amp",
"prefix": "X",
"spice_prefix": "X"
}
```
---
## search_spice_models
Search `.model` definitions in the LTspice library. These are discrete devices: transistors, diodes, JFETs.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>search</td><td><code>str | None</code></td><td><code>None</code></td><td>Case-insensitive search term for model name.</td></tr>
<tr><td>model_type</td><td><code>str | None</code></td><td><code>None</code></td><td>Filter by type: <code>NPN</code>, <code>PNP</code>, <code>NMOS</code>, <code>PMOS</code>, <code>D</code>, <code>NJF</code>, <code>PJF</code>.</td></tr>
<tr><td>limit</td><td><code>int</code></td><td><code>50</code></td><td>Maximum number of results.</td></tr>
</tbody>
</table>
**Returns:** `dict` with `models` (list of name, type, source_file, parameters) and `total_count`.
```json
// Example response (model_type='NPN', search='2N')
{
"models": [
{
"name": "2N2222",
"type": "NPN",
"source_file": "standard.bjt",
"parameters": "Is=14.34f Xti=3 Eg=1.11 Vaf=74.03 ..."
}
],
"total_count": 18
}
```
---
## search_spice_subcircuits
Search `.subckt` definitions in the library. These are complex components like op-amps, voltage regulators, and other ICs.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>search</td><td><code>str | None</code></td><td><code>None</code></td><td>Case-insensitive search term for subcircuit name.</td></tr>
<tr><td>limit</td><td><code>int</code></td><td><code>50</code></td><td>Maximum number of results.</td></tr>
</tbody>
</table>
**Returns:** `dict` with `subcircuits` (list of name, pins, pin_names, description, source_file, n_components) and `total_count`.
```json
// Example response (search='LT1')
{
"subcircuits": [
{
"name": "LT1001",
"pins": 5,
"pin_names": ["1", "2", "3", "4", "5"],
"description": "Low Offset, Low Drift Op Amp",
"source_file": "LT1001.sub",
"n_components": 42
}
],
"total_count": 156
}
```
---
## check_installation
Verify that LTspice and Wine are properly installed and accessible.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td colspan="4"><em>No parameters.</em></td></tr>
</tbody>
</table>
**Returns:** `dict` with `valid` (boolean), `message`, `paths` (ltspice_dir, ltspice_exe, wine_prefix, lib_dir, examples_dir), `lib_exists`, and `examples_exist`.
```json
// Example response (healthy installation)
{
"valid": true,
"message": "LTspice installation OK",
"paths": {
"ltspice_dir": "/home/user/ltspice/extracted/ltspice",
"ltspice_exe": "/home/user/ltspice/extracted/ltspice/XVIIx64.exe",
"wine_prefix": "/home/user/ltspice/extracted/ltspice/.wine",
"lib_dir": "/home/user/ltspice/extracted/ltspice/lib",
"examples_dir": "/home/user/ltspice/extracted/ltspice/examples"
},
"lib_exists": true,
"examples_exist": true
}
```
If `valid` is `false`, the `message` field explains what is missing and how to fix it. See [Prerequisites](/getting-started/prerequisites/) for setup instructions.

View File

@ -0,0 +1,137 @@
---
title: Noise Analysis Tools
description: Spectral density, spot noise, and integrated RMS noise.
---
import { Tabs, TabItem, Aside, Code } from '@astrojs/starlight/components';
These tools analyze output from LTspice `.noise` simulations. Run a noise simulation first with a directive like `.noise V(out) V1 dec 100 1 1meg`, then pass the resulting `.raw` file to any of the tools below.
<Aside type="note" title="onoise vs. inoise">
LTspice noise simulations produce two variables: **onoise** (output-referred noise) and **inoise** (input-referred noise). Output-referred noise is the noise spectral density measured at the output node --- it represents what an instrument would see at the output. Input-referred noise is calculated by dividing the output noise by the circuit's gain, giving the equivalent noise you would need to inject at the input to produce the same output. Use `onoise` when you care about absolute output noise levels; use `inoise` when comparing a circuit's noise floor against the source signal.
</Aside>
---
### analyze_noise
Comprehensive noise analysis from a `.noise` simulation. Parses the `.raw` file and returns spectral density across all simulated frequencies, spot noise at five standard frequencies (10 Hz, 100 Hz, 1 kHz, 10 kHz, 100 kHz), total integrated RMS noise over the full bandwidth, noise figure relative to the source resistance, and an estimate of the 1/f (flicker) corner frequency.
The noise figure calculation uses the formula NF(f) = 10 log10(|noise(f)|^2 / (4 k T R)), referenced to the IEEE standard temperature of 290 K.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to `.raw` file from a `.noise` simulation.</td></tr>
<tr><td>noise_signal</td><td>`str`</td><td>`"onoise"`</td><td>Which noise variable to analyze. `"onoise"` for output-referred, `"inoise"` for input-referred.</td></tr>
<tr><td>source_resistance</td><td>`float`</td><td>`50.0`</td><td>Source impedance in ohms, used for noise figure calculation.</td></tr>
</tbody>
</table>
**Returns:** A dict with five top-level keys:
- `spectral_density` -- arrays of `frequency_hz`, `noise_density_v_per_sqrt_hz`, and `noise_density_db`.
- `spot_noise` -- a dict keyed by frequency label (`"10Hz"`, `"100Hz"`, `"1kHz"`, `"10kHz"`, `"100kHz"`), each containing `spot_noise_v_per_sqrt_hz`, `spot_noise_db`, and `actual_freq_hz`. Only includes frequencies within the simulation range.
- `total_noise` -- `total_rms_v`, `integration_range_hz` (two-element array), and `equivalent_noise_bandwidth_hz`.
- `noise_figure` -- arrays of `noise_figure_db` and `frequency_hz`, plus `min_nf_db` and `nf_at_1khz`.
- `flicker_corner_hz` -- estimated 1/f corner frequency in Hz, or `null` if not detectable.
<details>
<summary>Example</summary>
```json
{
"spectral_density": {
"frequency_hz": [1.0, 1.26, 1.58, "..."],
"noise_density_v_per_sqrt_hz": [4.2e-7, 3.9e-7, 3.5e-7, "..."],
"noise_density_db": [-127.5, -128.2, -129.1, "..."]
},
"spot_noise": {
"10Hz": {
"spot_noise_v_per_sqrt_hz": 3.1e-7,
"spot_noise_db": -130.2,
"actual_freq_hz": 10.0
},
"1kHz": {
"spot_noise_v_per_sqrt_hz": 1.2e-7,
"spot_noise_db": -138.4,
"actual_freq_hz": 1000.0
}
},
"total_noise": {
"total_rms_v": 4.7e-5,
"integration_range_hz": [1.0, 1000000.0],
"equivalent_noise_bandwidth_hz": 156000.0
},
"noise_figure": {
"noise_figure_db": [12.3, 11.8, "..."],
"frequency_hz": [1.0, 1.26, "..."],
"min_nf_db": 3.2,
"nf_at_1khz": 5.1
},
"flicker_corner_hz": 850.0
}
```
</details>
---
### get_spot_noise
Get noise spectral density at a specific frequency. Interpolates linearly between adjacent simulation data points. If the target frequency falls outside the simulated range, the nearest boundary value is returned.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to `.raw` file from a `.noise` simulation.</td></tr>
<tr><td>target_freq</td><td>`float`</td><td>---</td><td>Frequency in Hz at which to measure noise density.</td></tr>
<tr><td>noise_signal</td><td>`str`</td><td>`"onoise"`</td><td>`"onoise"` for output-referred or `"inoise"` for input-referred.</td></tr>
</tbody>
</table>
**Returns:** A dict with `spot_noise_v_per_sqrt_hz` (noise density in V/sqrt(Hz)), `spot_noise_db` (20 log10 of the density), and `actual_freq_hz` (the frequency actually used --- equals `target_freq` when interpolation succeeds, or the clamped boundary frequency otherwise).
<details>
<summary>Example</summary>
```json
{
"spot_noise_v_per_sqrt_hz": 1.2e-7,
"spot_noise_db": -138.4,
"actual_freq_hz": 1000.0
}
```
</details>
---
### get_total_noise
Integrate noise spectral density over a frequency band to get total RMS noise. Computes `total_rms = sqrt(integral(|noise|^2 * df))` using trapezoidal integration. This is the value you would read on an RMS voltmeter with a bandwidth equal to the integration range.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to `.raw` file from a `.noise` simulation.</td></tr>
<tr><td>noise_signal</td><td>`str`</td><td>`"onoise"`</td><td>`"onoise"` or `"inoise"`.</td></tr>
<tr><td>f_low</td><td>`float | None`</td><td>`None`</td><td>Lower integration bound in Hz. Defaults to the minimum frequency in the simulation data.</td></tr>
<tr><td>f_high</td><td>`float | None`</td><td>`None`</td><td>Upper integration bound in Hz. Defaults to the maximum frequency in the simulation data.</td></tr>
</tbody>
</table>
**Returns:** A dict with `total_rms_v` (integrated RMS noise in volts), `integration_range_hz` (two-element array `[f_low, f_high]`), and `equivalent_noise_bandwidth_hz` (the bandwidth of a brick-wall filter with the same peak density that would pass the same total noise power).
<details>
<summary>Example</summary>
```json
{
"total_rms_v": 4.7e-5,
"integration_range_hz": [100.0, 100000.0],
"equivalent_noise_bandwidth_hz": 42000.0
}
```
</details>

View File

@ -0,0 +1,227 @@
---
title: MCP Prompts
description: Guided workflows for common circuit design tasks.
---
import { Aside, Code } from '@astrojs/starlight/components';
MCP prompts are conversation starters. Each prompt generates an initial message that guides the LLM through a multi-step workflow, telling it which tools to call and in what order. Think of them as runbooks --- they encode best practices so the LLM does not have to figure out the workflow from scratch.
mcltspice provides 7 prompts covering filter design, power supply analysis, debugging, optimization, Monte Carlo yield analysis, building circuits from descriptions, and troubleshooting simulation failures.
<Aside type="note">
Prompt support varies by client. In Claude Code, prompts appear as suggested workflows. In other MCP clients, they may be listed in a prompt library or triggered from a menu.
</Aside>
---
## design_filter
Walks through designing a filter circuit: selecting a topology, creating the netlist, simulating with AC analysis, measuring bandwidth, and iterating on component values.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>filter_type</td><td><code>str</code></td><td><code>"lowpass"</code></td><td>Filter response: <code>lowpass</code>, <code>highpass</code>, <code>bandpass</code>, or <code>notch</code>.</td></tr>
<tr><td>topology</td><td><code>str</code></td><td><code>"rc"</code></td><td>Circuit topology: <code>rc</code> (1st order), <code>rlc</code> (2nd order), or <code>sallen-key</code> (active).</td></tr>
<tr><td>cutoff_freq</td><td><code>str</code></td><td><code>"1kHz"</code></td><td>Target cutoff frequency with units.</td></tr>
</tbody>
</table>
**Workflow steps:**
1. Use `create_netlist` to build the filter circuit
2. Add `.ac` analysis directive for a frequency sweep
3. Add `.meas` directive for -3dB bandwidth
4. Simulate with `simulate_netlist`
5. Use `measure_bandwidth` to verify the cutoff frequency
6. Use `get_waveform` to inspect the full frequency response
7. Adjust component values and re-simulate if needed
**Design tips included in the prompt:**
- For RC lowpass: f_c = 1 / (2 * pi * R * C)
- For 2nd-order filters: Q controls peaking; Butterworth uses Q = 0.707
- Use `search_spice_models` to find op-amp models for active topologies
---
## analyze_power_supply
Guides through measuring the key performance metrics of a power supply: regulation, ripple, transient response, and efficiency.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>schematic_path</td><td><code>str</code></td><td><code>""</code></td><td>Path to the power supply schematic. If empty, the prompt asks the LLM to identify or create one first.</td></tr>
</tbody>
</table>
**Workflow steps:**
1. Use `read_schematic` to understand the circuit topology
2. Use `run_drc` to check for design issues
3. Simulate with `.tran` analysis, including a load step if applicable
4. Use `analyze_waveform` to measure:
- Peak-to-peak output ripple
- Settling time after load transients
- FFT of the output to identify noise frequencies
5. If AC analysis is available, use `measure_bandwidth` for loop gain
**Key metrics extracted:** output voltage regulation (DC accuracy), ripple voltage, load transient settling time, efficiency.
---
## debug_circuit
A systematic debugging workflow: validate the schematic, check models, run the simulation, inspect node voltages, and isolate problems by simplifying the circuit.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>schematic_path</td><td><code>str</code></td><td><code>""</code></td><td>Path to the problematic schematic. If empty, the prompt asks the LLM to identify it first.</td></tr>
</tbody>
</table>
**Workflow steps:**
1. **Validate** -- Run `run_drc` to catch missing ground, floating nodes, duplicate component names
2. **Check setup** -- Use `read_schematic` to review component values and connections
3. **Verify models** -- Use `search_spice_models` to confirm all referenced models exist
4. **Run and analyze** -- Simulate, then use `get_waveform` to inspect key node voltages and compare against expected values
5. **Isolate** -- Use `edit_component` to simplify (replace active devices with ideal sources), then `diff_schematics` to track which change fixed the issue
**Common issues surfaced:** wrong node connections, missing bias voltages, component values off by orders of magnitude, model name mismatches.
---
## optimize_design
An iterative optimization workflow that uses `optimize_circuit` and Monte Carlo analysis to tune a circuit toward a target specification.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>circuit_type</td><td><code>str</code></td><td><code>"filter"</code></td><td>Type of circuit: <code>filter</code>, <code>amplifier</code>, <code>regulator</code>, <code>oscillator</code>.</td></tr>
<tr><td>target_spec</td><td><code>str</code></td><td><code>"1kHz bandwidth"</code></td><td>Target specification to achieve.</td></tr>
</tbody>
</table>
**Workflow steps:**
1. Use `list_templates` to find a suitable starting point
2. Create the initial circuit with `create_from_template`
3. Simulate and measure current performance
4. Use `optimize_circuit` to automatically tune component values:
- Define target metrics (bandwidth, gain, settling time)
- Specify component ranges with preferred E-series values
- The optimizer iterates (typically 10-20 simulations)
5. Verify the optimized design with a full simulation
6. Run Monte Carlo with the `monte_carlo` tool to check yield under tolerances
**Metric targets by circuit type:**
- Filters: `bandwidth_hz`
- Amplifiers: `gain_db` and `phase_margin_deg`
- Regulators: `settling_time` and `peak_to_peak` (ripple)
---
## monte_carlo_analysis
Walks through a statistical yield analysis: running many simulations with randomized component tolerances, extracting metrics from each run, and computing pass/fail statistics.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>circuit_description</td><td><code>str</code></td><td><code>"RC filter"</code></td><td>Description of the circuit to analyze.</td></tr>
<tr><td>n_runs</td><td><code>str</code></td><td><code>"100"</code></td><td>Number of Monte Carlo iterations.</td></tr>
</tbody>
</table>
**Workflow steps:**
1. Create or identify the netlist
2. Use the `monte_carlo` tool with component tolerances:
- Resistors: 1% (0.01) or 5% (0.05)
- Capacitors: 10% (0.1) or 20% (0.2)
- Inductors: 10% (0.1)
3. For each run, extract key metrics using `get_waveform`, `analyze_waveform`, and `measure_bandwidth`
4. Compute statistics across all runs: mean, standard deviation, min/max, and yield percentage
**Tips included in the prompt:**
- Use `list_simulation_runs` to understand stepped data
- Start with 10-20 runs to verify the setup, then scale up
- Set a seed for reproducible results during development
- Typical tolerances: metal film resistors 1%, ceramic caps 10-20%, electrolytics 20%
---
## circuit_from_scratch
Builds a complete circuit from a text description, offering three approaches: using a template, building from individual components, or generating a graphical schematic.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>description</td><td><code>str</code></td><td><code>"audio amplifier"</code></td><td>Plain-text description of what circuit to build.</td></tr>
</tbody>
</table>
**Three approaches offered:**
1. **Template** (recommended for common circuits) -- `list_templates` then `create_from_template`
2. **Component-level** -- `create_netlist` with `search_spice_models` and `search_spice_subcircuits` for model lookup
3. **Graphical schematic** -- `generate_schematic` to produce an `.asc` file that can also be opened in the LTspice GUI
**Verification workflow:**
1. `run_drc` to catch design issues
2. `.op` analysis to verify DC bias point
3. `.tf` analysis for gain and impedance
4. `.ac` analysis for frequency response
5. `.tran` analysis for time-domain behavior
6. `diff_schematics` to compare design iterations
---
## troubleshoot_simulation
A diagnostic checklist for simulation failures and convergence issues. Works through the problem systematically: DRC, installation check, model verification, directive inspection, node analysis, and progressive simplification.
<table class="param-table">
<thead>
<tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr>
</thead>
<tbody>
<tr><td>error_description</td><td><code>str</code></td><td><code>""</code></td><td>What went wrong --- error message, unexpected results, etc. If empty, the prompt runs a full diagnostic.</td></tr>
<tr><td>schematic_path</td><td><code>str</code></td><td><code>""</code></td><td>Path to the problematic schematic or netlist.</td></tr>
</tbody>
</table>
**Diagnostic checklist (in order):**
1. **Design Rule Check** -- `run_drc` for missing ground, floating nodes, duplicate names, missing simulation directive
2. **Installation** -- `check_installation` to verify Wine and LTspice
3. **Model availability** -- `search_spice_models` and `search_spice_subcircuits` to confirm all referenced models exist
4. **Simulation directive** -- `read_schematic` to inspect the directive; verify analysis type, stop time, frequency range
5. **Node connections** -- `read_schematic` to list all components and nets; check for disconnected nodes
6. **Run and inspect** -- Simulate, check the log file for convergence warnings, use `get_waveform` to inspect node voltages
7. **Simplify and isolate** -- `edit_component` to swap active devices for ideal ones; remove non-essential subcircuits; test each stage independently
**Common failure modes addressed:**
- Convergence failure: reduce timestep, add initial conditions
- All-zeros output: check ground connections and source polarity
- Unexpected clipping: check supply voltages and headroom
- Oscillation in DC circuits: add small feedback capacitors
- Model not found: verify `.lib` / `.include` paths

View File

@ -0,0 +1,153 @@
---
title: MCP Resources
description: Read-only data sources exposed via MCP resource URIs.
---
import { Aside } from '@astrojs/starlight/components';
MCP resources are read-only data sources that clients can attach to conversations for context. Unlike tools, resources are not invoked with parameters --- they are referenced by URI and return structured data. A client might attach `ltspice://status` at the start of a session so the LLM knows what is available without making a tool call.
mcltspice exposes 5 resources.
<Aside type="note">
Resource support varies by MCP client. Claude Code currently reads resources when they are referenced in conversation context. Other clients may list available resources in a sidebar or attach them automatically.
</Aside>
---
## ltspice://symbols
All component symbols from the LTspice library, organized by category. This is equivalent to calling `list_symbols(limit=10000)`.
```json
// Response structure
{
"symbols": [
{ "name": "LT1001", "category": "Opamps", "path": "/home/user/ltspice/lib/sym/Opamps/LT1001.asy" },
{ "name": "1N4148", "category": "Misc", "path": "/home/user/ltspice/lib/sym/Misc/1N4148.asy" }
],
"total_count": 6523,
"returned_count": 6523
}
```
Use this when you need a complete inventory of available components. For targeted searches, the `list_symbols` tool with `category` or `search` parameters is more efficient.
---
## ltspice://examples
All example circuits from the LTspice installation. Equivalent to `list_examples(limit=10000)`.
```json
// Response structure
{
"examples": [
{ "name": "Buck", "category": "Educational", "path": "/home/user/ltspice/examples/Educational/Buck.asc" },
{ "name": "LT1001", "category": "jigs", "path": "/home/user/ltspice/examples/jigs/LT1001.asc" }
],
"total_count": 4102,
"returned_count": 4102
}
```
Examples are organized by category folder. Categories like `Educational` contain teaching circuits; `jigs` contains test and evaluation schematics for specific ICs.
---
## ltspice://status
Current installation status as JSON. Equivalent to calling `check_installation()`.
```json
// Response structure
{
"valid": true,
"message": "LTspice installation OK",
"paths": {
"ltspice_dir": "/home/user/ltspice/extracted/ltspice",
"ltspice_exe": "/home/user/ltspice/extracted/ltspice/XVIIx64.exe",
"wine_prefix": "/home/user/ltspice/extracted/ltspice/.wine",
"lib_dir": "/home/user/ltspice/extracted/ltspice/lib",
"examples_dir": "/home/user/ltspice/extracted/ltspice/examples"
},
"lib_exists": true,
"examples_exist": true
}
```
Attaching this resource at session start lets the LLM immediately know whether LTspice is ready and where files are located, without needing a tool call.
---
## ltspice://templates
All available circuit templates (both netlist and schematic formats) with their parameters and default values.
```json
// Response structure
{
"netlist_templates": [
{
"name": "rc_lowpass",
"description": "RC low-pass filter, fc ~ 1.59 kHz",
"params": { "r": "1k", "c": "100n", "f_start": "1", "f_stop": "1meg" }
},
{
"name": "buck_converter",
"description": "Synchronous buck converter",
"params": { "ind": "10u", "c_out": "100u", "r_load": "10", "v_in": "12", "duty_cycle": "0.5", "freq": "100k", "mosfet_model": "Si7336ADP", "diode_model": "CMDSH2-3" }
}
],
"schematic_templates": [
{
"name": "rc_lowpass",
"description": "RC low-pass filter (.asc schematic)",
"params": { "r": "1k", "c": "100n" }
}
]
}
```
The response separates netlist templates (`.cir` files created by `create_from_template`) from schematic templates (`.asc` files created by `generate_schematic`). Some templates appear in both lists with slightly different parameter sets.
---
## ltspice://template/\{name\}
Detail for a specific template by name. This is a URI template --- replace `{name}` with the template name.
**Example URIs:**
- `ltspice://template/rc_lowpass`
- `ltspice://template/buck_converter`
- `ltspice://template/sallen_key_lowpass`
```json
// Response for ltspice://template/rc_lowpass
{
"name": "rc_lowpass",
"netlist": {
"description": "RC low-pass filter, fc ~ 1.59 kHz",
"params": { "r": "1k", "c": "100n", "f_start": "1", "f_stop": "1meg" },
"type": "netlist (.cir)"
},
"schematic": {
"description": "RC low-pass filter (.asc schematic)",
"params": { "r": "1k", "c": "100n" },
"type": "schematic (.asc)"
}
}
```
If the template exists in only one format (netlist or schematic), only that key is present. If the template name is not found, the response contains an `error` field:
```json
// Response for unknown template
{
"error": "Template 'nonexistent' not found"
}
```
<Aside type="tip">
Use `ltspice://templates` to discover all available template names, then query `ltspice://template/{name}` for the one you need.
</Aside>

View File

@ -0,0 +1,416 @@
---
title: Schematic and Netlist Tools
description: Read, edit, compare, and create circuit files.
---
import { Tabs, TabItem, Aside, Code } from '@astrojs/starlight/components';
Eight tools for working with LTspice `.asc` schematics, SPICE `.cir` netlists, and Touchstone S-parameter files. These cover the full lifecycle: read an existing circuit, edit component values, compare revisions, run design rule checks, build new circuits from scratch or from templates, and parse RF measurement data.
---
### read_schematic
Read and parse an LTspice `.asc` schematic file. Extracts all component instances with their symbols, values, positions, and attributes; net flag names; SPICE directives (simulation commands, `.param`, `.lib`, etc.); and wire count.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>schematic_path</td><td>`str`</td><td>---</td><td>Path to the `.asc` schematic file.</td></tr>
</tbody>
</table>
**Returns:** A dict with `version` (schematic format version), `components` (array of objects each containing `name`, `symbol`, `value`, `x`, `y`, and `attributes`), `nets` (array of net flag names), `directives` (array of SPICE directive strings), and `wire_count`.
<details>
<summary>Example</summary>
```json
{
"version": 4,
"components": [
{
"name": "R1",
"symbol": "res",
"value": "10k",
"x": 192,
"y": 128,
"attributes": {"Value": "10k"}
},
{
"name": "C1",
"symbol": "cap",
"value": "100n",
"x": 320,
"y": 128,
"attributes": {"Value": "100n"}
},
{
"name": "V1",
"symbol": "voltage",
"value": "AC 1",
"x": 64,
"y": 128,
"attributes": {"Value": "AC 1"}
}
],
"nets": ["0", "in", "out"],
"directives": [".ac dec 100 1 1meg"],
"wire_count": 8
}
```
</details>
---
### edit_component
Modify a component's value in a schematic. Parses the `.asc` file, finds the component by instance name (case-insensitive), updates its value, and writes the result. Can overwrite the original file or save to a new path.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>schematic_path</td><td>`str`</td><td>---</td><td>Path to the `.asc` schematic file.</td></tr>
<tr><td>component_name</td><td>`str`</td><td>---</td><td>Instance name of the component to modify, e.g. `"R1"`, `"C2"`, `"M1"`.</td></tr>
<tr><td>new_value</td><td>`str`</td><td>---</td><td>New value string, e.g. `"10k"`, `"100n"`, `"2N7000"`.</td></tr>
<tr><td>output_path</td><td>`str | None`</td><td>`None`</td><td>Where to save the modified schematic. `None` overwrites the original.</td></tr>
</tbody>
</table>
**Returns:** A dict with `success` (boolean), `component` (the component name), `new_value`, `output_path` (path written to), and `symbol` (the component's symbol type). On failure, returns `success: false` with an `error` message listing available component names.
<details>
<summary>Example</summary>
```json
{
"success": true,
"component": "R1",
"new_value": "22k",
"output_path": "/tmp/filter_modified.asc",
"symbol": "res"
}
```
</details>
---
### diff_schematics
Compare two schematics and produce a structured diff. Reports component additions, removals, and value changes; directive additions, removals, and modifications; net flag additions and removals; and wire count changes. Components are matched by instance name, so renaming a component shows up as a removal plus an addition.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>schematic_a</td><td>`str`</td><td>---</td><td>Path to the "before" `.asc` file.</td></tr>
<tr><td>schematic_b</td><td>`str`</td><td>---</td><td>Path to the "after" `.asc` file.</td></tr>
</tbody>
</table>
**Returns:** A dict with `has_changes` (boolean), `component_changes` (array of objects with `name`, `change_type` of `"added"` / `"removed"` / `"modified"`, `symbol`, `old_value`, `new_value`, `old_attributes`, `new_attributes`, and `moved`), `directive_changes` (array with `change_type`, `old_text`, `new_text`), `nets_added`, `nets_removed`, `wires_added`, `wires_removed`, and a human-readable `summary` string.
<details>
<summary>Example</summary>
```json
{
"has_changes": true,
"component_changes": [
{
"name": "R1",
"change_type": "modified",
"symbol": "res",
"old_value": "10k",
"new_value": "22k",
"old_attributes": {"Value": "10k"},
"new_attributes": {"Value": "22k"},
"moved": false
},
{
"name": "C3",
"change_type": "added",
"symbol": "cap",
"old_value": null,
"new_value": "47n",
"old_attributes": {},
"new_attributes": {"Value": "47n"},
"moved": false
}
],
"directive_changes": [
{
"change_type": "modified",
"old_text": ".tran 1m",
"new_text": ".tran 10m"
}
],
"nets_added": ["feedback"],
"nets_removed": [],
"wires_added": 3,
"wires_removed": 0,
"summary": "1 component modified:\n R1: 10k -> 22k\n1 component added: C3 (cap) = 47n\n1 directive changed: .tran 1m -> .tran 10m\n1 net added: feedback\n3 wires added"
}
```
</details>
---
### run_drc
Run design rule checks on a schematic. Parses the `.asc` file and runs seven checks against common issues that cause simulation failures or unexpected behavior. Each violation is classified as `error` (will likely prevent simulation), `warning` (may produce unexpected results), or `info` (suggestion).
Checks performed:
1. **NO_GROUND** -- Missing ground (node `0`) connection.
2. **FLOATING_NODE** -- Wire endpoint with only one connection and no flag or component nearby.
3. **NO_SIM_DIRECTIVE** -- No simulation command (`.tran`, `.ac`, `.dc`, `.op`, `.noise`, `.tf`).
4. **VSOURCE_LOOP** -- Two voltage sources connected in parallel (short circuit).
5. **MISSING_VALUE** -- Resistor, capacitor, inductor, or source with no value set.
6. **DUPLICATE_NAME** -- Two components sharing the same instance name.
7. **UNCONNECTED_COMPONENT** -- Component with no wire endpoints within one grid step of its origin.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>schematic_path</td><td>`str`</td><td>---</td><td>Path to the `.asc` schematic file.</td></tr>
</tbody>
</table>
**Returns:** A dict with `passed` (boolean --- `true` if zero errors), `checks_run` (number of checks executed), `summary` (human-readable string), `error_count`, `warning_count`, and `violations` (array of objects each containing `rule`, `severity`, `message`, `component`, and `location`).
<details>
<summary>Example</summary>
```json
{
"passed": false,
"checks_run": 7,
"summary": "DRC FAILED: 7 checks run, 1 error, 1 warning.",
"error_count": 1,
"warning_count": 1,
"violations": [
{
"rule": "NO_GROUND",
"severity": "error",
"message": "No ground node found. Every circuit needs at least one ground (0) connection.",
"component": null,
"location": null
},
{
"rule": "MISSING_VALUE",
"severity": "warning",
"message": "Resistor 'R3' has no value set.",
"component": "R3",
"location": [320, 256]
}
]
}
```
</details>
---
### create_netlist
Create a SPICE netlist programmatically and save it as a `.cir` file. Build circuits from scratch without needing the LTspice graphical editor. The resulting file can be passed directly to `simulate_netlist`.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>title</td><td>`str`</td><td>---</td><td>Circuit title/description (appears as the first line of the `.cir` file).</td></tr>
<tr><td>components</td><td>`list[dict]`</td><td>---</td><td>List of component dicts. Each must have `name` (e.g. `"R1"`, `"V1"`, `"X1"`), `nodes` (list of node name strings, use `"0"` for ground), and `value` (value or model name). Optional `params` key for extra parameters.</td></tr>
<tr><td>directives</td><td>`list[str]`</td><td>---</td><td>List of SPICE directive strings, e.g. `[".tran 10m", ".meas tran vmax MAX V(out)"]`.</td></tr>
<tr><td>output_path</td><td>`str | None`</td><td>`None`</td><td>Where to save the `.cir` file. `None` saves to a temp directory with a name derived from the title.</td></tr>
</tbody>
</table>
**Returns:** A dict with `success` (boolean), `output_path` (where the file was written), `netlist_preview` (full rendered netlist text), and `component_count`.
<details>
<summary>Example -- RC lowpass filter</summary>
Calling `create_netlist` with these arguments:
```json
{
"title": "RC Lowpass Filter",
"components": [
{"name": "V1", "nodes": ["in", "0"], "value": "AC 1"},
{"name": "R1", "nodes": ["in", "out"], "value": "1k"},
{"name": "C1", "nodes": ["out", "0"], "value": "100n"}
],
"directives": [".ac dec 100 1 1meg"]
}
```
Produces this netlist:
```text
* RC Lowpass Filter
V1 in 0 AC 1
R1 in out 1k
C1 out 0 100n
.ac dec 100 1 1meg
.backanno
.end
```
And returns:
```json
{
"success": true,
"output_path": "/tmp/RC_Lowpass_Filter.cir",
"netlist_preview": "* RC Lowpass Filter\n\nV1 in 0 AC 1\nR1 in out 1k\nC1 out 0 100n\n\n.ac dec 100 1 1meg\n.backanno\n.end\n",
"component_count": 3
}
```
</details>
---
### create_from_template
Create a circuit netlist from a pre-built template. Each template generates a complete, ready-to-simulate `.cir` file with default component values that can be selectively overridden. All parameter values are passed as strings.
Available templates:
| Template | Description |
|---|---|
| `voltage_divider` | Resistive voltage divider with `.op` or custom analysis |
| `rc_lowpass` | RC lowpass filter with AC sweep |
| `inverting_amplifier` | Inverting op-amp (gain = -Rf/Rin), +/-15V supply |
| `non_inverting_amplifier` | Non-inverting op-amp (gain = 1 + Rf/Rin), +/-15V supply |
| `differential_amplifier` | Diff amp: Vout = (R2/R1)(V2-V1), +/-15V supply |
| `common_emitter_amplifier` | BJT common-emitter with voltage divider bias |
| `buck_converter` | Step-down DC-DC converter with MOSFET switch |
| `ldo_regulator` | LDO regulator: Vout = Vref * (1 + R1/R2) |
| `colpitts_oscillator` | LC oscillator: f ~ 1/(2 pi sqrt(L Cseries)) |
| `h_bridge` | 4-MOSFET H-bridge motor driver with dead time |
| `sallen_key_lowpass` | Sallen-Key lowpass (unity gain, 2nd order) |
| `boost_converter` | Step-up DC-DC converter with MOSFET switch |
| `instrumentation_amplifier` | 3-opamp instrumentation amp: gain = (1 + 2R1/Rgain)(R3/R2) |
| `current_mirror` | BJT current mirror with reference resistor |
| `transimpedance_amplifier` | TIA: Vout = -Iin * Rf |
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>template_name</td><td>`str`</td><td>---</td><td>Template name from the table above.</td></tr>
<tr><td>params</td><td>`dict[str, str] | None`</td><td>`None`</td><td>Optional parameter overrides as key-value string pairs. Use `list_templates` to see available parameters and defaults for each template.</td></tr>
<tr><td>output_path</td><td>`str | None`</td><td>`None`</td><td>Where to save the `.cir` file. `None` saves to `/tmp/<template_name>.cir`.</td></tr>
</tbody>
</table>
**Returns:** A dict with `success` (boolean), `template` (name used), `description`, `output_path`, `netlist_preview` (full rendered netlist text), `component_count`, and `params_used` (merged defaults and overrides).
<details>
<summary>Example</summary>
```json
{
"success": true,
"template": "rc_lowpass",
"description": "RC lowpass filter with AC sweep",
"output_path": "/tmp/rc_lowpass.cir",
"netlist_preview": "* RC Lowpass Filter\n\nV1 in 0 AC 1\nR1 in out 4.7k\nC1 out 0 10n\n\n.ac dec 100 1 1meg\n.backanno\n.end\n",
"component_count": 3,
"params_used": {
"r": "4.7k",
"c": "10n",
"f_start": "1",
"f_stop": "1meg"
}
}
```
</details>
---
### generate_schematic
Generate an LTspice `.asc` graphical schematic file from a template. Unlike `create_from_template` which produces a text-based `.cir` netlist, this tool creates a ready-to-open `.asc` file with proper component placement, wire routing, net labels, and simulation directives. The output can be loaded directly into the LTspice GUI.
Uses the same template names and parameters as `create_from_template`.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>template</td><td>`str`</td><td>---</td><td>Template name (same set as `create_from_template`).</td></tr>
<tr><td>params</td><td>`dict[str, str] | None`</td><td>`None`</td><td>Optional parameter overrides as key-value string pairs.</td></tr>
<tr><td>output_path</td><td>`str | None`</td><td>`None`</td><td>Where to save the `.asc` file. `None` saves to `/tmp/<template>.asc`.</td></tr>
</tbody>
</table>
**Returns:** A dict with `success` (boolean), `output_path` (path to the generated `.asc` file), `template` (name used), and `schematic_preview` (first 500 characters of the rendered `.asc` content).
<details>
<summary>Example</summary>
```json
{
"success": true,
"output_path": "/tmp/inverting_amp.asc",
"template": "inverting_amp",
"schematic_preview": "Version 4\nSHEET 1 880 680 0\nWIRE 96 192 96 128\nWIRE 96 320 96 256\nWIRE 224 160 160 160\nWIRE 224 224 160 224\n..."
}
```
</details>
---
### read_touchstone
Parse a Touchstone (.s1p, .s2p, .snp) S-parameter file. Supports all standard format types (MA, DB, RI), all frequency units (Hz, kHz, MHz, GHz), and any port count. Frequencies are converted to Hz and S-parameters are returned in dB magnitude.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>file_path</td><td>`str`</td><td>---</td><td>Path to the Touchstone file (`.s1p`, `.s2p`, `.s3p`, `.s4p`, etc.).</td></tr>
</tbody>
</table>
**Returns:** A dict with `filename`, `n_ports`, `n_frequencies` (number of frequency points), `freq_range_hz` (two-element array `[min, max]`), `reference_impedance` (ohms), `s_parameters` (a dict keyed by parameter name like `"S11"`, `"S21"`, each containing a `magnitude_db` array), and `comments` (first five comment lines from the file).
<details>
<summary>Example</summary>
```json
{
"filename": "filter.s2p",
"n_ports": 2,
"n_frequencies": 201,
"freq_range_hz": [100000000.0, 6000000000.0],
"reference_impedance": 50.0,
"s_parameters": {
"S11": {
"magnitude_db": [-25.3, -24.8, -23.1, "..."]
},
"S12": {
"magnitude_db": [-45.0, -44.2, -43.8, "..."]
},
"S21": {
"magnitude_db": [-0.8, -0.9, -1.2, "..."]
},
"S22": {
"magnitude_db": [-22.1, -21.5, -20.3, "..."]
}
},
"comments": [
"2-port bandpass filter measurement",
"VNA: Keysight N5222B",
"Date: 2025-01-15"
]
}
```
</details>

View File

@ -0,0 +1,206 @@
---
title: Signal Analysis Tools
description: Measure bandwidth, operating points, and signal characteristics.
---
import { Tabs, TabItem, Aside, Code } from '@astrojs/starlight/components';
<Aside type="note">
These tools operate on `.raw` files produced by [`simulate`](/reference/simulation/#simulate) or [`simulate_netlist`](/reference/simulation/#simulate_netlist). Make sure the simulation used the correct analysis directive for the tool you need --- for example, `measure_bandwidth` requires an AC analysis (`.ac`), while `get_operating_point` requires a `.op` directive.
</Aside>
---
### analyze_waveform
Run one or more analyses on a waveform extracted from simulation results. Combines multiple measurement types in a single call to avoid repeated file parsing. Available analyses: `"rms"`, `"peak_to_peak"`, `"settling_time"`, `"rise_time"`, `"fft"`, `"thd"`.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to the `.raw` file.</td></tr>
<tr><td>signal_name</td><td>`str`</td><td>---</td><td>Signal to analyze, e.g. `"V(out)"`.</td></tr>
<tr><td>analyses</td><td>`list[str]`</td><td>---</td><td>List of analysis types to run. Any combination of `"rms"`, `"peak_to_peak"`, `"settling_time"`, `"rise_time"`, `"fft"`, `"thd"`.</td></tr>
<tr><td>settling_tolerance_pct</td><td>`float`</td><td>`2.0`</td><td>Tolerance band (percent) for settling time measurement.</td></tr>
<tr><td>settling_final_value</td><td>`float | None`</td><td>`None`</td><td>Target value for settling time. `None` uses the last sample as the final value.</td></tr>
<tr><td>rise_low_pct</td><td>`float`</td><td>`10.0`</td><td>Low threshold percentage for rise time measurement.</td></tr>
<tr><td>rise_high_pct</td><td>`float`</td><td>`90.0`</td><td>High threshold percentage for rise time measurement.</td></tr>
<tr><td>fft_max_harmonics</td><td>`int`</td><td>`50`</td><td>Maximum number of harmonic bins to return in the FFT result.</td></tr>
<tr><td>thd_n_harmonics</td><td>`int`</td><td>`10`</td><td>Number of harmonics to include in the THD calculation.</td></tr>
</tbody>
</table>
**Returns:** A dict keyed by `signal` (echoed back) plus one entry per requested analysis. The structure of each entry depends on the analysis type:
- **rms** -- a single float value.
- **peak_to_peak** -- a dict with `min`, `max`, `peak_to_peak`, and `mean`.
- **settling_time** -- a dict with `settled` (bool), `settling_time` (seconds), `final_value`, and `tolerance_band`.
- **rise_time** -- a dict with `rise_time` (seconds), `low_value`, `high_value`, and `low_time`/`high_time`.
- **fft** -- a dict with `fundamental_freq`, `fundamental_magnitude`, and `harmonics` (list of freq/magnitude/phase entries).
- **thd** -- a dict with `thd_percent`, `fundamental_freq`, and per-harmonic data.
<details>
<summary>Example -- combined RMS, peak-to-peak, and settling time</summary>
```json
{
"signal": "V(out)",
"rms": 3.298,
"peak_to_peak": {
"min": -0.012,
"max": 4.988,
"peak_to_peak": 5.0,
"mean": 2.488
},
"settling_time": {
"settled": true,
"settling_time": 0.000342,
"final_value": 4.988,
"tolerance_band": [4.888, 5.088]
}
}
```
</details>
<details>
<summary>Example -- FFT analysis</summary>
```json
{
"signal": "V(out)",
"fft": {
"fundamental_freq": 1000.0,
"fundamental_magnitude": 1.414,
"harmonics": [
{ "harmonic": 1, "frequency": 1000.0, "magnitude": 1.414, "phase_deg": 0.0 },
{ "harmonic": 2, "frequency": 2000.0, "magnitude": 0.003, "phase_deg": 90.1 },
{ "harmonic": 3, "frequency": 3000.0, "magnitude": 0.471, "phase_deg": 0.2 }
]
}
}
```
</details>
---
### measure_bandwidth
Measure -3 dB bandwidth from an AC analysis result. Computes the frequency range where the signal magnitude is within 3 dB of its peak (or a specified reference level). Requires a `.raw` file from an `.ac` simulation.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to the `.raw` file from an AC simulation.</td></tr>
<tr><td>signal_name</td><td>`str`</td><td>---</td><td>Signal to measure, e.g. `"V(out)"`.</td></tr>
<tr><td>ref_db</td><td>`float | None`</td><td>`None`</td><td>Reference level in dB. `None` uses the peak magnitude as the reference.</td></tr>
</tbody>
</table>
**Returns:** A dict with `bandwidth_hz` (the -3 dB bandwidth), `f_low` (lower -3 dB frequency or null for lowpass), `f_high` (upper -3 dB frequency), `peak_db` (maximum gain in dB), and `peak_freq_hz` (frequency of peak gain).
<details>
<summary>Example</summary>
```json
{
"bandwidth_hz": 1591.5,
"f_low": null,
"f_high": 1591.5,
"peak_db": -0.01,
"peak_freq_hz": 1.0
}
```
</details>
---
### get_operating_point
Extract DC operating point results from a `.raw` file. The `.op` analysis computes all node voltages and branch currents at the DC bias point, stored as a single data point. This is the starting point for verifying bias conditions before running transient or AC analysis.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to the `.raw` file from a simulation that includes a `.op` directive.</td></tr>
</tbody>
</table>
**Returns:** A dict with `voltages` (node voltage map, e.g. `{"V(out)": 2.5}`), `currents` (branch current map, e.g. `{"I(R1)": 0.00025}`), `device_params` (any other operating point variables), and `total_entries` (count of all extracted values).
<details>
<summary>Example</summary>
```json
{
"voltages": {
"V(vcc)": 12.0,
"V(base)": 2.65,
"V(collector)": 7.14,
"V(emitter)": 1.98
},
"currents": {
"I(R1)": 0.000167,
"I(R2)": 0.000167,
"I(Rc)": 0.002208,
"I(Re)": 0.001983
},
"device_params": {},
"total_entries": 8
}
```
</details>
---
### get_transfer_function
Extract `.tf` (transfer function) results from a `.raw` file. The `.tf` analysis computes the DC transfer function (gain or transresistance), the input impedance at the source, and the output impedance at the output node. Requires a simulation with a `.tf` directive (e.g., `.tf V(out) V1`).
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to the `.raw` file from a simulation with a `.tf` directive.</td></tr>
</tbody>
</table>
**Returns:** A dict with `transfer_function` (the DC gain or transresistance value), `output_impedance_ohms`, `input_impedance_ohms`, and `raw_data` (all variables with their original LTspice names and values).
<details>
<summary>Example -- voltage gain</summary>
```json
{
"transfer_function": -10.0,
"output_impedance_ohms": 999.8,
"input_impedance_ohms": 10000.0,
"raw_data": {
"V(out)/V1": -10.0,
"output_impedance_at_V(out)": 999.8,
"input_impedance_at_V1": 10000.0
}
}
```
</details>
<details>
<summary>Example -- transresistance</summary>
```json
{
"transfer_function": 100000.0,
"output_impedance_ohms": 0.015,
"input_impedance_ohms": 1e-06,
"raw_data": {
"V(out)/I1": 100000.0,
"output_impedance_at_V(out)": 0.015,
"input_impedance_at_I1": 1e-06
}
}
```
</details>

View File

@ -0,0 +1,291 @@
---
title: Simulation Tools
description: Run simulations, sweep parameters, optimize circuits.
---
import { Tabs, TabItem, Aside, Code } from '@astrojs/starlight/components';
<Aside type="tip">
`simulate` and `simulate_netlist` are the main entry points for running simulations. Most other tools in this reference (waveform extraction, signal analysis, plotting) require a `.raw` file path, which these two tools return on success.
</Aside>
---
### simulate
Run an LTspice simulation on a schematic file. Executes any simulation directives (`.tran`, `.ac`, `.dc`, `.op`, etc.) found in the schematic. Returns available signal names and the path to the `.raw` file for waveform extraction.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>schematic_path</td><td>`str`</td><td>---</td><td>Absolute path to an `.asc` schematic file.</td></tr>
<tr><td>timeout_seconds</td><td>`float`</td><td>`300`</td><td>Maximum time in seconds to wait for the simulation to finish.</td></tr>
</tbody>
</table>
**Returns:** A dict containing `success` (bool), `elapsed_seconds`, `error` (str or null), `variables` (list of name/type pairs), `points` (total data points), `plotname` (analysis type string), `raw_file` (path to the binary `.raw` file), and optionally `measurements` and `log_errors` parsed from the LTspice log.
<details>
<summary>Example</summary>
```json
{
"success": true,
"elapsed_seconds": 1.42,
"error": null,
"variables": [
{ "name": "time", "type": "time" },
{ "name": "V(out)", "type": "voltage" },
{ "name": "I(R1)", "type": "device_current" }
],
"points": 8192,
"plotname": "Transient Analysis",
"raw_file": "/tmp/ltspice/my_circuit.raw"
}
```
</details>
---
### simulate_netlist
Run an LTspice simulation on a netlist file (`.cir` or `.net`). Functionally identical to `simulate`, but accepts a text-based netlist instead of a graphical schematic.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>netlist_path</td><td>`str`</td><td>---</td><td>Absolute path to a `.cir` or `.net` netlist file.</td></tr>
<tr><td>timeout_seconds</td><td>`float`</td><td>`300`</td><td>Maximum time in seconds to wait for the simulation to finish.</td></tr>
</tbody>
</table>
**Returns:** Same structure as `simulate` --- `success`, `elapsed_seconds`, `error`, `variables`, `points`, `raw_file`, and optional `measurements` / `log_errors`.
<details>
<summary>Example</summary>
```json
{
"success": true,
"elapsed_seconds": 0.87,
"error": null,
"variables": [
{ "name": "frequency", "type": "frequency" },
{ "name": "V(out)", "type": "voltage" }
],
"points": 801,
"raw_file": "/tmp/ltspice/bandpass.raw"
}
```
</details>
---
### parameter_sweep
Sweep a parameter across a range of values. Runs multiple simulations, substituting the parameter value each time. The netlist should contain a `.param` directive for the parameter being swept.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>netlist_text</td><td>`str`</td><td>---</td><td>Complete netlist text containing a `.param` directive for the target parameter.</td></tr>
<tr><td>param_name</td><td>`str`</td><td>---</td><td>Name of the parameter to sweep (e.g., `"Rval"`).</td></tr>
<tr><td>start</td><td>`float`</td><td>---</td><td>Start value of the sweep range.</td></tr>
<tr><td>stop</td><td>`float`</td><td>---</td><td>Stop value of the sweep range.</td></tr>
<tr><td>num_points</td><td>`int`</td><td>`10`</td><td>Number of linearly spaced sweep points.</td></tr>
<tr><td>timeout_seconds</td><td>`float`</td><td>`300`</td><td>Per-simulation timeout in seconds.</td></tr>
</tbody>
</table>
**Returns:** A dict with `success_count`, `failure_count`, `total_elapsed` (seconds), `parameter_values` (list of swept values), and `raw_files` (list of `.raw` file paths, one per sweep point --- null for failed runs).
<details>
<summary>Example</summary>
```json
{
"success_count": 10,
"failure_count": 0,
"total_elapsed": 12.5,
"parameter_values": [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000],
"raw_files": [
"/tmp/ltspice/sweep_0.raw",
"/tmp/ltspice/sweep_1.raw",
"/tmp/ltspice/sweep_2.raw",
"/tmp/ltspice/sweep_3.raw",
"/tmp/ltspice/sweep_4.raw",
"/tmp/ltspice/sweep_5.raw",
"/tmp/ltspice/sweep_6.raw",
"/tmp/ltspice/sweep_7.raw",
"/tmp/ltspice/sweep_8.raw",
"/tmp/ltspice/sweep_9.raw"
]
}
```
</details>
---
### temperature_sweep
Run simulations at different temperatures. Each temperature produces an independent simulation run with its own `.raw` file, letting you compare temperature-dependent behavior across the range.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>netlist_text</td><td>`str`</td><td>---</td><td>Complete netlist text.</td></tr>
<tr><td>temperatures</td><td>`list[float]`</td><td>---</td><td>List of temperatures in degrees Celsius (e.g., `[-40, 25, 85, 125]`).</td></tr>
<tr><td>timeout_seconds</td><td>`float`</td><td>`300`</td><td>Per-simulation timeout in seconds.</td></tr>
</tbody>
</table>
**Returns:** A dict with `success_count`, `failure_count`, `total_elapsed`, `parameter_values` (the temperature list), and `raw_files` (one `.raw` path per temperature).
<details>
<summary>Example</summary>
```json
{
"success_count": 4,
"failure_count": 0,
"total_elapsed": 5.3,
"parameter_values": [-40.0, 25.0, 85.0, 125.0],
"raw_files": [
"/tmp/ltspice/temp_0.raw",
"/tmp/ltspice/temp_1.raw",
"/tmp/ltspice/temp_2.raw",
"/tmp/ltspice/temp_3.raw"
]
}
```
</details>
---
### monte_carlo
Run Monte Carlo analysis with component tolerances. Randomly varies component values within tolerance using a normal distribution, then runs an independent simulation for each variant. Useful for yield analysis and worst-case estimation.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>netlist_text</td><td>`str`</td><td>---</td><td>Complete netlist text. Component names referenced in `tolerances` must appear in the netlist.</td></tr>
<tr><td>n_runs</td><td>`int`</td><td>---</td><td>Number of Monte Carlo iterations to run.</td></tr>
<tr><td>tolerances</td><td>`dict[str, float]`</td><td>---</td><td>Component tolerance map. Keys are component names, values are fractional tolerances (e.g., `{"R1": 0.05}` for 5%).</td></tr>
<tr><td>timeout_seconds</td><td>`float`</td><td>`300`</td><td>Per-simulation timeout in seconds.</td></tr>
<tr><td>seed</td><td>`int | None`</td><td>`None`</td><td>Optional RNG seed for reproducible results.</td></tr>
</tbody>
</table>
**Returns:** A dict with `success_count`, `failure_count`, `total_elapsed`, `parameter_values` (list of per-run component value dicts), and `raw_files` (one `.raw` path per run).
<details>
<summary>Example</summary>
```json
{
"success_count": 50,
"failure_count": 0,
"total_elapsed": 48.7,
"parameter_values": [
{ "R1": 1023.4, "C1": 9.87e-08 },
{ "R1": 978.2, "C1": 1.04e-07 },
{ "R1": 1051.0, "C1": 9.52e-08 }
],
"raw_files": [
"/tmp/ltspice/mc_0.raw",
"/tmp/ltspice/mc_1.raw",
"/tmp/ltspice/mc_2.raw"
]
}
```
</details>
---
### optimize_circuit
Automatically optimize component values to hit target specifications. Runs real LTspice simulations in a loop, adjusting component values using binary search (single component) or coordinate descent (multiple components). The netlist template uses `{ComponentName}` placeholders that get substituted each iteration.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>netlist_template</td><td>`str`</td><td>---</td><td>Netlist text with `{ComponentName}` placeholders (e.g., `{R1}`, `{C1}`) that are substituted each iteration.</td></tr>
<tr><td>targets</td><td>`list[dict]`</td><td>---</td><td>List of target specs. Each dict has: `signal_name` (e.g., `"V(out)"`), `metric` (one of `"bandwidth_hz"`, `"rms"`, `"peak_to_peak"`, `"settling_time"`, `"gain_db"`, `"phase_margin_deg"`), `target_value` (desired number), and `weight` (importance, default 1.0).</td></tr>
<tr><td>component_ranges</td><td>`list[dict]`</td><td>---</td><td>List of tunable components. Each dict has: `component_name` (matching a placeholder), `min_value` (base units), `max_value` (base units), and optional `preferred_series` (`"E12"`, `"E24"`, or `"E96"` to snap to standard values).</td></tr>
<tr><td>max_iterations</td><td>`int`</td><td>`20`</td><td>Maximum number of simulation-and-adjust iterations.</td></tr>
</tbody>
</table>
**Returns:** A dict with `best_values` (engineering-formatted strings like `"4.7k"`), `best_values_raw` (numeric values in base units), `best_cost` (final cost function value --- 0 means all targets met), `iterations` (how many loops ran), `targets_met` (bool), `final_metrics` (measured values at best point), and `history_length`.
<details>
<summary>Example</summary>
```json
{
"best_values": { "R1": "4.7k", "C1": "33n" },
"best_values_raw": { "R1": 4700.0, "C1": 3.3e-08 },
"best_cost": 0.002,
"iterations": 14,
"targets_met": true,
"final_metrics": {
"bandwidth_hz": 1025.3,
"gain_db": 20.1
},
"history_length": 14
}
```
</details>
---
### tune_circuit
Measure circuit performance and suggest parameter adjustments. Single-shot workflow: generates a circuit from a template, simulates it, measures key metrics, compares against targets, and suggests what to change. Call repeatedly with adjusted `params` until targets are met.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>template</td><td>`str`</td><td>---</td><td>Template name (from `list_templates`). Works with both netlist and schematic templates.</td></tr>
<tr><td>params</td><td>`dict[str, str] | None`</td><td>`None`</td><td>Component value overrides (e.g., `{"r": "2.2k", "c": "47n"}`). Use `list_templates` to see available parameters for each template.</td></tr>
<tr><td>targets</td><td>`dict[str, str] | None`</td><td>`None`</td><td>Performance targets to check against. Keys are metric names, values are comparison strings: `">5000"`, `"<0.1"`, or `"~1000"` (within 10%). Supported metrics: `bandwidth_hz`, `gain_db`, `rms`, `peak_to_peak`, `settling_time_s`, `dc_value`, `fundamental_freq_hz`.</td></tr>
<tr><td>signal</td><td>`str`</td><td>`"V(out)"`</td><td>Signal name to measure.</td></tr>
</tbody>
</table>
**Returns:** A dict with `template`, `params_used`, `metrics` (measured values), `targets` (per-target pass/fail with actual vs. expected), `targets_met` (bool), `suggestions` (list of human-readable tuning advice), `signal`, and `analysis_type` (`"ac"` or `"transient"`).
<details>
<summary>Example</summary>
```json
{
"template": "rc_lowpass",
"params_used": { "r": "2.2k", "c": "47n" },
"metrics": {
"bandwidth_hz": 1536.4,
"gain_db": -0.01,
"dc_value": 0.9998
},
"targets": {
"bandwidth_hz": {
"target": ">1000",
"actual": 1536.4,
"met": true
}
},
"targets_met": true,
"suggestions": [],
"signal": "V(out)",
"analysis_type": "ac"
}
```
</details>

View File

@ -0,0 +1,126 @@
---
title: Stability and Power Tools
description: Gain/phase margins and power analysis.
---
import { Tabs, TabItem, Aside, Code } from '@astrojs/starlight/components';
Three tools for evaluating feedback loop stability and computing power dissipation metrics from simulation results.
<Aside type="tip" title="Stability margins">
A system is stable when the gain margin is greater than 0 dB and the phase margin is greater than 0 degrees. In practice, you want at least 6 dB of gain margin and 45 degrees of phase margin to avoid ringing and oscillation under component variation. If either margin is negative, the feedback loop is unstable and the circuit will oscillate.
</Aside>
---
### analyze_stability
Measure gain margin and phase margin from AC loop gain data. Parses the `.raw` file from an AC simulation, extracts the specified signal as the complex loop gain T(jw), and computes the full Bode plot (magnitude in dB and unwrapped phase in degrees). Finds the gain crossover frequency (where |T| = 0 dB) and the phase crossover frequency (where phase = -180 degrees), then derives both margins.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to `.raw` file from an AC simulation.</td></tr>
<tr><td>signal_name</td><td>`str`</td><td>---</td><td>Loop gain signal name, e.g. `"V(out)"` or `"V(loop_gain)"`.</td></tr>
</tbody>
</table>
**Returns:** A dict with four keys:
- `gain_margin` -- contains `gain_margin_db` (dB above instability, or `Infinity` if no phase crossover exists), `phase_crossover_freq_hz` (frequency where phase crosses -180 degrees, or `null`), and `is_stable` (boolean).
- `phase_margin` -- contains `phase_margin_deg` (degrees above instability, or `Infinity` if gain is always below 0 dB), `gain_crossover_freq_hz` (frequency where gain crosses 0 dB, or `null`), and `is_stable` (boolean).
- `bode` -- arrays of `frequency_hz`, `magnitude_db`, and `phase_deg` for plotting.
- `is_stable` -- overall boolean: `true` only when both margins are positive.
<details>
<summary>Example</summary>
```json
{
"gain_margin": {
"gain_margin_db": 12.4,
"phase_crossover_freq_hz": 2450000.0,
"is_stable": true
},
"phase_margin": {
"phase_margin_deg": 62.3,
"gain_crossover_freq_hz": 485000.0,
"is_stable": true
},
"bode": {
"frequency_hz": [1.0, 1.26, 1.58, "..."],
"magnitude_db": [40.0, 39.8, 39.5, "..."],
"phase_deg": [-2.3, -2.9, -3.6, "..."]
},
"is_stable": true
}
```
</details>
---
### analyze_power
Compute power metrics from voltage and current waveforms in a transient simulation. Calculates instantaneous power P(t) = V(t) * I(t) and derives time-averaged, RMS, peak, minimum, and power factor values.
Power factor is computed as the ratio of average (real) power to apparent power (Vrms * Irms). A power factor of 1.0 means voltage and current are perfectly in phase; values below 1.0 indicate reactive loading.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to `.raw` file from a transient simulation.</td></tr>
<tr><td>voltage_signal</td><td>`str`</td><td>---</td><td>Voltage signal name, e.g. `"V(out)"`.</td></tr>
<tr><td>current_signal</td><td>`str`</td><td>---</td><td>Current signal name, e.g. `"I(R1)"`.</td></tr>
</tbody>
</table>
**Returns:** A dict with `avg_power` (time-averaged power in watts), `rms_power` (RMS of instantaneous power), `peak_power` (maximum instantaneous power), `min_power` (minimum instantaneous power), and `power_factor` (ratio of real to apparent power).
<details>
<summary>Example</summary>
```json
{
"avg_power": 0.245,
"rms_power": 0.312,
"peak_power": 0.588,
"min_power": -0.012,
"power_factor": 0.97
}
```
</details>
---
### compute_efficiency_tool
Compute power conversion efficiency by comparing input power to output power. Designed for evaluating regulators, DC-DC converters, and similar power stages. Both input and output power are calculated as time-averaged values over the full transient simulation window.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to `.raw` file from a transient simulation.</td></tr>
<tr><td>input_voltage_signal</td><td>`str`</td><td>---</td><td>Input voltage signal, e.g. `"V(vin)"`.</td></tr>
<tr><td>input_current_signal</td><td>`str`</td><td>---</td><td>Input current signal, e.g. `"I(Vin)"`.</td></tr>
<tr><td>output_voltage_signal</td><td>`str`</td><td>---</td><td>Output voltage signal, e.g. `"V(out)"`.</td></tr>
<tr><td>output_current_signal</td><td>`str`</td><td>---</td><td>Output current signal, e.g. `"I(Rload)"`.</td></tr>
</tbody>
</table>
**Returns:** A dict with `efficiency_percent` (output power / input power as a percentage), `input_power_watts`, `output_power_watts`, and `power_dissipated_watts` (input minus output, representing losses).
<details>
<summary>Example</summary>
```json
{
"efficiency_percent": 87.3,
"input_power_watts": 1.44,
"output_power_watts": 1.257,
"power_dissipated_watts": 0.183
}
```
</details>

View File

@ -0,0 +1,208 @@
---
title: Waveform Tools
description: Extract, transform, and visualize simulation data.
---
import { Tabs, TabItem, Aside, Code } from '@astrojs/starlight/components';
<Aside type="note">
All waveform tools require a `.raw` file path. Run [`simulate`](/reference/simulation/#simulate) or [`simulate_netlist`](/reference/simulation/#simulate_netlist) first to produce the `.raw` file, then pass its path to these tools.
</Aside>
---
### get_waveform
Extract waveform data from a `.raw` simulation results file. For transient analysis, returns time plus voltage/current values. For AC analysis, returns frequency plus magnitude (dB) and phase (degrees). For stepped simulations (`.step`, `.mc`, `.temp`), specify `run` (1-based) to extract a single run, or omit it to get all data combined.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to the `.raw` file produced by simulation.</td></tr>
<tr><td>signal_names</td><td>`list[str]`</td><td>---</td><td>Signal names to extract, e.g. `["V(out)", "I(R1)"]`.</td></tr>
<tr><td>max_points</td><td>`int`</td><td>`1000`</td><td>Maximum data points to return. If the simulation has more points, the data is uniformly downsampled.</td></tr>
<tr><td>run</td><td>`int | None`</td><td>`None`</td><td>Run number (1-based) for stepped simulations. `None` returns all data combined.</td></tr>
</tbody>
</table>
**Returns:** A dict with `x_axis_name` (`"time"` or `"frequency"`), `x_axis_data` (list of floats), `signals` (keyed by signal name --- each contains either `values` for real data, or `magnitude_db` and `phase_degrees` for complex/AC data), `total_points`, `returned_points`, `is_stepped`, and `n_runs`.
<details>
<summary>Example -- transient analysis</summary>
```json
{
"x_axis_name": "time",
"x_axis_data": [0.0, 1e-06, 2e-06, 3e-06],
"signals": {
"V(out)": {
"values": [0.0, 0.632, 0.865, 0.950]
}
},
"total_points": 8192,
"returned_points": 1000,
"is_stepped": false,
"n_runs": 1
}
```
</details>
<details>
<summary>Example -- AC analysis</summary>
```json
{
"x_axis_name": "frequency",
"x_axis_data": [1.0, 10.0, 100.0, 1000.0, 10000.0],
"signals": {
"V(out)": {
"magnitude_db": [-0.01, -0.04, -3.01, -20.04, -40.01],
"phase_degrees": [-0.57, -5.7, -45.0, -84.3, -89.4]
}
},
"total_points": 801,
"returned_points": 801,
"is_stepped": false,
"n_runs": 1
}
```
</details>
---
### list_simulation_runs
List runs in a stepped simulation (`.step`, `.mc`, `.temp`). Returns run count and boundary information for multi-run `.raw` files. Use this to discover how many runs exist before extracting individual runs with `get_waveform`.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to the `.raw` file from a stepped simulation.</td></tr>
</tbody>
</table>
**Returns:** A dict with `is_stepped` (bool), `n_runs`, `total_points`, `plotname`, `variables` (list of name/type pairs), and for stepped files a `runs` list where each entry has `run` (1-based index), `start_index`, `end_index`, and `points`.
<details>
<summary>Example</summary>
```json
{
"is_stepped": true,
"n_runs": 5,
"total_points": 40960,
"plotname": "Transient Analysis",
"variables": [
{ "name": "time", "type": "time" },
{ "name": "V(out)", "type": "voltage" }
],
"runs": [
{ "run": 1, "start_index": 0, "end_index": 8192, "points": 8192 },
{ "run": 2, "start_index": 8192, "end_index": 16384, "points": 8192 },
{ "run": 3, "start_index": 16384, "end_index": 24576, "points": 8192 },
{ "run": 4, "start_index": 24576, "end_index": 32768, "points": 8192 },
{ "run": 5, "start_index": 32768, "end_index": 40960, "points": 8192 }
]
}
```
</details>
---
### evaluate_waveform_expression
Evaluate a math expression on simulation waveforms. Supports the operators `+`, `-`, `*`, `/` and the functions `abs()`, `sqrt()`, `log10()`, `dB()`. Signal names in the expression reference variables from the `.raw` file directly.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to the `.raw` file.</td></tr>
<tr><td>expression</td><td>`str`</td><td>---</td><td>Math expression using signal names. Examples: `"V(out) * I(R1)"` for instantaneous power, `"V(out) / V(in)"` for voltage gain, `"dB(V(out))"` for magnitude in dB.</td></tr>
<tr><td>max_points</td><td>`int`</td><td>`1000`</td><td>Maximum data points to return.</td></tr>
</tbody>
</table>
**Returns:** A dict with `expression` (echoed back), `total_points`, `returned_points`, `x_axis_name`, `x_axis_data`, `values` (computed result array), and `available_signals` (list of signal names in the `.raw` file for reference).
<details>
<summary>Example -- instantaneous power</summary>
```json
{
"expression": "V(out) * I(R1)",
"total_points": 8192,
"returned_points": 1000,
"x_axis_name": "time",
"x_axis_data": [0.0, 1e-06, 2e-06],
"values": [0.0, 0.00125, 0.00198],
"available_signals": ["time", "V(out)", "V(in)", "I(R1)"]
}
```
</details>
---
### export_csv
Export waveform data to CSV format. Writes a file with the x-axis (time or frequency) as the first column and each requested signal as subsequent columns. Complex (AC) signals are split into magnitude (dB) and phase (degrees) columns automatically.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file_path</td><td>`str`</td><td>---</td><td>Path to the `.raw` file.</td></tr>
<tr><td>signal_names</td><td>`list[str] | None`</td><td>`None`</td><td>Signals to export. `None` exports all signals.</td></tr>
<tr><td>output_path</td><td>`str | None`</td><td>`None`</td><td>Where to save the CSV file. `None` auto-generates a path in `/tmp`.</td></tr>
<tr><td>max_points</td><td>`int`</td><td>`10000`</td><td>Maximum rows to export.</td></tr>
</tbody>
</table>
**Returns:** A dict with `output_path` (where the CSV was written), `rows` (number of data rows), and `columns` (list of column header strings).
<details>
<summary>Example</summary>
```json
{
"output_path": "/tmp/my_circuit.csv",
"rows": 8192,
"columns": ["time", "V(out)", "V(in)", "I(R1)"]
}
```
</details>
---
### plot_waveform
Generate an SVG plot from simulation results. Parses a `.raw` file and creates a waveform plot saved as an SVG file. Supports time-domain, Bode (magnitude and phase vs. frequency), and FFT spectrum plot types.
<table class="param-table">
<thead><tr><th>Parameter</th><th>Type</th><th>Default</th><th>Description</th></tr></thead>
<tbody>
<tr><td>raw_file</td><td>`str`</td><td>---</td><td>Path to the LTspice `.raw` binary file.</td></tr>
<tr><td>signal</td><td>`str`</td><td>`"V(out)"`</td><td>Signal name to plot (e.g., `"V(out)"`, `"I(R1)"`).</td></tr>
<tr><td>plot_type</td><td>`str`</td><td>`"auto"`</td><td>Plot style: `"auto"` (detect from data), `"time"`, `"bode"`, or `"spectrum"`.</td></tr>
<tr><td>output_path</td><td>`str | None`</td><td>`None`</td><td>Where to save the SVG. `None` auto-generates a path in `/tmp`.</td></tr>
</tbody>
</table>
**Returns:** A dict with `svg_path` (where the SVG was written), `plot_type` (the resolved type after auto-detection), `signal` (the matched signal name), and `points` (number of data points in the plot).
<details>
<summary>Example</summary>
```json
{
"svg_path": "/tmp/ltspice_plot_abc123.svg",
"plot_type": "bode",
"signal": "V(out)",
"points": 801
}
```
</details>

View File

@ -0,0 +1,88 @@
---
title: Design a Filter
description: Build an RC lowpass filter, simulate it, and iterate toward a target cutoff frequency.
---
import { Steps, Aside, Code } from '@astrojs/starlight/components';
This tutorial walks through a complete filter design workflow using mcltspice tools. You will create a circuit from a template, simulate it, measure the bandwidth, and adjust component values to hit a target specification.
## Goal
Design a 1st-order RC lowpass filter with a -3dB cutoff at 10 kHz.
## Workflow
<Steps>
1. **Create the circuit**
Use `create_from_template` to generate an RC lowpass filter netlist:
```json
{
"template_name": "rc_lowpass",
"params": {
"r": "1k",
"c": "15n"
}
}
```
The theoretical cutoff is `f_c = 1 / (2 * pi * R * C) = 1 / (2 * pi * 1000 * 15e-9) = 10,610 Hz`. Close to 10 kHz.
2. **Simulate**
Run AC analysis with `simulate_netlist` on the generated `.cir` file. The template includes an `.ac dec 100 1 1meg` directive by default.
3. **Measure bandwidth**
Use `measure_bandwidth` on the `.raw` file with signal `V(out)`:
```json
{
"raw_file_path": "/tmp/rc_lowpass.raw",
"signal_name": "V(out)"
}
```
This returns the -3dB frequency, which should be near 10.6 kHz.
4. **Iterate if needed**
If the cutoff is off-target, use `tune_circuit` to get suggestions:
```json
{
"template": "rc_lowpass",
"params": {"r": "1k", "c": "15n"},
"targets": {"bandwidth_hz": "~10000"},
"signal": "V(out)"
}
```
The tool will measure the actual bandwidth and suggest adjusted component values.
5. **Visualize**
Generate a Bode plot with `plot_waveform`:
```json
{
"raw_file": "/tmp/rc_lowpass.raw",
"signal": "V(out)",
"plot_type": "bode"
}
```
This creates an SVG showing magnitude and phase vs. frequency.
</Steps>
<Aside type="tip">
The `design_filter` prompt automates this entire workflow. Try it as a conversation starter and mcltspice will walk you through each step interactively.
</Aside>
## Key takeaway
The RC lowpass cutoff frequency is `f_c = 1 / (2 * pi * R * C)`. To lower the cutoff, increase R or C. To raise it, decrease them. The `tune_circuit` tool does this math for you and suggests standard component values from E12/E24 series.

View File

@ -0,0 +1,13 @@
---
title: Tutorials
description: Step-by-step walkthroughs for common circuit design tasks.
---
import { Card, CardGrid, LinkCard } from '@astrojs/starlight/components';
Tutorials walk you through complete workflows from start to finish. Each one builds a working circuit, simulates it, and analyzes the results.
<CardGrid>
<LinkCard title="Design a Filter" href="/tutorials/design-a-filter/" description="Build an RC lowpass filter, measure its bandwidth, and iterate toward a target cutoff frequency." />
<LinkCard title="Monte Carlo Yield" href="/tutorials/monte-carlo-yield/" description="Run statistical analysis on component tolerances to estimate manufacturing yield." />
</CardGrid>

View File

@ -0,0 +1,74 @@
---
title: Monte Carlo Yield Analysis
description: Run statistical analysis on component tolerances to estimate manufacturing yield.
---
import { Steps, Aside, Code } from '@astrojs/starlight/components';
Real components have manufacturing tolerances. A resistor labeled "10k" might be anywhere from 9.5k to 10.5k (5% tolerance). Monte Carlo analysis simulates your circuit hundreds of times with randomized component values to see how often the design meets spec.
## Goal
Determine whether an RC lowpass filter with 5% resistors and 10% capacitors reliably hits a 10 kHz bandwidth target.
## Workflow
<Steps>
1. **Define the circuit**
Start with a known-good netlist. You can generate one with `create_from_template`:
```json
{
"template_name": "rc_lowpass",
"params": {"r": "1.59k", "c": "10n"}
}
```
Read the generated `.cir` file content for the next step.
2. **Run Monte Carlo**
Use the `monte_carlo` tool with component tolerances:
```json
{
"netlist_text": "* RC Lowpass\nV1 in 0 AC 1\nR1 in out 1.59k\nC1 out 0 10n\n.ac dec 100 1 1meg\n.end",
"n_runs": 100,
"tolerances": {
"R1": 0.05,
"C1": 0.10
},
"seed": 42
}
```
This runs 100 simulations, each time varying R1 by up to +/-5% and C1 by up to +/-10% using a normal distribution.
3. **Analyze results**
The tool returns per-run `.raw` file paths. For each run, use `measure_bandwidth` to get the -3dB frequency, then compute statistics across all runs:
- Mean bandwidth
- Standard deviation
- Min / max range
- Yield: percentage of runs where bandwidth falls within your spec window (e.g., 8 kHz to 12 kHz)
4. **Interpret**
With 5% resistors and 10% capacitors, expect roughly +/-15% variation in cutoff frequency (tolerances add in quadrature for an RC product). If yield is too low, consider tighter-tolerance components or a design with more margin.
</Steps>
<Aside type="tip">
The `monte_carlo_analysis` prompt automates this entire workflow including the statistical summary. Use it as a conversation starter for quick yield estimates.
</Aside>
<Aside type="note">
Set `seed` for reproducible results during development. Remove it for truly random production analysis.
</Aside>
## Key takeaway
Monte Carlo analysis answers "will this design work in production?" rather than "does it work with ideal components?" Running 100 iterations typically takes under 30 seconds since each AC simulation is fast. For high-confidence yield estimates, use 500+ runs.

View File

@ -0,0 +1,50 @@
/* mcltspice docs -- teal accent, zinc grays
* Oscilloscope-trace aesthetic for an EDA tool */
@import "@astrojs/starlight-tailwind";
@import "tailwindcss";
:root {
--sl-color-accent-low: #083344; /* teal-950 */
--sl-color-accent: #0d9488; /* teal-600 */
--sl-color-accent-high: #ccfbf1; /* teal-100 */
--sl-color-gray-1: #fafafa; /* zinc-50 */
--sl-color-gray-2: #e4e4e7; /* zinc-200 */
--sl-color-gray-3: #a1a1aa; /* zinc-400 */
--sl-color-gray-4: #52525b; /* zinc-600 */
--sl-color-gray-5: #27272a; /* zinc-800 */
--sl-color-gray-6: #18181b; /* zinc-900 */
--sl-color-gray-7: #0f0f11; /* near-black */
}
:root[data-theme="dark"] {
--sl-color-accent-low: #083344;
--sl-color-accent: #2dd4bf; /* teal-400 in dark */
--sl-color-accent-high: #042f2e; /* teal-950 */
--sl-color-gray-1: #0f0f11;
--sl-color-gray-2: #18181b;
--sl-color-gray-3: #3f3f46;
--sl-color-gray-4: #a1a1aa;
--sl-color-gray-5: #d4d4d8;
--sl-color-gray-6: #e4e4e7;
--sl-color-gray-7: #fafafa;
}
/* Tool reference parameter tables */
.param-table th {
font-weight: 600;
text-align: left;
white-space: nowrap;
}
.param-table code {
font-size: 0.85em;
}
.param-table td:first-child {
font-family: var(--sl-font-mono);
font-weight: 500;
color: var(--sl-color-accent);
}

5
docs/tsconfig.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": "astro/tsconfigs/strict",
"include": ["src/**/*"],
"exclude": ["node_modules"]
}