Skip to main content

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.

Cody’s renderer windows are fully sandboxed (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 via window.desktop.* methods.
  • Event channels — the main process calls webContents.send(channel, payload) to push a one-way notification to a renderer. These are received via ipcRenderer.on and are surfaced as subscription callbacks by window.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 in electron/main/index.ts calls the isTrustedSender guard:
function isTrustedSender(event: Electron.IpcMainInvokeEvent): boolean {
  return (
    event.sender === assistantWindow?.webContents ||
    event.sender === petWindow?.webContents
  )
}
Only the two Cody-owned 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.
Several channels have additional sender restrictions beyond the generic trusted-sender check. pet-update only accepts calls from the assistant window. start-pet-drag, move-pet-drag, and end-pet-drag only accept calls from the pet window. Violations return false silently.

Input sanitization

All free-text inputs pass through cleanText(value, maxLength) before use:
const cleanText = (value: unknown, maxLength: number): string =>
  String(value ?? '')
    .replace(/[\u0000-\u001f\u007f]/g, ' ')  // strip control characters
    .replace(/\s+/g, ' ')                     // collapse whitespace
    .trim()
    .slice(0, maxLength)
Export filenames are additionally passed through 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 with ipcMain.handle and are accessible to the renderer via ipcRenderer.invoke.
ChannelPayloadReturnsNotes
load-datanoneAppState | nullReads cody-data.json; falls back to cody-data.backup.json on read failure
save-dataAppStatebooleanAtomic write via .tmp rename; throws if serialized JSON exceeds 5 MB
schedule-reminderReminderbooleanPayload normalized via normalizeReminder(); returns false for past or invalid timestamps
cancel-reminderstring (id)booleanClears the setTimeout for the given id; always returns true for trusted senders
show-notificationtitle: string, body: stringbooleanText sanitized to 180 chars; returns false if Notification.isSupported() is false
open-externalstring (url)booleanhttps:// prefix enforced; all other schemes blocked
open-assistantnonebooleanShows and focuses the assistant BrowserWindow; creates it if needed
show-petnonebooleanHides the assistant window and shows the pet widget
window-minimizenonebooleanMinimizes the assistant window; triggers transition to pet view
window-toggle-maximizenonebooleanMaximizes or unmaximizes the assistant window; returns false if window not present
window-closenonebooleanCloses the assistant window (intercepted → transitions to pet view)
show-pet-menunonebooleanDisplays the native context menu anchored to the pet window
start-pet-dragnonebooleanPet window only; records cursor start position and begins 16 ms polling interval
move-pet-dragnonebooleanPet window only; moves the window to follow the cursor
end-pet-dragnonebooleanPet window only; stops polling, clamps pet to work area; returns whether the pet actually moved
outlook-classic-sync{ ai?: AiConfig }OutlookSyncResultDynamically imports ./outlook and runs COM sync; throws on unauthorized sender
export-filedefaultName: string, content: stringstring | nullOpens Save dialog; returns absolute file path or null on cancel; content capped at 10 MB
export-diagnosticsnonestring | nullBuilds diagnostics report (no sensitive data); opens Save dialog
get-app-versionnonestringReturns app.getVersion(); empty string on untrusted sender
set-launch-at-loginbooleanbooleanCalls app.setLoginItemSettings; returns false in unpackaged builds
set-focusmode: FocusMode | null, minutes: numberbooleannull mode deactivates focus; minutes clamped to 1–480
get-focusnoneFocusState | nullReturns serialized focusState with until as ISO string, or null
pet-updatePetUpdatebooleanAssistant window only; forwards payload to pet window via webContents.send

Channel detail notes

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.
Data is written to 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:
Error: El archivo local de Cody excede el limite permitido.
The renderer must catch this error and surface a user-facing message.
Payloads are run through normalizeReminder() which:
  1. Casts all fields to strings via cleanText()
  2. Parses at as a Date — returns null if invalid
  3. Strips url values that do not start with https://
When a reminder fires during an active focus session:
  • focusState.mode === 'dnd' — all reminders suppressed
  • focusState.mode === 'focus' and reminder.id does not start with 'meeting-' — suppressed
  • focusState.mode === 'focus' and reminder.id starts with 'meeting-'delivered
Long-duration reminders (delay > 2_147_000_000 ms ≈ 24.8 days) are rescheduled recursively to work around the setTimeout integer limit.
The Outlook sync implementation is dynamically imported at invocation time:
const { syncOutlookClassic } = await import('./outlook')
return syncOutlookClassic(options)
This keeps the COM/PowerShell code out of the main-process startup bundle and avoids import-time errors on machines without Outlook installed.
In development, app.isPackaged is false, so this handler always returns false. In production, it calls:
app.setLoginItemSettings({ openAtLogin: enabled })
The startup entry points to the installed executable. The renderer should keep AppSettings.launchAtLogin in sync by reading the returned value.

Event Channels (main → renderer)

The following channels are emitted by the main process via webContents.send. They are surfaced to renderer code as callback subscriptions via window.desktop.on*().
ChannelPayloadTarget windowWhen fired
shortcutstring (action)Assistant windowA registered global hotkey fires an action targeted at the renderer
focus-changedFocusState | nullAssistant windowFocus mode is activated, deactivated (manually or via timer expiry)
pet-updatePetUpdatePet windowThe assistant window calls window.desktop.petUpdate()

Event channel detail

The main process registers four global shortcuts via globalShortcut.register:
AcceleratorAction sentEffect
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
Only Win+Shift+T and Win+Shift+S emit a shortcut event; the other two are handled entirely in the main process.Subscribe via:
const unsubscribe = window.desktop.onShortcut((action) => {
  if (action === 'new-task') openNewTaskDialog()
  if (action === 'sync') triggerSync()
})
Emitted by the broadcastFocus() helper, which is called whenever focus state changes. The payload is either a FocusState object:
{ mode: 'focus' | 'dnd', until: '2024-11-01T10:25:00.000Z' }
or null when the focus session ends. Subscribe via:
const unsubscribe = window.desktop.onFocusChanged((state) => {
  setFocusBanner(state)
})
The pet-update IPC channel is used in two directions:
  1. Invoke (assistant → main → pet): The assistant renderer calls window.desktop.petUpdate(payload), which invokes the pet-update channel. The main-process handler forwards the payload to the pet window via petWindow.webContents.send('pet-update', payload).
  2. Event (main → pet renderer): The pet renderer receives the forwarded payload via window.desktop.onPetUpdate(callback).
This asymmetry means the 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 via globalShortcut.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.
AcceleratorBehaviour
Win+Shift+CFocuses the assistant window if it is visible and focused; otherwise shows the assistant
Win+Shift+TShows the assistant and sends shortcut: 'new-task' to the renderer
Win+Shift+SSends shortcut: 'sync' to the renderer (does not change window focus)
Win+Shift+FStarts a 25-minute focus session, or ends the current session if one is active

Constants Reference

The following numeric constants are defined in electron/main/index.ts and govern IPC validation limits.
ConstantValueApplies to
MAX_DATA_BYTES5 * 1024 * 1024 (5 MB)save-data payload size limit
MAX_EXPORT_BYTES10 * 1024 * 1024 (10 MB)export-file content size limit
MAX_REMINDER_TEXT240 charactersReminder title and body fields
MAX_NOTIFICATION_TEXT180 charactersAd-hoc notification title and body fields
MAX_TIMEOUT2_147_000_000 msMaximum setTimeout duration before recursive rescheduling

Build docs developers (and LLMs) love