Skip to content

IPC Protocol Dictionary

1. Channel Topology

flowchart TB
  R[Renderer] --> P[preload.ts]
  P -->|ipcRenderer.send/invoke| M[main/index.ts ipcMain]
  M -->|HTTP + internal token| B[backend routes]

2. Channel Dictionary

ChannelIPC TypeParamsReturn SchemaMain Handler Behavior
app:close-windowsendnonenoneCloses focused window or main window
i18n:get-localeinvokenonePromise<string>Returns current resolved locale
i18n:set-localeinvokelocale: stringPromise<string>Resolves/persists in-memory locale and updates title
app:get-runtime-user-nameinvokenonePromise<string>Returns OS username fallback chain
app:get-version-infoinvokenonePromise<{ appName: string; version: string; buildVersion: string; buildTime: string; commit: string; electron: string; chromium: string; node: string; v8: string; os: string }>Returns About metadata including app version/build plus runtime technical information
app:get-pending-launch-working-directoryinvokenonePromise<string | null>Returns current pending context-launch working directory parsed from CLI
app:get-database-security-infoinvokenonePromise<{ runtimeMode: 'development' | 'production'; resolverMode: 'development-fixed-key' | 'safe-storage' | 'master-password-fallback'; safeStorageAvailable: boolean; databasePath: string; securityConfigPath: string; hasEncryptedDbMasterKey: boolean; hasMasterPasswordHash: boolean; hasMasterPasswordSalt: boolean; hasMasterPasswordEnv: boolean; fallbackReady: boolean }>Returns non-sensitive database encryption bootstrap diagnostics for Settings → Advanced
app:launch-working-directoryevent (main -> renderer)cwd: stringnonePushes context-launch working directory when a second instance is invoked
app:menu-actionevent (main -> renderer)action: 'open-about' | 'open-settings' | 'new-tab' | 'close-current-tab' | 'close-right-tabs' | 'show-tab-switcher'noneDispatches validated app-menu commands from the macOS system menu to renderer tab/state handlers
app:open-devtoolsinvokenonePromise<boolean>Opens devtools for the current main window when available
app:toggle-devtoolsinvokenonePromise<boolean>Toggles detached DevTools for the current main window (open when closed, close when open)
app:reload-webviewinvokenonePromise<boolean>Reloads the active renderer webContents and bypasses cache for deterministic debug refresh
app:restart-backend-runtimeinvokenonePromise<boolean>Restarts backend runtime in-place during development without full app restart
app:show-in-file-managerinvoketargetPath?: stringPromise<boolean>Opens file/folder in OS file manager
app:open-external-urlinvoketargetUrl: stringPromise<boolean>Opens trusted HTTP(S) URL with system default browser
app:set-windows-system-menu-symbol-colorinvokesymbolColor: stringPromise<boolean>Applies token-driven Windows title bar system-menu symbol color to current main window overlay
app:import-private-keyinvokenonePromise<{ canceled: boolean; content?: string }>Opens native file picker and returns UTF-8 private key content when selected
app:get-process-performance-statsinvokenonePromise<{ sampledAt: number; cpuPercent: number | null; mainProcessMemory: { rssBytes: number; heapTotalBytes: number; heapUsedBytes: number; externalBytes: number; arrayBuffersBytes: number }; rendererProcessMemory: { residentSetBytes: number; privateBytes: number; sharedBytes: number } | null; backendProcess: { pid: number; cpuPercent: number | null; memoryRssBytes: number | null } | null }>Samples main process CPU + memory, resolves renderer process memory from active window, and includes backend child-process CPU/RSS memory for debug monitoring overlay
app:export-main-heap-snapshotinvokenonePromise<{ ok: boolean; filePath?: string; message?: string }>Writes a V8 heap snapshot for the main process into app user-data debug snapshot directory
backend:test-pinginvokenonePromise<ApiTestPingResponse | ApiErrorResponse>Calls backend health test endpoint
backend:settings-getinvokenonePromise<ApiSettingsGetResponse | ApiErrorResponse>GET persisted application settings
backend:settings-updateinvokepayload: ApiSettingsUpdateRequestPromise<ApiSettingsUpdateResponse | ApiErrorResponse>PUT application settings snapshot
backend:ssh-list-serversinvokenonePromise<ApiSshListServersResponse | ApiErrorResponse>GET SSH server list
backend:ssh-create-serverinvokepayload: ApiSshCreateServerRequestPromise<ApiSshCreateServerResponse | ApiErrorResponse>POST create SSH server
backend:ssh-update-serverinvokeserverId: string, payload: ApiSshUpdateServerRequestPromise<ApiSshUpdateServerResponse | ApiErrorResponse>PUT update SSH server
backend:ssh-get-server-credentialsinvokeserverId: stringPromise<ApiSshGetServerCredentialsResponse | ApiErrorResponse>GET decrypted credentials
backend:ssh-list-foldersinvokenonePromise<ApiSshListFoldersResponse | ApiErrorResponse>GET folder list
backend:ssh-create-folderinvokepayload: ApiSshCreateFolderRequestPromise<ApiSshCreateFolderResponse | ApiErrorResponse>POST create folder
backend:ssh-update-folderinvokefolderId: string, payload: ApiSshUpdateFolderRequestPromise<ApiSshUpdateFolderResponse | ApiErrorResponse>PUT update folder
backend:ssh-list-tagsinvokenonePromise<ApiSshListTagsResponse | ApiErrorResponse>GET tag list
backend:ssh-create-taginvokepayload: ApiSshCreateTagRequestPromise<ApiSshCreateTagResponse | ApiErrorResponse>POST create tag
backend:ssh-list-keychainsinvokenonePromise<ApiSshListKeychainsResponse | ApiErrorResponse>GET keychain list
backend:ssh-create-keychaininvokepayload: ApiSshCreateKeychainRequestPromise<ApiSshCreateKeychainResponse | ApiErrorResponse>POST create keychain
backend:ssh-update-keychaininvokekeychainId: string, payload: ApiSshUpdateKeychainRequestPromise<ApiSshUpdateKeychainResponse | ApiErrorResponse>PUT update keychain
backend:ssh-get-keychain-credentialsinvokekeychainId: stringPromise<ApiSshGetKeychainCredentialsResponse | ApiErrorResponse>GET decrypted keychain credentials
backend:ssh-create-sessioninvokepayload: ApiSshCreateSessionRequestPromise<ApiSshCreateSessionResponse | ApiSshCreateSessionHostVerificationRequiredResponse | ApiErrorResponse>POST create SSH shell session
backend:ssh-trust-fingerprintinvokepayload: ApiSshTrustFingerprintRequestPromise<ApiSshTrustFingerprintResponse | ApiErrorResponse>POST trust host fingerprint
backend:ssh-close-sessioninvokesessionId: stringPromise<{ success: boolean }>DELETE SSH session
backend:ssh-delete-serverinvokeserverId: stringPromise<{ success: boolean }>DELETE SSH server
backend:ssh-delete-folderinvokefolderId: stringPromise<{ success: boolean }>DELETE SSH folder
backend:ssh-delete-keychaininvokekeychainId: stringPromise<{ success: boolean }>DELETE SSH keychain
backend:local-terminal-list-profilesinvokenonePromise<ApiLocalTerminalListProfilesResponse | ApiErrorResponse>GET local terminal profile list
backend:local-terminal-create-sessioninvokepayload: ApiLocalTerminalCreateSessionRequestPromise<ApiLocalTerminalCreateSessionResponse | ApiErrorResponse>POST local terminal session (Main may inject one-shot cwd from launch context)
backend:local-terminal-close-sessioninvokesessionId: stringPromise<{ success: boolean }>DELETE local terminal session

3. Schema Sources

  • API payload types come from @cosmosh/api-contract, generated from packages/api-contract/openapi/cosmosh.openapi.yaml.
  • Backend, Main IPC proxy, and renderer HTTP callers must use API_PATHS and related generated contract exports from @cosmosh/api-contract instead of hard-coded route strings.

3.1 SSH Visual Metadata Fields

The following SSH entity payloads now include visual metadata for persistent icon/color customization:

  • ApiSshCreateServerRequest / ApiSshUpdateServerRequest: optional iconKey, optional colorKey.
  • ApiSshCreateFolderRequest / ApiSshUpdateFolderRequest: optional iconKey, optional colorKey.
  • ApiSshListServersResponse: each server item includes iconKey and colorKey.
  • ApiSshListFoldersResponse: each folder item includes iconKey and colorKey.

colorKey is constrained to the predefined palette enum in the API contract.

SSH security policy fields in current contract:

  • ApiSshCreateServerRequest / ApiSshUpdateServerRequest: strictHostKey boolean.
  • ApiSshListServersResponse: each server item includes persisted strictHostKey.
  • ApiSshCreateSessionRequest: optional strictHostKey override used for one session attempt.

3.2 Terminal WebSocket Contract (Renderer ↔ Backend)

Although terminal stream messages are not Electron IPC channels, they are part of the same cross-process contract surface and must be versioned together.

  • Client to server (/ws/ssh/{sessionId} and /ws/local-terminal/{sessionId}):
    • input, resize, ping, close, history-delete
    • completion-request with requestId, linePrefix, cursorIndex, optional workingDirectoryHint, optional limit, optional fuzzyMatch, optional source filters (includeHistory, includeBuiltInCommands, includePathSuggestions, includePasswordSuggestions), and trigger (typing or manual)
  • Server to client:
    • ready, output, telemetry, history, pong, error, exit
    • completion-response with requestId, replacePrefixLength, and ranked completion items

Completion item contract notes:

  • items[].source includes history, inshellisense, and runtime-computed runtime.
  • items[].kind includes existing command-spec/history categories plus runtime categories (path, secret).
  • Runtime categories are used for path candidates and interactive secret-fill actions while preserving the same completion-response envelope.

Current implementation note:

  • Completion messages are handled in SshSessionService and LocalTerminalSessionService via shared normalization in terminal/shared.ts and shared ranking engine in terminal/completion/engine.ts.

4. Change Rules

When adding/modifying a channel, update in one commit:

  1. packages/main/src/preload.ts
  2. packages/main/src/index.ts
  3. packages/renderer/src/vite-env.d.ts
  4. relevant renderer transport/service wrappers
  5. this file (docs/developer/core/ipc-protocol.md)

5. Channel Addition Template

Use this checklist when introducing a new channel:

  1. Channel name: domain:action-name
  2. IPC type: invoke or send
  3. Params schema: explicit type in bridge and renderer declarations
  4. Return schema: success and error shape
  5. Main behavior: backend proxy or privileged local action
  6. Security notes: token/header handling, permission boundary, exposure limits
  7. Docs sync: update EN + ZH protocol pages in same change set