Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Cherry Studio Admin & Developer Guide

Generated June 2026 from CherryHQ/cherry-studio at 9751cfb

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is the deep technical reference for Cherry Studio — its architecture, configuration, security model, build and distribution pipeline, data layer, and internals. It is written for administrators deploying Cherry Studio in a team, power users who automate it, and developers who want to understand or extend the codebase.

For end-user instructions (chatting, knowledge bases, paintings, translation, settings walkthroughs), see the companion User Guide.

Note

Cherry Studio is a large, actively developed Electron monorepo (~4,900 files, ~10.2M characters of source at the documented commit). This guide focuses on the structures that matter for operating and extending it, not an exhaustive file-by-file dump.


Table of Contents

  1. Executive Summary
  2. System Architecture
  3. Process Model & Startup
  4. The IPC Surface
  5. The Embedded API Server (CSaaS)
  6. Provider & Model System
  7. Data Layer & Schema
  8. Subsystem Reference
  9. Requirements & Dependencies
  10. Configuration Reference
  11. Security Model
  12. Build & Distribution
  13. Updates & Upgrade Path
  14. Operations & Maintenance
  15. Testing & Quality Gates
  16. Development Setup
  17. Things That Do Not Exist
  18. Troubleshooting (Operator Reference)
  19. Quick Reference

Executive Summary

Cherry Studio is a cross-platform Electron desktop application (Windows, macOS, Linux) that acts as a unified front end to many LLM providers and as a local AI workstation. It is built with:

Layer Technology
Shell Electron 41 (com.cherryai.cherrystudio)
Main process Node.js (TypeScript), service-oriented lifecycle, Express API server
Renderer React 19 + Redux Toolkit + TanStack Router/Query, styled-components + Tailwind, Ant Design
Build electron-vite (Vite via rolldown-vite), electron-builder, pnpm workspaces
Data SQLite via Drizzle ORM; libsql vector store for RAG; Dexie (IndexedDB) on the renderer
AI runtime Vercel AI SDK (@ai-sdk/*), Anthropic Claude Agent SDK, MCP SDK, embedjs

Its distinguishing capabilities for administrators:

  • A local API gateway ("CSaaS") that re-exposes every configured provider behind OpenAI- and Anthropic-compatible HTTP endpoints.
  • MCP (Model Context Protocol) client and host support, including built-in servers.
  • Autonomous agents that can connect to messaging channels (Telegram, Feishu, QQ, WeChat, Discord, Slack).
  • A local knowledge base (RAG) with a libsql vector store.
  • Multiple backup destinations: WebDAV, S3, Nutstore, local directory, and LAN transfer.

License: AGPL-3.0 (Community), with a separately licensed Enterprise Edition for centralized management and private deployment.

Important

Because Cherry Studio is a client, "deployment" means distributing and configuring the desktop app on user machines — there is no central Cherry Studio server in the Community Edition. The closest thing to a server is the optional, locally-bound API server described in The Embedded API Server.


System Architecture

Cherry Studio follows the standard Electron three-tier split, with a strict service architecture in the main process.

┌──────────────────────────────────────────────────────────────────────┐
│                        Electron Application                           │
│                     (appId: com.cherryai.cherrystudio)                │
│                                                                       │
│  ┌─────────────────────────┐        ┌──────────────────────────────┐ │
│  │      Renderer (React)    │        │        Main (Node.js)        │ │
│  │                          │  IPC   │                              │ │
│  │  TanStack Router pages:  │◄──────►│  Lifecycle services:         │ │
│  │   chat / agents / code   │ window │   Application + serviceList  │ │
│  │   knowledge / paintings  │  .api  │   WindowManager, Preference  │ │
│  │   translate / notes ...  │        │   ProviderService, Channels  │ │
│  │  Redux Toolkit store     │        │   Knowledge, FileStorage ... │ │
│  │  Dexie (IndexedDB)       │        │                              │ │
│  └─────────────────────────┘        │  ┌────────────────────────┐  │ │
│             ▲                        │  │  Express API server    │  │ │
│             │ contextBridge          │  │  (CSaaS, :port)        │◄─┼─┼── external
│  ┌──────────┴───────────┐            │  │  /v1/chat/completions  │  │ │   OpenAI/Anthropic
│  │   Preload (bridge)    │            │  │  /v1/messages, /mcps   │  │ │   compatible clients
│  └──────────────────────┘            │  └────────────────────────┘  │ │
│                                      │                              │ │
│                                      │  SQLite (Drizzle) + libsql   │ │
│                                      │  vector store + file storage │ │
│                                      └──────────────────────────────┘ │
│                                                  │                    │
└──────────────────────────────────────────────────┼────────────────────┘
                                                    ▼
                       External providers (OpenAI, Anthropic, Gemini,
                       Ollama, LM Studio, web search, OCR services, MCP)

Repository layout

Path Purpose
src/main/ Electron main process: lifecycle, services, IPC, API server, AI runtime
src/renderer/ React UI: routes/pages, components, hooks, Redux store, services
src/preload/ contextBridge API exposed to the renderer
src/shared/ Code shared by main and renderer: types, config, utilities, IPC channel enum
packages/ Published workspace packages (see below)
migrations/sqlite-drizzle/ Drizzle SQL migrations for the SQLite schema
resources/ Bundled runtime assets: databases, builtin agents, skills, data
config/ App-upgrade segment definitions
tests/ Vitest unit/integration + Playwright e2e

Workspace packages

The monorepo (pnpm workspaces, managed with Changesets) publishes several internal packages:

Package Role
@cherrystudio/ai-core (packages/aiCore) Provider-agnostic AI runtime core (providers, models, plugins, runtime)
@cherrystudio/ai-sdk-provider Cherry Studio's Vercel AI SDK provider integration
@cherrystudio/provider-registry Provider/model registry data and schemas
@cherrystudio/ui (packages/ui) Shared component library, icons, design tokens
@cherrystudio/extension-table-plus TipTap editor table extension
@vectorstores/libsql libsql-backed vector store for RAG
@cherrystudio/mcp-trace MCP tracing (OpenTelemetry)

Process Model & Startup

The main entry point is src/main/index.ts. Its own header comment is explicit: "This file is glue — it should only shrink." New services belong in the lifecycle system, not the entry file.

Startup proceeds through ordered phases:

  1. BootConfig load — @main/data/bootConfig is imported first (before any other import) so the userData path is configured before Electron reads it.
  2. Preboot (order matters):
    • resolveUserDataLocation() — resolve where app data lives.
    • requireSingleInstance() — enforce a single running instance.
    • configureChromiumFlags() — set Chromium command-line flags.
    • initCrashTelemetry() — install crash reporting.
    • application.initPathRegistry() — freeze the path registry (bootstrap asserts this completed).
  3. V2 migration gate — runV2MigrationGate(). If a major data migration is required, a migration window takes over and normal startup is skipped ('handled').
  4. App identity — electronApp.setAppUserModelId('com.cherryai.cherrystudio') (Windows notification/taskbar identity).
  5. Lifecycle bootstrap — application.registerAll(serviceList) then application.bootstrap() runs in parallel with app.whenReady(). The BeforeReady lifecycle stage overlaps Electron readiness.
  6. Version recording — versionService.recordCurrentVersion() for upgrade-path tracking.
  7. IPC registration — registerIpc() wires the (currently monolithic) IPC handler table.

Note

Service initialization is structured: a ServiceInitError during bootstrap() is handled internally (dialog → exit/relaunch). The top-level catch in index.ts is only a safety net for unexpected escapes, which call application.forceExit(1).

Lifecycle service pattern

Services are registered with the central application object and resolved by name, e.g. application.get('PreferenceService'), application.get('WindowManager'), application.get('ChannelManager'). Some services are conditionally activated by platform/CPU (e.g., the OpenVINO Model Server manager runs only on Windows + Intel via @Conditional(onPlatform('win32'), onCpuVendor('intel'))).

Note

A TODO(v2) in the code notes that the monolithic IPC registration (registerIpc()) creates timing coupling between bootstrap and IPC readiness; the intended direction is per-service ipcHandle/ipcOn inside lifecycle services.


The IPC Surface

The renderer never touches Node APIs directly. It calls main-process handlers through a contextBridge-exposed API in src/preload/, and the main process registers handlers keyed by a typed IpcChannel enum (@shared/IpcChannel). This channel table — registered in src/main/ipc.ts and across lifecycle services — is effectively Cherry Studio's internal API.

Representative channel groups (each ipcMain.handle(IpcChannel.X, ...)):

Group Examples Service
App App_Info, App_ClearCache, App_GetCacheSize, App_Select, App_ResetData, App_GetDiskInfo, App_SetLaunchOnBoot, App_HandleZoomFactor, App_SetEnableSpellCheck AppService / ConfigManager
File File_Open/Save/Read/Write/Delete/Move/Rename, File_Upload, File_SaveBase64Image, File_ListDirectory, File_BatchUploadMarkdown FileStorage / FileSystemService
PDF / FS Pdf_ExtractText, Fs_Read, Fs_ReadText shared PDF util / FileService
Backup Backup_Backup/Restore, Backup_BackupToWebdav, Backup_BackupToS3, Backup_BackupToLocalDir, Backup_CreateLanTransferBackup, *_List*, *_Check*Connection LegacyBackupManager
Skills Skill_List/Install/Uninstall/Toggle/InstallFromZip/InstallFromDirectory/ReadFile/ListFiles/ListLocal SkillService
Cloud/auth Copilot_* (GitHub Copilot), VertexAI_GetAuthHeaders/AccessToken, Nutstore_*, Obsidian_GetVaults/GetFiles CopilotService / VertexAiService / NutstoreService / ObsidianVaultService
Channels Channel_GetLogs, Channel_GetStatuses, WeChat_HasCredentials ChannelManager
System System_GetDeviceType/Hostname/CpuName, System_CheckGitBash, System_GetGitBashPath(Info), System_SetGitBashPath, System_ToggleDevTools system utils
Security Aes_Encrypt, Aes_Decrypt, Cherryai_GetSignature aes util / cherryai integration
Binaries App_IsBinaryExist, App_GetBinaryPath, App_InstallUvBinary, App_InstallBunBinary, App_InstallOvmsBinary, Ovms_IsSupported process util / OvmsManager
Misc Open_Website (validated URL), Open_Path, Notification_Send, Zip_Compress/Decompress, Export_Word various

Important

Open_Website does not blindly open URLs — it calls isSafeExternalUrl(url) and refuses untrusted schemes (logged as a warning). This is part of the defense against renderer-driven navigation attacks.


The Embedded API Server (CSaaS)

src/main/apiServer/ runs an Express 5 HTTP server inside the main process that re-exposes Cherry Studio's configured providers behind standard APIs. Internally this feature is named CSaaS ("Cherry Studio as a Service").

Lifecycle

The ApiServer class (server.ts) wraps a Node http.Server. It reads feature.csaas.host and feature.csaas.port from the PreferenceService, builds the Express app via the createApp() factory, applies timeouts, and listens. On successful listen it broadcasts IpcChannel.ApiServer_Ready to the main window. It exposes start(), stop(), restart(), and isRunning().

Timeouts: request timeout 5 minutes, headers timeout request+5s, keep-alive 60s, and per-socket timeout disabled (setTimeout(0)) so long streaming responses aren't cut off.

Note

The createApp() factory pattern is a deliberate timing workaround so Express construction, OpenAPI setup, and route mounting don't run before preboot. A TODO flags the app↔routes↔services coupling for a future refactor.

Routes

Method Path Auth Backed by
GET /health none inline (status/timestamp/version)
GET / none inline (endpoint catalog)
GET /api-docs, /api-docs.json none swagger-ui-express + generated OpenAPI spec
POST /v1/chat/completions API key chatCompletionService (OpenAI-compatible)
POST /v1/messages API key messagesService (Anthropic-compatible)
POST /{provider}/v1/messages API key messagesService, provider from URL
GET /v1/mcps, /v1/mcps/{server_id} API key mcpApiService
ALL /v1/claw/{agentId}/claw-mcp API key ClawServer (per-session MCP over Streamable HTTP)
* /v1/knowledge-bases, /v1/knowledge-bases/search API key knowledge routes

The OpenAPI docs are mounted before the protected router so they stay public. Provider-specific messages and the /v1 router each apply authMiddleware.

Request handling details

  • Streaming: /v1/chat/completions with stream:true returns text/event-stream, writes data: <chunk>\n\n frames, ends with data: [DONE]\n\n, and aborts the upstream provider stream when the HTTP client disconnects (so provider tokens aren't wasted on a closed socket).
  • Model resolution: the model field is parsed as providerId::modelId (parseUniqueModelId). The provider is resolved via providerService.getByProviderId, its API key is fetched with key rotation (getRotatedApiKey), and the correct endpoint base URL is selected from provider.endpointConfigs[ENDPOINT_TYPE.OPENAI_CHAT_COMPLETIONS]. If no OpenAI-compatible base URL is configured, the request is rejected rather than risk sending the provider's key to api.openai.com.
  • Error mapping: errors are normalized to OpenAI/Anthropic-style error bodies with type/code, trusting the SDK's structured .status rather than regex-matching messages (a genuine 500 is not remapped to 502).
  • Claw MCP: each MCP session gets its own ClawServer + StreamableHTTPServerTransport pair (the MCP SDK Server supports one transport at a time); sessions have a 30s init timeout and are keyed by mcp-session-id.

Authentication

middleware/auth.ts accepts a credential as either x-api-key: <key> or Authorization: Bearer <key>, compared against feature.csaas.api_key with crypto.timingSafeEqual (constant-time). Responses: missing credentials → 401; no server key configured → 403; wrong key → 403.

Caution

CORS is set to origin: '*'. The server has no built-in rate limiting and no per-client identity beyond the single shared API key. Bind it to 127.0.0.1 for single-machine use; only expose it on a LAN/host interface deliberately, ideally behind a reverse proxy that adds TLS and rate limiting.


Provider & Model System

Cherry Studio abstracts many AI vendors behind a uniform model interface.

  • Provider registry (packages/provider-registry, bundled to resources/provider-registry) ships known providers and models with their endpoints and capabilities.
  • AI core (packages/aiCore) holds the provider-agnostic runtime: a provider/extension registry, model definitions, plugins, and a runtime loop, built on the Vercel AI SDK (@ai-sdk/* for OpenAI, Anthropic, Google, Bedrock, Azure, Cohere, Groq, Mistral, Perplexity, xAI, Together, HuggingFace, and more).
  • Endpoint configs: each provider can declare multiple endpoint types (e.g., OpenAI chat-completions vs. Anthropic messages). Mixed providers (e.g., aihubmix, new-api, cherryin) ship multiple endpoint keys, so the code selects the endpoint by type, never by "first value."
  • API-key rotation: providerService.getRotatedApiKey() supports multiple keys per provider, rotating across requests.
  • Custom provider extensions: aiCore's ExtensionRegistry/ProviderExtension allow registering provider aliases and custom integrations (with validation — e.g., a provider extension must have a name; OpenAI-compatible providers require settings).

Note

Local inference is just another provider: point an OpenAI-compatible provider at Ollama or LM Studio. There is no special "local mode" — it's the same endpoint-config mechanism with a localhost base URL.


Data Layer & Schema

Persistent state lives in a SQLite database accessed through Drizzle ORM (WAL-oriented; migrations under migrations/sqlite-drizzle/). The renderer additionally uses Dexie (IndexedDB) for some client-side state, and redux-persist persists Redux slices. A libsql vector store backs knowledge-base embeddings. Migrations are generated/checked with drizzle-kit (db:migrations:generate, db:migrations:check).

Core tables

Table Holds
assistant Chat assistants (prompt + model + params)
assistant_knowledge_base, assistant_mcp_server Join tables linking assistants to knowledge bases and MCP servers
topic, message Conversations and their messages
group, pin Organization/grouping and pinned items
prompt Reusable prompt snippets
tag, entity_tag Tagging across entities
preference Key/value user preferences (the PreferenceService store)
app_state Internal application state
user_provider, user_model User-configured providers and models

Agent & automation tables

Table Holds
agent, agent_session, agent_session_message Agents and their running sessions/messages
agent_channel, agent_channel_task Messaging-channel bindings and their task links
agent_global_skill, agent_skill Installed skills and per-agent enablement
agent_task, agent_task_run_log Agent tasks and execution logs
agent_workspace Agent working directories
job, job_schedule Scheduled-task engine records

Feature tables

Table Holds
knowledge_base, knowledge_item RAG knowledge bases and their indexed items
mcp_server Configured MCP servers
mini_app Installed mini apps
note Notes
painting Generated images
translate_history, translate_language Translation history and language config
file_entry, file_ref File storage metadata and reference counting

Channel & permission constraints (from the schema)

The agent_channel table enforces, via CHECK constraints, the valid channel types and permission modes:

CHECK("agent_channel"."type" IN ('telegram','feishu','qq','wechat','discord','slack'))
CHECK("agent_channel"."permission_mode" IS NULL OR
      "agent_channel"."permission_mode" IN ('default','acceptEdits','bypassPermissions','plan'))

Important

The V2 data refactor introduced a migration engine (src/main/data/migration/v2/) with a startup migration gate. It validates foreign keys after migrating (PRAGMA foreign_keys) and aborts on integrity violations (Foreign key check failed: N violation(s)). The __new_* shadow tables in migrations are the standard SQLite table-rebuild pattern.


Subsystem Reference

A tour of the major main-process subsystems (src/main/):

Subsystem Path Responsibility
AI runtime ai/runtime, ai/streamManager, ai/provider Drive model calls, manage streaming lifecycle, build provider clients
Agents ai/agents, ai/agentSession, ai/skills Autonomous agent execution, sessions, skill loading
Claude Code ai/runtime/claudeCode, shared/ai/claudecode Agentic coding via the Claude Agent SDK
MCP ai/mcp (servers/browser, servers/filesystem, servers/claw), ai/tools MCP client + built-in MCP servers + tool adapters
Observability ai/observability OpenTelemetry tracing of AI/MCP calls (@cherrystudio/mcp-trace)
Channels ai/channels (adapters/telegram,feishu,qq,wechat,discord,slack) IM bot integrations
Knowledge services/knowledge, knowledge/embedjs, knowledge/reranker RAG indexing, retrieval, reranking strategies
File processing services/fileProcessing (processors/tesseract,paddleocr,mineru,doc2x,mistral,ovocr,system) OCR & document-to-markdown pipeline
Files services/file, services/FileStorage Sandboxed file storage and access
Web search services/webSearch (providers/api/*) Tavily/Exa/SearXNG/Bocha/Jina/Querit/MCP search
Backup services/LegacyBackupManager, services/nutstore WebDAV/S3/local/LAN/Nutstore backup
LAN transfer services/lanTransfer Direct device-to-device backup over LAN (bonjour discovery)
Protocol services/protocol cherrystudio:// deep-link handling
Scheduler core/scheduler, core/job Scheduled tasks (croner)
Window mgmt core/window, MainWindowService BrowserWindow lifecycle, multi-window
Updates services/AppUpdaterService, VersionService electron-updater integration + segmented upgrades
Integrations services/ObsidianVaultService, CopilotService, VertexAiService, integration/cherryai Obsidian, GitHub Copilot, Vertex AI, CherryIN
OVMS services/OvmsManager OpenVINO Model Server (Windows + Intel only)

The renderer (src/renderer/) mirrors these with pages (TanStack Router, file-based under routes/), a Redux Toolkit store (store/, 28 slices), hooks (hooks/, 73 files), and services (services/, 27 files).


Requirements & Dependencies

Runtime / build requirements

Requirement Value
Node.js (build/dev) >=24.11.1
Package manager pnpm@10.27.0 (workspaces)
Electron 41.2.1
electron-builder 26.8.1
electron-vite 5.0.0 (Vite via rolldown-vite@7.3.0)
TypeScript ~5.8.3 (type-checked with tsgo / native preview)
React 19.x

Key dependency families

Area Libraries
AI SDKs ai, `@ai-sdk/openai
Agents/MCP @anthropic-ai/claude-agent-sdk, @modelcontextprotocol/sdk, @anthropic-ai/sdk, @cherrystudio/openai
RAG @cherrystudio/embedjs*, @vectorstores/*, @libsql/client, @langchain/*
OCR/docs tesseract.js, @napi-rs/system-ocr, sharp, officeparser, pdf-parse, pdf-lib, mammoth/word-extractor, epub, @e965/xlsx
Editor/markdown @tiptap/*, react-markdown, remark-*/rehype-*, shiki, katex, mermaid
Server express, cors, swagger-ui-express, swagger-jsdoc, express-validator, ws
Data drizzle-orm, drizzle-kit, dexie, redux/@reduxjs/toolkit, redux-persist
Channels grammy (Telegram), @larksuiteoapi/node-sdk (Feishu)
Cloud @aws-sdk/client-s3, webdav, google-auth-library, @google/genai

Note

Several dependencies are patched (pnpm.patchedDependencies) — including electron-updater, tesseract.js, multiple @ai-sdk/* providers, @langchain/*, libsql, and antd. When upgrading these, re-validate the patches. Native modules (selection-hook, sharp, @napi-rs/*, libsql, @anthropic-ai/claude-agent-sdk) are platform-specific optional dependencies and are unpacked from the asar at runtime.


Configuration Reference

Cherry Studio is configured almost entirely through the UI, which persists to the preference table via the PreferenceService. There is no user-editable config file or environment-variable-based runtime configuration for end users.

Preference keys (operationally significant)

Key Controls
feature.csaas.host API server bind host
feature.csaas.port API server port
feature.csaas.api_key API server authentication key
app.spell_check.languages Spell-check languages
app.zoom_factor UI zoom
Git Bash path (ConfigKeys.GitBashPath, GitBashPathSource) Windows shell path (manual/auto)

Generation defaults (constants)

Constant Value
DEFAULT_TEMPERATURE 1.0
DEFAULT_CONTEXTCOUNT 5
DEFAULT_MAX_TOKENS 8192
DEFAULT_TIMEOUT 1800000 ms (30 min)
DEFAULT_STREAM_OPTIONS_INCLUDE_USAGE true

Environment variables (build/dev and OS-derived only)

These are not product configuration knobs; they are read by build tooling or for OS path resolution:

Variable Used for
NODE_ENV Vite build mode
MAIN_VITE_CHERRYAI_CLIENT_SECRET CherryAI integration client secret (build-time)
VITE_RENDERER_INTEGRATED_MODEL Renderer integrated-model build flag
CLAUDE_CODE_GIT_BASH_PATH Git Bash discovery for Claude Code
APPDATA, LOCALAPPDATA, XDG_CONFIG_HOME, HOME/USERPROFILE, PATH, SHELL OS path/shell resolution
PORTABLE_EXECUTABLE_DIR Detect Windows portable build
APPIMAGE Detect Linux AppImage

Application paths

The frozen path registry (application.getPath(...)) defines logical locations such as app.root, app.userdata, app.install, cherry.config, feature.files.data, feature.notes.data, feature.agents.channels, app.session.cache, and the logs directory. The App_Info IPC returns these to the renderer.

Warning

Changing the data path at runtime is incompatible with the frozen path registry; the code marks App_SetAppDataPath for a v2 redesign and the renderer currently triggers a relaunch after a path change. Treat data-path changes as "set, then restart."


Security Model

Cherry Studio's security posture has several named layers. Administrators should understand each.

1. Process isolation (Electron)

Renderer windows run with Chromium's process isolation. The renderer reaches the main process only through the contextBridge-exposed preload API (window.api/window.*), never via direct Node integration in app windows. Web content (mini apps, webviews) runs in a separate session partition (persist:webview).

2. URL & navigation safety

External URL opening goes through isSafeExternalUrl() (rejecting untrusted schemes). Remote URL fetches enforce remoteUrlSafety checks: local/private addresses are blocked (Unsafe remote url: local or private addresses are not allowed), and credentials embedded in URLs are rejected (credentials are not allowed). Web-search results can be filtered by a blacklist match-pattern engine.

3. Filesystem sandboxing

File operations validate that source and destination paths are absolute and inside allowed directories, enforce a maximum recursion depth, and reject path-traversal (Path is outside allowed directory). Agent file access is further scoped by each agent's accessible paths. Path-resolver code rejects null bytes in entry ids/paths.

4. Secrets at rest

API keys and tokens are stored locally. An AES utility (Aes_Encrypt/Aes_Decrypt IPC) is available for encrypting sensitive values. OAuth flows (CherryIN, Copilot, Nutstore, Vertex AI) are handled by dedicated services; CherryIN OAuth validates the API host against an allowlist and requires a managed window.

5. API server authentication

The CSaaS server uses constant-time API-key comparison (crypto.timingSafeEqual) and refuses requests with missing or mismatched credentials. See The Embedded API Server.

6. Agent permission modes

Agent tool execution is gated by permission_mode (default / acceptEdits / bypassPermissions / plan), enforced both in the UI (tool-approval bridge) and recorded in the schema.

Caution

The strongest operational risks are (1) running the API server on a non-loopback interface without a proxy, and (2) granting agents bypassPermissions with broad accessible paths. Both are admin choices, not defaults — review them in managed deployments.

Reporting vulnerabilities

The repository includes a SECURITY.md; report security issues through the channel it specifies rather than public issues.


Build & Distribution

Build pipeline

# Install (pnpm workspaces)
pnpm install

# Type-check (node + web + aiCore projects in parallel via tsgo)
pnpm typecheck

# Full production build (generates OpenAPI spec, typechecks, builds with electron-vite)
pnpm build

# Package for a platform (electron-builder)
pnpm build:win        # NSIS + portable, x64 + arm64
pnpm build:mac        # dmg + zip, arm64 + x64
pnpm build:linux      # AppImage + deb + rpm, x64 + arm64

Note

pnpm build runs generate:openapi first — the API server's OpenAPI spec is generated from JSDoc and committed (src/main/apiServer/generated/openapi-spec.json); CI enforces it is up to date (openapi:check).

electron-builder configuration (electron-builder.yml)

Setting Value
appId com.cherryai.cherrystudio
productName Cherry Studio
Protocol scheme cherrystudio
Windows targets nsis (configurable install dir, desktop shortcut, not one-click) + portable
macOS targets dmg + zip; entitlements for camera/microphone/Documents/Downloads; notarization via scripts/notarize.js
Linux targets AppImage + deb + rpm; category Utility; registers x-scheme-handler/cherrystudio
Publish generic provider at https://releases.cherry-ai.com
Electron mirror https://npmmirror.com/mirrors/electron/
asarUnpack resources/**, sharp binaries, the Claude Agent SDK native CLI (must live on disk to spawn)
extraResources Drizzle migrations and the provider-registry data

Build hooks: beforePack, afterPack, afterSign (notarize), and artifactBuildCompleted scripts customize packaging and signing (Windows signing via scripts/win-sign.js).

Artifact naming

Artifacts follow ${productName}-${version}-${arch}-..., e.g. Cherry Studio-2.0.0-x64-setup.exe, Cherry Studio-2.0.0-arm64.dmg, Cherry Studio-2.0.0-x64.AppImage.


Updates & Upgrade Path

Cherry Studio uses electron-updater against the generic feed https://releases.cherry-ai.com, with GitHub and GitCode mirrors. Update routing is defined by segments in config/app-upgrade-segments.json:

Segment Type Match Meaning
gateway-v1.8.1 legacy exactly 1.8.1 All users below v1.8.1 must upgrade to v1.8.1 first
current-v1 latest >=1.8.1 <2.0.0 Latest v1.x (supports latest/rc/beta channels)
gateway-v2 breaking exactly 2.0.0 Required intermediate stop for entering v2.x (minCompatible 1.9.0)
current-v2 latest >=2.0.0 <3.0.0 Latest v2.x (latest/rc/beta channels)

Important

The gateway/breaking segments enforce a staged upgrade so the V2 data migration runs from a known-good baseline. Very old clients are routed through v1.8.1 and v2.0.0 before reaching the newest release. The VersionService records the current version on each launch to support this path.

The electron-updater dependency is patched; auto-update behavior differs by build flavor (AppImage and some Linux targets may rely on external/package-manager updates).


Operations & Maintenance

Where data lives

All state is under the resolved userData directory (platform-dependent: %APPDATA% on Windows, ~/Library/Application Support on macOS, ~/.config on Linux), including the SQLite database, knowledge-base vectors, files, notes, logs, and the session cache.

Logs

Logging uses winston with daily rotation (winston-daily-rotate-file). The logs directory is returned by App_Info and surfaced in the UI; loggerService.withContext(...) tags log lines by subsystem (e.g., ApiServer, IPC, MigrationEngine).

Cache management

App_ClearCache clears Chromium session caches (default + persist:webview) and temp files. App_GetCacheSize reports the session cache size.

Backup operations

Backups can be scripted through the UI's destinations (WebDAV, S3, Nutstore, local, LAN). For team deployments, prefer WebDAV or S3 with a scheduled cadence. LAN transfer accepts ZIP only with a size cap.

Managed-deployment checklist

  • [ ] Decide whether the API server should be enabled, and if so bind it to 127.0.0.1 with a strong key.
  • [ ] Standardize provider configuration (consider the Enterprise Edition for centralized model management).
  • [ ] Constrain agent accessible paths and avoid bypassPermissions by policy.
  • [ ] Choose and test a backup destination.
  • [ ] Pin an update channel (latest vs rc/beta) appropriate to your risk tolerance.
  • [ ] On Windows, pre-provision Git Bash if users will use agentic coding.

Testing & Quality Gates

Tool Purpose
Vitest Unit/integration tests, split by project: main, renderer, aiCore, ui, shared, provider-registry, vectorstores, scripts
Playwright End-to-end tests (tests/e2e/) with page objects
oxlint + ESLint Linting (oxlint first, then ESLint with project config)
Biome Formatting + lint (pnpm format)
tsgo Fast type-checking (node/web projects)
i18n checks i18n:check, i18n:hardcoded:strict, i18n:unused (no hardcoded strings)
OpenAPI check openapi:check (generated spec must be current)
Skills check skills:check
Changesets Versioning/release of workspace packages

CI runs in two phases: ci:basic-check (lint, format, typecheck, i18n, hardcoded-strings, openapi, skills) and ci:test-check (all Vitest projects). Bundle size is analyzed via rollup-plugin-visualizer (analyze:renderer/analyze:main).

Note

Database migration tests use a harness that asserts PRAGMA foreign_keys = 1 and runs PRAGMA integrity_check, failing fast if the test DB isn't healthy.


Development Setup

# Prerequisites: Node >= 24.11.1, pnpm 10.27.0, (Windows) Git Bash
pnpm install

# Generate the API OpenAPI spec + run the dev app (electron-vite)
pnpm dev

# Dev with renderer hot-reload watcher
pnpm dev:watch

# Run tests
pnpm test                 # all (silent)
pnpm test:main            # main-process project only
pnpm test:e2e             # Playwright

# Lint & format
pnpm lint
pnpm format

# Generate a DB migration after schema changes
pnpm db:migrations:generate

The project uses Git hooks (prek) and a blame-ignore-revs file (configured by pnpm prepare). Contributions follow the branching strategy and Contributor Co-creation Program described in the repo's README.md and CONTRIBUTING.md.

Note

The repo includes a v2-refactor-temp/ directory of transitional tooling and docs from the V1→V2 data refactor. Treat it as scaffolding, not stable API.


Things That Do Not Exist

Stating absent surfaces prevents fabricated configuration and false expectations:

  • No central server in the Community Edition. The only HTTP server is the optional, locally-bound CSaaS API server. (Centralized server/admin backend is an Enterprise Edition feature.)
  • No user-facing config file or .env for runtime configuration. Settings live in the SQLite preference table, edited through the UI. Environment variables are build/dev or OS-path only.
  • No cloud account required to use the app. There is no Cherry Studio login for core functionality; provider keys are yours.
  • No telemetry-by-key configuration exposed as a product knob (crash telemetry is initialized internally; there is no user "API config" for it).
  • No multi-tenant/RBAC in Community Edition (that's Enterprise).
  • No webhook receiver — Cherry Studio is an outbound client and a local API server, not a webhook endpoint host.
  • OVMS (OpenVINO Model Server) integration exists only on Windows + Intel CPUs; the Ovms_* IPC is gated accordingly.

Troubleshooting (Operator Reference)

Errors below are taken from the source; messages may include interpolated values.

MigrationEngine not initialized — call initialize() first / Foreign key check failed: N violation(s)

Context: V2 data migration. The engine wasn't initialized, or post-migration FK validation failed. Action: Let the staged upgrade run from a clean baseline (v1.8.1 → v2.0.0). If a migration aborts on FK violations, restore from a pre-upgrade backup and retry; report the violation sample to the maintainers.

Provider '<id>' not found or not enabled (API server)

Context: A request used a providerId::modelId whose provider isn't enabled, or the provider lacks an OpenAI-compatible endpoint. Action: Enable the provider and configure its endpoint; verify the providerId::modelId format.

Provider '<id>' has no OpenAI-compatible chat-completions endpoint configured

Context: Calling /v1/chat/completions for a provider that only exposes an Anthropic endpoint. Action: Use /v1/messages for Anthropic-style providers, or configure an OpenAI-compatible endpoint for that provider.

Unsafe remote url: local or private addresses are not allowed

Context: A fetch (web search/knowledge import) targeted a private/loopback address. Action: Expected protection. Use a public URL, or load local content through the file pipeline instead.

File too large. Maximum size is ... / Only ZIP files are supported (LAN transfer)

Context: LAN transfer constraints. Action: Use WebDAV/S3 for large backups; LAN transfer is for ZIP archives under the size cap.

Git Bash not found (Windows, agentic features)

Context: Code/Agent shell features need Git Bash. Action: Install Git for Windows; the path auto-discovers or can be set via System_SetGitBashPath.

VertexAI requires iam-gcp auth configuration.

Context: Vertex AI selected without service-account/IAM config. Action: Provide a valid GCP service-account configuration in the provider settings.

API server returns 401/403

Context: Missing/empty credentials (401) or no/incorrect server key (403). Action: Set feature.csaas.api_key (API Server settings) and send it as x-api-key or Authorization: Bearer.

Path is outside allowed directory / Permission denied

Context: A file operation escaped allowed directories or lacked OS permissions. Action: Keep operations within agent accessible paths; verify OS permissions on the target.


Quick Reference

Identity & platform

Item Value
App ID com.cherryai.cherrystudio
Product name Cherry Studio
URL scheme cherrystudio://
License AGPL-3.0 (Community); commercial/Enterprise available
Platforms Windows, macOS, Linux (x64, arm64)
Update feed https://releases.cherry-ai.com (+ GitHub/GitCode mirrors)

API server endpoints (auth: x-api-key or Authorization: Bearer)

Method Path
GET /health, /, /api-docs, /api-docs.json (public)
POST /v1/chat/completions (OpenAI)
POST /v1/messages, /{provider}/v1/messages (Anthropic)
GET /v1/mcps, /v1/mcps/{server_id}
* /v1/knowledge-bases, /v1/knowledge-bases/search, /v1/claw/{agentId}/claw-mcp

Key commands

Command Purpose
pnpm dev Run the app in development
pnpm build Production build (OpenAPI + typecheck + electron-vite)
`pnpm build:win mac
pnpm test / pnpm test:e2e Vitest / Playwright
pnpm lint / pnpm format Lint / format
pnpm db:migrations:generate Generate Drizzle migration

Channel types & agent permission modes

  • Channels: telegram, feishu, qq, wechat, discord, slack
  • Permission modes: default, acceptEdits, bypassPermissions, plan