How to Export Data from PI Desktop: Complete Guide to Workspace Backup

PI Desktop exports your workspace to a prettified JSON file via an IPC call from the renderer to the main Electron process, writing the serialized state to a user-selected path using Node.js file system APIs.

PI Desktop is an Electron-based application that stores your projects, notes, plugins, and configuration in a JSON-based workspace model. When you need to backup or migrate your data, the application provides both UI-driven and programmatic methods to export data from PI Desktop using internal IPC handlers and native file dialogs.

Understanding the Export Architecture

PI Desktop uses a standard Electron architecture split between the main process and renderer process. The workspace state lives in the main process memory, managed by functions defined in packages/shared/src/protocol.ts.

When you initiate an export, the renderer process sends an IPC message (export-data) to the main process. The handler in apps/desktop/electron/main/user-mcp.ts retrieves the current workspace object, serializes it to formatted JSON, and writes it to disk using Node.js fs APIs.

Exporting via the User Interface

The UI export flow begins when you select File → Export from the application menu. The renderer process opens a native save dialog and invokes the export-data channel.

// apps/desktop/electron/shared/plugin-panel-chrome.ts
async function exportWorkspace() {
  const { filePath } = await window.electron.showSaveDialog({
    title: 'Export PI Desktop Data',
    defaultPath: 'pi-workspace.json',
    filters: [{ name: 'JSON', extensions: ['json'] }]
  });
  if (filePath) {
    await window.electron.invoke('export-data', filePath);
    window.showToast('Workspace exported successfully');
  }
}

This code uses window.electron.showSaveDialog to prompt for a destination, then calls window.electron.invoke('export-data', filePath) to trigger the main process handler. The filters array restricts the output to .json files.

Main Process Export Handler

The actual serialization and file writing occur in the main process. The ipcMain.handle listener in apps/desktop/electron/main/user-mcp.ts receives the file path, retrieves the current workspace state, and writes the JSON payload.

// apps/desktop/electron/main/user-mcp.ts
import { ipcMain } from 'electron';
import { getWorkspace } from '../../packages/shared/src/protocol';
import { promises as fs } from 'fs';

ipcMain.handle('export-data', async (_event, filePath: string) => {
  const workspace = getWorkspace();                 // ← retrieves current state
  const data = JSON.stringify(workspace, null, 2); // ← serialises to JSON
  await fs.writeFile(filePath, data, 'utf‑8');      // ← writes to chosen file
  return true;
});

The getWorkspace() function fetches the in-memory workspace object from the shared protocol layer. JSON.stringify(workspace, null, 2) produces human-readable output with 2-space indentation. The handler uses fs.promises.writeFile for asynchronous, non-blocking I/O.

Command-Line and Automated Exports

For headless environments, CI pipelines, or Linux distribution packaging, PI Desktop provides scripts/export-linux-asar.mjs. This script programmatically exports the workspace before building an ASAR archive.

// scripts/export-linux-asar.mjs
import { build } from 'electron-builder';
import { exportWorkspace } from '../apps/desktop/electron/main/user-mcp.js';

async function main() {
  // Ensure the latest workspace is persisted
  await exportWorkspace('/tmp/pi-workspace.json');

  // Build ASAR package for Linux
  await build({
    config: {
      appId: 'com.vastsa.pidesktop',
      linux: { target: 'AppImage' },
      directories: { output: 'dist/linux' },
    },
  });
}
main().catch(console.error);

This approach imports the exportWorkspace function directly from the main process module, allowing you to export data from PI Desktop without launching the full GUI. The script first writes the workspace to /tmp/pi-workspace.json, then packages the application using electron-builder.

Data Structure and File Format

The exported file is a UTF-8 encoded JSON document containing the complete workspace state. According to the protocol definitions in packages/shared/src/protocol.ts, the payload includes:

  • Projects – Your organized project hierarchies
  • Notes – All user-created notes and documents
  • Plugins – Installed plugin configurations and state
  • Settings – Application preferences and UI state

The output uses prettified JSON (null, 2 spacing), making the file human-readable and suitable for version control systems like Git.

Summary

Frequently Asked Questions

Where is the export data format defined in PI Desktop?

The data structures for the workspace, including projects, notes, and plugins, are defined in packages/shared/src/protocol.ts. This shared package ensures consistency between the main process, renderer process, and any CLI scripts that import the workspace types.

Can I export PI Desktop data without opening the GUI?

Yes. You can import the exportWorkspace function from apps/desktop/electron/main/user-mcp.js (or .ts when transpiled) into a Node.js script, as demonstrated in scripts/export-linux-asar.mjs. This allows you to programmatically export the workspace state for backup or migration without launching the Electron window.

What data is included in the exported JSON file?

The export contains the complete workspace object retrieved by getWorkspace(), which includes all user projects, notes, plugin configurations, and application settings. The JSON is serialized with JSON.stringify(workspace, null, 2) to preserve readability and structure.

How does PI Desktop validate the export file path?

The application relies on Electron's native showSaveDialog to validate the destination path in UI mode, which returns a validated absolute path or undefined if the user cancels. In programmatic exports, the script passes the path directly to fs.promises.writeFile, and errors are caught via standard Node.js exception handling.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →