docs/references/ipc/README.md
Entry point for IpcApi — Cherry Studio's unified, type-safe channel for RPC-over-IPC: command/capability calls from the renderer into the main process, plus typed main→renderer events.
IpcApi is the fifth parallel subsystem alongside BootConfig / Cache / Preference / DataApi. It does not absorb any of them — it collects the "business capability IPC" those four cannot cover (window/system/shell/notification/external-service/file commands).
Status: the Stage-0 framework (schema mechanism,
IpcRouter,IpcApiService, preload forwarder, renderer facade,useIpcOn) has shipped, and the business-channel migration is essentially complete —IpcChannel.tsnow holds only the data/IpcApi infrastructure channels plus the intentionally-not-migrated groups (v1-only, the frozen file cluster, deferred lan_transfer / micro-domains / copilot, the skill scaffold, and theTab_MoveWindow/ Python escape hatches; each carries a self-contained comment inIpcChannel.ts). The endgame collapse (shrinkingIpcChannel.tstoipc/channels.ts, removingBaseService.ipcHandle/ipcOn, narrowingwindow.electron) is still pending.
IpcContext, error model, securitybroadcast/send + useIpcOn), three-process end-to-end examples*RequestSchemas/*EventSchemas, IpcRoute/IpcEventName, ESLint key validationipcMain.handle/this.ipcHandle/hand-written preload per domain, the send work-list, escape hatch (when a channel stays out), exposure-surface audit| Need | System | API |
|---|---|---|
| Read/write SQLite business data | DataApi | useQuery / useMutation |
| User setting (syncs across windows) | Preference | usePreference |
| Disposable / shared transient state | Cache | useCache / useSharedCache / usePersistCache |
| Pre-lifecycle boot config | BootConfig | usePreference('BootConfig.*') |
| Any other command-style call into main (window/system/shell/notification/external/file) | IpcApi | ipcApi.request / useIpcOn |
Decision rule: SQLite data → DataApi; user setting → Preference; losable/shared state → Cache; pre-lifecycle config → BootConfig; everything else, every imperative capability call into main → IpcApi. Same BeforeReady phase does not mean same responsibility — the boundary is responsibility (data/state/config vs command), not phase.
| Concept | Identifier |
|---|---|
| Product name | IpcApi |
| Channels | IpcApi_Request (ipc-api:request) / IpcApi_Event (ipc-api:event) |
| Main coordinator | IpcApiService (request dispatch + broadcast/send) |
| Preload bridge | window.api.ipcApi ({ request, on }) |
| Renderer facade | ipcApi (ipcApi.request('window.set_minimum_size', x)) + useIpcOn |
| Route / event names | dot snake_case, any depth ≥ 2 (file.read_doc, ai.agent.task.create); resource path first, verb last; payload fields stay camelCase |
| Request schemas | *RequestSchemas → ipcRequestSchemas / IpcRoute |
| Event contracts (pure types) | *EventSchemas → IpcEventSchemas / IpcEventName |
| Router / handlers / error | IpcRouter / ipcHandlers / IpcError |
| Directories | src/{shared,main,renderer}/ipc/, src/preload/ipc.ts |
| File | Role |
|---|---|
src/shared/ipc/define.ts | defineRoute + RouteDef |
src/shared/ipc/schemas/ipcSchemas.ts | ipcRequestSchemas / IpcRoute / IpcEventSchemas / IpcEventName |
src/shared/ipc/types.ts | InputFor / OutputFor / EventPayload / IpcHandlersFor / IpcContext / WindowId |
src/shared/ipc/errors/IpcError.ts | framework core: IpcError / IpcErrorCode (framework codes, single source of truth) / SerializedIpcError / IpcResult |
src/shared/ipc/errors/<domain>.ts | per-domain error-code maps (as const), imported directly by handler + renderer — errors/ has no aggregating barrel |
src/main/ipc/IpcRouter.ts | request router (key lookup + zod parse + dispatch) |
src/main/ipc/IpcApiService.ts | BeforeReady coordinator: handler registration + broadcast/send |
src/main/core/security/validateSender.ts | source-trust gate (validateSender / isAppRendererUrl), shared with the DataApi IpcAdapter, the Preference/Cache subsystem handlers, and the will-navigate guards |
src/main/ipc/handlers/ipcHandlers.ts | global ipcHandlers (exhaustive, the audited exposure surface) |
src/preload/ipc.ts | generic forwarder → window.api.ipcApi |
src/renderer/ipc/index.ts | typed facade ipcApi |
src/renderer/ipc/useIpcOn.ts | event subscription hook |