Last Updated: 2026-03-06 17: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, go2rtc-based camera streaming (WebRTC/MSE), 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).
For detailed architectural information, see the comprehensive reference documents in ai_docs/:
- ARCHITECTURE.md - High-level system overview, bootstrap sequence, managers, services, file organization
- MULTI_CONTEXT.md - Multi-printer context system, coordinators, polling architecture, service dependencies
- IPC_COMMUNICATION.md - IPC handlers, security model, communication patterns, handler registration
- UI_COMPONENTS.md - Renderer architecture, component system, settings dialog, GridStack layout
- WEBUI_HEADLESS.md - Headless mode, WebUI server, static client, CLI modes
- INTEGRATIONS.md - Camera streaming, Spoolman, notifications, Discord, persistence
- THEME_SYSTEM.md - CSS variables, theme computation, design patterns, hardcoded CSS detection
- TOOLING.md - Development tools, commands, testing constraints, code search MCP tools
-
Invoke the
best-practicesskill for universal software engineering principles (SOLID, DRY, KISS, YAGNI, etc.) and theelectronskill for Electron-specific guidance. These skills provide authoritative best practices. -
Gather context efficiently: Prefer
code-search-mcptools for fast, comprehensive codebase searching (see TOOLING.md). For simple queries, useGreporGlobbuilt-in tools. -
Package Manager: This project uses pnpm (not npm or yarn). Use
pnpm install,pnpm add,pnpm <script>, orpnpm run <script>for all package operations. -
Windows Python: On this Windows development environment, always use
pythonnotpython3when running Python scripts or skills. -
Plan before coding: create a multi-step plan (skip only for trivial edits) and keep it updated as you complete steps.
-
Editing: prefer
Edittool for targeted changes, keep diffs minimal, and never revert user-owned changes. Maintain ASCII unless the file already uses Unicode. -
Documentation: every repo-maintained
.ts,.tsx,.js,.jsx, and.cjssource file should begin with an@fileoverviewblock describing purpose, key exports, and relationships. Usepnpm docs:checkto catch gaps undersrc/andpnpm docs:combineto refreshfileoverview-report.md. -
Testing workflow:
pnpm testruns Jest oversrc/,pnpm test:e2eruns browser Playwright against the built WebUI fixture server, andpnpm test:e2e:electron*covers desktop Playwright flows.test:allcurrently excludes the Electron suites, so run the Electron slice explicitly when desktop behavior changes. -
Validation: run the smallest meaningful checks (
pnpm type-check,pnpm lint, targeted scripts) before handing work back. Reservepnpm build*for user requests or when architectural changes demand it. -
Completion Checklist (from TOOLING.md):
- Run type checking, if there's errors iterate until they are fixed properly (no band-aids, etc)
- Once type checking passes, run build. This ensures electron-vite compiles both main and renderer processes without errors, and if there are any, iterate until they are fixed properly (no band-aids, etc)
- Once build passes, the final check is running lint. It's important to never ignore the errors, the more they pile up the harder it becomes to do cleanups/maintain the codebase.
Do not say you are done with something despite not having run one/any of these checks, and the same if one fails. All must be run and pass to ensure codebase quality and production readiness.
-
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 (for example, the 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 streaming:
Go2rtcServiceprovides unified streaming via go2rtc (WebRTC/MSE).Go2rtcBinaryManagerhandles binary lifecycle and configuration handoff. Do not manually configure go2rtc streams outside that service stack. -
Headless mode and desktop mode share the same connection/polling/camera stack. Avoid
isHeadlessMode()forks unless absolutely necessary; duplicating logic leads to drift. -
Theme System: NEVER hardcode colors in CSS. Always use CSS variables from the theme system (
--theme-primary,--theme-primary-hover,--surface-elevated, etc.). The theme system handles light/dark themes automatically. See THEME_SYSTEM.md. -
Per-printer settings access:
PrinterDetailsManagerdoes NOT have agetSettings()method. Per-printer settings (likeshowCameraFps,customCameraUrl,rtspFrameRate, etc.) are stored directly onPrinterDetails. Access them viacontext.printerDetails.showCameraFpsrather than inventing manager methods. Seesrc/shared/types/printer.tsfor the fullPrinterDetailsinterface. -
Release versioning: Semver treats stable versions as newer than prereleases with the same base (
1.0.3 > 1.0.3-alpha.X). After releasing a stable version, the next alpha MUST bump the version number. Correct flow:1.0.3-alpha.1 -> 1.0.3-alpha.2 -> 1.0.3 (stable) | 1.0.4-alpha.1 -> 1.0.4-alpha.2 -> 1.0.4 (stable)Never continue
X.Y.Z-alpha.Nafter releasingX.Y.Zstable -electron-updaterwill look foralpha.ymlin the stable release (which doesn't have it) and 404. -
Legacy mode is per-printer: backend selection must read the saved printer/context setting instead of any global
ForceLegacyAPIoverride. If a 5M-series printer needs legacy behavior, seed or update that printer's own settings rather than adding a process-wide fallback. -
Discovery alignment: the desktop discovery path now follows the updated
@ghosttypes/ff-apidiscovery API. If printers connect but tab state or discovery rows look wrong, inspectsrc/main/index.ts,PrinterDiscoveryService.ts, and renderer tab updates together instead of patching only one layer. -
WebUI cache regressions: built WebUI assets must remain version-stamped and served with no-cache headers. The browser Playwright suite exists specifically to catch stale asset mixes, icon hydration mismatches, and camera bootstrap regressions before release.
-
Desktop E2E boundaries: use
tests/e2e/electron/desktop-smoke.spec.tsfor live%APPDATA%smoke coverage andtests/e2e/electron/desktop-emulator.spec.tsfor isolated emulator-backed lifecycle coverage. On Windows, prefer the dedicatedpackage.jsonscripts over ad hoc Playwright grep invocations.
src/main/bootstrap.ts- sets app name/userData path before anything else loadssrc/main/index.ts- main-process orchestrator (imports bootstrap first, registers IPC, creates windows)src/preload/index.ts/src/renderer/src/ui/component-dialog/component-dialog-preload.ts- context bridges for main + dialog renderers
src/main/managers/PrinterContextManager.ts,PrinterBackendManager.ts,ConnectionFlowManager.ts,PrinterDetailsManager.ts,HeadlessManager.ts,LoadingManager.tssrc/main/services/MultiContextPollingCoordinator.ts,MultiContextPrintStateMonitor.ts,MultiContextTemperatureMonitor.ts,MultiContextSpoolmanTracker.ts,MultiContextNotificationCoordinator.tssrc/main/services/MainProcessPollingCoordinator.ts,PrinterPollingService.tsfor legacy single-printer paths
src/main/printer-backends/*.ts- Legacy, Adventurer5M, Adventurer5M Pro, AD5X implementationssrc/main/printer-backends/ad5x/*- material station transforms/types/utils
- Bootstrap order matters. The HTTP
/detailendpoint requires authentication (serialNumber+checkCode), so during the very first connection — before the user has supplied a check code — we cannot read the firmware-setpidfrom/detail.ConnectionEstablishmentService.tstherefore opens an unauthenticated TCPM115first viatcpClient.getPrinterInfo()and uses the resultingTypeName(firmware-controlled, e.g."FlashForge Adventurer 5M Pro") for backend selection inPrinterUtils.ts(detectPrinterModelType/detectPrinterFamily). This is correct and intentional —TypeNameis firmware-set and not the same as the user-mutableNamefrom/detail. - Once paired, trust the library. After the check code is provided and
FiveMClient.initialize()succeeds,client.isPro/client.isAD5X/info.Pid(from@ghosttypes/ff-api>=1.3.1) are derived from the firmwarepid(35 = 5M, 36 = 5M Pro, 38 = AD5X). All later capability gating should read those flags, not re-substring-matchinfo.Name— that field is user-mutable via the LCD or cloud and re-deriving capabilities from it re-introduces the bug fixed inff-5mp-hass#13. - Don't mutate
client.isAD5Xafter the fact. If the upstream library disagrees with what you expected, fix the library or the backend selection upstream — don't patch the flag locally.
src/renderer/src/renderer.ts,src/renderer/src/gridController.ts,src/renderer/src/shortcutButtons.ts,src/renderer/src/perPrinterStorage.ts,src/renderer/src/logging.tssrc/renderer/src/ui/components/**(ComponentManager, printer tabs, job info, etc.) +src/renderer/src/ui/gridstack/**for layout/palette logicsrc/renderer/src/ui/component-dialog/**- component dialog renderer + preload mirrors
src/main/ipc/handlers/index.ts+ domain handlers insrc/main/ipc/handlers/*.ts,camera-ipc-handler.ts,printer-context-handlers.ts,WindowControlHandlers.ts,DialogHandlers.tssrc/main/windows/WindowManager.ts,src/main/windows/WindowFactory.ts,src/main/windows/factories/*,src/main/windows/dialogs/*
src/renderer/src/ui/settings/settings-renderer.ts- main orchestrator for dual settings management (global + per-printer)src/renderer/src/ui/settings/sections/SettingsSection.ts- base interface for modular sectionssrc/renderer/src/ui/settings/sections/*.ts- individual setting sections (AutoUpdate, DesktopTheme, Discord, InputDependency, PrinterContext, RoundedUI, SpoolmanTest, Tab)src/renderer/src/ui/settings/types.ts,src/renderer/src/ui/settings/types/external.ts- shared type definitions
src/main/services/Go2rtcService.ts,Go2rtcBinaryManager.tssrc/main/ipc/camera-ipc-handler.ts,src/main/webui/server/routes/camera-routes.tssrc/main/services/notifications/*,src/main/services/discord/DiscordNotificationService.ts
src/main/services/SpoolmanIntegrationService.ts,SpoolmanService.ts,SpoolmanUsageTracker.ts,SpoolmanHealthMonitor.tssrc/main/ipc/handlers/spoolman-handlers.ts,src/renderer/src/ui/spoolman-dialog/*,src/renderer/src/ui/spoolman-offline-dialog/*src/main/webui/server/routes/spoolman-routes.ts,src/main/webui/static/features/spoolman.ts
src/main/utils/HeadlessArguments.ts,HeadlessDetection.ts,HeadlessLogger.ts,src/main/managers/HeadlessManager.tssrc/main/webui/server/*(WebUIManager, AuthManager, WebSocketManager, route modules) +src/main/webui/static/*(AppState, Transport, features, grid)docs/README.md- user-facing headless instructions (keep updated)
src/**/__tests__/*- Jest coverage for managers, services, calibration, WebUI server/routes, WebUI static helpers, and build utilitiestests/e2e/browser/webui-smoke.spec.ts,tests/e2e/browser/webui-auth.spec.ts,tests/e2e/browser/helpers/webui-fixture-server.ts- browser Playwright coverage for the built WebUItests/e2e/electron/desktop-smoke.spec.ts- live desktop smoke test against the local FlashForgeUI profiletests/e2e/electron/desktop-emulator.spec.ts,tests/e2e/electron/helpers/emulator-harness.ts- emulator-backed Electron lifecycle coverage across modern and legacy printerstests/fixtures/calibration/- synthetic calibration fixture data (not referenced by automated tests; used for manual local testing)scripts/run-playwright-electron-live.cjs,scripts/run-playwright-electron-emulator.cjs- entry points for the Electron Playwright suitespackage.json- canonical place for the Electron slice scripts (test:e2e:electron:emulator,:legacy,:legacy-multi,:modern-multi,:smoke,:live)
- ARCHITECTURE.md: High-level system overview and architectural patterns
- Specialized Guides: See full list in Architecture Quick Reference section above
GEMINI.md,QWEN.md: Sibling agent guides for cross-AI alignmentdocs/README.md: User-facing setup + headless instructions (update alongside feature changes)ai_specs/*: Authoritative specs for in-flight features; always review before touching scoped areasai_specs/CAMERA_PRIORITY_SPEC.md: Camera proxy + RTSP behavior specificationai_specs/webui-push-notifications.md: Upcoming WebUI push feature plan
fileoverview-report.md(repo root): Aggregates every@fileoverviewblock acrosssrc/**/*.{ts,tsx,js,jsx}. Use it to understand module responsibilities quickly before editing and regenerate it withpnpm docs:combineafter large doc/header refreshes.pnpm find:console: Surfacesconsole.<level>calls (pass-- --level=debugetc.) so you can strip leftover logs before packaging or focus on specific severities quickly.pnpm find:lucide: Shows every file touching Lucide icons, making it simple to prune unused imports or confirm icon hydration paths.pnpm docs:check: Ensures new/updated source files keep their@fileoverviewheaders synchronized with this inventory, including tests, vendored JS copies, and declaration files undersrc/.
Keep this guide synchronized with the repository - update sections when services, flows, specs, or test surfaces change.