svg2drawio

SVG in. Editable draw.io out.

svg2drawio converts an SVG into a .drawio file whose cells are native draw.io shapes — real rectangles, ellipses, edges with draggable endpoints and text you can retype. Not an embedded picture: a diagram you can keep working on.

diagram.svg <rect x="10" y="10" …/> <circle cx="80" …/> <path d="M0 0 C…"/> <text>label</text> <line … marker-end/> svg2drawio diagram.drawio label open draw.io move restyle retype text reconnect export
Every SVG element lands as its own draw.io cell, in the same place, with the same colours.

Install

A single static binary. macOS and Linux, Intel and Apple Silicon.

# Homebrew
brew tap bcollard/svg2drawio
brew install --cask svg2drawio

# or with a Go toolchain
go install github.com/bcollard/svg2drawio/cmd/svg2drawio@latest

Usage

The bare command converts; subcommands cover the rest.

# One file → diagram.drawio next to it
svg2drawio diagram.svg

# A tree of icons into one output directory
svg2drawio -o out/ icons/

# Several SVGs as pages of a single file
svg2drawio -o all.drawio a.svg b.svg c.svg

# Straight into draw.io's Extras → Edit Diagram box
svg2drawio -o - diagram.svg | pbcopy

Why not just import the SVG?

draw.io can place an SVG on the canvas, but it stays one opaque picture.

Real cells, not a picture

Each shape is its own mxCell with its own fill, stroke and geometry. Select it, move it, recolour it.

Connectors stay connectors

Lines, polylines and straight paths become edges with draggable endpoints and waypoints; SVG markers become arrowheads.

Text stays text

Font family, size, weight, colour and alignment carry over into editable labels — no re-typing, no bitmap text.

Curves become native shapes

Arbitrary paths are emitted as inline stencils, the same object draw.io writes for its own custom shapes.

CSS is resolved first

Class-driven SVGs from design tools and LLMs work: <style> rules are applied through the cascade before conversion.

One binary, no runtime

Pure Go, no dependencies, MIT licensed. Runs in CI as easily as on a laptop.

What converts

The mapping from SVG to draw.io, element by element.

SVGdraw.io
rect (with rx/ry)native rectangle, rounded with an absolute arc size
circle, ellipsenative ellipse
line, open polyline, straight pathedge with floating endpoints and waypoints
polygon, curved or filled pathvertex with an inline stencil
text, tspantext cell with font family, size, colour, weight and alignment
imageshape=image, data URIs rewritten the way draw.io stores them
gdraw.io group, children rebased on the group origin
use, symbolexpanded before conversion
gradientsfillColor + gradientColor + gradientDirection
marker-start, marker-endblock arrowheads on the edge
transformbaked into coordinates; rotation survives as rotation=
viewBox, width, heightpage size and user-unit scale

For AI coding agents

svg2drawio ships an Agent Skill, so tools like Claude Code know when and how to use it without being told each session.

svg2drawio skill install        # → ~/.claude/skills/svg2drawio/SKILL.md
svg2drawio skill install --print # write it anywhere you like

Questions

How are curved shapes handled?

Anything draw.io has no native shape for — a curved or filled path, a polygon — is written as an inline stencil, the same object draw.io produces for its own custom shapes. It stays a real cell: selectable, resizable, and recolourable from the format panel.

What does not survive the conversion?

clipPath, mask, filter and pattern fills are ignored, fill-rule="evenodd" has no mxGraph equivalent, and text on a path is placed at its anchor point. Text box sizes are estimated, because draw.io lays text out itself — a long label may need a nudge after import.

Does it phone home?

No. It reads files and writes files. No network access, no telemetry, nothing uploaded to a conversion service.

Can I check the result into git?

Yes — the output is plain XML with stable ids, so diffs are readable. Keep the source SVG next to it; the conversion is one-way.