Open standardApache-2.0 · CC BY 4.0Format 1.0

Electrical diagrams, as code.

An open standard to describe electrical installations (sources, protective devices, cables, loads) in JSON or Python. From one file any tool can read: single-line and multi-line drawings, compliance checks, bills of materials and wire lists. No coordinates, no CAD file: a text file you can diff and review.

pip install uniwire
house.uniwire.jsonJSON
{  "$schema": "https://uniwire.sh/schema/v1/uniwire.schema.json",  "uniwire": "1.0.0",  "profiles": ["nfc15100"],  "meta": {    "title": "House: consumer unit", "project": "UW-0001",    "author": "J. Martin", "date": "2026-10-12",    "revisions": [{ "index": "A", "date": "2026-10-12",                    "description": "First issue" }]  },  "installation": { "earthing": "TT", "system": "1P+N", "un_V": 230,                    "supply": "Utility 12 kVA" },  "templates": {    "C16": { "type": "breaker", "in_A": 16, "curve": "C" },    "C20": { "type": "breaker", "in_A": 20, "curve": "C" },    "C32": { "type": "breaker", "in_A": 32, "curve": "C" }  },  "sources": [    { "type": "grid", "label": "Utility", "supply": "12 kVA",      "children": [      { "type": "main_breaker", "ref": "-Q0", "range_A": "15-60",        "idn_mA": 500, "selective": true, "children": [        { "type": "board", "ref": "DB1", "label": "Consumer unit",          "children": [          { "type": "rcd", "ref": "-Q1", "in_A": 40, "idn_mA": 30,            "rcd_type": "AC", "children": [            { "type": "breaker", "ref": "-Q11", "use": "C16",              "cable": { "cores": "3G", "section_mm2": 1.5 }, "children": [              { "type": "lighting", "label": "Lighting", "points": 8 } ] },            { "type": "breaker", "ref": "-Q12", "use": "C20",              "cable": { "cores": "3G", "section_mm2": 2.5 }, "children": [              { "type": "socket", "label": "Sockets", "points": 8 } ] },            { "type": "breaker", "ref": "-Q13", "use": "C20",              "cable": { "cores": "3G", "section_mm2": 2.5 }, "children": [              { "type": "socket", "label": "Sockets", "points": 6 } ] }          ] },          { "type": "rcd", "ref": "-Q2", "in_A": 40, "idn_mA": 30,            "rcd_type": "A", "children": [            { "type": "breaker", "ref": "-Q21", "use": "C32",              "cable": { "cores": "3G", "section_mm2": 6 }, "children": [              { "type": "cooking", "kind": "hob", "label": "Hob",                "p_kW": 7.2 } ] },            { "type": "breaker", "ref": "-Q22", "use": "C20",              "cable": { "cores": "3G", "section_mm2": 2.5 }, "children": [              { "type": "appliance", "kind": "washing_machine",                "label": "Washing machine" } ] },            { "type": "breaker", "ref": "-Q23", "use": "C20",              "cable": { "cores": "3G", "section_mm2": 2.5 }, "children": [              { "type": "water_heater", "label": "Water heater",                "volume_L": 200, "p_kW": 2.4 } ] }          ] }        ] }      ] }    ] }  ],  "views": [    { "id": "sld", "paper": "A4",      "cartouche": ["label", "ref", "protection", "idn_mA", "cable",                    "p_kW"] },    { "id": "ml", "kind": "multi-line", "paper": "A4",      "color": "conductors" }  ]}
house.svgA4 · sheet 1/1 open in the viewer
Single-line diagram of a house consumer unit: utility supply, 500 mA main breaker, two 30 mA RCDs feeding six circuits, circuit schedule and title block.

Fig. 1: the file on the left, drawn by the library on the right. Nothing on the sheet was placed by hand.

Hover a line with a ref to find the device on the sheet.

02Drawings

One file, two drawings.

The single-line diagram and the multi-line power diagram come from the same document. The multi-line view needs no extra data: one line per conductor, one contact per pole, RCD toroids, PEN split, motor terminals U V W.

Single-line diagram of the house.
Fig. 2uniwire render house.uniwire.jsonOpen in the viewer
Multi-line power diagram of the same house, conductors in IEC 60445 colours.
Fig. 3uniwire render house.uniwire.json --kind multi-lineOpen in the viewer

Colour mode of fig. 3

The colours are the document's own: set "color": "conductors" on a view, pick the iec or us preset, override any of them with a palette.

  • Colour by conductor, phase, source, status (existing, new, future, removed) or voltage level: strokes only, texts stay black, legend in a free corner.
  • Title block, folio numbering, revisions and notes on every sheet; large boards split across sheets with cross-references.
  • SVG and PDF. In the PDF, every “→ sheet 3” is a link and every sheet a bookmark.
03Code first

Or write it in Python.

The code-first builder writes the same document. with makes an element the parent of what is created inside it, >> chains elements, and ratings and cables are written the way they appear on drawings: "C16", "3G2,5".

house.py
from uniwire.build import *

with Installation("House: consumer unit", earthing="TT", system="1P+N", un="230 V",
                  profiles=["nfc15100"], project="UW-0001", author="J. Martin",
                  date="2026-10-12", supply="Utility 12 kVA",
                  revisions=[{"index": "A", "date": "2026-10-12", "description": "First issue"}]) as inst:
    with Grid("Utility", supply="12 kVA"), \
            MainBreaker("-Q0", "15-60 A", "500 mA", selective=True), \
            Board("DB1", label="Consumer unit"):
        with RCD("-Q1", "40 A", "30 mA", type="AC"):
            Breaker("-Q11", "C16", cable="3G1,5") >> Lighting("Lighting", points=8)
            for ref, points in [("-Q12", 8), ("-Q13", 6)]:
                Breaker(ref, "C20", cable="3G2,5") >> Socket("Sockets", points=points)
        with RCD("-Q2", "40 A", "30 mA", type="A"):
            Breaker("-Q21", "C32", cable="3G6") >> Cooking("Hob", kind="hob", p="7,2 kW")
            Breaker("-Q22", "C20", cable="3G2,5") >> Appliance("Washing machine", kind="washing_machine")
            Breaker("-Q23", "C20", cable="3G2,5") >> WaterHeater("Water heater", volume_L=200, p="2,4 kW")
    inst.view(id="sld", paper="A4", cartouche=["label", "ref", "protection", "idn_mA", "cable", "p_kW"])
    inst.view(id="ml", kind="multi-line", paper="A4", color="conductors")

for finding in inst.check():
    print(finding)
inst.save("house.uniwire.json")
inst.render("house.pdf")

This script and the JSON file of fig. 1 produce the same sheet, byte for byte, and the website build checks it.

Loops, functions and your own templates are plain Python: a board per floor, a feeder per motor, a variant per client.

Format
*.uniwire.json, JSON Schema draft 2020-12
Units
in the field names: in_A, idn_mA, section_mm2
Typing
closed: calibre instead of in_A is an error
Types
53 node types, from utility grid to EV charger
Needs
Python 3.10+ and pydantic
04Rules

Checked before it is drawn.

Rule profiles catch mistakes while they are still cheap. Here is the house of fig. 1 with three typical errors: a 32 A breaker on 2.5 mm², ten lighting points on one circuit, a hob behind a type AC RCD.

terminal · exit code 1
$ uniwire check house.uniwire.json
house.uniwire.json: 5 finding(s)
  ERROR   nfc15100.section [Q12]: 32 A breaker on 2.5 mm² (max 20 A)
  ERROR   nfc15100.points [lighting]: 10 points on a lighting circuit (max 8)
  ERROR   nfc15100.rcd-type-A [cooking]: Hob: type A (or F, B) RCD required, type AC excluded
  ERROR   nfc15100.rcd-type-A [appliance]: Washing machine: type A (or F, B) RCD required, type AC excluded
  WARNING nfc15100.rcd-count [Q1]: no type A 30 mA RCD (dwellings: at least 1; set installation.premises for other premises)
core
always on: unique tags, rating cascade, transfer switches, keyed interlocks
nfc15100
French dwellings: cross-sections, points per circuit, 30 mA and type A RCDs, circuits per RCD
iec60364
cable current-carrying capacity
PLC
slots, channels, coil voltages, WAGO bus end

Each finding carries a level, a stable rule id, the node and, for rules based on a standard, the clause it relies on. These are consistency checks: they do not replace the standard, nor the verification of the installation by a qualified person.

All rules and their sources
05Viewer

The library, in your browser.

The web viewer runs the real uniwire Python library on Pyodide. Validation messages, findings, drawings and bill of materials are exactly those of the command line, and the document never leaves your machine.

The uniwire viewer: JSON editor on the left, drawing of example 24 on the right, issues panel below.

Edit, see

JSON editor with error markers, live re-rendering, one tab per sheet, single-line and multi-line, colour modes.

Explore

Hover a symbol to see what feeds it and what it feeds; follow a conductor across the sheet; click “→ sheet 3” to jump there.

Share

A link carries the whole document, compressed in the URL fragment, which is never sent to a server. Download SVG, PDF or the BOM.

Open the viewer

06Panel builders

Wire marks, from the same file.

Declare a marking rule in a view (sequential, by potential, or a pattern such as {cable}-{conductor}) and the marks appear on the multi-line drawing and in the wiring lists. Example 24, a motor control centre, numbers its motor wires from 101.

Multi-line diagram of a motor control centre: incomer, starters, variable-speed drives and soft starter, motor wires marked 101 to 128.
Fig. 4examples/24_factory_mcc_motor_starters.uniwire.json, view marks, title block croppedOpen in the viewer

uniwire markers · wire marker list (excerpt)

markendterminal_displaysection_mm2enclosure
1L1fromIN185
1L1toMCC-2185MCC
1L2fromIN185
1L2toMCC-2185MCC
1L3fromIN185
1L3toMCC-2185MCC
PEfromIN95
PEtoMCC-295MCC
101from-KM12.5MCC

uniwire cables · cable schedule (excerpt)

refcoressection_mm2length_mfromtocores_used
W13x18540INMCC4
W114G2.535KM1M14
W124G1.525KM2M24
W134G1620F3M34
W244G256Q0Q44
W144G2530VFD4M44
W154G5045SS5M54

Also uniwire wires (one row per conductor), uniwire bom (manufacturer, part number, accessories) and uniwire marks --write to freeze the numbering once the panel is built. Stable column names, ready for a label printer or a spreadsheet.

07Developers & LLMs

A format machines can write, too.

Closed typing and precise errors make uniwire a good target for code generators and language models. Tell your assistant uniwire.sh: it reads llms.txt (the full reference card included), answers with one JSON document and a link that opens it in the web viewer, drawn and checked. With MCP, the assistant validates, checks, patches and renders by itself.

ChatGPT with the uniwire app one run, unedited excerpts · 2026-10-13

@uniwire draw the single-line diagram of a small bakery, three-phase 400 V: 12 kW oven, 3 kW dough mixer, cold room, lighting, sockets and a till. Check it and give me the PDF.

ThinkingThought for 1m 1s

  • uniwire get_reference_card
  • uniwire validate
  • uniwire check 0 errors · 0 warnings
  • uniwire render

Validation passed …

Download the single-line diagram (PDF)

The design uses six dedicated circuits, each with 30 mA residual-current protection. The total estimated connected load is 21.5 kW.

Important: The automated check passed, but this is a preliminary design, not an electrical compliance certificate. The cold-room compressor characteristics, actual cable lengths, installation conditions, short-circuit levels and supply capacity must be verified before installation.

Single-line diagram of the bakery checked by the uniwire app: three-phase supply, main breaker, distribution board and six circuits: oven, dough mixer, cold room, lighting, sockets and till
Fig. 5The document behind the PDF link, drawn by uniwire render, title block croppedOpen in the viewer

Tool calls from the server logs; the answer is quoted in part (“…” marks a cut). The PDF link opens the editor on the checked document and downloads the PDF drawn by uniwire; here it points to the same document, kept with this page. Without the app, an assistant can follow llms.txt. Setup: uniwire in your assistant.

hosted MCP server
https://mcp.uniwire.sh/mcp

Nothing to install. Public mode: no file access, bounded documents, renderings and time per call.

local server · Claude Code
pip install "uniwire[mcp]"
claude mcp add uniwire -- uniwire-mcp
other MCP clients · .mcp.json
{"mcpServers": {"uniwire": {"command": "uniwire-mcp"}}}
Schema
uniwire.sh/schema/v1/uniwire.schema.json
llms.txt
uniwire.sh/llms.txt, full reference card included
Viewer
uniwire.sh/viewer/: paste a document to check and draw it
Card
uniwire card: the format in about 3,100 tokens, generated from the model
Describe
uniwire describe: a deterministic outline with stable ids
Patch
uniwire patch: edits by id: set, add, move, link…
Evals
15 tasks that score model-written documents, offline
Graph
terminal / connectivity-node graph, CIM, IFC and IEC 61850 SCL mappings

LLM tools   Python API

08Examples

52 installations, drawn by the library.

Dwellings in France, the UK, the US and Germany, shops and offices, an operating theatre and server rooms, motor control centres, MV/LV substations, PV, EV charging, storage, PLCs, a marina, a −48 V telecom shelter. Each one opens in the viewer.

All 52 examples

09Open standard

The common language of electrical installations.

The specification is published under CC BY 4.0: write your own reader, exporter or checker, in any language, in commercial software. The reference library and the JSON Schema are Apache-2.0.

Licences

  • Code, CLI, JSON Schema: Apache-2.0
  • Specification text: CC BY 4.0
  • Optional IEC 81346-2 class table: CC BY-SA 4.0, separate package

Governance

Every change to the format goes through a public uniwire Enhancement Proposal: use case, proposal, compatibility, implementation. Minor versions only add; breaking changes wait for 2.0 and come with a migration function.

The UEP process

Next: format 2.0

UEP-0001 · Terminals, terminal strips and wires (draft): named ports, terminal strips, wires and cables as objects, potentials. The part the current format can carry (wire marking and the wiring exports) already ships.

Read UEP-0001
10Get started

Three commands to a first sheet.

  1. Install

    Python 3.10 or later. The [pdf] extra adds PDF output.

    pip install "uniwire[pdf]"
  2. Check

    Schema, integrity, then the rule profiles named in the document.

    uniwire check house.uniwire.json
  3. Draw

    SVG sheets in out/, or one PDF with bookmarks.

    uniwire render house.uniwire.json -f pdf

Read the documentation