A lightweight, cross-platform EDA tool for RF design — for the RF community, by the RF community.
circuitRF is a full-featured EDA tool for RF and microwave design — schematic capture, layout and
simulation in one cross-platform application. DC, S-parameter and harmonic-balance
analyses with first-class loadpull / sourcepull, over designs from a handful of components to
hierarchical, multi-port ones with thousands. A layout editor for PCB and MMIC work, with
substrate-aware microstrip components, schematic↔layout generation, DRC and LVS, and two-way
interchange with Gerber + Excellon, GDSII, DXF and .kicad_pcb boards. A 2.5D
electromagnetic solver over the layout's own substrate stackup. And a headless command line that
runs all of it. The file formats are human-readable, and the headline goal is to make loadpull as
easy as a few clicks.
📖 Read the user documentation online
circuitRF is for RF practitioners or researchers who can't justify the cost of traditional tools (or find those tools too heavy for a quick investigation): power-amplifier, LNA, and mixer designers; RF EDA and device-modeling engineers; academic researchers; and capable hobbyists. It is written in C# / .NET 10, with an Avalonia 12 GUI rendered through SkiaSharp, and it was built largely AI-assisted (see AI-assisted development).
Status: v1 beta — almost at v1 release... please file issues. What is not in it yet: the open green fields.
Build hierarchical RF circuits on a virtualized canvas: drag from the palette, wire, label nets, set parameters and sweeps, and Run.
Draw the glyph for any cell and place its connection pins — the same renderer the schematic uses.
Plot S-parameters, spectra, power sweeps, and loadpull contours; overlay measured Touchstone/.spl/
.lpcwave data on simulated results.
Draw and edit physical geometry on a technology-defined layer stack: microstrip components generated from their schematic parameters, hierarchy with arrays, and export to GDSII, DXF and Gerber.
While circuitRF is in beta, Settings ▸ Security & Permissions ▸ Include beta releases is ticked by default. Beta versions are published as GitHub pre-releases, and that box is what puts them on your update channel — untick it and you stay on the version you installed until the first stable release.
| Platform | Download |
|---|---|
| Windows, Intel/AMD | circuitRF-1.0.0-beta.31-win-x64-user.msi |
| Windows, ARM | circuitRF-1.0.0-beta.31-win-arm64-user.msi |
| Windows, 32-bit | circuitRF-1.0.0-beta.31-win-x86-user.msi |
| macOS, Apple Silicon | circuitRF-1.0.0-beta.31-arm64.dmg |
| macOS, Intel | circuitRF-1.0.0-beta.31-x64.dmg |
| Linux, Intel/AMD | circuitRF-1.0.0-beta.31-linux-x64.tar.gz |
| Linux, ARM | circuitRF-1.0.0-beta.31-linux-arm64.tar.gz |
Linux — unpack and run install.sh. It writes only inside ~/.local, puts circuitrf on your PATH
and registers the menu entry and file types; --uninstall removes it and leaves your work alone.
tar xzf circuitRF-1.0.0-beta.31-linux-x64.tar.gz
./circuitRF-1.0.0-beta.31/install.shInstalling for everyone on the machine? The Windows .msi files without -user, and the .deb
files, are on the releases page. They need
administrator rights, so they cannot update themselves — they tell you when a new version is out
instead.
Automatic updates can be turned off in Settings ▸ Security & Permissions. Building the installers yourself: BUILDING.md.
circuitRF is meant to be community-driven, by and for the RF engineering community. We value RF domain knowledge as much as software experience. If you design power amplifiers, LNAs, or mixers; build RF EDA tooling; do device modeling; or develop transistor technology (GaN-on-SiC, GaN-on-Si, LDMOS, …), you are exactly who this project needs — and circuitRF is a great place to use AI to build the simulation features you want.
You do not need to be a professional software developer. If you've scripted in MATLAB or Python, you have enough to start. Pair yourself with Claude Code (or your AI assistant of choice) and let it do the heavy lifting on the C#.
circuitRF is built in strictly one-directional layers — dependencies point up the stack only, and
nothing below the UI knows the UI exists. This is what keeps the simulator (the actual value of the
product) independent of any GUI framework. Full detail:
docs/design/ui-architecture.md.
src/RfCore shared result/network library: Touchstone I/O, S/Z/Y math,
▲ the DataSet/DataCube result model, loadpull readers/writers
│
src/Core Design + Elaboration: cells, instances, nets, parameters, the expression
▲ engine; flatten + resolve → an "elaborated netlist". No UI, no numerics.
│
src/Engine Numeric layer: sparse MNA, DC, S-parameters, harmonic balance, loadpull,
▲ and the planar method-of-moments EM kernel. Consumes the elaborated
│ netlist, produces a DataSet. No UI.
│
src/Design Design-layer DOCUMENTS: the .clay layout model, the .ctech technology and
▲ stackup, the .ccell cell folder, the .csch/.csym schematic and symbol models
│ with net extraction, the .cem EM setup and its extractors, the interchange
│ readers/writers, the DRC and LVS engines, and the functions that CREATE a
│ workspace, a cell and an imported part. No UI: it draws nothing and docks
│ nothing; the EDITORS all stay in src/Ui.
│
src/Render The Skia RENDERERS: schematic, symbol, layout and bondwire, their themes and
▲ caches, the colour-theme model and .ccolor reader, and the overlay descriptions
│ of a frame's transient chrome. SkiaSharp only — pixels out, and nothing in.
│ Referenced by BOTH src/Ui and src/Cli, so there is exactly one renderer.
│
src/Ui Presentation: Avalonia 12 + SkiaSharp. Schematic/symbol/layout editors,
Data Display, workspace. Depends on everything above. Nothing depends on it.
src/Diagnostics The coded-diagnostic leaf: an id, typed arguments and an English template.
Referenced by every layer that authors user-facing text, including RfCore and
WBond, which have no common ancestor. No UI.
src/Harmonica harmonicaRF's framework-free half — interactive harmonic loadpull on one
src/WBond wBond's framework-free half — bondwire geometry + its own 3D MoM kernel
Both also ship as standalone apps: src/Ui with a different Main().
src/Cli Headless driver — depends on Core/Engine/RfCore/Design, NOT on src/Ui. Proof
the engines are fully usable with no GUI; the engines' primary test harness.
Verbs: sparam, dc, hb, lp, lpp, em, elab, netlist, check, explain, lvs,
rail, smith, convert, new, import, render, plot, find, read, reference,
history, serve. See docs/user/reference/cli.html.
- Design layer (
src/Core) — what you edit: cells (each with Symbol / Schematic / Layout views), instances, nets, parameters (hierarchical, with overrides), global variables, and a TestBench (the thing you simulate — top cell + analyses + measurements). Serialized to human-readable files (.cnlnetlist, JSON). - Elaboration layer (
src/Core) — flattens the hierarchy, resolves every parameter and expression top-down (with mandatory cycle detection), and numbers the nodes → an elaborated netlist. This is the single thing the engine consumes, whether it came from a hand-written.cnlor from the schematic editor's net extractor. - Numeric layer (
src/Engine) — matrices, unknown vectors, and analyses. It never sees a domain object or an unresolved expression. Every run returns aDataSet: a named collection ofDataCubes, each a labeled, unit-bearing, N-D array of a single kind (Real or Complex).
One expression engine (tokenize → Pratt-parse → AST → evaluate; never string substitution) serves
global variables, cell parameters, the SDD's device equations, and measurements
(docs/design/expressions.md).
- Linear / S-parameters — complex sparse MNA (CSparse.NET) over a frequency sweep, with
renormalization and Touchstone (
.sNp) blocks with interpolation. (docs/design/linear-engine.md) - Nonlinear DC — Newton–Raphson with gmin/source stepping; diode, FET, BJT, and the SDD
(Symbolically-Defined Device: you write
i = f(v)and exact Jacobians come from forward-mode automatic differentiation). (docs/design/nonlinear-dc.md,docs/design/sdd.md) - Harmonic balance — multidimensional Newton with a conversion-matrix Jacobian, a clean
linear/nonlinear partition, single- and two-tone (diamond truncation, mixing order ≥ 5), and
power-step continuation for convergence at drive.
(
docs/design/harmonic-balance.md) - Loadpull / sourcepull — the headline differentiator: sweep source/load Γ over a Smith-chart grid,
run HB per point, and report FOMs (Pout, gain, efficiency, PAE) as contours. Includes a pursuit
engine and a post-processor that derives the display metrics measured files carry.
(
docs/design/loadpull.md,docs/design/loadpull-contours.md) - Electromagnetic (
src/Engine/Mom) — two kernels behind one registry: a quasi-static cross-section solver for uniform lines (Z₀, ε_eff, loss, RLGC) and a full-wave planar method-of-moments solver over a layered Green's function, with meshing, ports, de-embedding, adaptive frequency sampling and an AIM accelerator. Fed bysrc/Design's extractors, driven by the GUI's EM Setup panel or bycircuitrf em. (docs/design/mom-engine.md)
The GUI is Avalonia 12 (the cross-platform .NET UI framework — the same window, menu and dock machinery on all three OSes). But circuitRF does not render schematics, layouts or plots as Avalonia controls — a 10,000-component schematic would die under one control per component. Each canvas draws itself with SkiaSharp through a custom control, with viewport virtualization and a spatial index for hit-testing and pan/zoom. The split is deliberate: a pure renderer (Skia only, no Avalonia types) draws a model + transform onto a surface, and a thin Avalonia control hosts that surface and pumps input events. The rendering investment lives in the renderer.
The circuitRF engines must be skinnable by any new UI with as little trouble as possible — so
RfCore, src/Core, src/Engine, src/Design, src/Render, src/Cli, src/Diagnostics,
src/Harmonica and src/WBond reference no UI framework at all (no Avalonia). This is not a
hope; it's an enforced invariant — tests/Firewall.Tests loads each of
those nine assemblies and fails the build if any references Avalonia*.
That firewall is why circuitrf em, circuitrf lvs and circuitrf render work from a terminal at
all: the EM run service, the DRC and LVS engines and the renderers all sit below the line, so the
headless answer and the on-screen one come from one implementation instead of two that drift.
The entire engine↔UI contract is two shapes: design model down, DataSet up. A replacement UI
re-implements only the presentation of those two; the engines, elaboration, analyses, result model
and file formats are untouched. That's the whole point of the firewall: the simulator survives the
UI. Detail in docs/design/ui-architecture.md.
circuitRF/
├─ src/
│ ├─ RfCore/ Shared RF result/network library (no UI) — Touchstone I/O, S/Z/Y math and
│ │ renormalization, interpolation, the DataSet/DataCube result model, the
│ │ .npy/.mat/TSV exporters, loadpull surfaces, contours and FOM dialects
│ ├─ Core/ Design + elaboration, and the expression engine (no UI, no numerics) —
│ │ cells, instances, TestBench, analyses, measurements; flatten and resolve
│ │ top-down; the ComponentModel family including the SDD and the
│ │ substrate-aware microstrip models; the .cnl reader/writer
│ ├─ Engine/ Numeric layer (no UI) — sparse MNA, DC, S-parameters, parametric sweeps,
│ │ harmonic balance, loadpull + pursuit, and the two MoM EM kernels
│ │ (quasi-static cross-section, and full-wave planar with AIM)
│ ├─ Design/ Design-layer DOCUMENTS, and the code that reads, writes, validates and
│ │ CREATES them (no UI: it draws nothing and docks nothing). Referenced by
│ │ BOTH src/Ui and src/Cli, so there is exactly one of each:
│ │ Layout/ .clay model, integer-DBU geometry, booleans, spatial index,
│ │ .ctech technology + stackup, footprints, the DRC and LVS
│ │ engines, the GDSII / DXF / Gerber+Excellon / .kicad_pcb
│ │ readers AND writers, and Em/ — the .cem setup, its
│ │ extractors and EmRunService
│ │ Schematic/ .csch model, persistence and NetExtractor (EDITOR: src/Ui)
│ │ Symbol/ Cells/ Workspace/ RailRf/ Matching/ Revision/ Results/
│ ├─ Render/ The Skia RENDERERS, below the firewall — schematic, symbol, layout and
│ │ bondwire, their themes, caches and LOD tiers, the .ccolor colour-theme
│ │ model, and the hit-test / handle / snap / overlay geometry shared with the
│ │ editors. Called by the GUI *and* by the CLI, so there is one renderer.
│ ├─ Ui/ Avalonia 12 + SkiaSharp — the only place UI-framework code lives: the
│ │ schematic, symbol, layout, .cem and .ctech EDITORS, the PCell generators,
│ │ the Data Display, the harmonicaRF / wBond / railRF views, the docs
│ │ factory's capture side, the updater, and the MVVM shell
│ ├─ Diagnostics/ The coded-diagnostic leaf: an id, typed arguments, an English template
│ ├─ Harmonica/ harmonicaRF's framework-free half — interactive harmonic loadpull (no UI)
│ ├─ WBond/ wBond's framework-free half — bondwire geometry + its own 3D MoM (no UI)
│ └─ Cli/ Headless driver + the engines' test harness (no UI) — docs/design/cli.md
├─ tools/ Programs that are not part of the application (none in circuitRF.slnx):
│ DocGen (the user-docs factory), IconGen, the device workers (C), the
│ Python PCell host, the release signer, the macOS build VM
├─ packaging/ One script per platform, each building everything that platform ships
├─ docs/ PRD.md, Development_Plan.md, design/ (the "why" — start here to go deep),
│ skills/, sonnet-briefs/, and user/ (the shipped documentation — GENERATED;
│ sources in docs/user/src/)
├─ examples/ The workspaces Tools ▸ Examples opens
├─ testdata/ Golden references + regression fixtures (the five heroes live here)
├─ tests/ Core, Engine, Ui, RfCore, Harmonica, WBond and Firewall test projects
├─ VERSION The ONE place the version number is written
└─ CLAUDE.md Standing project memory (architecture, invariants) — root + per subsystem
You can help develop circuitRF using Windows, macOS, or Linux.
| Tool | Why | Get it |
|---|---|---|
| .NET 10 SDK | builds and runs circuitRF | https://dotnet.microsoft.com/download/dotnet/10.0 |
| Git | clone the repos | https://git-scm.com/downloads |
| Visual Studio Code | edit + debug (lightweight, cross-platform) | https://code.visualstudio.com/ |
| VS Code C# Dev Kit extension | C# editing/IntelliSense/debug in VS Code | https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit |
Verify the SDK is installed:
dotnet --version # should print 10.x.x# cd to a working folder, then:
git clone https://github.com/potatobeanradio/circuitRF.gitcd circuitRF
dotnet build # restores packages + compiles everything
dotnet run --project src/Ui # from the circuitRF/ directory:dotnet test # optional 10-15 min of circuitRF development testsA handful of loadpull tests read lab-measured .spl/.lpcwave files that are third-party data held
under terms that do not permit redistribution, so they have never been committed here. On a fresh
clone those tests report as Skipped, naming the path they wanted — they never fail, and a fresh
clone is green without them. Your own measurements in either format, dropped at those paths, exercise
the same code.
To build the device workers:
Needed only for PDKs whose device models ship as compiled libraries. dotnet build builds the
workers itself if a C compiler is on PATH — with none, it warns and carries on, and such a kit
refuses at Run.
Install one, then rebuild:
winget install zig.zig # Windows (or: scoop install zig)brew install zig # macOS
sudo snap install zig --classic --beta # Linux (or your package manager)dotnet buildmacOS also runs those Linux models in a VM circuitRF ships — one extra ~330 MB download, once:
dotnet build src/Ui -p:CrfBuildVmImage=trueAlternatives to zig (MinGW gcc, Docker/Podman) and the rest:
BUILDING.md ▸ Helper programs.
BUILDING.md has step-by-step instructions for producing the installers users
download: .msi (Windows x64/arm64/x86, per-machine and per-user), .zip (the Windows update
payload), .dmg (macOS arm64/x64), .deb (Linux x64/arm64) and .tar.gz (the Linux user-local
channel). One script per platform, run from the repository root.
# from the circuitRF/ directory:
dotnet run --project src/UiFull CLI documentation: the
Command Line chapter of the user docs (design notes in
docs/design/cli.md).
# S-parameters: sweep 1-3 GHz in 50 MHz steps, write a Touchstone file
dotnet run --project src/Cli -- sparam mycircuit.cnl --freq 1GHz:3GHz:50MHz -o mycircuit.s2p
# DC operating point
dotnet run --project src/Cli -- dc mycircuit.cnl
# Harmonic balance (runs the parametric sweep, if one wraps the analysis)
dotnet run --project src/Cli -- hb hero2.cnl --set Pavl_dbm=0 -o hero2.npy
# Loadpull over the directive's Gamma grid, exported as loadpull interchange
dotnet run --project src/Cli -- lp hero3.cnl --pin -20:1:15 -o hero3.spl
# Loadpull pursuit: search for the max-power and max-efficiency terminations
dotnet run --project src/Cli -- lpp hero3B.cnl --out-grid found.gam -o hero3B.npy
# Electromagnetic extraction of the layout a .cem names — no other arguments needed
dotnet run --project src/Cli -- em Amp.cem
# Author a correct initial document: a workspace, then a cell inside it
dotnet run --project src/Cli -- new workspace ~/designs/Amp --tech pcb-4layer_FR-4_62mil_1oz
dotnet run --project src/Cli -- new cell ~/designs/Amp Stage1 --views schematic,symbol
# Bring artwork or a component in: one interchange format to another, or a part as a cell
dotnet run --project src/Cli -- convert Filter.dxf -o gerbers/
dotnet run --project src/Cli -- import part parts/ --into ~/designs/Amp --cell SOT-23
# Is it well formed, does it resolve, is it sound? Runs no analysis and writes nothing
dotnet run --project src/Cli -- check ~/designs/Amp
# Does the artwork match the drawing? (LVS — read-only; -o writes a report)
dotnet run --project src/Cli -- lvs ~/designs/Amp/Stage1
# What did circuitRF DECIDE — which technology, which chain, what value?
dotnet run --project src/Cli -- explain Amp.cem
dotnet run --project src/Cli -- explain Stage1.csch --expr "Zopt*2"
# Read a result back, or a document, as one JSON document
dotnet run --project src/Cli -- read results/Amp_em.npy --only S --json
# Dump the elaborated netlist (flattened + parameters resolved) - great for debugging
dotnet run --project src/Cli -- elab mycircuit.cnl
# Speak a protocol to an external client over stdin/stdout, confined to one directory
dotnet run --project src/Cli -- serve --root ~/designs
# Help
dotnet run --project src/CliThe whole pipeline is three calls — read → elaborate → run — which is exactly what the CLI does:
using CircuitRF.Core.Netlist;
using CircuitRF.Core.Elaboration;
using CircuitRF.Engine;
var (lib, testbench) = CnlReader.ReadFile("mycircuit.cnl");
var netlist = new Elaborator(lib).Elaborate(testbench);
var dataset = SParameterEngine.Run(netlist, freqsHz); // → a DataSet of DataCubescircuitRF is v1 beta, and it is feature-complete for v1: the five "hero" circuits in
docs/PRD.md (a 4-port S-parameter network, a single-FET PA power sweep, a loadpull,
a 2-stage PA and a two-tone IM case) are the validated acceptance anchors, and what is left before
the stable release is beta test.
So the useful question is no longer what circuitRF does — it is what it doesn't. These are the open green fields, and each is a good place to contribute:
- Tuning and optimization — no interactive parameter tuner, and no optimizer.
- Noise analysis — no noise figure, no phase noise, no Fmin / Γopt / Rn extraction.
- Transient analysis — circuitRF is frequency-domain by design; there is no time-domain solver.
- Envelope analysis — no simulation of modulated waveforms.
- 3D EM, and thermal — the electromagnetic solver is 2.5D planar method-of-moments over a layered stackup. There is no 3D FEM solver, and no thermal solver.
Full roadmap and current status: docs/Development_Plan.md.
The user documentation — Quick Start, New User's Guide and Reference Guide — is published at
https://potatobeanradio.github.io/circuitRF/. It lives in docs/user/, is what
Help ▸ circuitRF Documentation opens, and is served online straight from this repository,
so the web pages and the shipped pages are the same bytes. It is generated, not hand-edited. One
command rebuilds every page and every figure from the live application:
dotnet run --project tools/DocGen -- --out docs/userProse is authored as Markdown under docs/user/src/; the pages under docs/user/ are the output and
any edit to one is reverted by the next run. Figures are vector captures of the running interface
— the generator opens circuitRF headlessly, drives real views with real content, and writes SVG — so
they cannot drift from the application. Component parameter tables come from the live registry for
the same reason. There are no screenshots in this documentation and there are not meant to be.
tools/DocGen/check-docs-current.sh regenerates and diffs, and fails if the committed output is not
what the generator produces. Run it after a UI change that moves a figure. The design note is
docs/design/user-docs-factory.md.
The same sources also produce four landscape PDF decks into docs/slides/ (git-ignored, a build
product). Both options default to everything:
dotnet run --project tools/DocGen -- --slides docs/slides # all 4, light + dark
dotnet run --project tools/DocGen -- --slides docs/slides --deck overview --theme dark--deck overview | new-user | quick-start | reference— why adopt it; first principles; the fast path for engineers who already use simulators; the Reference Guide in outline. Comma-separated.--theme light | dark | both— picks the screenshots as well as the page colour.
Contributions are welcome and encouraged. circuitRF is community-driven, by and for the RF community, and RF domain knowledge counts as much as software experience. You don't need to be a career programmer — MATLAB/Python scripting experience plus an AI assistant is plenty.
Good first contributions:
- Build a circuit in the schematic editor and report what's confusing or broken
- Improve a design note in
docs/design/, or aCLAUDE.md, where the docs lag the code. - Pick up a roadmap item (the noise green field is wide open).
The ground rules:
- The architecture is layered and the UI firewall is enforced — keep Avalonia out of
RfCore/Core/Engine/Design/Cli/Harmonica/WBond(a CI test will catch you). Renderers stay Skia-only. - Every numerical change needs a
testdata/regression test within the tolerance the PRD states. - The core is MIT — never ingest GPL code.
- Each subsystem has a
CLAUDE.mdwith its local conventions; read the relevant one before diving in.
Open an issue to discuss anything substantial before a large PR, so we can point you at the right design note (and save you rework).
circuitRF was built largely with AI assistance (primarily Claude /
Claude Code), and AI-assisted contributions are first-class
here. The codebase is structured for it: spatial CLAUDE.md memory files capture the invariants and
local conventions of each subsystem, docs/design/ holds the reasoning behind each part, and
docs/skills/ holds step-by-step procedures you can hand directly to an AI agent.
This is the deliberate bet of the project: an RF expert with an AI assistant can build the simulation features they need. If that describes you, you're in the right place.
circuitRF's own source code is released under the MIT License. A future commercial superset, if any, layers on through a clean extension boundary without forking the core.
The distribution also contains third-party components under their own terms, inventoried in THIRD-PARTY-NOTICES.md. Two of them are copyleft and worth knowing about before you redistribute a build:
- CSparse.NET (sparse complex LU, used throughout the engine) is LGPL-2.1-only. The packaged installers link it statically, so LGPL §6's relink requirement applies — satisfied here by publishing complete source, since anyone can substitute a modified CSparse.NET and rebuild. If you redistribute circuitRF binaries, that obligation travels with them.
tools/osdi-worker/osdi.his MPL-2.0 (© 2022 SemiMod GmbH, from ngspice). MPL is copyleft at file scope: the file may live inside an MIT project, but it stays MPL and its header notice must not be removed.
No strong-copyleft (GPL/AGPL) code is ingested, and none is planned — see CLAUDE.md for the standing
rule on learning from GPL simulators without copying them.
- Avalonia (cross-platform UI — MIT)
- SkiaSharp (2D rendering — MIT)
- CSparse.NET (sparse complex LU — LGPL-2.1-only)
- NumFlat (dense linear algebra — MIT)
- FftFlat (FFT — MIT)
- Clipper2 (integer-coordinate polygon clipping and offsetting, used by the layout editor — Boost Software License)
- CommunityToolkit.MVVM (MIT)
- Dock.Avalonia (docking — MIT)
- Material.Icons.Avalonia (icon set — MIT)
- PureHDF (HDF5 export — MIT)
- Markdig (Markdown rendering — BSD-2-Clause)
- Svg (MS-PL) and Svg.Skia (MIT), used by
tools/IconGenat packaging time - Fonts: IBM Plex Sans and Inter (SIL Open Font License 1.1), DejaVu Sans (Bitstream Vera Fonts License)
osdi.hfrom the ngspice OSDI component (© 2022 SemiMod GmbH — MPL-2.0)
Full terms, and what each one obliges you to do if you redistribute a build, are in THIRD-PARTY-NOTICES.md.



