Last Updated: 2025-11-15 18:54 ET (America/New_York)
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
IMPORTANT: This file is automatically loaded into Claude Code's context at the start of each session. To ensure accuracy:
- Check the timestamp above against the current date/time at the start of each session
- If it's been more than 24 hours since the last update, suggest reviewing and updating this file
- After confirming with the user, review all sections for accuracy against the current codebase state
- Update the timestamp after making any changes to this file
- CRITICAL: ALWAYS use the
mcp__time__get_current_timetool with timezoneAmerica/New_Yorkto get the accurate current time before updating the timestamp - NEVER guess or manually write timestamps
The information in this file directly influences how Claude Code understands and works with the codebase, so keeping it current is essential for effective assistance.
FlashForgeUI is an Electron-based desktop and headless controller for FlashForge printers. It supports multi-context printing, material station workflows, Spoolman-powered filament tracking, RTSP/MJPEG camera streaming, Discord + desktop notifications, and a fully authenticated WebUI. The app runs on Windows/macOS/Linux with both GUI and headless entry points (headless automatically boots the WebUI server).
src/bootstrap.tsmust be the first import insidesrc/index.ts. It sets the Electron app name/AppUserModelID before singletons (ConfigManager, PrinterDetailsManager, etc.) readapp.getPath('userData'), preventing headless/Desktop desync.src/index.tsorchestrates the main process: enforces single-instance locks, parses CLI/headless flags, registers all IPC handlers (src/ipc/handlers/index.ts+ legacy handlers), instantiates managers/services, and only creates windows after everything else is wired.src/preload.tsexposes the typedwindow.apibridge with whitelisted channels plus scoped APIs (loading,camera,printerContexts,printerSettings,spoolman, etc.). Every renderer (main window + dialogs) depends on this contract, so keep backward compatibility and cleanup helpers (removeListener,removeAllListeners) intact.src/renderer.tsand helpers undersrc/renderer/*.tsinitialize the component system, printer tabs, shortcut buttons, layout persistence, and logging hooks before delegating most logic to components/services in the main process.
src/managers/ConfigManager.ts– centralized config store wrappingAppConfig(src/types/config.ts)src/managers/PrinterContextManager.ts– issues context IDs, tracks active context, propagates lifecycle eventssrc/managers/ConnectionFlowManager.ts– discovery flows (GUI + headless), manual IP, auto-connect, saved printer restoresrc/managers/PrinterBackendManager.ts– instantiates + maps printer backends (src/printer-backends/*) per contextsrc/managers/PrinterDetailsManager.ts– persistsprinter_details.json+ per-printer settings insideapp.getPath('userData')src/managers/HeadlessManager.ts– orchestrates--headlessboot, WebUI startup, polling, and graceful shutdownsrc/managers/LoadingManager.ts– modal loading overlays surfaced via IPC (main window + dialogs)src/windows/WindowManager.ts/src/windows/WindowFactory.ts– renderer/window lifecycle coordination (main window + dialogs)
- Polling & monitoring:
PrinterPollingService,MainProcessPollingCoordinator(single-printer),MultiContextPollingCoordinator,PrintStateMonitor,MultiContextPrintStateMonitor,TemperatureMonitoringService,MultiContextTemperatureMonitor - Connection/discovery:
PrinterDiscoveryService,ConnectionEstablishmentService,ConnectionStateManager,AutoConnectService,SavedPrinterService,DialogIntegrationService - Camera & streaming:
CameraProxyService,RtspStreamService,PortAllocator,ThumbnailCacheService,ThumbnailRequestQueue - Notifications:
PrinterNotificationCoordinator,MultiContextNotificationCoordinator,services/notifications/*,services/discord/DiscordNotificationService.ts - Filament:
SpoolmanService,SpoolmanIntegrationService,SpoolmanUsageTracker,MultiContextSpoolmanTracker,SpoolmanHealthMonitor - Misc/system:
PrinterDataTransformer,PrintStateMonitor,EnvironmentDetectionService,AutoUpdateService,LogService,StaticFileManager
- IPC entry:
src/ipc/handlers/index.tsregisters domain handlers (backend,camera,component-dialog,connection,control,dialog,job,material,printer-settings,shortcut-config,spoolman, etc.) plus supporting modules (camera-ipc-handler.ts,printer-context-handlers.ts,WindowControlHandlers.ts, legacyDialogHandlers.ts). - Renderer entry:
src/renderer.tsbootstraps printer tabs (src/ui/components/printer-tabs),ComponentManager, grid layout, shortcut buttons, and shared renderer helpers (src/renderer/*.ts). - Dialogs/live UIs:
src/ui/hosts component dialogs, gridstack dashboard, spoolman dialogs, palette/material dialogs, settings, shortcuts, uploaders, log windows, etc. - Window definitions:
src/windows/dialogs/*,src/windows/factories/*(includingComponentDialogWindowFactory).
src/index.ts– Electron entry (detects--headless, sets headless mode, registers IPC, creates main window)src/utils/HeadlessArguments.ts/HeadlessDetection.ts/HeadlessLogger.ts– CLI + detection helpers shared by GUI/headless bootssrc/webui/server/*– WebUI server (WebUIManager, AuthManager, WebSocketManager) + domain routes (routes/camera-routes.ts,context-routes.ts,job-routes.ts,printer-control-routes.ts,printer-status-routes.ts,spoolman-routes.ts,temperature-routes.ts, etc.)src/webui/static/*– TypeScript client (state store, transport, features for auth/camera/spoolman/context switching, responsive grid system, dialogs, headers)
src/utils/PortAllocator.ts– per-context camera proxy ports (8181–8191 range)src/utils/HeadlessArguments.ts,HeadlessDetection.ts,HeadlessLogger.ts,RoundedUICompatibility.ts,CSSVariables.ts,time|camera|error|extraction.utils.ts,EventEmitter.tssrc/types/– contexts, polling, config, printers, spoolman, discord, camera, printer backend operations, IPC
ComponentManager(src/ui/components/ComponentManager.ts) registers every component fromsrc/ui/components/**, initializes them in DOM order, and fans outpolling-updatepayloads. Keep component constructors idempotent—GridStack recreates DOM nodes frequently.- Grid/backplane orchestration lives in
src/renderer/gridController.ts+src/ui/gridstack/*. These modules handle component registration, palette toggles, edit mode, layout serialization, and widget hydration (log panel, job info, etc.). - Printer tabs (
src/ui/components/printer-tabs/*) provide the multi-context UX. IPC events from tabs feed directly intoPrinterContextManager; avoid bypassing these events when adding context-sensitive UI. - Renderer helpers:
src/renderer/perPrinterStorage.ts(layout + shortcut persistence per context),src/renderer/shortcutButtons.ts(top-bar shortcuts + dialog wiring),src/renderer/logging.ts(shared log forwarding). Touch these only when changing renderer-wide behaviors. - Component dialogs reuse the same component stack via
src/windows/factories/ComponentDialogWindowFactory.ts,src/ui/component-dialog/*, and the mirrored preload (component-dialog-preload.ts). Import typings withimport typeonly—runtime.d.tsimports break the preload bootstrap.
The settings dialog uses a modular, section-based architecture for improved maintainability and testability:
- Base Contract:
src/ui/settings/sections/SettingsSection.tsdefines theSettingsSectioninterface withinitialize()anddispose()lifecycle hooks. All sections implement this contract. - Section Implementations (
src/ui/settings/sections/*.ts):AutoUpdateSection: Auto-update configuration and version checkingDesktopThemeSection: Theme selection with live CSS variable updatesDiscordWebhookSection: Discord webhook configuration and testingInputDependencySection: Manages dependent input states (e.g., port fields enabled only when feature is enabled)PrinterContextSection: Per-printer context indicator and settings toggleRoundedUISection: Rounded UI toggle with platform compatibility checks and CSS injectionSpoolmanTestSection: Spoolman server connection testingTabSection: Tab navigation state management
- Orchestrator:
src/ui/settings/settings-renderer.tsinstantiates all sections, coordinates lifecycle, manages dual settings routing (global config.json vs. per-printer printer_details.json), and handles save/validation logic. - Type Definitions:
src/ui/settings/types.tsandsrc/ui/settings/types/external.tsprovide shared interfaces for settings APIs and mutable state.
When adding new settings sections:
- Create a new class in
src/ui/settings/sections/implementing theSettingsSectioninterface - Instantiate and wire it in
settings-renderer.ts'sinitializeElements()method - Call
initialize()during setup anddispose()during cleanup - Keep section logic isolated—sections should not directly manipulate other sections' state
src/ipc/handlers/index.tsis the authoritative registry. Add new handlers there and ensure they are registered before any BrowserWindow is created.- Domain handlers:
backend-handlers.ts,camera-handlers.ts,component-dialog-handlers.ts,connection-handlers.ts,control-handlers.ts,dialog-handlers.ts,job-handlers.ts,material-handlers.ts,printer-settings-handlers.ts,shortcut-config-handlers.ts,spoolman-handlers.ts. - Supporting modules:
camera-ipc-handler.ts(legacy camera IPC surface),printer-context-handlers.ts(context CRUD + switching),WindowControlHandlers.ts(custom title bar), andDialogHandlers.ts(loading overlay + connection dialogs). Keep APIs in sync with the preload’s whitelist. - When adding IPC channels, update
src/preload.tschannel allowlists plus any typed surface (PrinterContextsAPI,SpoolmanAPI, etc.). Dialog-specific handlers should route throughcomponent-dialog-handlers.tsunless they are part of the legacyDialogHandlerspath.
- Context creation:
PrinterContextManagerissues IDs likecontext-1-<timestamp>wheneverConnectionFlowManagercompletes a connect path. Tabs inPrinterTabsComponentdrive the active context via IPC. - Backend wiring:
PrinterBackendManagerinstantiates the correct backend (Legacy, Adventurer5M, Adventurer5M Pro, AD5X) per context, exposes capability flags, and registers printer-specific helpers (material station ops, gcode routing, etc.). - Polling cadence:
MultiContextPollingCoordinatorspins up aPrinterPollingServiceper context. Active contexts poll every 3 s; inactive ones slow to 30 s but still push cached data instantly on tab switch.MainProcessPollingCoordinatorremains for legacy single-printer paths. - Derived monitors:
MultiContextPrintStateMonitor,MultiContextTemperatureMonitor,MultiContextSpoolmanTracker, andMultiContextNotificationCoordinatorlisten for new/remove events to wire per-context instances (print monitors, cooling monitors, spool usage trackers, notification coordinators). Services expect untouchedpolling-updatepayloads. - Integrations: Camera services (
CameraProxyService,RtspStreamService) usePortAllocatorto reserve unique MJPEG/RTSP ports per context. Discord + desktop notifications, Spoolman usage updates, and eventual web push flows (ai_specs/webui-push-notifications.md) hang off the same events. - Cleanup: When
PrinterContextManageremitscontext-removed, every coordinator disposes listeners, closes sockets/servers, releases camera ports, and removes spoolman usage trackers/Discord timers to prevent leaks.
- CLI flags are parsed in
src/utils/HeadlessArguments.tsand validated viavalidateHeadlessConfig. Supported modes:--last-used,--all-saved-printers, or--printers="<ip>:<type>:<checkcode,...>". Extra flags include--webui-port,--webui-password, and camera overrides. HeadlessManager.initialize()(invoked fromsrc/index.ts) forcesWebUIEnabled, applies overrides, connects printers (respecting discovery + saved printers), starts the WebUI server, launches polling/camera proxies, and sets up graceful shutdown.- Headless mode is documented for users in
docs/README.md(update that doc whenever CLI or defaults change).DEFAULT_CONFIG.WebUIPortis 3000; any mention of 3001 is legacy. - The WebUI server (
src/webui/server/WebUIManager.ts) wires Express, authentication (AuthManager), route registration (server/routes/*.tsfor camera, contexts, jobs, printer control/status, spoolman, temperature, theme, filtration), andWebSocketManagerfor per-context real-time updates. Routes reuse the same services/IPC calls as the desktop UI—avoid duplicating logic. - Static client code under
src/webui/static/*mirrors the desktop component model:app.tsbootstraps,core/AppState.ts+core/Transport.tsmanage state + IPC bridge,features/*.tsimplement auth, camera streaming, context switching, job control, layout theme, spoolman, etc., andgrid/*handles component registration + layout persistence (WebUIComponentRegistry,WebUIGridManager,WebUILayoutPersistence,WebUIMobileLayoutManager). WebSocketManagerfans out polling updates per context and feeds the static client; headless deployments typically rely on this for dashboards with no desktop UI running.
CameraProxyService(MJPEG) spins up an Express proxy per context on ports 8181–8191 (managed byPortAllocator). Keep-alive timers were moved to the sharedCameraPriorityspec—do not recycle ports manually or short-circuit the allocator.RtspStreamServiceenables RTSP cameras by wrappingnode-rtsp-stream+ ffmpeg, exposing WebSocket ports starting at 9000 (per context). It auto-detects ffmpeg in common OS paths; missing ffmpeg should produce warnings but never crash the app.- Renderer-side components (
src/ui/components/camera-preview) and the WebUI both expect the proxy URLs emitted by these services. Maintain parity across GUI/headless flows (seeai_specs/CAMERA_PRIORITY_SPEC.mdfor rationale).
- Configuration toggles live in
AppConfig:SpoolmanEnabled,SpoolmanServerUrl,SpoolmanUpdateMode. IPC handlers insrc/ipc/handlers/spoolman-handlers.tsexpose config/get/set/selection APIs to both renderer and WebUI. SpoolmanIntegrationServiceis the source of truth for active spool assignments. It persists selections per printer inprinter_details.json, enforces AD5X/material-station blocking (feature detection + model prefix), validates configuration, and emits events for desktop/WebUI consumers. Do not bypass it.SpoolmanServicewraps the REST API with 10 s timeouts, usage updates (weight or length), search, and connectivity checks.SpoolmanUsageTracker+MultiContextSpoolmanTrackerlisten for print completion/cooling to submit usage updates, whileSpoolmanHealthMonitorpings the server and resets cache/UI state when connectivity flips.- WebUI routing lives in
src/webui/server/routes/spoolman-routes.ts; the static client feature issrc/webui/static/features/spoolman.ts. Keep API responses consistent between desktop and WebUI flows. - Renderer dialogs:
src/ui/spoolman-dialog,src/ui/spoolman-offline-dialog, and spool badges/components embedded in both the main gridstack dashboard and component dialogs. Maintainspoolman-changedevents so everything rehydrates correctly.
- Desktop notifications flow through
services/notifications/NotificationService+PrinterNotificationCoordinator. MultiContextNotificationCoordinatorensures every context gets its own coordinator regardless of which tab is active.- Discord integration (
src/services/discord/DiscordNotificationService.ts) mirrors printer events to webhook embeds with rate limiting and per-context timers. Config keys:DiscordSync,WebhookUrl,DiscordUpdateIntervalMinutes. - Web push notifications are specced in
ai_specs/webui-push-notifications.md. Implementations should addWebPushService, subscription managers, and WebUI UI/worker updates without regressing desktop/Discord flows.
PrinterDetailsManagermanages JSON persistence for printers, last-used serials, per-printer settings (camera, LEDs, spoolman, custom features) and stores runtime context-to-printer mappings.SavedPrinterServiceexposes helpers to match discovered printers, track IP changes, and updatelastConnected. It is the single source for UI lists and headless boot data.AutoConnectServiceandConnectionFlowManagerrely on these stores to auto-launch saved printers or rehydrate contexts after restarts.
- Read the references in
ai_reference/typescript-best-practices.mdandai_reference/electron-typescript-best-practices.mdat the start of every coding session. They capture project-wide patterns (strict typing, IPC hygiene, preload rules, etc.). - Gather context with
rg/rg --filesrather than slower commands. Use targetedsed -n/node -pfor previews. - Plan before coding: create a multi-step plan (skip only for trivial edits) and keep it updated as you complete steps.
- Editing: prefer
apply_patchfor manual changes, keep diffs minimal, and never revert user-owned changes. Maintain ASCII unless the file already uses Unicode. - Documentation: every
.tsfile must begin with an@fileoverviewblock describing purpose, key exports, and relationships. Runnpm run docs:checkif unsure. - Validation: run the smallest meaningful checks (
npm run type-check,npm run lint, targeted scripts) before handing work back. Reservenpm run build*for user requests or when architectural changes demand it.
| Command | Purpose | Notes |
|---|---|---|
npm run type-check |
tsc --noEmit for main process + shared types |
Required before concluding substantial TypeScript changes |
npm run lint / lint:fix |
ESLint across src/**/*.ts |
Run lint:fix first when practical; re-run lint to confirm |
npm run docs:check |
PowerShell script scanning for missing @fileoverview blocks |
Use from Windows shell or ensure PowerShell is available |
npm run knip (+variants) |
Dead code/dependency analysis | Expect intentional false positives (Electron patterns) |
npm run build:* |
Build main / renderer / WebUI / platform packages | Only when user asks or when structural build impacts occur |
npm run linecount |
PowerShell LOC summary | Informational only |
Claude agents can run:
- Static inspection, reasoning about architecture
npm run type-check,npm run lint,npm run docs:check,npm run knip- Targeted node scripts (no GUI)
Agents cannot:
- Launch the Electron UI or WebUI interactively
- Connect to physical printers, cameras, or material stations
- Validate RTSP/MJPEG streams, LED hardware, or actual Spoolman servers
- Perform visual/UI regression testing or multi-window click-throughs
Call out unverified runtime assumptions explicitly in deliverables.
- Component dialog preloads must import typings with
import type {} from '../../types/global';—runtime.d.tsimports break the dialog bootstrap. - The component dialog expects untouched
polling-updatepayloads; do not transform the shape before forwarding toComponentManager.updateAll. - GridStack initialization (
src/ui/gridstack/) already registers and wires widgets (e.g., log panel). Removing or duplicating that flow leaves globals unset. - Spoolman integration deliberately blocks AD5X/material-station contexts (
src/services/SpoolmanIntegrationService.ts). Removing the guard regresses filament safety checks. - Camera proxy keep-alive + port management live in
CameraProxyService/PortAllocatorand the camera priority spec. Do not bypass the allocator or reuse ports manually, especially in headless mode. - Headless mode and desktop mode share the same connection/polling/camera stack. Avoid
isHeadlessMode()forks unless absolutely necessary; duplicating logic leads to drift.
Bootstrapping & Entry
src/bootstrap.ts– sets app name/userData path before anything else loadssrc/index.ts– main-process orchestrator (imports bootstrap first, registers IPC, creates windows)src/preload.ts/src/ui/component-dialog/component-dialog-preload.ts– context bridges for main + dialog renderers
Managers & Multi-Context Core
src/managers/PrinterContextManager.ts,PrinterBackendManager.ts,ConnectionFlowManager.ts,PrinterDetailsManager.ts,HeadlessManager.ts,LoadingManager.tssrc/services/MultiContextPollingCoordinator.ts,MultiContextPrintStateMonitor.ts,MultiContextTemperatureMonitor.ts,MultiContextSpoolmanTracker.ts,MultiContextNotificationCoordinator.tssrc/services/MainProcessPollingCoordinator.ts,PrinterPollingService.tsfor legacy single-printer paths
Backends & Printers
src/printer-backends/*.ts– Legacy, Adventurer5M, Adventurer5M Pro, AD5X implementationssrc/printer-backends/ad5x/*– material station transforms/types/utils
Renderer & Components
src/renderer.ts,src/renderer/gridController.ts,src/renderer/shortcutButtons.ts,src/renderer/perPrinterStorage.ts,src/renderer/logging.tssrc/ui/components/**(ComponentManager, printer tabs, job info, etc.) +src/ui/gridstack/**for layout/palette logicsrc/ui/component-dialog/**– component dialog renderer + preload mirrors
IPC & Windows
src/ipc/handlers/index.ts+ domain handlers insrc/ipc/handlers/*.ts,camera-ipc-handler.ts,printer-context-handlers.ts,WindowControlHandlers.ts,DialogHandlers.tssrc/windows/WindowManager.ts,src/windows/factories/*,src/windows/dialogs/*
Settings Dialog
src/ui/settings/settings-renderer.ts– main orchestrator for dual settings management (global + per-printer)src/ui/settings/sections/SettingsSection.ts– base interface for modular sectionssrc/ui/settings/sections/*.ts– individual setting sections (AutoUpdate, DesktopTheme, Discord, InputDependency, PrinterContext, RoundedUI, SpoolmanTest, Tab)src/ui/settings/types.ts,src/ui/settings/types/external.ts– shared type definitions
Camera, Notifications & Ports
src/services/CameraProxyService.ts,RtspStreamService.ts,src/utils/PortAllocator.tssrc/services/notifications/*,src/services/discord/DiscordNotificationService.ts
Spoolman & Filament
src/services/SpoolmanIntegrationService.ts,SpoolmanService.ts,SpoolmanUsageTracker.ts,SpoolmanHealthMonitor.tssrc/ipc/handlers/spoolman-handlers.ts,src/ui/spoolman-dialog/*,src/ui/spoolman-offline-dialog/*src/webui/server/routes/spoolman-routes.ts,src/webui/static/features/spoolman.ts
Headless & WebUI
src/utils/HeadlessArguments.ts,HeadlessDetection.ts,HeadlessLogger.ts,src/managers/HeadlessManager.tssrc/webui/server/*(WebUIManager, AuthManager, WebSocketManager, route modules) +src/webui/static/*(AppState, Transport, features, grid)docs/README.md– user-facing headless instructions (keep updated)
Specs & References
ai_reference/ARCHITECTURE.md– additional architecture primerai_reference/typescript-best-practices.md,ai_reference/electron-typescript-best-practices.mdai_specs/CAMERA_PRIORITY_SPEC.md– camera proxy + RTSP behaviorai_specs/webui-push-notifications.md– upcoming WebUI push feature plan
fileoverview-collection.json(repo root) aggregates every@fileoverviewblock acrosssrc/**/*.ts. Use it to understand module responsibilities quickly before editing; it lists ~230 entries with filenames plus their summaries.- Run
npm run docs:checkto ensure new/updated files keep their@fileoverviewheaders synchronized with this inventory.
ai_reference/ARCHITECTURE.md: overall system map (consult early).ai_reference/typescript-best-practices.md&ai_reference/electron-typescript-best-practices.md: required reading for code-style and IPC rules.AGENTS.md,GEMINI.md,QWEN.md: sibling agent guides for cross-AI alignment.docs/README.md: user-facing setup + headless instructions (update alongside feature changes).ai_specs/*: authoritative specs for in-flight features; always review before touching scoped areas.
Keep this guide synchronized with the repository—update sections when services, flows, or specs change.