Repository navigation
Desktop App
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.
-
Submodule. drawio-desktop includes this repository as the git submodule
drawio(.gitmodules: pathdrawio, branchdev). Clone withgit clone --recursive https://github.com/jgraph/drawio-desktop.git, thennpm installandnpm start. The app version is taken fromdrawio/VERSIONbynpm 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.htmlfrom 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:js/PreConfig.jsjs/app.min.js-
js/diagramly/DesktopLibrary.jsandjs/diagramly/ElectronApp.js(not minified) js/extensions.min.js-
js/stencils.min.jsandjs/shapes-14-6-5.min.js js/plantuml/drawio-plantuml.min.jsjs/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.
| 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.mainreplaces the page's Content-Security-Policy with a stricter one and setsurlParams['plugins'] = '0'.App.prototype.loadandloadArgsopen files passed on the command line or through file associations.App.modeisApp.MODE_DEVICE,DRAWIO_BASE_URLandDRAWIO_SERVER_URLare'.'so that nothing is loaded from the online site, andmxStencilRegistry.allowEvalisfalse. -
Files:
LocalFile.prototype.saveFile,isConflict(comparesfs.stat().mtimeMs),getLatestVersion,synchronizeFileandsaveDraftwork on real paths.App.prototype.saveFileandpickFileuse native dialogs. Recent files are listed under File > Open Recent. Drafts and backups are written next to the file, as hidden.$<name>...dtmpand.$<name>.bkpfiles. -
Export and print:
EditorUi.prototype.createDownloadRequestsends export requests to the main process (mxElectronRequest), which rendersexport3.htmland uses Electron'sprintToPDForcapturePage. 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.isExternalDataCommsreturnsfalse.
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 whenwindow.process.versions.electronis set. The desktop preload script exposesprocess.versionsfor 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.
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
BrowserWindowusescontextIsolation: true,nodeIntegration: false,webviewTag: falseandwebSecurity: true. -
Bridge: the preload script exposes only
window.electron(request,sendMessage,registerMsgListener,listenOnce) andwindow.process(type,versions) throughcontextBridge. All file access goes through named actions on one IPC channel.validateSenderrejects requests from frames that are not the app's own page.assertReadablePathandassertWritablePathlimit 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-navigateis always prevented, webviews cannot be attached, and new windows other thanabout:blankare opened externally. Onlyhttp(s),mailto,telandcalltoURLs 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.
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-ois 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-ois 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,.svgand.pdffiles. 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.drawioThe 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.
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.
- Import and export
-
Storage backends:
LocalFileand the other file classes - Building
- Plugins
- Security
- Related repositories
Describes the dev branch of jgraph/drawio as of release 32.3.0 (October 2026). Internal JavaScript APIs change between releases; check the code of the version you use. · Questions: Discussions · Bugs: Issues · Vulnerabilities: report privately · User docs: drawio.com/docs
Get started
Concepts
Guides
- Self-hosting
- Configuration
- Storage backends
- OneDrive app registration
- Embedding
- Diagrams in GitHub
- Plugins
- Extending the editor
- Shapes and stencils
- Import and export
- Desktop app
- Internationalization
Reference
Project
Elsewhere