This file provides guidance to AI coding assistants when working with code in this repository. Adherence to these guidelines is crucial for maintaining code quality and consistency.
- Keep it clear: Write code that is easy to read, maintain, and explain.
- Match the house style: Reuse existing patterns, naming, and conventions.
- Search smart: Prefer
ast-grepfor semantic queries; fall back torg/grepwhen needed. - Log centrally: Route all logging through
loggerServicewith the right context—noconsole.log. - Research via subagent: Lean on
subagentfor external docs, APIs, news, and references. - Always propose before executing: Before making any changes, clearly explain your planned approach and wait for explicit user approval to ensure alignment and prevent unwanted modifications.
- Lint, test, and format before completion: Coding tasks are only complete after running
pnpm lint,pnpm test, andpnpm formatsuccessfully. - Write conventional commits: Commit small, focused changes using Conventional Commit messages (e.g.,
feat:,fix:,refactor:,docs:). - Sign commits: Use
git commit --signoffas required by contributor guidelines.
When creating a Pull Request, you MUST use the gh-create-pr skill.
If the skill is unavailable, directly read .agents/skills/gh-create-pr/SKILL.md and follow it manually.
When reviewing a Pull Request, do NOT run pnpm lint, pnpm test, or pnpm format locally.
Instead, check CI status directly using GitHub CLI:
- Check CI status:
gh pr checks <PR_NUMBER>- View all CI check results for the PR - Check PR details:
gh pr view <PR_NUMBER>- View PR status, reviews, and merge readiness - View failed logs:
gh run view <RUN_ID> --log-failed- Inspect logs for failed CI runs
Only investigate CI failures by reading the logs, not by re-running checks locally.
When creating an Issue, you MUST use the gh-create-issue skill.
If the skill is unavailable, directly read .agents/skills/gh-create-issue/SKILL.md and follow it manually.
IMPORTANT: The
mainbranch is now under code freeze. Only critical bug fixes submitted viahotfix/*branches are accepted. Fix PRs must be minimal in scope and must not include any refactoring code.All new features, refactoring, and optimizations should be developed on the
v2branch. We welcome every developer to actively participate in v2 development!The
v2branch will only accept new feature submissions after all current features have been fully refactored.
- Install:
pnpm install— Install all project dependencies (requires Node ≥22, pnpm 10.27.0) - Development:
pnpm dev— Runs Electron app in development mode with hot reload - Debug:
pnpm debug— Starts with debugging; attach viachrome://inspecton port 9222 - Build Check:
pnpm build:check— REQUIRED before commits (pnpm lint && pnpm test)- If having i18n sort issues, run
pnpm i18n:syncfirst - If having formatting issues, run
pnpm formatfirst
- If having i18n sort issues, run
- Full Build:
pnpm build— TypeScript typecheck + electron-vite build - Test:
pnpm test— Run all Vitest tests (main + renderer + aiCore + shared + scripts)pnpm test:main— Main process tests only (Node environment)pnpm test:renderer— Renderer process tests only (jsdom environment)pnpm test:aicore— aiCore package tests onlypnpm test:watch— Watch modepnpm test:coverage— With v8 coverage reportpnpm test:e2e— Playwright end-to-end tests
- Lint:
pnpm lint— oxlint + eslint fix + TypeScript typecheck + i18n check + format check - Format:
pnpm format— Biome format + lint (write mode) - Typecheck:
pnpm typecheck— Concurrent node + web TypeScript checks usingtsgo - i18n:
pnpm i18n:sync— Sync i18n template keyspnpm i18n:translate— Auto-translate missing keyspnpm i18n:check— Validate i18n completeness
- Bundle Analysis:
pnpm analyze:renderer/pnpm analyze:main— Visualize bundle sizes - Agents DB:
pnpm agents:generate— Generate Drizzle migrationspnpm agents:push— Push schema to SQLite DBpnpm agents:studio— Open Drizzle Studio
src/
main/ # Node.js backend (Electron main process)
renderer/ # React UI (Electron renderer process)
preload/ # Secure IPC bridge (contextBridge)
packages/
aiCore/ # @cherrystudio/ai-core — AI SDK middleware & provider abstraction
shared/ # Cross-process types, constants, IPC channel definitions
mcp-trace/ # OpenTelemetry tracing for MCP operations
ai-sdk-provider/ # Custom AI SDK provider implementations
extension-table-plus/ # TipTap table extension
| Alias | Resolves To |
|---|---|
@main |
src/main/ |
@renderer |
src/renderer/src/ |
@shared |
packages/shared/ |
@types |
src/renderer/src/types/ |
@logger |
src/main/services/LoggerService (main) / src/renderer/src/services/LoggerService (renderer) |
@mcp-trace/trace-core |
packages/mcp-trace/trace-core/ |
@cherrystudio/ai-core |
packages/aiCore/src/ |
Node.js backend services. Key services:
| Service | Responsibility |
|---|---|
WindowService |
Electron window lifecycle management |
MCPService |
Model Context Protocol server management |
KnowledgeService |
RAG / knowledge base (via @cherrystudio/embedjs) |
AnthropicService |
Anthropic API integration |
LoggerService |
Winston-based structured logging (daily rotate) |
StoreSyncService |
Syncs Redux state to/from main process |
BackupManager |
Data backup/restore (WebDAV, S3, Nutstore) |
ApiServerService |
Express HTTP API server (Swagger docs at /api-docs) |
AppUpdater |
electron-updater auto-update |
ShortcutService |
Global keyboard shortcuts |
ThemeService |
System theme detection/application |
SelectionService |
Text selection toolbar feature |
CopilotService |
GitHub Copilot OAuth integration |
PythonService |
Pyodide WASM Python runtime |
OvmsManager |
OpenVINO model server management |
NodeTraceService |
OpenTelemetry trace export |
Agents subsystem (src/main/services/agents/):
- Drizzle ORM + LibSQL (SQLite) schema at
database/schema/index.ts - Migrations in
resources/database/drizzle/ - Currently undergoing v2 refactor — only critical bug fixes accepted
React 19 + Redux Toolkit SPA. Key structure:
aiCore/ # Legacy middleware pipeline (deprecated, migrating to packages/aiCore)
api/ # IPC call wrappers (typed electron API calls)
components/ # Shared UI components (Ant Design 5 + styled-components + TailwindCSS v4)
databases/ # Dexie (IndexedDB) — topics, files, message_blocks, etc.
hooks/ # React hooks (useAssistant, useChatContext, useModel, etc.)
pages/ # Route pages (home, settings, knowledge, paintings, notes, etc.)
services/ # Frontend services (ApiService, ModelService, MemoryService, etc.)
store/ # Redux Toolkit slices
types/ # TypeScript type definitions
workers/ # Web Workers
windows/ # Multi-window entry points (mini, selection toolbar, trace)
Slices (redux-persist enabled):
| Slice | State |
|---|---|
assistants |
AI assistant configurations |
settings |
App-wide settings |
llm |
LLM provider/model configs |
mcp |
MCP server configs |
messageBlock |
Message block rendering state |
knowledge |
Knowledge base entries |
paintings |
Image generation state |
memory |
Memory system config |
websearch |
Web search settings |
shortcuts |
Keyboard shortcuts |
tabs |
Tab management |
BLOCKED: Do not add new Redux slices or change existing state shape until v2.0.0.
- IndexedDB (Dexie):
src/renderer/src/databases/index.ts- Tables:
files,topics,settings,knowledge_notes,translate_history,quick_phrases,message_blocks,translate_languages - Schema versioned with upgrade functions (
upgradeToV5,upgradeToV7,upgradeToV8) - BLOCKED: Do not modify schema until v2.0.0.
- Tables:
- SQLite (Drizzle ORM + LibSQL):
src/main/services/agents/- Used for the agents subsystem
- DB path:
{userData}/Data/agents.db(e.g., on macOS:~/Library/Application Support/CherryStudioDev/Data/agents.dbin dev,~/Library/Application Support/CherryStudio/Data/agents.dbin prod)
- Channel constants defined in
packages/shared/IpcChannel.ts - Renderer → Main:
ipcRenderer.invoke(IpcChannel.XXX, ...args)viaapi.*wrappers insrc/preload/index.ts - Main → Renderer:
webContents.send(channel, data) - Tracing:
tracedInvoke()in preload attaches OpenTelemetry span context to IPC calls - Typed API surface exposed via
contextBridgeaswindow.api
The @cherrystudio/ai-core package abstracts AI SDK providers:
src/core/
providers/ # Provider registry (HubProvider, factory, registry)
middleware/ # LanguageModelV2Middleware pipeline (manager, wrapper)
plugins/ # Built-in plugins
runtime/ # Runtime execution
options/ # Request option preparation
- Built on Vercel AI SDK v5 (
aipackage) withLanguageModelV2Middleware HubProvideraggregates multiple provider backends- Supports: OpenAI, Anthropic, Google, Azure, Mistral, Bedrock, Vertex, Ollama, Perplexity, xAI, HuggingFace, Cerebras, OpenRouter, Copilot, and more
- Custom fork of openai package:
@cherrystudio/openai
The renderer builds multiple HTML entry points:
index.html— Main application windowminiWindow.html— Compact floating window (src/renderer/src/windows/mini/)selectionToolbar.html— Text selection action toolbarselectionAction.html— Selection action popuptraceWindow.html— MCP trace viewer
import { loggerService } from "@logger";
const logger = loggerService.withContext("moduleName");
// Renderer only: loggerService.initWindowSource('windowName') first
logger.info("message", CONTEXT);
logger.warn("message");
logger.error("message", error);- Backend: Winston with daily log rotation
- Log files in
userData/logs/ - Never use
console.log— always useloggerService
packages/mcp-trace/provides trace-core and trace-node/trace-web adaptersNodeTraceServiceexports spans via OTLP HTTPSpanCacheServicecaches span entities for the trace viewer window- IPC calls can carry span context via
tracedInvoke()
| Layer | Technologies |
|---|---|
| Runtime | Electron 38, Node ≥22 |
| Frontend | React 19, TypeScript ~5.8 |
| UI | Ant Design 5.27, styled-components 6, TailwindCSS v4 |
| State | Redux Toolkit, redux-persist, Dexie (IndexedDB) |
| Rich Text | TipTap 3.2 (with Yjs collaboration) |
| AI SDK | Vercel AI SDK v5 (ai), @cherrystudio/ai-core |
| Build | electron-vite 5 with rolldown-vite 7 (experimental) |
| Test | Vitest 3 (unit), Playwright (e2e) |
| Lint/Format | ESLint 9, oxlint, Biome 2 |
| DB (main) | Drizzle ORM + LibSQL (SQLite) |
| DB (renderer) | Dexie (IndexedDB) |
| Logging | Winston + winston-daily-rotate-file |
| Tracing | OpenTelemetry |
| i18n | i18next + react-i18next |
- Strict mode enabled; use
tsgo(native TypeScript compiler preview) for typechecking - Separate configs:
tsconfig.node.json(main),tsconfig.web.json(renderer) - Type definitions centralized in
src/renderer/src/types/andpackages/shared/
- Biome handles formatting (2-space indent, single quotes, trailing commas)
- oxlint + ESLint for linting;
simple-import-sortenforces import order - React hooks:
eslint-plugin-react-hooksenforced - No unused imports:
eslint-plugin-unused-imports
- React components:
PascalCase.tsx - Services, hooks, utilities:
camelCase.ts - Test files:
*.test.tsor*.spec.tsalongside source or in__tests__/subdirectory
- All user-visible strings must use
i18next— never hardcode UI strings - Run
pnpm i18n:checkto validate;pnpm i18n:syncto add missing keys - Locale files in
src/renderer/src/i18n/
Several dependencies have patches in patches/ — be careful when upgrading:
antd,@ai-sdk/google,@ai-sdk/openai,@anthropic-ai/vertex-sdk@google/genai,@langchain/core,@langchain/openaiollama-ai-provider-v2,electron-updater,epub,tesseract.js@anthropic-ai/claude-agent-sdk
- Tests use Vitest 3 with project-based configuration
- Main process tests: Node environment,
tests/main.setup.ts - Renderer tests: jsdom environment,
tests/renderer.setup.ts,@testing-library/react - aiCore tests: separate
packages/aiCore/vitest.config.ts - All tests run without CI dependency (fully local)
- Coverage via v8 provider (
pnpm test:coverage) - Features without tests are not considered complete
The main branch is under code freeze. All development has moved to the v2 branch.
mainbranch: Only accepts critical bug fixes viahotfix/*branches. Minimal changes, no refactoring.v2branch: All new features, refactoring, and optimizations go here.
Files marked with the following header are blocked for feature changes:
/**
* @deprecated Scheduled for removal in v2.0.0
* ⚠️ NOTICE: V2 DATA&UI REFACTORING
* STOP: Feature PRs affecting this file are currently BLOCKED.
*/Do not introduce new features to these files. Bug fixes only.
- Never expose Node.js APIs directly to renderer; use
contextBridgein preload - Validate all IPC inputs in main process handlers
- URL sanitization via
strict-url-sanitise - IP validation via
ipaddr.js(API server) express-validatorfor API server request validation