Cody’s renderer windows are fully sandboxed (Documentation Index
Fetch the complete documentation index at: https://mintlify.com/miu-ll/Cody-assistant/llms.txt
Use this file to discover all available pages before exploring further.
sandbox: true, contextIsolation: true, nodeIntegration: false) and cannot access Node.js APIs directly. All communication between the renderer and the Electron main process therefore flows through two classes of IPC channel:
- Invoke channels — the renderer calls
ipcRenderer.invoke(channel, ...args)and awaits a response from the main process. These are two-way request/response calls exposed to renderer code viawindow.desktop.*methods. - Event channels — the main process calls
webContents.send(channel, payload)to push a one-way notification to a renderer. These are received viaipcRenderer.onand are surfaced as subscription callbacks bywindow.desktop.on*()methods.
Renderer code should never call
ipcRenderer directly. Use the
window.desktop bridge documented in the
Desktop API reference. The channel names
listed here are for architectural documentation and debugging purposes.Security Model
Before processing any invoke, every IPC handler inelectron/main/index.ts calls the isTrustedSender guard:
BrowserWindow instances (the assistant panel and the pet widget) can invoke these channels. Requests from any other origin return false, null, or an empty string without performing any work.
Input sanitization
All free-text inputs pass throughcleanText(value, maxLength) before use:
safeFileName(), which removes path-traversal characters (<>:"/\|?* and control chars) and caps the result at 120 characters.
Invoke Channels (renderer → main)
The following channels are registered withipcMain.handle and are accessible to the renderer via ipcRenderer.invoke.
| Channel | Payload | Returns | Notes |
|---|---|---|---|
load-data | none | AppState | null | Reads cody-data.json; falls back to cody-data.backup.json on read failure |
save-data | AppState | boolean | Atomic write via .tmp rename; throws if serialized JSON exceeds 5 MB |
schedule-reminder | Reminder | boolean | Payload normalized via normalizeReminder(); returns false for past or invalid timestamps |
cancel-reminder | string (id) | boolean | Clears the setTimeout for the given id; always returns true for trusted senders |
show-notification | title: string, body: string | boolean | Text sanitized to 180 chars; returns false if Notification.isSupported() is false |
open-external | string (url) | boolean | https:// prefix enforced; all other schemes blocked |
open-assistant | none | boolean | Shows and focuses the assistant BrowserWindow; creates it if needed |
show-pet | none | boolean | Hides the assistant window and shows the pet widget |
window-minimize | none | boolean | Minimizes the assistant window; triggers transition to pet view |
window-toggle-maximize | none | boolean | Maximizes or unmaximizes the assistant window; returns false if window not present |
window-close | none | boolean | Closes the assistant window (intercepted → transitions to pet view) |
show-pet-menu | none | boolean | Displays the native context menu anchored to the pet window |
start-pet-drag | none | boolean | Pet window only; records cursor start position and begins 16 ms polling interval |
move-pet-drag | none | boolean | Pet window only; moves the window to follow the cursor |
end-pet-drag | none | boolean | Pet window only; stops polling, clamps pet to work area; returns whether the pet actually moved |
outlook-classic-sync | { ai?: AiConfig } | OutlookSyncResult | Dynamically imports ./outlook and runs COM sync; throws on unauthorized sender |
export-file | defaultName: string, content: string | string | null | Opens Save dialog; returns absolute file path or null on cancel; content capped at 10 MB |
export-diagnostics | none | string | null | Builds diagnostics report (no sensitive data); opens Save dialog |
get-app-version | none | string | Returns app.getVersion(); empty string on untrusted sender |
set-launch-at-login | boolean | boolean | Calls app.setLoginItemSettings; returns false in unpackaged builds |
set-focus | mode: FocusMode | null, minutes: number | boolean | null mode deactivates focus; minutes clamped to 1–480 |
get-focus | none | FocusState | null | Returns serialized focusState with until as ISO string, or null |
pet-update | PetUpdate | boolean | Assistant window only; forwards payload to pet window via webContents.send |
Channel detail notes
load-data — backup fallback
load-data — backup fallback
The primary file is
cody-data.json in Electron’s userData directory.
If that file cannot be read (e.g. it is corrupt JSON or has been deleted),
the handler attempts to read cody-data.backup.json. A backup is taken
at most once per calendar day, just before each successful save-data
write. The backup always represents the previous day’s last save.save-data — atomic write and size limit
save-data — atomic write and size limit
Data is written to The renderer must catch this error and surface a user-facing message.
cody-data.json.tmp first, then atomically renamed to
cody-data.json. This prevents a partial write from corrupting the primary
data file. If the serialized payload would exceed 5 MB (UTF-8 bytes), the
handler throws:schedule-reminder — normalization and suppression
schedule-reminder — normalization and suppression
Payloads are run through
normalizeReminder() which:- Casts all fields to strings via
cleanText() - Parses
atas aDate— returnsnullif invalid - Strips
urlvalues that do not start withhttps://
focusState.mode === 'dnd'— all reminders suppressedfocusState.mode === 'focus'andreminder.iddoes not start with'meeting-'— suppressedfocusState.mode === 'focus'andreminder.idstarts with'meeting-'— delivered
2_147_000_000 ms ≈ 24.8 days) are
rescheduled recursively to work around the setTimeout integer limit.outlook-classic-sync — deferred import
outlook-classic-sync — deferred import
The Outlook sync implementation is dynamically imported at invocation time:This keeps the COM/PowerShell code out of the main-process startup bundle
and avoids import-time errors on machines without Outlook installed.
set-launch-at-login — packaged builds only
set-launch-at-login — packaged builds only
In development, The startup entry points to the installed executable. The renderer should
keep
app.isPackaged is false, so this handler always returns
false. In production, it calls:AppSettings.launchAtLogin in sync by reading the returned value.Event Channels (main → renderer)
The following channels are emitted by the main process viawebContents.send. They are surfaced to renderer code as callback subscriptions via window.desktop.on*().
| Channel | Payload | Target window | When fired |
|---|---|---|---|
shortcut | string (action) | Assistant window | A registered global hotkey fires an action targeted at the renderer |
focus-changed | FocusState | null | Assistant window | Focus mode is activated, deactivated (manually or via timer expiry) |
pet-update | PetUpdate | Pet window | The assistant window calls window.desktop.petUpdate() |
Event channel detail
shortcut — global hotkey actions
shortcut — global hotkey actions
The main process registers four global shortcuts via
Only
globalShortcut.register:| Accelerator | Action sent | Effect |
|---|---|---|
Win+Shift+C | (no IPC) | Toggles between assistant and pet view |
Win+Shift+T | 'new-task' | Opens assistant and triggers quick-add task |
Win+Shift+S | 'sync' | Triggers an Outlook sync |
Win+Shift+F | (no IPC) | Toggles Focus 25 min on/off |
Win+Shift+T and Win+Shift+S emit a shortcut event; the other
two are handled entirely in the main process.Subscribe via:focus-changed — state broadcast
focus-changed — state broadcast
Emitted by the or
broadcastFocus() helper, which is called whenever focus
state changes. The payload is either a FocusState object:null when the focus session ends. Subscribe via:pet-update — assistant to pet forwarding
pet-update — assistant to pet forwarding
The
pet-update IPC channel is used in two directions:-
Invoke (assistant → main → pet): The assistant renderer calls
window.desktop.petUpdate(payload), which invokes thepet-updatechannel. The main-process handler forwards the payload to the pet window viapetWindow.webContents.send('pet-update', payload). -
Event (main → pet renderer): The pet renderer receives the
forwarded payload via
window.desktop.onPetUpdate(callback).
pet-update name appears in both the invoke
table and the event table but represents a single logical message flow:
assistant renderer → main process → pet renderer.Registered Global Shortcuts Reference
These shortcuts are registered at startup viaglobalShortcut.register and unregistered when the app quits (will-quit). If another application has already claimed a shortcut, Cody logs a warning and the shortcut is silently unavailable.
| Accelerator | Behaviour |
|---|---|
Win+Shift+C | Focuses the assistant window if it is visible and focused; otherwise shows the assistant |
Win+Shift+T | Shows the assistant and sends shortcut: 'new-task' to the renderer |
Win+Shift+S | Sends shortcut: 'sync' to the renderer (does not change window focus) |
Win+Shift+F | Starts a 25-minute focus session, or ends the current session if one is active |
Constants Reference
The following numeric constants are defined inelectron/main/index.ts and govern IPC validation limits.
| Constant | Value | Applies to |
|---|---|---|
MAX_DATA_BYTES | 5 * 1024 * 1024 (5 MB) | save-data payload size limit |
MAX_EXPORT_BYTES | 10 * 1024 * 1024 (10 MB) | export-file content size limit |
MAX_REMINDER_TEXT | 240 characters | Reminder title and body fields |
MAX_NOTIFICATION_TEXT | 180 characters | Ad-hoc notification title and body fields |
MAX_TIMEOUT | 2_147_000_000 ms | Maximum setTimeout duration before recursive rescheduling |