Skip to content

Desktop App

David Benson edited this page Oct 7, 2026 · 1 revision

draw.io Desktop is an Electron app in its own repository, jgraph/drawio-desktop, that runs the editor from this repository offline. This page explains how the two fit together, the desktop-specific code that lives here, the app's security model, and its command-line export. For developers who build the desktop app, script exports, or debug a problem that only appears on the desktop.

Facts about drawio-desktop below refer to its latest release (v31.7.0 at the time of writing). Check the repository for later changes.

How the desktop app uses this repository

  • Submodule. drawio-desktop includes this repository as the git submodule drawio (.gitmodules: path drawio, branch dev). Clone with git clone --recursive https://github.com/jgraph/drawio-desktop.git, then npm install and npm start. The app version is taken from drawio/VERSION by npm run sync (sync.cjs), so a desktop release carries the number of the draw.io release it was built from. Not every draw.io release gets a desktop release, so the latest desktop version can be behind app.diagrams.net.
  • No separate desktop bundle. The main process (src/main/electron.js) loads drawio/src/main/webapp/index.html from disk (file://). It passes URL parameters that switch off all cloud storage and select device mode: gapi=0, db=0, od=0, gh=0, gl=0, tr=0, browser=0, picker=0, mode=device. bootstrap.js recognises Electron and loads, in order:
    1. js/PreConfig.js
    2. js/app.min.js
    3. js/diagramly/DesktopLibrary.js and js/diagramly/ElectronApp.js (not minified)
    4. js/extensions.min.js
    5. js/stencils.min.js and js/shapes-14-6-5.min.js
    6. js/plantuml/drawio-plantuml.min.js
    7. js/PostConfig.js
  • Headless pages. Exports and the command line render through export3.html in a hidden window. Visio input on the command line goes through vsdxImporter.html. See Import and export.

To test a change to this repository in the desktop app, rebuild the bundles here (Building) and run npm start in drawio-desktop with the submodule pointing at your checkout. The drawio-desktop README notes that if you use a symlink instead of the submodule, you must also symlink node_modules inside drawio/src/main/webapp.

Desktop code in this repository

File Contents
js/diagramly/ElectronApp.js Overrides that replace browser behaviour with calls to the main process (window.electron.request). It is only loaded in Electron.
js/diagramly/DesktopLibrary.js DesktopLibrary extends LocalLibrary for library files on disk. Its hash is 'S' + encodeURIComponent(path).

What ElectronApp.js changes, by area:

  • Start-up: App.main replaces the page's Content-Security-Policy with a stricter one and sets urlParams['plugins'] = '0'. App.prototype.load and loadArgs open files passed on the command line or through file associations. App.mode is App.MODE_DEVICE, DRAWIO_BASE_URL and DRAWIO_SERVER_URL are '.' so that nothing is loaded from the online site, and mxStencilRegistry.allowEval is false.
  • Files: LocalFile.prototype.saveFile, isConflict (compares fs.stat().mtimeMs), getLatestVersion, synchronizeFile and saveDraft work on real paths. App.prototype.saveFile and pickFile use native dialogs. Recent files are listed under File > Open Recent. Drafts and backups are written next to the file, as hidden .$<name>...dtmp and .$<name>.bkp files.
  • Export and print: EditorUi.prototype.createDownloadRequest sends export requests to the main process (mxElectronRequest), which renders export3.html and uses Electron's printToPDF or capturePage. PDF export therefore works without an export service and without the browser's print dialog.
  • Menus and settings: desktop-only menu entries, and toggles for automatic updates, spell checking, Google Fonts and backup files.
  • No external data: App.prototype.isExternalDataComms returns false.

Code shared with the web app checks two globals:

  • mxIsElectron (bootstrap.js) tests the user agent, before the app is loaded.
  • EditorUi.isElectronApp (diagramly/EditorUi.js) is true when window.process.versions.electron is set. The desktop preload script exposes process.versions for this.

Search for EditorUi.isElectronApp to see what differs on the desktop: cloud storage, sharing and the Microsoft 365 client are hidden, autosave is off by default (Settings.js), and PDF export is local.

Security model

The drawio-desktop README states the design goal: the app is isolated from the Internet apart from the update check, no diagram data or analytics are sent out, and the Content-Security-Policy forbids remotely loaded JavaScript. Requests to enable external connections by default are declined. Diagrams can still reference external images and fonts, which are fetched when the diagram is shown. How the code enforces this, in src/main/electron.js and src/main/electron-preload.js:

  • Isolation: every BrowserWindow uses contextIsolation: true, nodeIntegration: false, webviewTag: false and webSecurity: true.
  • Bridge: the preload script exposes only window.electron (request, sendMessage, registerMsgListener, listenOnce) and window.process (type, versions) through contextBridge. All file access goes through named actions on one IPC channel. validateSender rejects requests from frames that are not the app's own page. assertReadablePath and assertWritablePath limit file actions to paths the user chose.
  • Content-Security-Policy: set as a response header on every request: default-src 'self', script-src 'self' 'wasm-unsafe-eval', connect-src 'self' (plus Google Fonts only if the user enables them), object-src 'none', base-uri 'none'. File requests outside the app directory are blocked.
  • Navigation: will-navigate is always prevented, webviews cannot be attached, and new windows other than about:blank are opened externally. Only http(s), mailto, tel and callto URLs are allowed (openExternal).
  • Plugins: loading external plugin files was removed in 31.1.5 (jgraph/drawio-desktop#2499). The Plugins dialog only offers the built-in plugins in App.publicPlugin (App.js). See Plugins.

Published advisories for the desktop app are on its security page. See also Security.

Command-line interface

The executable doubles as a command-line exporter. The binary is drawio in the Linux packages, draw.io.exe on Windows and draw.io.app/Contents/MacOS/draw.io on macOS. --help prints the options defined in src/main/args.js:

Usage: drawio [options] [input file/folder]...
Option Description
-x, --export Export the input files or folders. Besides draw.io files, .vsdx, .csv and Mermaid (.mmd, .mermaid) inputs are accepted.
-f, --format <format> pdf (default), png, jpg, svg, xml or html. Ignored if --output has one of these extensions.
-o, --output <file/folder> Output file, or an existing folder. Default: next to the input, with the format as extension.
-r, --recursive For folder inputs, include sub-folders
-k, --check Do not overwrite existing files; append -1, -2, ... instead
-a, --all-pages Export all pages (PDF and HTML)
-p, --page-index <n> Export page n, 1-based. Images export the first page by default.
-g, --page-range <from>..<to> Page range, 1-based (PDF only)
-l, --layers <i,j,...> Layer indexes to export (all pages)
-s, --scale <scale> Scale the diagram
--width <px>, --height <px> Fit into this width or height, keeping the aspect ratio
-b, --border <px> Border around the diagram (default 0)
--crop Crop PDF pages to the diagram
--size <diagram|page> PNG, JPEG and SVG: crop to the diagram (default) or export whole pages
-t, --transparent Transparent background (PNG, SVG)
-e, --embed-diagram Include a copy of the diagram (PNG, SVG, PDF)
--embed-svg-images Embed images in SVG
--embed-svg-fonts <true|false> Embed fonts in SVG (default true)
-u, --uncompressed Uncompressed XML (XML and SVG)
-q, --quality <n> JPEG quality (default 90)
--theme <dark|light|auto> Theme of the exported SVG, PNG, JPEG or PDF. --svg-theme is deprecated.
--svg-links-target <auto|new-win|same-win> Link target in SVG
--html-theme, --html-zoom, --html-lightbox, --html-layers, --html-tags, --html-fit, --html-link-target, --html-link-color, --html-edit-link Options of the HTML viewer for -f html
--layout <name|json> Run a layout before export: verticalFlow, horizontalFlow, verticalTree, horizontalTree, radialTree, organic, or a JSON array as in the Layout dialog, see JSON layout specification
--normalize Repair the model before layout and export, for example for generated diagrams
--mermaid-image <true|false> Open Mermaid input as an image instead of editable shapes
--timeout <seconds> Fail a file that takes longer and continue with the next (default 0, no limit)
-z, --zoom <zoom> Scale the user interface
-c, --create Create a new empty file if no file is given (opens the editor)
--disable-update, --no-silent-update Disable update checks, or ask before downloading updates
-V, --version, -h, --help Version, help

How exports behave:

  • Output path: without -o, each output is written next to its input as <name>.<format>. If -o is an existing folder, all outputs go into it flat, so files with the same name in different sub-folders overwrite each other unless you use -k. Any other -o is treated as a file name, and several inputs into one file are rejected.
  • Folder input: a folder input picks up .drawio, .dio, .xml, .csv, .vsdx, .mmd, .mermaid, .png, .svg and .pdf files. PNG, SVG and PDF files without an embedded diagram are skipped, and symbolic links are not followed.
  • Results: each export prints input -> output. The exit code is 1 if any file failed; the batch continues after a failure.
  • Options with a value: give the value as a separate argument (-f png) or with = (--format=png). Do not combine it with a short flag group, as in -xf png.

Examples:

# PNG of the first page, format taken from the output extension
drawio -x -o diagram.png diagram.drawio

# All pages into one PDF, pages cropped to the diagram
drawio -x -f pdf -a --crop -o handbook.pdf handbook.drawio

# Every diagram under docs/ to SVG with embedded images, into an existing folder
mkdir -p exported && drawio -x -r -f svg --embed-svg-images -o exported docs

# Page 2 at twice the size, transparent, 10px border, with the diagram embedded
drawio -x -f png -p 2 -s 2 -t -b 10 -e diagram.drawio

Updates and offline use

The desktop app needs no network connection. Its only outgoing connection by default is the update check. electron-updater checks GitHub Releases of jgraph/drawio-desktop at start-up and downloads updates from there. To turn the check off for managed installs, do one of:

  • set the environment variable DRAWIO_DISABLE_UPDATE=true;
  • pass --disable-update;
  • build with npm run sync -- disableUpdate.

DRAWIO_NO_SILENT_UPDATE=true or --no-silent-update makes the app ask before downloading. The Microsoft Store build is built with updates disabled, and Flatpak installs disable them at run time. Installers and packages for Windows, macOS and Linux are on the releases page. The README describes the Windows installer types.

To build an unsigned copy of a fork for your own use, see doc/BUILDING_FOR_PERSONAL_USE.md in drawio-desktop.

Reporting desktop issues

Report problems that only occur in the desktop app (installation, file handling, the command line, updates, native menus) in jgraph/drawio-desktop issues, and ask questions in its discussions. Editor problems that also occur on app.diagrams.net belong in this repository, see Getting support. Include the version (the last entry of the Help menu) and your operating system. drawio-desktop is closed to contributions.

See also

Clone this wiki locally