Skip to main content

Startup Phases

Elftia's main process startup flow is divided into 13 phases, each with clearly defined responsibilities and dependencies. All phase code is located in the createServices() function within packages/desktop/app/main/index.ts.

Startup Phase Overview

flowchart TB
P0[Phase 0: Protocol Registration + Logger]
P1[Phase 1: Core Services]
P2[Phase 2: Feature Services]
P25[Phase 2.5: Package Loading]
P26[Phase 2.6: Package Sync]
P27[Phase 2.7: Package Management Service]
PS1[Phase S1: Magi Dispatch]
PS2[Phase S2: MagiService]
PS25[Phase S2.5: CronService]
PC1[Phase C1: Channel Plugins]
PS3[Phase S3: ChannelMagiBridge]
P3[Phase 3: IPC Route Registration]
PT[Phase T1-T3: Todo/Task/Notes]
PW1[Phase W1: Window Creation]
PW2[Phase W2: WebSocket/Protocol]

P0 --> P1 --> P2 --> P25 --> P26 --> P27
P27 --> PS1 --> PS2 --> PS25
PS25 --> PC1 --> PS3
PS3 --> P3 --> PT --> PW1 --> PW2

Phase 0: Protocol Registration + Logger

Executes before app.whenReady(). Registers custom protocols and the core logging service.

flowchart LR
A[Register elftia:// protocol] --> B[Register privileged schemes]
B --> C[wallpaper://]
B --> D[media://]
B --> E[resource://]
StepActionDescription
1app.setAsDefaultProtocolClient('elftia')Register Deep Link protocol
2protocol.registerSchemesAsPrivileged()Register wallpaper/media/resource privileged protocols
3new LoggerService()Create logging service (Winston + daily-rotate)
4setIpcLogger(logger)Set IPC layer logger
5new ErrorHandler(logger)Create global error handler
6setIpcErrorHandler(errorHandler)Set IPC layer error handler
7new AutoUpdateService(logger)Create auto-update service
8new DownloadService(logger)Create download service
9new WebUpdateService(logger, downloadManager)Create web update service

Key files: packages/desktop/app/main/services/infra/logger/LoggerService.ts, packages/desktop/app/main/services/infra/error/ErrorHandler.ts

Phase 1: Core Services

Creates the foundational services required for the application to run; these services have no external dependencies.

flowchart LR
RT[RuntimeService] --> AP[AppPaths]
AP --> DB[DbClient + ready]
DB --> SS[SettingsService]
SS --> CS[ConfigStore]
CS --> Migrate[Config Migration]
Migrate --> Auth[Auth Service Chain]
Auth --> WC[WindowControlsService]
StepServiceDependenciesDescription
1RuntimeServiceNoneRuntime information (version, platform, channel)
2AppPathsNonePath resolution
3DbClientAppPathsDatabase Worker creation
4await db.ready()DbClientBlocking wait until Worker initialization completes
5initDatabase()db.readyDrizzle ORM + WAL + migrate
6SettingsServiceAppPathsApplication settings
7ConfigStoreAppPathselectron-store config file
8migrateSettingsToConfigStore()Settings, ConfigStoreSQLite -> config.json migration
9settings.setConfigStore(configStore)-Delegate pattern connection
10configStore.startWatching()-fs.watch config hot-reload
11AccountServiceAppPathsUser credentials
12AuthTokenStoreAccountServiceToken storage
13AuthSessionServiceRuntime, AuthStore, AuthApiAuth session
14AppPreferencesServiceConfigStoreApplication preferences
15WindowControlsServiceSettingsWindow controls

Key point: await db.ready() is the blocking point that ensures the SQLite Worker has finished creating the schema before proceeding. This prevents the SQLITE_BUSY error that occurs when two connections write simultaneously on first startup.

Phase 2: Feature Services

Creates lightweight feature services; heavy initialization is deferred until use.

ServiceDependenciesDescription
ConfigManagerLogger, AppPathsConfig file management
SecurityServiceLoggerAES-256-GCM encryption
PerformanceMonitorLoggerPerformance monitoring
CacheServiceLoggerGeneral-purpose cache
DatabaseOptimizerLogger, DbClientSQLite optimization
NotificationServiceLoggerDesktop notifications
PluginManagerLoggerPlugin lifecycle
ProjectServiceDbClient, AccountServiceProject management
DiagnosticsServiceAppPaths, ProjectServiceDiagnostics service
ChatServiceLoggerChat service
McpServiceLoggerMCP server management
LLMConfigServiceAppPaths, DbClientLLM configuration
CompletionServiceAppPaths, LLMConfigServiceLLM completion
ApiKeyPoolServiceDB, CompletionServiceMulti-key round-robin
ElfiServiceConfigStore, LLMConfig, CompletionElfi assistant
MediaConfigServiceAppPaths, DbClientMedia configuration
ImageGenerationServiceMediaConfigImage generation
ThemeServiceSettings, AuthSessionTheme management
AgentServiceDbClient, Settings, LoggerAgent service
TransformerService-Request transformation
WebSearchService-Web search
EngineDispatcher + engine registrationEach engine's dependenciesEngine dispatch

Engine Registration Order

{/* Engine registration */}
engineDispatcher.registerEngine(new ApiEngine(...));
engineDispatcher.registerEngine(new ChatEngine(...));
engineDispatcher.registerEngine(new ClaudeSdkEngine(...));
engineDispatcher.registerEngine(new CliRunnerEngine(...));
engineDispatcher.registerEngine(new TinyElfEngine(...));
engineDispatcher.registerEngine(new STChatEngine(...));

Phase 2.5: Package Loading

Loads Agent packages, Persona packages, and Script plugins from disk into memory.

flowchart TB
subgraph "Phase 2.5a: Agent Packages"
AL[AgentPackageLoader] --> BP[Load builtin packages]
BP --> UP[Load user packages]
UP --> AR[AgentPackageRegistry]
end

subgraph "Phase 2.5b: Persona Packages"
PL[PersonaPackageLoader] --> BPP[Load builtin packages]
BPP --> UPP[Load user packages]
UPP --> PR[PersonaPackageRegistry]
end

subgraph "Phase 2.5c: Script Plugins"
SL[ScriptPluginLoader] --> BSP[Load builtin plugins]
BSP --> USP[Load user plugins]
USP --> SR[ScriptPluginRegistry]
end

Load paths (dual-directory pattern):

Package TypeBuiltin Path (packaged)Builtin Path (dev)User Path
Agentresources/agent-packages/../../agent-packages/{userData}/agent-packages/
Personaresources/persona-packages/../../persona-packages/{userData}/persona-packages/
Scriptresources/script-plugins/../../script-plugins/{userData}/script-plugins/

Phase 2.6-2.7: Package Sync and Management

PhaseActionDescription
2.6PackageSyncService.syncAll()Syncs in-memory package definitions to the database (upsert FK anchors + persona data)
2.7new AgentPackageService(...)Creates the package management service, supporting install/uninstall

Phase S1: Magi Dispatch

Creates services related to Agent orchestration and dispatch.

flowchart TB
AGM[AgentManagementService] --> EB[SessionEventBus]
EB --> AD[AgentDiscovery]
AD --> AO[AgentOrchestrator]
AO --> MR[MessageRouter]
MR --> SDI[SessionDispatcherImpl]

AO -.->|setEngineDispatcher| ED[EngineDispatcher]
AO -.->|setDbProvider| DB[DbClient]
SDI -.->|injected into| TE[TinyElfEngine]
StepServiceDescription
1AgentManagementServiceAgent CRUD + package registry queries
2InternalSessionEventBusSession event publish/subscribe
3AgentDiscoverySchedulable Agent roster (discovered from DB + package registry)
4AgentOrchestratorAgent dispatch and orchestration; API dispatch handler
5MessageRouterDual-mode message routing (direct / via Orchestrator)
6SessionDispatcherImplCross-session dispatch implementation
7Injected into TinyElfEnginetinyElfEngine.setSessionDispatcher(sessionDispatcher)
8SubagentRegistry.setDb(db)Subagent registry write-through persistence

Historical note: The DispatchServer HTTP dispatch server was removed in cleanup-legacy-mcp (2026-05-19). The dispatch tool is now assembled in-process via MagiDispatchProvider + MagiDispatchHandlers through the unified registry; handlers call AgentOrchestrator / AgentDiscovery directly without going through HTTP. CLI subprocesses access it through the central services/capabilities/tools/mcp-builtin/BuiltinMcpHttpServer.ts.

Phase S2: MagiService

Creates the core message-processing service and injects all dependencies.

{/* MagiService dependency injection chain */}
const magiService = new MagiService(
magiWorkspace, magiSession, magiOptionsBuilder,
magiOrchestrator, magiMessageRouter, magiEventBus,
llmConfig, logger, configStore,
);

// Deferred injection (avoids circular dependencies)
magiService.setAgentService(agent);
magiService.setCompletionService(completion);
magiService.setAsrService(new AsrService(asrConfig));
magiService.setEngineDispatcher(engineDispatcher);
magiService.setDbProvider(db);
magiService.setMcpListProvider(() => mcp.list());
magiService.setDeveloperModeProvider(() => ...);

MCP hot-reload: When the MCP server list changes, it automatically syncs to the Magi workspace and hot-reloads active sessions:

mcp.on('servers:changed', () => {
magiService.syncMcpServersToWorkspace();
magiService.notifyMcpChanged();
});

Phase S2.5: CronService

Creates the Cron scheduled task service:

InjectionPurpose
setNotificationService(notification)Desktop notifications
setNotificationChecker(...)Check notification preferences
setAgentExecutor(...)Execute scheduled tasks via MagiService
setStatusBroadcaster(...)Broadcast task status to the frontend

Phase C1: Channel Plugins

Discovers, loads, and registers Channel plugins.

flowchart TB
CL[ChannelPluginLoader] --> Discover[discover plugins]
Discover --> Load[load each plugin]
Load --> CR[ChannelPluginRegistry.registerPlugin]
CR --> CM[ChannelMarketplaceService<br/>async fetch remote manifest]

subgraph "Security Service Wiring"
UPS[UserPermissionService] --> CMR[ChannelMessageRouter]
CPG[ChannelPermissionGate] --> CMR
AL[AuditLogger] --> TE[TinyElfEngine]
RL[RateLimiter] --> CMR
IS[InputSanitizer] --> CMR
PG[PromptGuardian] --> CMR
end

CR --> CMR

Load paths (dual-directory pattern):

SourcePath (packaged)Path (dev)
Bundled (read-only)resources/bundled-channel-plugins/elftia-channels/dist-plugins/
Marketplace (writable){userData}/channel-plugins/same

Security service wiring order:

  1. UserPermissionService -> ChannelMessageRouter (user permission check)
  2. ChannelPermissionGate -> ChannelMessageRouter + TinyElfEngine (permission confirmation)
  3. AuditLogger -> TinyElfEngine (audit logging)
  4. RateLimiter -> ChannelMessageRouter (rate limiting)
  5. InputSanitizer -> ChannelMessageRouter (input sanitization)
  6. PromptGuardian -> ChannelMessageRouter (prompt injection detection)

Phase S3: ChannelMagiBridge

Bridges Channel events to MagiService:

const channelMagiBridge = new ChannelMagiBridge(
channelRegistry,
channelMessageRouter,
magiService,
logger,
);

Historical note: The ChannelServer HTTP server was removed in cleanup-legacy-mcp (2026-05-19). The channel_send / channel_list and other tools are now assembled in-process via MagiChannelProvider + MagiChannelHandlers through the unified registry; handlers call ChannelPluginRegistry / ChannelMessageRouter directly.

Phase 3: IPC Route Registration

All IPC handlers are registered before window creation.

const router = new Router(/* 60+ service dependencies */);
const { skillHubDownloadService } = router.register();

registerAllRouters() internally creates and registers 68+ Router instances:

Router ClassChannel Prefix
AuthRouterauth:*
ProjectRouterprojects:*
SessionRoutersessions:*
CompletionRoutercompletion:*
LLMRouterllmProviders:*, llmModels:*
MediaRoutermedia:*
MagiRoutermagi:*
ChannelPluginRouterchannels:*
SecurityRoutersecurity:*
TodoRoutertodo:*
TaskRoutertasks:*
NoteRouternotes:*
SubagentRoutersubagents:*
ElfiRouterelfi:*
EnvironmentRouterenv:*
... and 50+ other routers...

Phase T1-T3: Todo/Task/Notes

flowchart LR
T1[Phase T1: TodoService] --> T1a[initialize — load TODO.md]
T2[Phase T2: TaskService] --> T2a[initialize — scan tasks]
T3[Phase T3: NoteFileService + NoteWatcher] --> T3a[ensureVaultDir]
T3a --> T3b[scanAllNotes + reindex]
T3b --> T3c[DB notes migration check]
PhaseServiceAction
T1TodoServiceInitialize the Markdown to-do system
T2TaskServiceInitialize filesystem + SQLite task management
T3NoteFileServiceEnsure vault directory exists
T3NoteWatcherFilesystem watcher
T3Notes migrationOne-time migration from DB to .md files
T3Startup reindexScan all notes and update DB index

Phase W1: Window Creation

Creates the BrowserWindow after all services and IPC routes are registered:

mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
sandbox: true,
preload: preloadPath,
},
});

Phase W2: WebSocket/Protocol Handling

Post-window-creation initialization:

StepAction
1Register wallpaper:// protocol handler
2Register media:// protocol handler
3Register resource:// protocol handler
4Load renderer URL (dev server or file://)
5Process pending Deep Links
6Restore Channel instances (autoConnect)
7Content Security Policy configuration
8Navigation interception (isAllowedNavigation)

Startup Timing

createServices() records timing at key phases:

[INFO] Core services initialized { duration: ~50ms }
[INFO] Feature services created { duration: ~200ms }
[INFO] Agent packages loaded { builtin: N, user: M }
[INFO] Persona packages loaded { builtin: N, user: M }
[INFO] Script plugins loaded { builtin: N, user: M }
[INFO] Magi dispatch services created (Phase S1)
[INFO] MagiService created (Phase S2)
[INFO] ChannelMagiBridge created (Phase S3)
[INFO] IPC handlers registered { duration: ~500ms }
FileDescription
packages/desktop/app/main/index.tsMain process entry; createServices() function
packages/desktop/app/main/services/routers/index.tsregisterAllRouters() route registration
packages/desktop/app/main/db/index.tsinitDatabase() database initialization
packages/desktop/app/main/workers/DbClient.tsDatabase Worker client
packages/desktop/app/main/services/infra/logger/LoggerService.tsLogging service
packages/desktop/app/main/services/infra/paths/paths.tsAppPaths path management
packages/desktop/app/main/services/platform/config/store/ConfigStore.tsConfig store + fs.watch
packages/desktop/app/main/services/agent-core/agent/AgentPackageLoader.tsAgent package loader
packages/desktop/app/main/services/agent-core/agent/PersonaPackageLoader.tsPersona package loader
packages/desktop/app/main/services/capabilities/tools/script-plugin/ScriptPluginLoader.tsScript plugin loader
packages/desktop/app/main/services/capabilities/integrations/channel/ChannelPluginLoader.tsChannel plugin loader
packages/desktop/app/main/services/agent-core/magi/MagiService.tsMagi core service
packages/desktop/app/main/services/agent-core/magi/AgentOrchestrator.tsAgent dispatch orchestrator
packages/desktop/app/main/services/platform/cron/CronService.tsScheduled task service
packages/desktop/app/main/services/content/workspace/todo/TodoService.tsTo-do service
packages/desktop/app/main/services/content/workspace/tasks/TaskService.tsTask management service
packages/desktop/app/main/services/content/workspace/notes/NoteFileService.tsNote file service