# drawio-desktop User Guide

`drawio-desktop` is the official offline desktop edition of the popular **draw.io** (also known as **diagrams.net**) diagram editor. It is an Electron application (Electron 40 on Node 20) that wraps the upstream [`jgraph/drawio`](https://github.com/jgraph/drawio) web app and runs it locally with full file-system access, native OS menus, file associations for `.drawio` and `.vsdx`, and a powerful command-line export pipeline. The desktop edition publishes signed installers for Windows (NSIS, MSI, AppX, 32-bit and ARM64), macOS (DMG, ZIP, universal), and Linux (AppImage, `.deb`, `.rpm`, snap).

This guide documents the **desktop wrapper itself** — installation, the desktop-specific menu and file-handling surface, the command-line export interface, and the configuration flags honored by the Electron main process. The actual diagram editor (shapes, libraries, layers, the canvas, plugins, keyboard shortcuts inside a diagram) is implemented in the upstream `jgraph/drawio` web project — see [diagrams.net documentation](https://www.drawio.com) and the upstream repo for editor-side reference.

---

## 1. Quick Start

The fastest way to get drawio-desktop running is to download a prebuilt installer from the project's GitHub Releases page — there is no compilation required and updates are signed and delivered automatically.

**Prerequisite:** a 64-bit Windows 10+, macOS 11+, or Linux desktop. Disk: under 300 MB. RAM: 1 GB minimum.

1. Open [github.com/jgraph/drawio-desktop/releases](https://github.com/jgraph/drawio-desktop/releases/latest).
2. Pick the asset for your platform from the table below.
3. Run the installer (Windows/macOS) or extract/install the package (Linux).
4. Launch **draw.io** from your Start menu / Applications folder / app launcher.

| Platform | Recommended Asset | Notes |
|----------|-------------------|-------|
| Windows 10/11 (x64) | `drawio-<version>-windows-installer.exe` | NSIS installer, per-machine, lets you choose install dir |
| Windows 10/11 (x64, IT) | `drawio-<version>.msi` | MSI for Group Policy / Intune deployment |
| Windows ARM64 | `drawio-arm64-<version>-windows-arm64-installer.exe` | NSIS installer for Surface / Snapdragon devices |
| Windows 32-bit | `drawio-ia32-<version>-windows-32bit-installer.exe` | Legacy 32-bit only |
| macOS Intel/Apple Silicon | `drawio-<arch>-<version>.dmg` | `arch` = `x64`, `arm64`, or `universal`; signed and notarized |
| Linux x64 / ARM64 | `drawio-<arch>-<version>.AppImage` | Portable, no install required |
| Debian / Ubuntu | `drawio-<arch>-<version>.deb` | `sudo apt install ./drawio-amd64-<version>.deb` |
| Fedora / RHEL / openSUSE | `drawio-<arch>-<version>.rpm` | `sudo rpm -i drawio-x86_64-<version>.rpm` |
| Snap (Ubuntu) | `drawio_<version>_amd64.snap` | `sudo snap install --dangerous ./drawio_*.snap` |
| Microsoft Store | AppX bundle | Auto-managed via Store, no manual update |

The artifact name templates come from the project's electron-builder configs (`electron-builder-win.json`, `electron-builder-linux-mac.json`, `electron-builder-win-arm64.json`, `electron-builder-win32.json`, `electron-builder-snap.json`, and `electron-builder-appx.json`), so substitute your version (e.g. `29.6.6`) and architecture (`x64`, `arm64`, `ia32`, `universal`).

Once installed, double-click any `.drawio` file in your file manager — drawio-desktop registers itself as the default application for that extension and will open it directly.

> [!TIP]
> You can also pass a file straight to the binary on launch: `drawio path/to/diagram.drawio`. The main process opens the file in the first window via the `args-obj` IPC payload that the renderer listens for, and subsequent file-open requests from the OS spawn additional windows.

---

## 2. Installation

drawio-desktop ships as platform-specific signed binaries for every common desktop OS. The recommended path is always the prebuilt installer from the GitHub Releases page; build-from-source is reserved for contributors.

### 2.1 System requirements

| Resource | Minimum | Notes |
|----------|---------|-------|
| OS | Windows 10 (1809+), macOS 11 Big Sur, modern Linux (glibc 2.31+) | Bundled Electron 40 sets the floor |
| CPU | 64-bit x86 or ARM64 | 32-bit Windows still produced via `release-win32` |
| RAM | 1 GB | 4 GB+ recommended for large multi-page diagrams |
| Disk | 300 MB | Includes bundled Chromium runtime |
| Display | 1024x768 | Application starts at `1200x800` and remembers `lastWinSize` |
| Node (build only) | `>=20` | Per `package.json` `engines` field |

### 2.2 Windows

=== "NSIS installer (most users)"
    Download `drawio-<version>-windows-installer.exe` and run it. The installer is **per-machine** (`perMachine: true`), prompts for an install directory (`allowToChangeInstallationDirectory: true`), and does **not** automatically create a desktop shortcut (`createDesktopShortcut: false`) or run the app after install (`runAfterFinish: false`). Confirm those defaults match your environment before clicking Install.

=== "MSI (Intune / Group Policy)"
    Download `drawio-<version>.msi` and deploy via Microsoft Endpoint Manager, Group Policy software installation, PDQ Deploy, or `msiexec`:
    ```powershell
    msiexec /i drawio-29.6.6.msi /qn /norestart
    ```
    The MSI shares the NSIS post-install behavior — no shortcut, no auto-run.

=== "Microsoft Store (AppX)"
    Search "draw.io Diagrams" in the Microsoft Store. The AppX is published under publisher `CN=9E628CCB-BE04-4557-A5A8-81EC34B09733` and identity `draw.io.draw.ioDiagrams`. Updates are managed by the Store — disable in-app update checks if you use this channel (see `DRAWIO_DISABLE_UPDATE` in Section 3).

=== "Windows ARM64"
    Use `drawio-arm64-<version>-windows-arm64-installer.exe` (NSIS) or the corresponding **portable** EXE if you cannot install. The portable build runs the application without writing to `Program Files`.

=== "Windows 32-bit"
    Use `drawio-ia32-<version>-windows-32bit-installer.exe`. Only build separately maintained for legacy systems.

> [!IMPORTANT]
> Windows installers are not Authenticode-signed by every distributor — verify the GitHub Releases SHA against the published `latest.yml` from the same release tag. The `electron-updater` integration uses the GitHub provider (`provider: "github"`, `owner: jgraph`, `repo: drawio-desktop`) for in-app updates, but the **first** install must be trusted manually.

### 2.3 macOS

Download the `.dmg` matching your CPU. Three variants exist:

| Variant | When to use |
|---------|-------------|
| `drawio-x64-<version>.dmg` | Intel Macs only |
| `drawio-arm64-<version>.dmg` | Apple Silicon (M1/M2/M3/M4) |
| `drawio-universal-<version>.dmg` | Single binary that runs natively on both architectures |

Open the DMG, drag **draw.io** into `/Applications`, eject the volume. The app is signed with the **Hardened Runtime** enabled (`hardenedRuntime: true`) and Apple-notarized via the project's `build/notarize.mjs` pipeline, so Gatekeeper allows it without `xattr` workarounds. Entitlements are inherited from `build/entitlements.mac.plist` for both the parent process (`entitlements`) and child Electron helpers (`entitlementsInherit`).

> [!NOTE]
> The macOS bundle declares `LSItemContentTypes: ["com.jgraph.drawio"]` with `LSHandlerRank: "Owner"`, meaning Finder treats drawio-desktop as the **owning** application for `.drawio` files (UTI `com.jgraph.drawio`, conforms to `public.xml` and `public.data`) and assigns it as default opener on first run. `.vsdx` is registered as `LSHandlerRank: "Default"` — drawio-desktop accepts opens but does not claim exclusive ownership.

### 2.4 Linux

=== "AppImage"
    Most portable. Single file, runs anywhere:
    ```bash
    chmod +x drawio-amd64-29.6.6.AppImage
    ./drawio-amd64-29.6.6.AppImage
    ```

=== ".deb (Debian / Ubuntu)"
    ```bash
    sudo apt install ./drawio-amd64-29.6.6.deb
    drawio
    ```
    The Debian package installs the binary as `drawio` (per `executableName: "drawio"`) and registers `.drawio` and `.vsdx` MIME handlers.

=== ".rpm (Fedora / RHEL / openSUSE)"
    ```bash
    sudo dnf install drawio-x86_64-29.6.6.rpm
    drawio
    ```
    The RPM is built with `--rpm-rpmbuild-define=_build_id_links none` and `--rpm-digest=sha256` for maximum compatibility across RPM distros.

=== "Snap"
    ```bash
    sudo snap install drawio
    ```
    The snap package uses `base: core20` and requests the `default` and `removable-media` plugs. The first plug grants standard desktop access; `removable-media` allows opening diagrams from USB sticks and external drives. Ubuntu users on 22.04+ may see GitHub issue [#2219](https://github.com/jgraph/drawio-desktop/issues/2219) (snap depends on a very old GNOME package) — prefer the `.deb` or AppImage on those systems.

=== "Flatpak"
    drawio-desktop is **not** published as a first-party Flatpak by jgraph, but a community Flathub build exists. The main process detects flatpak sandboxing via the presence of `/.flatpak-info` and **automatically disables the in-app updater** in that case (since flatpak handles its own updates).

> [!WARNING]
> The Linux `.desktop` entry sets `StartupWMClass: "draw.io"`. Some tiling window managers (i3, Sway, Hyprland) match against this exact class name — if your config rules use lowercase `drawio`, taskbar icons or window-grouping rules may not match.

### 2.5 Build from source (contributors)

Only required if you intend to patch the desktop wrapper. The diagram editor itself lives in the [`jgraph/drawio`](https://github.com/jgraph/drawio) submodule.

```bash
git clone --recurse-submodules https://github.com/jgraph/drawio-desktop.git
cd drawio-desktop
nvm use            # uses the version pinned in .nvmrc
npm install
npm run sync       # node ./sync.cjs (syncs upstream drawio assets)
npm start          # electron .
```

To produce installers locally, run one of the published `release-*` scripts (each uses a dedicated `electron-builder-*.json` config):

| Script | Purpose |
|--------|---------|
| `npm run release-win` | NSIS + MSI x64 |
| `npm run release-win32` | NSIS ia32 |
| `npm run release-win-arm64` | NSIS + portable arm64 |
| `npm run release-appx` | Microsoft Store AppX x64 |
| `npm run release-linux` | AppImage / deb / rpm + macOS dmg/zip |
| `npm run release-snap` | snap (publishes `never` by default) |

> [!CAUTION]
> The `release-win`, `release-win32`, `release-win-arm64`, `release-appx`, and `release-linux` scripts pass `--publish always` to electron-builder, which uploads artifacts to GitHub Releases using the credentials in your environment (`GH_TOKEN`). Only run these if you are an official maintainer with publish rights. For local-only builds, change `always` to `never` in your invocation: `npx electron-builder --config electron-builder-win.json --publish never`.

---

## 3. Configuration

drawio-desktop configuration is split across **environment variables**, **command-line flags**, and an **`electron-store` JSON file** persisted under the OS-standard app-data directory. There is no `config.yaml` or `~/.drawiorc` — all desktop preferences live in one of these three places.

### 3.1 Environment variables

| Variable | Effect | Source |
|----------|--------|--------|
| `DRAWIO_DISABLE_UPDATE` | Set to `true` to suppress all auto-update checks (combine with packaging that handles updates externally — Microsoft Store, snap, flatpak) | `electron.js:33` |
| `DRAWIO_SILENT_UPDATE` | Set to `true` to download and install updates in the background without prompting; only honored when updates are not already disabled | `electron.js:36` |
| `DRAWIO_ENV` | Set to `dev` to enable developer mode: opens DevTools on launch, logs window-lifecycle events, exposes upstream draw.io test/dev URL parameters | `electron.js:74` |

> [!IMPORTANT]
> `DRAWIO_DISABLE_UPDATE` is also implicitly enabled when the app detects flatpak sandboxing (`/.flatpak-info` present) or when the `--disable-update` command-line flag is passed. Snap and AppX channels manage their own updates; explicitly setting this variable in those packages is harmless but redundant.

### 3.2 Command-line flags (Electron main process)

These flags are honored by the desktop wrapper itself, **not** the upstream Electron framework. Pass them as the first argument when launching the binary directly.

| Flag | Effect |
|------|--------|
| `--disable-update` | Same as `DRAWIO_DISABLE_UPDATE=true` |
| `--silent-update` | Same as `DRAWIO_SILENT_UPDATE=true` |
| `--disable-acceleration` | Calls `app.disableHardwareAcceleration()` before window creation. Use on systems where GPU compositing causes rendering glitches |
| `--enable-plugins` | Allows loading plugins from the per-user plugins directory (see Section 4.6). Plugins are blocked by default for security |
| `--no-sandbox` | Stripped from input-file path lists during CLI export. Pass it for compatibility on container/CI environments where the chrome sandbox is unavailable |

The full export-mode CLI surface is described in Section 4.4; those flags are only active when `-x`/`--export` is passed.

### 3.3 Persistent store (`electron-store`)

User preferences are saved automatically through the [`electron-store`](https://github.com/sindresorhus/electron-store) package, which writes a JSON file under the OS standard:

| Platform | Path |
|----------|------|
| Windows | `%APPDATA%\draw.io\config.json` |
| macOS | `~/Library/Application Support/draw.io/config.json` |
| Linux | `~/.config/draw.io/config.json` |

Recognized keys written by drawio-desktop:

| Key | Type | Default | Purpose |
|-----|------|---------|---------|
| `lastWinSize` | string | `1200,800,0,0,false,false` | `width,height,x,y,maximized,fullscreen` — restored on next launch |
| `enableSpellCheck` | bool | `true` on macOS, `false` elsewhere | Toggles Chromium spellchecker in the renderer |
| `enableStoreBkp` | bool | `true` | Keeps `.bkp` backup of every saved file |
| `isGoogleFontsEnabled` | bool | `false` | Allows fetching `fonts.googleapis.com` and `fonts.gstatic.com` (relaxes CSP) |
| `dontCheckUpdates` | bool | `false` | Set to true to suppress the periodic `autoUpdater.checkForUpdates()` call on launch |

> [!TIP]
> Delete `config.json` while the app is closed to fully reset window position, spell-check, backup, and Google-Fonts state to defaults. The next launch regenerates the file with built-in defaults.

### 3.4 `urlParams.json` overlay

If a file named `urlParams.json` exists in the **process's current working directory** at launch, every key inside is merged into the URL query passed to the bundled draw.io web app. This is an undocumented but supported escape hatch for forcing upstream draw.io URL parameters (for example, enabling experimental modes) without modifying the bundle.

```json
{
  "ui": "atlas",
  "tr": 0,
  "math": 1
}
```

> [!CAUTION]
> Only place a `urlParams.json` you trust in the working directory — values are merged unconditionally into the URL the renderer loads. A malicious overlay could enable upstream features that bypass the desktop wrapper's defaults.

### 3.5 Logging

The desktop wrapper uses [`electron-log`](https://github.com/megahertz/electron-log) for auto-updater diagnostics. Default file-level threshold is `error`; pass `--enable-logging` (a standard Electron flag) to forward Chromium console output to the controlling terminal for renderer-side debugging.

| Log file | Location |
|----------|----------|
| Windows | `%USERPROFILE%\AppData\Roaming\draw.io\logs\main.log` |
| macOS | `~/Library/Logs/draw.io/main.log` |
| Linux | `~/.config/draw.io/logs/main.log` |

---

## 4. Core Usage

This section covers the **desktop-specific** surface — file association behavior, native menus, multi-window management, the auto-update flow, and the command-line export pipeline. Everything that happens **inside** the diagram canvas (drawing, editing, libraries, search) lives in the upstream `jgraph/drawio` web app and is identical across desktop, web, and Confluence/Jira embeds.

### 4.1 Opening files

drawio-desktop accepts diagram files in three ways:

1. **Double-click in your file manager** — the OS dispatches an `open-file` event (macOS) or relaunches the binary with the path appended to `argv` (Windows/Linux). The first window opens the file directly; if a window is already loaded, a **second window** is created for the new file.
2. **Drag a file onto the dock/taskbar icon** — same path as #1.
3. **Pass on the command line** — `drawio diagram.drawio`. Multiple files can be passed; each opens in a new window.

The desktop wrapper enforces a **single-instance lock** via `app.requestSingleInstanceLock()`. Launching `drawio` while another instance is running forwards the file path to the existing process via the `second-instance` event, and the existing process opens it in a new window.

> [!NOTE]
> When you save a `.drawio` file, the wrapper writes through `O_SYNC | O_CREAT | O_WRONLY | O_TRUNC` and reads the file back to verify content integrity. If verification fails it retries up to **3 times** before reporting `Error: all saving trials failed`. A `.bkp` sibling file is also created when `enableStoreBkp` is true.

### 4.2 File associations

The installer registers the application as a handler for these extensions on every supported platform:

| Extension | Role | MIME type | Default opener? |
|-----------|------|-----------|-----------------|
| `.drawio` | `Editor` | `application/vnd.jgraph.mxfile` | Yes (claimed exclusively) |
| `.vsdx` | `Editor` | `application/vnd.visio` | No (registers without claiming) |

The `.dio` extension (sometimes seen on legacy diagrams) is **not** in the registered list — files with that extension must be renamed or opened via **File → Open** inside the application.

> [!WARNING]
> Per GitHub issue [#2338](https://github.com/jgraph/drawio-desktop/issues/2338), `.drawio.pdf` files (PDFs with embedded diagram XML) sometimes do not open via double-click on Windows because the OS routes them to the system PDF handler. Open these from the application's **File → Open** menu instead, or rename the file to `.drawio` if you want to edit the diagram content.

### 4.3 Native menus and windows

On **macOS**, drawio-desktop installs an application menu with these items:

| Menu | Items |
|------|-------|
| **draw.io** | About draw.io (opens https://www.drawio.com), Support (opens GitHub issues), **Check for updates** (hidden when updates disabled), Actual Size / Zoom In / Zoom Out, Hide / Hide Others / Show All, Quit |
| **Edit** | Undo, Redo, Cut, Copy, Paste, Paste and Match Style, Select All |

On **Windows** and **Linux** the application menubar is hidden (`menu.setApplicationMenu(null)`); all commands are reached through the in-canvas menus rendered by the upstream draw.io web app.

The wrapper intercepts `Ctrl+Shift+V` (Windows/Linux) and `Cmd+Shift+V` (macOS) at the `before-input-event` stage and routes it to `webContents.pasteAndMatchStyle()`. This is the desktop-only fix tracked in issue [#2380](https://github.com/jgraph/drawio-desktop/issues/2380).

> [!TIP]
> A right-click in any text input field shows a custom context menu (via `electron-context-menu`) with **Copy / Save Image / Save Image As / Select All** plus **Paste and Match Style** when plain text is on the clipboard. Searching the web and dictionary lookups are deliberately disabled for offline-first behavior.

### 4.4 Command-line export

Pass `-x` / `--export` to put drawio-desktop into **headless export mode**. The application creates a hidden `BrowserWindow`, loads the diagram, renders it, writes the output, and quits. No editor UI appears.

#### Basic syntax

```bash
drawio --export [options] <input file or folder>
```

#### Format and output flags

| Flag | Default | Description |
|------|---------|-------------|
| `-c, --create` | — | Create a new empty file if no input is passed |
| `-k, --check` | — | Do not overwrite existing files; suffix with `-1`, `-2` instead |
| `-x, --export` | — | Enables export mode |
| `-r, --recursive` | — | For folder input, recurse into subdirectories |
| `-o, --output <path>` | input name + format ext | Output file or folder |
| `-f, --format <fmt>` | `pdf` | One of `pdf`, `svg`, `png`, `jpeg`, `jpg`, `xml`, `html` |

#### Image quality and layout

| Flag | Default | Description |
|------|---------|-------------|
| `-q, --quality <n>` | `90` | JPEG quality 0-100 |
| `-t, --transparent` | — | Transparent PNG background |
| `-b, --border <n>` | `0` | Border around the diagram |
| `-s, --scale <n>` | `1` | Scale factor |
| `--width <n>` | — | Fit to width, preserve aspect ratio |
| `--height <n>` | — | Fit to height, preserve aspect ratio |
| `--crop` | — | Crop PDF to diagram size |

#### Page selection

| Flag | Description |
|------|-------------|
| `-a, --all-pages` | Export all pages (PDF and HTML only) |
| `-p, --page-index <n>` | Select a specific 1-based page |
| `-g, --page-range <from>..<to>` | 1-based inclusive range (PDF only) |
| `-l, --layers <comma-list>` | Layer indexes to export (applies to all pages) |

#### Embedding

| Flag | Default | Description |
|------|---------|-------------|
| `-e, --embed-diagram` | — | Embed source XML inside the output (PNG/SVG/PDF) |
| `--embed-svg-images` | — | Embed referenced raster images inside SVG |
| `--embed-svg-fonts <true/false>` | `true` | Embed fonts inside SVG |
| `-u, --uncompressed` | — | Uncompressed XML / SVG output |

#### SVG-specific

| Flag | Default | Description |
|------|---------|-------------|
| `--svg-theme <theme>` | `auto` | `dark`, `light`, or `auto` |
| `--svg-links-target <target>` | `auto` | `auto`, `new-win`, or `same-win` |

#### HTML-specific (interactive viewer)

| Flag | Default | Description |
|------|---------|-------------|
| `--html-theme <theme>` | `auto` | `dark`, `light`, `auto` |
| `--html-zoom <true/false>` | `true` | Show zoom controls |
| `--html-lightbox <true/false>` | `true` | Enable lightbox |
| `--html-layers <true/false>` | `true` | Show layers toolbar |
| `--html-tags <true/false>` | `true` | Show tags toolbar |
| `--html-fit <true/false>` | `true` | Responsive fit-to-container |
| `--html-link-target <target>` | `auto` | `auto`, `blank`, `self` |
| `--html-link-color <color>` | `#0000ff` | Highlight color for links |
| `--html-edit-link <url>` | — | URL for the **Edit** button in the viewer |

#### Other

| Flag | Description |
|------|-------------|
| `-z, --zoom <n>` | Scale the application interface itself (used in normal mode too) |
| `--enable-plugins` | Allow plugin loading during export |
| `-V, --version` | Print version and quit |
| `-h, --help` | Print help and quit |

> [!IMPORTANT]
> When the `--output` path's extension is one of the recognized format extensions (`pdf`, `svg`, `png`, `jpeg`, `jpg`, `xml`, `html`), it **wins** over `--format`. Use `--format` when piping output to a folder so each file inherits the chosen format.

### 4.5 Auto-update behavior

drawio-desktop ships with `electron-updater` configured against the GitHub provider:

```javascript
autoUpdater.setFeedURL({
  provider: 'github',
  repo: 'drawio-desktop',
  owner: 'jgraph'
})
```

On launch, unless `dontCheckUpdates` is `true` or updates are disabled, `autoUpdater.checkForUpdates()` runs once. If a newer release is found:

- **Default mode**: a dialog asks **Ok / Cancel / Don't Ask Again** before downloading.
- **Silent mode** (`DRAWIO_SILENT_UPDATE=true` or `--silent-update`): downloads + installs on next quit with no prompt (`autoDownload: true`, `autoInstallOnAppQuit: true`).
- **Disabled** (`DRAWIO_DISABLE_UPDATE=true`, `--disable-update`, or running in flatpak): no check at any time.

During the download a progress window from `electron-progressbar` shows real-time progress (Mac receives no `download-progress` events from electron-updater, so the bar runs indeterminate until completion). When ready to install, a final dialog offers **Install / Later** — choosing Later defers application until the next quit.

### 4.6 Plugin loading

Plugins are JavaScript files placed in the per-user plugins directory beneath the OS app-data folder. They are blocked unless one of these is true:

- The user passes `--enable-plugins` on the command line.
- An IPC `installPlugin` request from the renderer succeeded (the renderer surfaces this through draw.io's **Extras → Plugins** menu).

The desktop wrapper enforces that plugin scripts can only load files from the per-user plugins URL or the bundled application URL — anything else is blocked at the `session.webRequest.onBeforeRequest` layer. This is intentional defense-in-depth; even with plugins enabled, an installed plugin cannot pull in arbitrary `file://` resources.

### 4.7 Relationship to the upstream draw.io web app

drawio-desktop **does not implement the diagram editor itself**. The `drawio/` directory is a git submodule pointing at [`jgraph/drawio`](https://github.com/jgraph/drawio). At build time the submodule's `src/main/webapp/` directory is packaged into the desktop app and loaded by the Electron main process via:

```javascript
const codeDir = path.join(__dirname, '/../../drawio/src/main/webapp');
mainWindow.loadURL(`file://${codeDir}/index.html?...`)
```

For diagram-editor questions (how to add a shape, connect arrows, use the formula editor, work with libraries) consult the upstream documentation at [www.drawio.com](https://www.drawio.com) and the [`jgraph/drawio`](https://github.com/jgraph/drawio) repository. The desktop wrapper only adds: file-system bridges, OS menus, file associations, the CLI export pipeline, the auto-updater, and platform-specific packaging.

---

## 5. Common Tasks

Every recipe below is grounded in actual drawio-desktop behavior — no invented flags, no upstream-only features.

### 5.1 Install and open your first diagram

**Goal:** verify the install end-to-end with one round trip.

1. Download and install the appropriate package from Section 2.
2. Launch the app from your Start menu / Applications / app launcher.
3. Click **+ Create New Diagram**, pick any template, choose **Device** as the storage backend, and save as `~/Documents/test.drawio`.
4. Close the app.
5. Open your file manager and double-click `test.drawio`.

**Verify:** the application reopens with `test.drawio` already loaded and the title bar shows the file name.

### 5.2 Set drawio-desktop as the default for `.drawio` and `.vsdx`

The installer attempts this automatically, but OS preferences sometimes win.

=== "Windows"
    1. Right-click any `.drawio` file → **Open with → Choose another app**.
    2. Pick **draw.io**, check **Always use this app**, click OK.
    3. Repeat for `.vsdx` if desired.

=== "macOS"
    1. Right-click a `.drawio` file in Finder → **Get Info**.
    2. Under **Open with**, select **draw.io**, click **Change All...**.

=== "Linux (XDG)"
    ```bash
    xdg-mime default drawio.desktop application/vnd.jgraph.mxfile
    xdg-mime default drawio.desktop application/vnd.visio
    ```

### 5.3 Export a diagram from the command line

**Goal:** generate a 2x-scaled PNG with no background, embedding the source XML so the file remains editable.

```bash
drawio --export --format png --scale 2 --transparent --embed-diagram \
       --output my-diagram.png my-diagram.drawio
```

```text
my-diagram.drawio -> my-diagram.png
```

**Goal:** convert every `.drawio` in a folder tree to a single multi-page PDF each.

```bash
drawio --export --recursive --format pdf --all-pages \
       --output ./pdfs ./diagrams
```

> [!TIP]
> Combine `--check` with `--output` pointing at a folder to avoid overwriting prior runs — the wrapper appends `-1`, `-2`, ... to the basename when targets exist.

### 5.4 Run multiple windows of the same app

drawio-desktop supports unlimited concurrent windows in a single process. Open a second window via:

- **macOS** menu: **File → New** (rendered by the upstream web app).
- **Cross-platform**: launch the binary again — the single-instance lock will route the request to the existing process, which spawns a new window.

```bash
drawio &
drawio another-diagram.drawio &
```

> [!NOTE]
> Per-window state (zoom level, fullscreen) is **not** persisted; only the **last** closed window's size, position, maximized, and fullscreen flags are written to `lastWinSize` in the electron-store JSON.

### 5.5 Diagnose a startup or rendering problem with `--enable-logging`

When the app fails to start or produces blank windows, run from a terminal with `--enable-logging` and `DRAWIO_ENV=dev`:

```bash
DRAWIO_ENV=dev drawio --enable-logging
```

```text
in preload C:\Program Files\draw.io\resources\app.asar\src\main
createWindow {}
Window on close 0 ...
```

The wrapper opens DevTools automatically when `DRAWIO_ENV=dev`, exposing the renderer console for upstream-app errors. Capture both the terminal output and the DevTools Console for any bug report.

### 5.6 Deploy via Group Policy on Windows

For enterprise rollouts, distribute the MSI rather than the NSIS exe.

1. Build/download `drawio-29.6.6.msi`.
2. Place the file on a UNC share readable by all target machines.
3. In **Group Policy Management Console** → **Computer Configuration → Software Settings → Software Installation** → **New → Package**.
4. Point at the UNC path and select **Assigned**.
5. Optionally push `DRAWIO_DISABLE_UPDATE=true` as a system environment variable via **Preferences → Environment** so machines do not pull updates from GitHub directly.

> [!IMPORTANT]
> The MSI installs **per-machine** by default — confirm your GPO context (computer vs. user) matches that scope. Pushing via user-context GPO with a per-machine MSI fails silently on lockdown.

### 5.7 Customize the cache directory

The Electron `userData` directory holds the electron-store config, plugins, draft files, and Chromium cache. Move it by setting the standard Electron environment variable before launch:

=== "Linux / macOS"
    ```bash
    export ELECTRON_USER_DATA=/data/drawio
    drawio
    ```

=== "Windows (PowerShell)"
    ```powershell
    $env:ELECTRON_USER_DATA = "D:\drawio-data"
    & "C:\Program Files\draw.io\draw.io.exe"
    ```

This is useful for shared workstation builds, encrypted-volume setups, and CI runners.

### 5.8 Build the desktop wrapper from source for a contribution

```bash
git clone --recurse-submodules https://github.com/jgraph/drawio-desktop.git
cd drawio-desktop
nvm install
nvm use
npm install
npm run sync
npm start
```

After validating your change locally:

```bash
# Linux test build (does not publish):
npx electron-builder --config electron-builder-linux-mac.json --publish never
```

Open a PR against `master` of [`jgraph/drawio-desktop`](https://github.com/jgraph/drawio-desktop). Editor-side fixes should target [`jgraph/drawio`](https://github.com/jgraph/drawio) instead — see the upstream contributing guide for details.

---

## 6. Troubleshooting

### Error: `Failed to process page <n>. The file may be corrupt.`

**Cause:** during multi-page PDF combination via `@cantoo/pdf-lib`, one of the per-page render outputs failed to load. Most often caused by a font missing from the system or a malformed shape on the offending page.

**Solution:**

1. Re-run the export with a single page using `--page-index <n>` to isolate the broken page.
2. Open the diagram in the GUI, navigate to that page, and look for shapes with broken text or missing image references.
3. As a workaround, export each page individually with `--page-index` and merge externally.

**Prevention:** install all referenced custom fonts on the system (drawio-desktop reads them via `fc-list` on Linux/mac and PowerShell `InstalledFontCollection` on Windows).

### Error: `Invalid file data`

**Cause:** the wrapper's `checkFileContent()` saw the destination path under the application's own asar/install directory or the file body did not match any recognized header (XML, JSON, PNG, JPEG, WebP, PDF, ZIP, mxfile).

**Solution:**

1. Confirm the save target is **outside** `Program Files\draw.io` / `/Applications/draw.io.app` / the snap mountpoint.
2. Confirm the file extension matches the actual content — saving an arbitrary binary as `.drawio` will trip the magic-byte check.

**Prevention:** save into your home directory, Documents folder, or any user-writable location. Never target the install directory; the asar archive is read-only by design.

### Error: `all saving trials failed`

**Cause:** after writing the file with `O_SYNC`, the wrapper read it back and the bytes did not match the original. Retried 3 times; all failed. Caused by network drives, certain antivirus realtime scanners, or filesystems that reject `O_SYNC`.

**Solution:**

1. Save to local disk first; copy to network share manually.
2. Add an antivirus exclusion for the directory.
3. Check disk health (`fsck`, `chkdsk`).

**Prevention:** keep working diagrams on local SSD. The `.bkp` companion file (when `enableStoreBkp` is true) holds the previous version even after this error.

### Error: `conflict`

**Cause:** the file's modification timestamp on disk changed since drawio-desktop loaded it (someone else saved over it, or git rewrote it). The wrapper refuses to overwrite without explicit confirmation.

**Solution:** the in-app dialog offers **Overwrite / Reload / Save As** — pick **Save As** to preserve both versions or **Overwrite** if you are sure your version supersedes the other.

**Prevention:** close the file when stepping away for long periods; re-open after pulling git changes.

### Cannot open `.drawio.pdf` files

**Cause:** GitHub issue [#2338](https://github.com/jgraph/drawio-desktop/issues/2338). The OS routes the file to the system PDF handler because `.pdf` wins over `.drawio.pdf` in MIME resolution.

**Solution:** open from inside drawio-desktop via **File → Open** and select the file manually. The wrapper detects the embedded XML via `readPdfXml()` and reconstructs the diagram.

### Math rendering does not work in exports

**Cause:** issue [#2354](https://github.com/jgraph/drawio-desktop/issues/2354) (closed). MathJax is loaded by the upstream web app but the headless export path may finish before MathJax typesets if many equations are present.

**Solution:** add a `--scale 2` or `--width 2000` flag to slow the render path and give MathJax time to complete; in extreme cases pass `--all-pages` (which serializes per-page rendering) instead of single-page.

### Linux: app does not start on Ubuntu 24.04+

**Cause:** issue [#2263](https://github.com/jgraph/drawio-desktop/issues/2263). Snap's `core20` base ships an older glibc/GNOME stack that may conflict with newer Ubuntu kernels and AppArmor policies.

**Solution:** switch to the `.deb` or AppImage on Ubuntu 24.04+; both run against the host's libraries.

### macOS: cannot print from desktop app

**Cause:** issue [#2317](https://github.com/jgraph/drawio-desktop/issues/2317). System print dialog interaction was broken in some Electron 40 builds on macOS Ventura+.

**Solution:** use **File → Export As → PDF** with the `--all-pages` equivalent, then open the PDF in Preview and print from there. Track the issue for an upstream fix.

### Dark mode does not match website

**Cause:** issue [#2346](https://github.com/jgraph/drawio-desktop/issues/2346). The desktop wrapper does not propagate OS-level dark-mode preference to the upstream web app's theme picker on first launch.

**Solution:** open **Extras → Theme** inside the diagram editor and select **Dark** or **Auto** explicitly.

### Snap Scratchpad errors on launch

**Cause:** issue [#2341](https://github.com/jgraph/drawio-desktop/issues/2341) (closed in 29.5.2). The snap's confined data directory was not writable for the Scratchpad initialization on some configurations.

**Solution:** upgrade to v29.5.2 or later. As a workaround on older versions, switch to `.deb` or AppImage.

### `%pagenumber%` placeholder does not render in PDF export

**Cause:** issue [#2376](https://github.com/jgraph/drawio-desktop/issues/2376). The placeholder substitution is performed by the upstream web app **before** PDF rendering, and is not re-applied after the per-page combine step in the desktop wrapper's `mergePdfs()` flow.

**Solution:** track the upstream fix; as a workaround, hardcode page numbers in the diagram itself before export.

### Light/Dark switch needs full app restart to take effect

**Cause:** issue [#2366](https://github.com/jgraph/drawio-desktop/issues/2366) (closed). The Electron `nativeTheme` change event was not wired through the IPC bridge in earlier 29.x versions.

**Solution:** upgrade to the latest release. As a workaround, **File → Quit** and relaunch after toggling the theme.

> [!CAUTION]
> If the app refuses to launch at all and you suspect a corrupt store, exit fully (check Task Manager / Activity Monitor for stray processes), back up `~/.config/draw.io/config.json` (or platform equivalent), then delete it. The next launch regenerates defaults. Note that this also resets your last window size and Google Fonts opt-in.

---

## 7. FAQ

**Q: What is the difference between drawio-desktop and the website at draw.io?**

The website (drawio.com / app.diagrams.net) and drawio-desktop run the **same** diagram editor — drawio-desktop bundles the upstream `jgraph/drawio` web app inside an Electron shell. The desktop edition adds full offline operation, OS file associations, native menus on macOS, the command-line export pipeline, and a built-in auto-updater. It removes Google Drive / OneDrive / GitHub cloud storage by default (`gapi=0`, `od=0`, `gh=0`, `gl=0`, `tr=0` in the URL query); files always save to your local disk.

**Q: Where is my diagram data stored?**

Wherever you save it — drawio-desktop never sends diagram content to a server. The application's own preferences live in the OS standard app-data directory (`%APPDATA%\draw.io\` on Windows, `~/Library/Application Support/draw.io/` on macOS, `~/.config/draw.io/` on Linux). Drafts of unsaved files are kept beside the original file as `.$<filename>.dtmp` and deleted once you save.

**Q: Does drawio-desktop work fully offline?**

Yes. The default URL query disables every cloud backend (`mode: 'device'`, all storage flags off). The only outbound traffic is: (1) the GitHub auto-updater check on launch (suppressible — see Section 3), and (2) optionally `fonts.googleapis.com` if you toggle **Google Fonts** in settings (off by default).

**Q: How do I update drawio-desktop?**

When a new release lands on the GitHub Releases page, the `electron-updater` shows a dialog at next launch offering to download. Choose **Ok** to download in the background; once complete, accept the **Install / Later** prompt. To skip checks entirely, set `DRAWIO_DISABLE_UPDATE=true`. AppX (Microsoft Store), snap, and flatpak users get updates from their package manager — auto-update is automatically suppressed in flatpak via the `/.flatpak-info` detection.

**Q: Can I open Visio (`.vsdx`) files?**

Yes — drawio-desktop registers `.vsdx` as an editable file type and converts them transparently on open via the bundled `vsdxImporter.html`. CLI export of `.vsdx` is also supported: `drawio --export --format png input.vsdx`.

**Q: Does it support `.dio` files (the legacy extension)?**

The installer does not register `.dio`. Open such files via **File → Open** within the application, or rename them to `.drawio`.

**Q: How do I disable the in-app updater for managed deployments?**

Set the environment variable `DRAWIO_DISABLE_UPDATE=true` system-wide, or pass `--disable-update` on every launch (e.g. wrap the binary in a shell script). For Microsoft Store users, the AppX channel handles updates automatically; for flatpak users, detection of `/.flatpak-info` disables the updater automatically.

**Q: Can I run drawio-desktop in a CI/headless container?**

Yes — pass `--export` to enable headless mode and `--no-sandbox` if you cannot run with the chrome sandbox (the wrapper strips `--no-sandbox` from input file paths so it works as expected). Use `xvfb-run drawio --export ...` on Linux CI runners that lack a display.

**Q: How do I install plugins and where do they go?**

Inside the editor, open **Extras → Plugins... → Add**. The IPC `installPlugin` action stores the JS file under your `userData/plugins/` directory. Plugins are blocked at runtime unless you launch with `--enable-plugins`. Plugins are **not** sandboxed beyond the file-protocol whitelist — only install plugins from sources you trust.

**Q: My diagrams open at the wrong window size after restart.**

Window size, position, maximize and fullscreen are persisted in `lastWinSize` (electron-store key, default `1200,800,0,0,false,false`). If the saved coordinates are off-screen (external monitor disconnected), the wrapper's `isWithinDisplayBounds()` check resets position to default. To force a reset, edit or delete `config.json` in your app-data directory.

**Q: Can I use drawio-desktop alongside the web app?**

Yes — they are isolated. Diagrams created in one open identically in the other (same XML format, same file extensions). You can keep `.drawio` files in a synced folder (Dropbox, OneDrive, iCloud) and edit them from any device.

**Q: How do I report a bug?**

Open an issue at [github.com/jgraph/drawio-desktop/issues](https://github.com/jgraph/drawio-desktop/issues). Include your OS, drawio-desktop version (visible in **Help → About** or `drawio --version`), and a minimal `.drawio` file that reproduces the problem. Diagram-editor bugs (canvas, shapes, formulas) should go to [jgraph/drawio](https://github.com/jgraph/drawio/issues) instead — they are fixed upstream and rolled into the next desktop release.

**Q: Where can I see what changed between versions?**

The GitHub Releases page lists each version with release notes. Underlying editor changes come from upstream `jgraph/drawio` — its `CHANGELOG` covers shape and feature additions.

---

_Generated April 2026 from jgraph/drawio-desktop at 5986014. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
