This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
pnpm start- Start Expo development serverpnpm android- Run on Android device/emulatorpnpm ios- Run on iOS device/simulatorpnpm prebuild- Generate native code (required before first native run)
npx drizzle-kit generate- Generate database migrations (required before first app run)npx drizzle-kit studio- Open Drizzle Studio for database inspection
pnpm lint- Run ESLint with auto-fixpnpm format- Run Prettier and ESLint formattingpnpm test- Run Jest tests with watch modepnpm check:i18n- Validate internationalization files for missing translationspnpm sync:i18n- Sync translation keys across all language files
Cherry Studio is a React Native/Expo AI chat application with clean architecture principles:
- SQLite + Drizzle ORM: Type-safe database operations with schema-first approach
- Redux Toolkit: State management with persistence via AsyncStorage
- MMKV: High-performance key-value storage for sensitive data
Provider abstraction supporting multiple LLM services (OpenAI, Anthropic, Google, etc.):
Providerclasses handle authentication and request formattingModelManagermanages model configurations and capabilitiesStreamingServicehandles Server-Sent Events for real-time responses- Middleware pattern for request/response processing
Business logic separated from UI components:
BackupService- Data import/export functionalityLoggerService- Application logging with contextFileService- File upload/management operationsTopicService- Chat conversation management
Redux slices with specific purposes:
app- Application initialization and onboarding stateassistant- Assistant configurations and marketplacetopic- Chat conversations and active topicsettings- User preferences and app configurationruntime- Temporary state (not persisted)
Key entities managed via Drizzle ORM:
assistants- AI assistant configurationstopics- Chat conversation threadsmessages- Individual chat messages with metadataproviders- LLM service configurationsfiles- Uploaded attachments and documents
- UI components in
src/components/with clear separation (ui/, sheets/, message-input/) - Screen components in
src/screens/organized by feature area - Custom hooks in
src/hooks/for reusable logic - HeroUI components styled with UniwindCSS utilities for consistent design tokens
Stack-based navigation with React Navigation v7. Main flow: WelcomeScreen → HomeScreen with nested navigators for Settings and Assistant Market.
Supports 5 languages with strict validation. Use t('key') from react-i18next. Translation files in src/i18n/locales/. Scripts ensure consistency across all languages.
- Database schemas:
db/schema/with.sqlfile imports - Type definitions:
src/types/with domain-specific files - Configuration:
src/config/for models and constants - Utils:
src/utils/for pure functions and helpers
Always run npx drizzle-kit generate after schema changes. Database files are handled via Metro bundler configuration supporting .sql imports.
When adding new LLM providers, extend the Provider base class and implement required methods. Register in ModelManager with proper capability flags.
Use Redux Toolkit patterns. Most slices persist automatically except runtime. Handle async operations with createAsyncThunk.
IMPORTANT: When working with Redux state or SQLite database operations, always consult docs/data.md (or docs/data-zh.md for Chinese) for comprehensive data structure documentation including:
- Complete Redux store slice interfaces and relationships
- Full SQLite database schema with all tables and indexes
- Data flow patterns and entity relationships
- Storage considerations and persistence rules
Jest with Expo preset configured. Place tests adjacent to source files with .test.ts suffix.
ESLint enforces import sorting, unused import removal, and React Compiler optimizations. Prettier handles formatting. Both run automatically with pnpm format.
This project uses React Compiler for automatic performance optimization. Generally avoid useCallback and useMemo unless explicitly needed to express intent, as the compiler handles these optimizations automatically.
// Main process
import { loggerService } from '@/services/LoggerService'
const logger = loggerService.withContext('moduleName')
// Renderer process (set window source first)
loggerService.initWindowSource('windowName')
const logger = loggerService.withContext('moduleName')
// Logging
logger.info('message', CONTEXT)
logger.error('message', new Error('error'), CONTEXT)error- Critical errors causing crash/unusable functionalitywarn- Potential issues that don't affect core functionalityinfo- Application lifecycle and key user actionsverbose- Detailed flow information for feature tracingdebug- Development diagnostic info (not for production)silly- Extreme debugging, low-level information