Skip to main content

Overview

SuperCmd is built on Electron, leveraging a multi-process architecture that separates system operations (main process) from UI rendering (renderer process). This design provides security, stability, and native OS integration.
The main process code lives in src/main/, while renderer code is in src/renderer/. The two processes communicate via IPC (Inter-Process Communication) through a secure preload script.

Process Architecture

Main Process

The main process (src/main/main.ts) handles:

Window Management

Creating, showing, hiding, and positioning windows with native glass effects

System Integration

Global shortcuts, menu bar, system tray, and macOS-specific features

File System

All file I/O operations, including extension installation and script execution

Native Modules

Swift binaries for speech recognition, window management, and input monitoring

Initialization Flow

app.whenReady().then(async () => {
  // 1. Initialize stores
  initSnippetStore();
  initQuickLinkStore();
  
  // 2. Start background services
  startClipboardMonitor();
  startFileSearchIndexing();
  
  // 3. Register global shortcuts
  const settings = loadSettings();
  registerGlobalShortcut(settings.hotkey || 'Command+Space');
  
  // 4. Create launcher window
  mainWindow = createLauncherWindow();
  
  // 5. Start window manager worker
  ensureWindowManagerWorker();
});

Renderer Process

The renderer process (src/renderer/src/) is a React application that:
  • Renders the launcher UI and extension views
  • Manages application state with React hooks
  • Communicates with main process via IPC
  • Executes extension code in isolated contexts

Application Structure

// src/renderer/src/App.tsx
function App() {
  // State management hooks
  const viewManager = useAppViewManager();
  const aiChat = useAiChat();
  const menuBarExtensions = useMenuBarExtensions();
  
  // Route to appropriate view
  if (viewManager.currentView === 'extension') {
    return <ExtensionView {...viewManager.extensionProps} />;
  }
  
  if (viewManager.currentView === 'ai-chat') {
    return <AiChatView {...aiChat} />;
  }
  
  // ... other views
}

Preload Script

The preload script (src/main/preload.ts) creates a secure IPC bridge:
// Expose safe APIs to renderer
contextBridge.exposeInMainWorld('electron', {
  // Window management
  hideWindow: () => ipcRenderer.invoke('hideWindow'),
  showWindow: () => ipcRenderer.invoke('showWindow'),
  
  // Extension operations
  getExtensionBundle: (extName, cmdName) => 
    ipcRenderer.invoke('getExtensionBundle', extName, cmdName),
  
  // AI operations
  aiAsk: (prompt, options) => 
    ipcRenderer.invoke('aiAsk', prompt, options),
  
  // Listeners
  onAIStreamChunk: (callback) => {
    ipcRenderer.on('ai-stream-chunk', (_, data) => callback(data));
  },
});

Window Management

Launcher Window

The main launcher window uses native glass effects on macOS:
function createLauncherWindow(): BrowserWindow {
  const { width, height } = screen.getPrimaryDisplay().workAreaSize;
  
  const win = new BrowserWindow({
    width: DEFAULT_WINDOW_WIDTH,
    height: DEFAULT_WINDOW_HEIGHT,
    x: Math.floor((width - DEFAULT_WINDOW_WIDTH) / 2),
    y: Math.floor(height * 0.2),
    frame: false,
    transparent: true,
    backgroundColor: '#00000000',
    skipTaskbar: true,
    alwaysOnTop: true,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false,
      contextIsolation: true,
    },
  });
  
  // Apply native glass effects
  applyLiquidGlassToWindow(win);
  
  return win;
}

Detached Windows

SuperCmd supports detached popup windows for features like Whisper (dictation) and Speak (TTS):
const DETACHED_WHISPER_WINDOW_NAME = 'supercmd-whisper-window';
const DETACHED_SPEAK_WINDOW_NAME = 'supercmd-speak-window';

// Renderer requests a popup via window.open()
const whisperWin = window.open(
  `/whisper?sc_detached=${DETACHED_WHISPER_WINDOW_NAME}`,
  DETACHED_WHISPER_WINDOW_NAME,
  'width=266,height=84'
);

// Main process intercepts and creates BrowserWindow
mainWindow.webContents.setWindowOpenHandler((details) => {
  const popupName = resolveDetachedPopupName(details);
  
  if (popupName === DETACHED_WHISPER_WINDOW_NAME) {
    const features = parsePopupFeatures(details.features);
    const position = computeDetachedPopupPosition(
      popupName,
      features.width,
      features.height
    );
    
    return {
      action: 'allow',
      overrideBrowserWindowOptions: {
        ...features,
        ...position,
        frame: false,
        transparent: true,
        alwaysOnTop: true,
        skipTaskbar: true,
      },
    };
  }
  
  return { action: 'deny' };
});

IPC Communication

Request/Response Pattern

Most IPC follows a simple request/response pattern:
// Call from renderer
const bundle = await window.electron.getExtensionBundle(
  'my-extension',
  'search'
);

console.log(bundle.code); // Bundled JavaScript

Event Streaming

For long-running operations like AI streaming, SuperCmd uses event-based communication:
// Subscribe to stream chunks
window.electron.onAIStreamChunk((data) => {
  if (data.requestId === myRequestId) {
    console.log(data.chunk);
  }
});

window.electron.onAIStreamDone((data) => {
  if (data.requestId === myRequestId) {
    console.log('Stream complete');
  }
});

// Start request
await window.electron.aiAsk('Write a story', { requestId: myRequestId });

Global Shortcuts

SuperCmd registers global keyboard shortcuts using Electron’s globalShortcut API:
function registerGlobalShortcut(accelerator: string): boolean {
  // Unregister previous shortcut
  if (currentShortcut) {
    globalShortcut.unregister(currentShortcut);
  }
  
  // Register new shortcut
  const success = globalShortcut.register(accelerator, () => {
    if (isVisible) {
      hideLauncher();
    } else {
      showLauncher();
    }
  });
  
  if (success) {
    currentShortcut = accelerator;
    globalShortcutRegistrationState = {
      requestedShortcut: accelerator,
      activeShortcut: accelerator,
      ok: true,
    };
  } else {
    globalShortcutRegistrationState = {
      requestedShortcut: accelerator,
      activeShortcut: '',
      ok: false,
    };
  }
  
  return success;
}

Per-Command Hotkeys

Individual commands can register their own shortcuts:
const registeredHotkeys = new Map<string, string>(); // shortcut → commandId

ipcMain.handle('registerCommandHotkey', (event, commandId, accelerator) => {
  // Unregister if already bound
  for (const [shortcut, cmdId] of registeredHotkeys.entries()) {
    if (cmdId === commandId) {
      globalShortcut.unregister(shortcut);
      registeredHotkeys.delete(shortcut);
    }
  }
  
  // Register new shortcut
  const success = globalShortcut.register(accelerator, async () => {
    // Execute command directly
    await executeCommand(commandId);
  });
  
  if (success) {
    registeredHotkeys.set(accelerator, commandId);
  }
  
  return success;
});

Window Manager Worker

For advanced window management, SuperCmd uses a forked Node.js worker process:

Worker Architecture

// Main process spawns worker
const windowManagerWorker = fork(
  path.join(__dirname, 'window-manager-worker.js'),
  [],
  { stdio: ['ignore', 'ignore', 'ignore', 'ipc'] }
);

// Send requests via IPC
function callWindowManagerWorker<T>(
  method: string,
  payload?: any
): Promise<T> {
  const id = ++requestSeq;
  
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      reject(new Error('Worker request timeout'));
    }, 1400);
    
    pending.set(id, { resolve, reject, timer });
    
    windowManagerWorker.send({ id, method, payload });
  });
}

// Receive responses
windowManagerWorker.on('message', (response) => {
  const pending = pendingRequests.get(response.id);
  if (!pending) return;
  
  clearTimeout(pending.timer);
  
  if (response.ok) {
    pending.resolve(response.result);
  } else {
    pending.reject(new Error(response.error));
  }
});

Worker Operations

const windows = await callWindowManagerWorker<WindowInfo[]>('list-windows');

console.log(windows);
// [
//   { id: 123, title: 'Safari', path: '/Applications/Safari.app', ... },
//   { id: 124, title: 'Terminal', path: '/System/Applications/Terminal.app', ... }
// ]
const active = await callWindowManagerWorker<WindowInfo>('get-active-window');

console.log(active.title); // 'Visual Studio Code'
await callWindowManagerWorker('set-window-bounds', {
  id: '123',
  x: 0,
  y: 0,
  width: 1920,
  height: 1080,
});

Native Protocol

SuperCmd registers a custom sc-asset:// protocol for loading extension assets:
protocol.registerFileProtocol('sc-asset', (request, callback) => {
  const url = request.url.replace('sc-asset://', '');
  const [extName, ...pathParts] = url.split('/');
  const assetPath = pathParts.join('/');
  
  const extPath = resolveInstalledExtensionPath(extName);
  if (!extPath) {
    return callback({ error: -6 }); // FILE_NOT_FOUND
  }
  
  const fullPath = path.join(extPath, 'assets', assetPath);
  
  if (!fs.existsSync(fullPath)) {
    return callback({ error: -6 });
  }
  
  callback({ path: fullPath });
});
Extensions reference assets like:
<Image source="sc-asset://my-extension/logo.png" />

Settings Management

Settings are persisted as JSON and cached in memory:
let cachedSettings: AppSettings | null = null;

export function loadSettings(): AppSettings {
  if (cachedSettings) return cachedSettings;
  
  const settingsPath = path.join(
    app.getPath('userData'),
    'settings.json'
  );
  
  if (!fs.existsSync(settingsPath)) {
    cachedSettings = getDefaultSettings();
    saveSettings(cachedSettings);
    return cachedSettings;
  }
  
  try {
    const raw = fs.readFileSync(settingsPath, 'utf-8');
    cachedSettings = JSON.parse(raw);
    return cachedSettings;
  } catch (error) {
    console.error('Failed to load settings:', error);
    return getDefaultSettings();
  }
}

export function saveSettings(partial: Partial<AppSettings>): void {
  const current = loadSettings();
  const updated = { ...current, ...partial };
  
  const settingsPath = path.join(
    app.getPath('userData'),
    'settings.json'
  );
  
  fs.writeFileSync(settingsPath, JSON.stringify(updated, null, 2));
  cachedSettings = updated;
  
  // Notify renderer
  if (mainWindow && !mainWindow.isDestroyed()) {
    mainWindow.webContents.send('settings-updated', updated);
  }
}

Performance Optimizations

Window Pooling

Reuse hidden windows instead of creating new ones for better performance

IPC Batching

Group related IPC calls to reduce round-trips

Worker Processes

Offload expensive operations to separate processes

Lazy Loading

Load extension code only when needed

Blur-Hide Debouncing

To prevent accidental hiding during file dialogs:
let suppressBlurHide = false;

mainWindow.on('blur', () => {
  if (suppressBlurHide) return;
  if (oauthBlurHideSuppressionDepth > 0) return;
  
  // Hide after a small delay
  setTimeout(() => {
    if (!mainWindow.isFocused() && !suppressBlurHide) {
      hideLauncher();
    }
  }, 100);
});

// Temporarily suppress blur-hide
ipcMain.on('openFilePicker', () => {
  suppressBlurHide = true;
  dialog.showOpenDialog({ /* ... */ }).then(() => {
    suppressBlurHide = false;
  });
});

See Also

Extension Runtime

How extensions are bundled and executed

Raycast API

Complete API compatibility reference

Native Modules

Swift integration for macOS features

Build docs developers (and LLMs) love