docs/references/data/boot-config-schema-guide.md
This guide explains how to add new boot config keys and covers the V1-to-V2 data migration pipeline.
BootConfig is for a very narrow set of configuration items. Before adding a key here, ask:
| Question | If Yes | If No |
|---|---|---|
| Must it load before the lifecycle system takes over? | BootConfig | Preference |
| Does it affect process-level behavior (Chromium flags, data directory)? | BootConfig | Preference |
Can it wait for the BeforeReady lifecycle phase? | Preference | BootConfig |
| Can it be changed at runtime without restart? | Preference | BootConfig |
Rule of thumb: If the setting can wait until the lifecycle's BeforeReady phase, it belongs in Preference. BootConfig is only for settings that must be available before the lifecycle system even starts. Keep it minimal.
Boot config keys follow the same naming convention as preferences.
namespace.key_name — at least 2 segments separated by dots.
Rules:
/^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$/| Valid | Invalid | Reason |
|---|---|---|
app.disable_hardware_acceleration | disableHardwareAcceleration | Missing dot separator |
app.user_data_path | App.userDataPath | Uppercase, camelCase |
chromium.gpu_compositing | gpu | Single segment |
File: src/shared/data/bootConfig/bootConfigSchemas.ts (auto-generated — do not edit by hand)
The zod schema is the single source of truth: the BootConfigSchema type is inferred from it, and BootConfigService validates file/set values against it at runtime. The current shape:
export const bootConfigSchema = z.object({
'app.disable_hardware_acceleration': z.boolean(),
'app.user_data_path': z.record(z.string(), z.string())
})
export type BootConfigSchema = z.infer<typeof bootConfigSchema>
export const DefaultBootConfig: BootConfigSchema = {
'app.disable_hardware_acceleration': false,
'app.user_data_path': {}
}
This file is fully auto-generated. To add a key, edit
classification.json(simpleboolean/string/numbertypes map to zod automatically) orMANUAL_BOOT_CONFIG_ITEMSin the generator (complex types need an explicitzodTypeexpression), then regenerate — see V1 to V2 Data Migration below.
File: src/shared/data/bootConfig/bootConfigTypes.ts
For simple types (boolean, string, number), no changes needed — the type is inferred from the schema. For custom types, define them alongside BootConfigKey:
export type BootConfigKey = keyof BootConfigSchema
// Custom types if needed
export type GpuMode = 'auto' | 'disabled' | 'software'
Only for settings that must take effect before lifecycle:
File: src/main/main.ts
import { bootConfigService } from '@main/data/bootConfig'
// Apply before app.whenReady()
if (bootConfigService.get('app.disable_hardware_acceleration')) {
app.disableHardwareAcceleration()
}
No additional wiring needed. The BootConfigPreferenceKeys mapped type automatically adds the BootConfig. prefix, making the key available through the unified preference API:
// Renderer — works immediately after adding to schema
const [disableHardwareAcceleration, setDisableHardwareAcceleration] = usePreference(
'BootConfig.app.disable_hardware_acceleration'
)
// Main process lifecycle service
const disableHardwareAcceleration = preferenceService.get('BootConfig.app.disable_hardware_acceleration')
Internal
temp.*keys are the exception. Keys under thetemp.*prefix are main-process-internal transient state and are deliberately excluded from the unified preference API — not inUnifiedPreferenceType, not reachable viausePreference, and rejected at the PreferenceService IPC boundary. Access them only viabootConfigServicedirectly (at any phase), and usebootConfigService.onChange()for notification. See Internaltemp.*namespace.
For detailed usage of usePreference, see Preference Usage Guide.
This section covers the migration toolchain used to move legacy data from V1 (Redux/ElectronStore/Dexie) into the V2 boot config system. This is not the regular path for adding new keys.
The v2-refactor-temp/tools/data-classify/ directory contains the code generation pipeline for migrating legacy data into V2 systems. classification.json is the single source of truth that classifies every legacy key into its target system (Preference, BootConfig, Cache, or DataApi).
classification.json with "category": "bootConfig" maps a legacy key to a boot config keysrc/shared/data/bootConfig/bootConfigSchemas.ts — zod schema, inferred BootConfigSchema type, and defaultssrc/main/data/migration/v2/migrators/mappings/BootConfigMappings.ts — legacy-to-new key mappingsBootConfigMigrator reads values from legacy sources (Redux, ElectronStore, Dexie settings, localStorage, and the legacy home config file) and writes them to bootConfigService| Source | Accessor | Example |
|---|---|---|
| Redux Store | ReduxStateReader with category + dot-path | settings.disableHardwareAcceleration |
| ElectronStore | ConfigManager.get(key) | Direct key lookup |
| Dexie settings | Key-value table | Direct key lookup |
| localStorage | localStorage.getItem(key) | Direct key lookup |
| Legacy home config file | LegacyHomeConfigReader | ~/.cherrystudio/config/config.json (appDataPath field only) |
Config-file source mappings are manually maintained. The
data-classifytoolchain'sclassification.jsondoesn't model config-file sources yet. In two places, a small hand-maintained list complements the classification-driven pipeline:
- Schema keys:
MANUAL_BOOT_CONFIG_ITEMSat the top ofv2-refactor-temp/tools/data-classify/scripts/generate-boot-config.js— these items are merged with the classification-derived items and emitted intobootConfigSchemas.tsas part of the normal auto-generated output. The resulting schema file is fully auto-generated (no manual sections). Each manual item needs an explicitzodTypeexpression string (classification-derived simple types map to zod automatically); the generator aborts on items it cannot map.- Mappings: inline
configFileMappingsinsideBootConfigMigrator.loadMigrationItems()— a smallReadonlyArray<{ originalKey: string; targetKey: BootConfigKey }>whoseBootConfigKeyannotation is the regen safety net: if the schema losesapp.user_data_path, this array fails to compile at its declaration site.To add a new config-file-sourced key in the future: add an entry to
MANUAL_BOOT_CONFIG_ITEMSin the generator, add the matching entry toBootConfigMigrator.loadMigrationItems()'sconfigFileMappings, and runnpm run generate.
To migrate a legacy key to boot config:
classification.json:{
"originalKey": "disableHardwareAcceleration",
"source": "redux",
"category": "bootConfig",
"status": "classified",
"targetKey": "app.disable_hardware_acceleration",
"targetType": "boolean",
"defaultValue": false,
"reduxCategory": "settings"
}
cd v2-refactor-temp/tools/data-classify && npm run generate
BootConfigMappings.ts| Legacy Source | Legacy Key | Target Key |
|---|---|---|
Redux (settings) | disableHardwareAcceleration | app.disable_hardware_acceleration |
Config file (~/.cherrystudio/config/config.json) | appDataPath | app.user_data_path |
The v1 ~/.cherrystudio/config/config.json stores appDataPath as an array of { executablePath, dataPath } entries keyed by executable path. On AppImage Linux builds and Windows portable builds, src/main/utils/init.ts:51-60 writes a special executablePath that differs from app.getPath('exe'):
path.dirname(process.env.APPIMAGE) + '/cherry-studio.appimage'process.env.PORTABLE_EXECUTABLE_DIR + '/cherry-studio-portable.exe'Consumers of app.user_data_path must use getNormalizedExecutablePath() from src/main/core/preboot/userDataLocation.ts so migrated records under AppImage/portable match the lookup key.
| File | Purpose |
|---|---|
src/shared/data/bootConfig/bootConfigSchemas.ts | Zod value schema (single source), inferred BootConfigSchema type, and default values |
src/shared/data/bootConfig/bootConfigTypes.ts | BootConfigKey, Public/InternalBootConfigKey, BootConfigPreferenceKeys mapped type |
src/main/data/bootConfig/BootConfigService.ts | Service implementation |
src/main/data/bootConfig/types.ts | BootConfigLoadError type |
v2-refactor-temp/tools/data-classify/data/classification.json | Migration source of truth |
v2-refactor-temp/tools/data-classify/scripts/generate-boot-config.js | Schema generator (migration) |
src/main/data/migration/v2/migrators/BootConfigMigrator.ts | Migration executor |
src/main/data/migration/v2/migrators/mappings/BootConfigMappings.ts | Auto-generated migration mappings |
namespace.key_name pattern as preferences for consistency.usePreference hook and service API