This document is for AI coding agents (and humans) making changes to OpenSpoolMan. Follow it as the default “operating manual” when creating PRs.
OpenSpoolMan augments SpoolMan with Bambu Lab / AMS awareness and optional NFC workflows:
- Keep all operations local-first (LAN where possible).
- NFC is optional; the web UI must remain fully usable without NFC.
- The system is an “adapter + UI” on top of SpoolMan, not a replacement.
If a proposed change alters any of these fundamentals, stop and propose it as a design discussion first.
- Never commit secrets (printer access codes, API keys, cookies, tokens, personal URLs).
- Do not log secrets. Mask them if you must log configuration.
- Treat everything coming from MQTT / HTTP as untrusted input.
- Preserve existing env vars and default behaviors unless explicitly versioned.
- UI behavior must remain functional for:
- No NFC usage
- SpoolMan available/unavailable (graceful handling)
- AUTO_SPEND disabled
- Network calls must have timeouts, error handling, and retry/backoff where appropriate.
- Never introduce busy loops. Prefer event-driven updates or bounded polling.
Key folders/files you will interact with:
app.py/wsgi.py: application entry pointstemplates/,static/: server-rendered UI assetsmqtt_bambulab.py: Bambu printer connectivity (LAN / MQTT)spoolman_client.py,spoolman_service.py: SpoolMan integration layerfilament.py,filament_usage_tracker.py,print_history.py: domain logicscripts/: helper scripts (e.g., initialization / tooling)data/: runtime artifacts (DBs, mismatch logs)tests/: Python testse2e/,playwright.config.js,package.json: end-to-end UI testsdocker-compose.yaml/compose.yaml/Dockerfile: containerizationhelm/openspoolman: Helm chart
- Configure environment (see §5). Create
config.envfromconfig.env.templateor export env vars. - Start the server:
python wsgi.py
Notes:
- Default listen port is
8001(to avoid clashing with SpoolMan). - Depending on SSL mode and mapping you may also access
https://<host>:8443.
- Configure env vars, then:
docker compose up -d
Use docker compose port openspoolman 8001 to see mapped host port if needed.
- Use the bundled chart:
helm dependency update helm/openspoolmanhelm upgrade --install openspoolman helm/openspoolman -f values.yaml --namespace openspoolman --create-namespace
- Validate:
kubectl get pods -n openspoolman
OPENSPOOLMAN_BASE_URL- HTTPS URL where OpenSpoolMan is reachable
- No trailing slash
- Required for NFC writes
PRINTER_ID- Printer settings → Setting → Device → Printer SN
PRINTER_ACCESS_CODE- Setting → LAN Only Mode → Access Code
- (LAN Only Mode toggle may stay off)
PRINTER_IP- Setting → LAN Only Mode → IP Address
SPOOLMAN_BASE_URL- URL of SpoolMan without trailing slash
AUTO_SPENDTrueenables legacy slicer-estimate tracking.
TRACK_LAYER_USAGETrueswitches to per-layer tracking/consumption only ifAUTO_SPEND=True.- If
AUTO_SPEND=False, tracking remains disabled regardless ofTRACK_LAYER_USAGE.
DISABLE_MISMATCH_WARNINGTruehides mismatch warnings in the UI (still detected and logged).
CLEAR_ASSIGNMENT_WHEN_EMPTYTrueclears SpoolMan assignment and resets AMS tray when the printer reports an empty slot.
- Print history DB default:
data/3d_printer_logs.db - Override via:
OPENSPOOLMAN_PRINT_HISTORY_DB - Mismatch log output:
logs/filament_mismatch.json(now includes the detected color distance when a color mismatch occurs)
If you change OPENSPOOLMAN_BASE_URL, NFC tags must be reconfigured.
- SpoolMan can print QR-code labels. When using them with OpenSpoolMan:
- Set SpoolMan’s base URL to OpenSpoolMan before generating labels
- Otherwise labels point back to SpoolMan, not OpenSpoolMan
Agents must not “simplify away” these fields without an explicit migration plan.
Add these extra fields in SpoolMan:
- Filaments:
type(Choice)nozzle_temperature(Integer Range)filament_id(Text)
- Spools:
tag(Text)active_tray(Text)
(Exact choice values are defined in the README; keep behavior compatible with existing installations.)
Filament IDs can be sourced from Bambu Studio’s filament base directory (see README). Do not hardcode user paths; keep it documentation-only.
OpenSpoolMan matches SpoolMan spools to AMS tray metadata:
- Spool
materialmust match AMStray_type(main type). - For Bambu filaments, AMS reports a sub-brand; it must match the spool’s sub-brand.
- Model this either as:
material = full Bambu material(e.g.,PLA Wood) andtypeempty, ORmaterial = base(e.g.,PLA) andtype = add-on(e.g.,Wood)
- Model this either as:
- Parenthesized notes in
materialare ignored during matching (e.g.,PLA CF (recycled)).
If matching fails:
- Prefer improving diagnostics and tooling.
- The UI warning can be hidden with
DISABLE_MISMATCH_WARNING=truebut mismatches must still be logged.
- Read
README.mdsections: installation, environment configuration, matching rules, AUTO_SPEND notes. - Identify the minimal module(s) involved:
- Printer connectivity:
mqtt_bambulab.py - SpoolMan calls:
spoolman_client.py/spoolman_service.py - Domain logic:
filament*.py,print_history.py - UI:
templates/,static/
- Printer connectivity:
- Decide whether you need:
- Python tests (
tests/) - E2E tests (
e2e/via Playwright)
- Python tests (
- Keep functions small and testable.
- Prefer explicit types where they improve clarity (especially for payloads).
- Validate external payloads defensively (missing keys, type mismatches).
- When reading runtime state (e.g.,
PRINTER_STATE, MQTT payloads), prefer accessing the original object via.get(...)rather than copying into temporary locals unless the value needs transformation; this keeps guard logic close to the source and avoids stale snapshots. - Avoid introducing new dependencies without a strong justification.
- Keep logging structured and helpful; never leak secrets.
Minimum expectations before PR:
- If logic changes: update/add Python tests under
tests/. - If UI changes: ensure at least a smoke check and, when possible, run the E2E suite.
- If env/config changes: update README +
config.env.templateaccordingly.
Notes:
- Python tests are configured via
pytest.ini. - E2E is set up via
playwright.config.jsandpackage.json. Use the existing npm scripts rather than inventing new ones unless necessary.
- Scope is minimal; no unrelated refactors
- No secrets or sensitive values introduced
- Errors handled (timeouts, retries/backoff if applicable)
- Tests added/updated (or justification if not)
- README/config updated if behavior or configuration changed
- Docker/Helm impact considered (ports, env vars, volumes)
- Filament matching rules preserved (or explicitly enhanced with tests)
If you touch runtime behavior, check:
- Docker:
Dockerfiledocker-compose.yaml/compose.yamlenv var passing and volumes
- Helm:
helm/openspoolmanchart values and templates- Ensure env vars and defaults align with README
Do not silently change exposed ports or default bindings without updating:
- README
- Compose
- Helm chart
When debugging:
- Confirm
SPOOLMAN_BASE_URLandOPENSPOOLMAN_BASE_URLhave no trailing slash. - Confirm printer values:
PRINTER_IPreachable from the OpenSpoolMan host/containerPRINTER_ACCESS_CODEcorrect
- Inspect mismatch log:
logs/filament_mismatch.json
- Confirm print history DB path:
data/3d_printer_logs.dborOPENSPOOLMAN_PRINT_HISTORY_DB
For AUTO_SPEND / tracking:
- Ensure
AUTO_SPEND=Truebefore expecting any tracking. TRACK_LAYER_USAGE=Trueonly matters whenAUTO_SPEND=True.
- Do not hardcode user-specific paths, hostnames, or ports.
- Do not break “no NFC” operation.
- Do not require cloud access for core workflows.
- Do not change matching semantics without tests and clear migration notes.
- Do not broaden logs to include access codes or private URLs.
- Cloud prints already contain
ams_mappingin theirproject_filepayload, so OpenSpoolMan can map every logical filament to a tray immediately. - Local prints (LAN mode) do not ship
ams_mappingupfront, so we delay applying AMS mappings until the printer reports a concretetray_tar(typically during stage 4 / filament change). That’s why the MQTT log often showstray_tar=255for seconds and only flips to the real tray once the tray itself is loaded.
Prefer these options, in order:
- Add instrumentation and tests rather than guessing.
- Make the smallest change that improves correctness.
- Document assumptions in the PR description and in code comments where necessary.
End of file.