Self-hosted print archive and management system for Bambu Lab 3D printers
저장소 README에서 가져옴
README
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Self-hosted print archive, management and automation system for Bambu Lab 3D printers
Hard fork of Bambuddy by maziggy, with Telegram bot, multi-chat auth, Ukrainian locale and more
BamDude grew out of a volunteer workshop. Its author volunteers with
DrukArmy — Ukraine's largest volunteer 3D-printing
effort for the front line — printing, and running the FPV direction as senior curator.
BamDude grew out of a volunteer workshop. Its author volunteers with
DrukArmy — Ukraine's largest volunteer 3D-printing
effort for the front line — printing, and running the FPV direction as senior curator.
Batches, deadlines and a farm that has to keep moving around the clock do not fit any
off-the-shelf tool, so every feature here earned its place on a real order first. That is also
why Ukrainian is a first-class locale rather than an afterthought.
If you have a printer and want it to do something useful:
join DrukArmy.
Ukraine's largest volunteer 3D-printing community, printing for the front line. BamDude was born in this workshop — and if you have a printer, there is useful work waiting for it: join.
A volunteer 3D-printing initiative: a 24/7 print farm making plastic gear for Ukraine's defense forces, with fully transparent finances — everything public, counted automatically.
Ukraine's #1 3D-printing marketplace: post a job and verified makers place blind bids — FDM, SLA and SLS printing, 3D modelling and post-processing.
Support
BamDude is free and stays free — AGPL-3.0, no paid tiers, no pro edition. The most valuable
support is a bug report, a translation PR or a star. If you would rather chip in:
0.7.1 keeps whether a file carries its own plate-swap sequence as a fact of the print file — older archives are unknown until you declare them — and lets you review and repair unresolved print-state conflicts from System. Smart-plug schedules repeat every day, energy accounting and Telegram cards are steadier, and printers can opt into automatic assignment of full inventory spools on loading. It also adds server-rendered pictures of printed parts, STEP thumbnails, whole-plate order quantities, forecasts that account for operator hours, loose stock components in order plans and a saved extra percentage on printed BOM parts. Swap farms: review the declaration of older archives before reprinting with BamDude's swap macros — see the 0.7.1 changelog.
0.7.0 adds configurable products (SKU, version, category and variants), five order views with stages and responsible operators, finished-goods stock and numbered dispatch notes. Orders, Products, Customers and Stock have separate permissions; review custom groups after upgrading. From a library file or its plate gallery, Add to order… opens a one-off product with that file already selected.
After 0.7.1, in the current development branch: shared editable order plans and machine-hour comparisons, improved plate selection, LAN HTTP submission, bulk retry of failed queue jobs, quieter AutoQueue obstacle notifications, filament-segment accounting, camera-light fixes, and responsive library controls with corrected folder trash handling. An unclean shutdown pauses new farm starts until an operator confirms recovery; reconnects do not revoke that confirmation or block the macros of an existing print. Info shows print-state inconsistencies and offers confirmed repair actions, including inspection of a completed queue item still held by a printing queue header.
Docker latest follows the latest stable release tag; dev follows the beta channel. Check the release changelog for what your image includes.
What's different from Bambuddy?
BamDude is a hard fork of Bambuddy, aimed at print farm operators. It still tracks upstream — each release is adapted through a tracked audit rather than a blind merge — so what the two projects share is deliberately not listed here. Each item below is either absent upstream or built on a different principle.
A queue built for a farm, in two tiers
Waiting is an explicit choice, not an unexplained green button. Print and Schedule check the complete filament assignment. If compatibility is unverified or refused, normal submission is disabled with an explanation; a separate confirmed action queues the job to wait, warning that it can hold up later jobs on that printer. Auto-Queue distinguishes an absent target model and offers deliberate storage for a future printer. A compatible but busy printer still accepts queue work. See the routing guide.
One queue per printer, plus an Auto-Queue that distributes between them. Work you have already assigned waits in that printer's own queue. Work you have not goes to the Auto-Queue, which routes it to whichever printer can take it — matching filament type and colour, and preferring an idle printer without refusing a busy one.
A queued file is independent of its original. Accepting work makes one verified, immutable copy in data/queue-sources/. A laptop can sleep, an SMB share can disconnect, an external library file can be moved or deleted, and an archive can be cleaned without changing a job already in either queue. Copy Queue reuses that accepted copy for another compatible printer, then asks for that printer's current AMS mapping and options; it never needs the original again. Identical bytes are stored once and remain until their last printer-queue or Auto-Queue job is removed; portable backups include the queue copies that their database snapshot names.
The Schedule dialog asks once per group, not once per file. Files whose answers would coincide — same printer model and nozzle, same filament types, same build plate — are grouped, and one dialog stands for the group: the printer or auto-queue you chose, when it should start, how many copies, the print options and macros. Each file still keeps its own plates and gets its own filament mapping. A different filament colour does not split a group; a filament type nothing on the chosen printer can supply stops the run and shows you that file. Any group can be declined with a tick, and then its files are asked about one by one — already filled in with the answer you gave.
A single dispatch layer. Queued prints, prints started from the printer's own screen, and files sent straight from a slicer all leave through one dispatcher. It claims the printer for the whole plate change, creates exactly one archive per physical print, and runs the swap macro before letting the next job in.
Firmware for the whole farm, not one printer at a time
A console for bulk firmware updates. Upstream updates a printer. BamDude takes a set of them, groups the set by model, downloads each model's firmware once into a shared store, and fans the transfer out under a concurrency cap — applying remotely where the model allows it.
A printer that is printing is skipped, not interrupted, and one printer failing does not stop the rest of the batch.
It is deliberately a separate orchestrator from print dispatch: firmware is not a print, and the single-dispatch rule stays intact.
Telegram as a full second interface
Upstream can send a Telegram message — a notification channel, one way, over the Bot API. BamDude's is a complete aiogram 3.x bot you can hold a conversation with:
Live status, printer control, camera snapshots and print-speed mode
Controls under the camera snapshot — see the problem, act on it in the same message, rather than reaching for a VPN and the web
Skip a failed object — the plate seen from above with a numbered pin on each part; press the number, confirm by name, and the other nineteen carry on printing
Print from the library — pick a file, pick a model-compatible printer, print now or queue it
Send the bot a file — it lands in the library with the same checks as a web upload, and offers to print it right there
Maintenance — see what is overdue, mark it done, edit the hours
Add a printer — type an IP and let SSDP fill in the serial, name and model
Multi-chat with roles — every chat gets its own permission group, so a shop-floor chat and an admin chat are not the same thing
Per-chat notification settings — event types, printer scope, milestone floor, quiet hours and the daily digest belong to the chat, not to a global switch
Actionable notifications — "Clear plate" and "Mark maintenance done" are buttons in the message itself
Zigbee, with no hub in between
BamDude drives the radio itself. Upstream reaches Zigbee devices only through a Zigbee2MQTT bridge, as MQTT topics; BamDude talks to the dongle over USB or Ethernet, so smart plugs and temperature/humidity sensors pair into a network it owns — no Home Assistant, no Zigbee2MQTT, no broker to keep alive.
Reporting intervals per device, defaulted from ZHA's own values and changed from the device's card.
Measurement history — power draw and room conditions recorded as they arrive and kept for a month, charted per plug and per sensor. It is written above the plug drivers, so all five plug types get it rather than only the Zigbee ones.
Sensor alarms — a lowest and/or highest value for anything a sensor measures, including its own battery.
A Virtual Printer that saves into the library
A file sent from the slicer lands in the file library, not in the print archive. Upstream's virtual printer archives whatever it receives, or holds it for review. BamDude's default mode saves the 3MF into the library as a file you can browse, tag, move into a folder and print later — which leaves the archive as what it is meant to be, a record of prints that actually happened.
It can also feed either queue tier — a printer's own queue, or the Auto-Queue — as well as relay to a real printer.
The archive is a record of prints, and it is kept honest
One record, not two. Upstream keeps a print log beside the archive. BamDude has no separate log because the archive is the log: every print is a row there — with its file, its plate, its filament, its energy and how it ended — so there is never a second list to reconcile against the first.
A print nobody queued is still archived. Started from the printer's own screen, or sent straight from a slicer — BamDude notices it and builds the archive around it.
If the file could not be fetched at the time, BamDude keeps trying. A printer that was busy, offline or mid-reconnect leaves an archive with no 3MF behind it; a retry service fills it in later from four separate triggers — a sweep at startup, the printer reconnecting, the print finishing, and a button.
A reconciliation sweep compares what BamDude believes is printing against what the printers actually report, so a job that ended in a way nobody saw does not sit there forever claiming to be running.
Two hashes per archive, because the file that prints is not always the file you handed over. BamDude patches the 3MF on its way to the printer, so an archive records both the original and the bytes actually sent. Deduplication on disk keys off the original — the same plate printed on five printers is stored once — and deleting an archive removes the file only when the last reference to it goes.
Projects are orders, and they say what to print next
A project used to be a folder with a target number written on it. It is an order now: who it is for, what it is worth, when it is due — and lines that each say product × quantity. What a thing is made of is a property of the product, not of the order that happens to want twelve of them.
Customers, orders, products and stock — four sections that mean different things. A line names a product and a quantity, with a material that filters and a colour that only hints; the order above it carries the customer, the price (and therefore the margin), the priority and the deadline. A product carries its parts — printed ones with how many go into one unit, purchased ones with a price and a link — and its plates, a plate being no more than "this plate of this file makes these parts". The same part sliced once per printer model is two plates of one product, not two products. Stock tracks finished configurations and free parts separately, with reservations, issues and dispatch notes.
"What to print next", per line, recalculated on every read. BamDude picks plates greedily against the farm as it is loaded, until the line's shortfall is covered: plates that make the same still-needed parts are compared by when they would finish all of that work — one printer gets one 10-piece plate rather than two 5-piece prints, several printers still share it — and useful parts per hour only break ties. It subtracts what is already committed: prints in progress, everything sitting in both queues, and stock reserved for the line. Take from stock also reserves loose components even when no complete kit is available, so the plan asks only for the missing parts. Nothing is cached, so putting six plates in the queue and asking again offers six fewer.
A line whose parts are sliced for two machines is offered both. Alternative plates of equal yield come with the row, and the count can be split across them — which is the only way one line's work reaches two printer models, because the auto-queue routes each file to the machines it was sliced for. Work sent from the plan carries the full print profile you saved for that model, macros and all, rather than the writer's own defaults.
The split is a starting point, not a sentence. With Rebalance across printer models on (off by default), idle printers of another model take a line's still-pending prints when that finishes the line sooner — recalculating plates and counts for that bed, so a 6-part plate becomes three 2-part prints on a mini, or two parts one print on a bigger bed with at most a plate's worth of surplus. The same procedure runs on demand from the line's Rebalance button and from any pending row or ×N block on the auto-queue panel, which says why a row cannot move. Never moved: prints already handed to a printer, scheduled, staged, pinned to filament slots, aimed at a location, queued from an archive, or not filed under a line; a moved row wears a ← P1S badge.
A print is filed under its order where it is started. The print and auto-queue dialogs ask "which order is this for?" and offer the orders that still need this plate first, with how many prints each still wants; the queue writers fill in the line themselves when exactly one line of the named order can accept the plate, and refuse to guess between two. An order is never guessed — one product stands in many orders, and only the person pressing Print knows which.
Locations that nest
A workshop holds shelves, a shelf holds printers. Printers, sensors and spool storage attach at whichever level fits, and the printers, queues and maintenance views group by them.
A wider command base to the printer
Both projects can set a temperature, a fan speed and jog the bed. BamDude speaks a considerably wider slice of the MQTT protocol beyond that, mirrored from BambuStudio's own sequences:
The extruder and the steppers. Push and retract filament, and release the motors so the head can be pushed by hand. Both refuse a cold nozzle and a running print.
The air duct as a whole, not just a fan speed — mode, filtration and every fan the machine has, with each fan's controllability resolved per mode, and the steps the printer actually accepts rather than a made-up 0/25/50/75/100.
The print options Bambu Studio exposes and upstream never sends: air-print detection, auto-recovery, automatic filament switching, filament tangle, nozzle-blob detection, plate alignment, plate marking, plate type, air purification, sound, and saving remote prints to storage.
The AMS as a device, not just slots — calibrate it, switch its firmware personality, reset its sequence, change its user settings. Backed by a Printer Settings and an AMS Settings dialog, each writing through MQTT and recording every applied change in an audit table.
AMS Backup compatibility emulation — per printer, off by default: manually assigned spools can be advertised to the AMS under one canonical colour and/or the Generic profile of their base material, so the firmware treats several compatible spools as one auto-refill group. Only the advertisement changes — the spool, its colour, brand and accounting stay as they are, routing and dispatch keep matching the real spool, and RFID spools are never touched. The AMS Backup dialog applies the policy to the assigned slots with a preview and a per-slot reason, and the same button rolls them back; the printer's own reported backup groups stay the only proof a group actually formed.
Filament calibration over MQTT — Pressure Advance and flow-rate runs started, tracked and read back, with K-profiles per nozzle and per extruder.
Timelapse storage — which medium records it on a machine that has two, how much room is left there, and dropping the oldest recording to make room for the next one.
The printer's answer is read back. Commands carry an acknowledgement listener, so a refusal is reported as a refusal instead of as success — and temperature requests are bounded by the machine's own limits rather than by a fixed table.
Also here:
G-code macros — sequences you define, sent over MQTT, with plate-swap macros firing automatically between queued prints.
3MF patching on the way to the printer — mesh-mode flags and G-code injection are applied to a copy, so the archived file on disk stays the unpatched original.
The printer's built-in storage, not only the card
X2D, P2S and the H2 family keep files in built-in storage as well as on a card. Both projects talk to those printers over FTP, which only ever sees the card — so with no card inserted the file browser is empty and every print fails, on a machine that needs no card at all.
BamDude speaks the printer's own file channel alongside FTP, and the difference shows up as ordinary behaviour rather than as a feature:
The file browser has a SD card / Internal storage switch, and everything it does works on both — listing, downloading, plate previews, importing into the library, deleting. A printer with no card opens on its internal storage instead of on an empty list. Printers that have only a card show no switch and behave exactly as before.
A print goes to internal storage when there is no card, over the same dispatch as always. Whether a printer gets this is decided by what the printer reports about itself, not by a list of model names — and a card that is present but unreadable still stops the print rather than being routed around.
A print started from the printer's own screen gets its file into the archive, pulled back off the machine even when the card that would normally hold it isn't there.
Timelapses are found on whichever medium recorded them, and the right one is attached. The printer reports the full path of the recording it has just finished, so that file is taken by name rather than "the first one that was not there before". On internal storage it also says which print each recording belongs to, matching it to the right archive outright.
The channel exists only on that newer generation, and BamDude decides by asking the printer rather than by model name — an open port proves nothing, since on A1 and P1 the same port belongs to the camera.
Filament identity the way the slicers model it
Bambu Studio thinks in filament families: one identity (filament_id) behind every "Generic PETG" or your own custom filament, with per-printer presets hanging under it. BamDude adopts that model outright:
A built-in catalog of every official filament, distilled from Bambu Studio and OrcaSlicer themselves — names, vendors, types, temperatures, which printers each preset fits. No hardcoded tables, no cloud round-trips: slot names, tooltips and assignments resolve locally and offline.
Your own cloud presets are mirrored in the background from both Bambu Cloud and Orca Cloud, so a custom filament created in either slicer is known here minutes later — family included.
One family picker everywhere — the spool form, the AMS slot dialog, the K-profile editor. Spools link to a family, calibration auto-matching keys on it, and custom filaments finally match their own K-profiles instead of collapsing onto Generic.
Create a filament in BamDude itself — vendor + type + serial, exactly like Bambu Studio's Create Filament dialog, with a Bambu-Studio-compatible identity and a root preset cloned per printer profile you tick. Optionally push it to Bambu Cloud, and desktop Bambu Studio sees it on its next sync; create it from the Bambu Cloud tab and it is born in the cloud outright.
Smaller, but still ours
Automatically assign full stock spools (since 0.7.1, built-in inventory). Opt in per printer and select an exact filament group. A witnessed insertion into an empty AMS slot takes the oldest eligible unused spool; manual assignments and RFID take priority. For an external holder, assignment requires an identified runout and the operator's resume, not ordinary loading. This assumes a new full reel: returning the old partial reel after runout needs manual assignment before insertion or resume. See setup and limits.
Ukrainian. Upstream ships twelve locales and Ukrainian is not among them. BamDude ships English and Ukrainian only, and both are strict: a key missing from either fails CI, and so does a placeholder that drifted between them.
Swap Mode — driving an A1 / A1 Mini / A2L plate swapper, with Kit, STL and JobOx profiles, swap files detected automatically, and the swap macro fired between queued prints.
Low-stock forecast alerts — the reorder forecast raises a notification rather than only colouring a panel nobody has open.
An audit row for every applied change to printer settings, AMS settings and calibration — what was sent, when, and by whom.
Notes on library files, and print-dialog options remembered per user and per printer model.
Why BamDude?
Own your data — All print history stored locally, no cloud dependency
Works offline — Uses Developer Mode for direct printer control via local network
Full automation — Schedule prints, auto power-off, get notified when done
Multi-printer support — Manage your entire print farm from one interface
Features
Print Archive
Automatic 3MF archiving with metadata
3MF download recovery — when the printer's FTP fails during archive, recovery triggers fire on startup / printer reconnect / print-complete / manual button; per-archive lock prevents duplicate FTP sessions
Per-plate awareness — multi-plate prints record which plate of the source 3MF was actually printed; thumbnail, print info, G-code preview, and 3D model all reflect that plate (m038 backfills historical archives)
3D model preview (Three.js) with build-volume wireframe matching the printer's bed
Duplicate detection & full-text search (source-hash chain-of-custody for patched files)
Save a printed file back into the library — pick a folder and the archive's 3MF is read in the way an upload is, arriving with its metadata, thumbnail, per-plate detail and badges filled in. Saving the same print twice keeps the one already there rather than making a second copy
Per-plate layer counts — read from each plate's own G-code, because plates of one file routinely differ by hundreds of layers
Photo attachments & failure analysis
Timelapse editor (trim, speed, music)
Re-print to any printer with AMS mapping
Archive comparison, tag management
Monitoring & Control
Printer calibration — bed leveling, vibration, motor noise, nozzle offset, high-temp heatbed (model-aware, from UI and Telegram bot)
Real-time printer status via WebSocket
Live camera streaming & snapshots — fan-out broadcaster so multiple browser tabs / HA cards / Frigate share a single upstream connection (the printer itself only allows one)
Camera Wall — every tile opens as a snapshot with its last successful frame time; click one tile to make it the wall's only LIVE view, another to move it, or the same tile to stop it. Error and pause tiles remain visibly marked before a camera is opened. Signed-in tiles can raise the existing M-size printer card; token kiosks stay passive and redacted. Snapshots retain the last image while refreshing, and off-screen tiles pause.
One floating camera — another printer replaces the current popup, cancelling its old stream. Refresh, minimize, close and page navigation release the actual image request.
Isolated camera worker — camera transport and FFmpeg run in one supervised local process; there is no in-process camera fallback. Worker failure leaves unrelated printing and queues available; jobs requiring a camera check may wait for recovery. System shows its state. This is isolation, not hardware acceleration or a guarantee against browser/network bottlenecks. See the camera guide.
Isolated 3MF analysis — filament-usage projections parse archive G-code in a supervised local service, share one cache per live print, and do not block the web server. The input file stays local; only a bounded result crosses the embedded broker. See System diagnostics.
Streaming overlay for OBS
External camera support (MJPEG, RTSP, USB)
Cameras that belong to no printer — a view of the room, the shelf or the filament dryer, with its own name, source and optional location. It appears on the camera wall and the kiosk wall, opens in the same floating window a printer's camera does, and one upstream connection is shared by everyone watching. It feeds nothing else: no finish photo, no plate check, no Obico — a room has no printer to have them
Light for the camera (off by default) — switches the chamber light on before any use of the camera and off again afterwards: a photo in Telegram, a stream in the browser, the camera wall, the finish photo, the plate check — but not the frame kept every few layers for the finish photo, which would blink it all print long. Only a light that was off is switched on, and only a light BamDude switched on is switched off; a light you set yourself is never touched
Filament Calibration
In-app calibration wizard (Bambu Studio parity) — runs the calibration tests from inside BamDude; no Bambu Studio desktop needed
Pressure Advance — PA Line, PA Pattern, PA Tower; measured K saved to the printer's 16-slot K-profile history over MQTT and auto-bound to the AMS slot
Towers — Temperature, Volumetric Speed, VFA and Retraction; print-and-eyeball with a finish-step result calculator
Flow Rate — two-pass test (9-block coarse → 10-block fine, end-to-end auto-dispatch); pass-1 baseline auto-prefilled from your filament preset's filament_flow_ratio, override-able to a fresh 1.0 without editing the slicer profile
Calibration scaffold sliced against your own printer / process / filament presets through the OrcaSlicer or Bambu Studio sidecar, then printed via the normal dispatch pipeline
Per-(printer, filament, nozzle, extruder) result cache, H2D dual-extruder per-extruder tabs, Calibration History modal
Scheduling & Automation
Per-printer queues with status tracking (idle/printing/paused/error)
Load a queue from the library — a file picker on the printer card, the per-printer queue and the auto-queue: folder tree on the left, small cards on the right, and ticks that survive moving between folders, so a batch assembled from three folders is one selection. Only files that can actually run are offered — sliced, and on a printer only those sliced for that machine
Copy one printer's queue onto other printers of the same model — pick what and where, and the Schedule dialog opens once per group of items that would be answered the same way, with every chosen printer pinned; filament is mapped per printer inside that one dialog. Each copied item keeps the plate it was queued with, and any block you had grouped in the source queue comes out as a block on the target. A print started outside the queue counts as part of it
Drop a batch of files on a printer, its queue or the auto-queue — files that would be answered the same way are grouped and answered once, and anything that cannot be printed says why, by name. On the auto-queue each item's target model comes from its own slicing and cannot be changed
Queue organization — group prints into collapsible batches, drag-reorder by grip handle, and sort the Printers page by ETA; the timeline shows only committed schedules
ETA that counts the waiting — an order's Ready ≈ (shown only when every planned print can be dated) and a printer's free at include staggered starts (per group, with the slots heating right now), the plate-clear confirmation and the file transfer plus preheat, read from the very state the scheduler gates on rather than a second copy of it. A missing estimate or printer model names its reason instead of turning the routable subset into a completion date.
Run next, without touching a running print — the Schedule dialog can put an ASAP job before a selected printer's pending work. Several selected plates stay together as one block; each printer is changed independently, and Auto-Queue keeps its own routing order.
The auto-queue is a real queue — items listed in true dispatch order, batches expand into their copies, and everything drags: a batch as a block or a single copy anywhere in the order. Any copy (or a whole batch) edits in the same dialog the per-printer queue uses; with shortest-job-first the distributor owns the order and the handles hide
Rebalance across printer models — behind a setting (off by default) the distributor moves an order line's still-pending copies to idle printers of another model when that finishes the line sooner, recalculating plates and print counts for that model's bed; a line is left alone for five minutes after a move. The line's Rebalance button and the panel's per-row action run it on demand regardless of the setting
File Manager (Library)
Upload and organize sliced files
Composite file tags + chip-row filter — format / readiness / modifiers / provenance chips drive both the badge row and a chip filter on the toolbar (sliced vs project vs raw geometry, single- vs multi-plate, MakerWorld provenance)
User-authored tags — cross-cutting labels with a tag-filter rail and a bulk Tag action (separate from the automatic format/provenance badges)
Sort folders by recent activity, search recursively inside subfolders, and per-folder Markdown description panels (renders README.md)
All Files now lists your own uploads; a new External sidebar entry holds linked-folder files
One plate at a time on the card — a multi-plate file is browsed with arrows and a plate counter, and the picture, print time, weight, object count and filament types on the card all belong to the plate on screen rather than to a whole-file total nobody prints; in list view a row shows plate 1 with an N plates count, and its thumbnail opens that same card in a window
Per-plate gallery + 3D / G-code preview with build-volume wireframe — multi-plate 3MFs expose every plate; library viewer hides tabs that don't apply to the file (e.g. no 3D tab for sliced .gcode.3mf); dual-handle layer slider (crop both top and bottom), travel-moves toggle, layer-play with 1× / 2× / 4× / 8× speeds, theme-synced canvas, wireframe / X-ray toggle, OBJ format support, Export-as-PNG
External folder mounting (NAS, USB)
STL / OBJ thumbnail generation — shaded surfaces with Lambertian lighting + transparent background so cards "float" on whatever theme is rendering them
STEP / STP thumbnails (since 0.7.1) — made in the background by the Open CASCADE geometry kernel, behind sliced files and STL/OBJ previews, with a reason of its own when a model is too large, too slow or only partly readable. The Docker image and the Windows installer carry the CAD component; on a native install it is the administrator's choice (install.sh --with-step-preview, or install/step-preview.sh enable later). The source of its copyleft parts is attached to every release
Folder structure with drag-and-drop
Print directly or add to queue
The same file is never stored twice — every path a file can arrive by (upload, API, drop, product import, slicer output, Send-to-Printer, and linked NAS folders) checks the content hash first and reuses the library row that already holds those bytes. You are told which file was used instead; a row whose bytes went missing gets them back in place, keeping its name, folder, notes, tags, products and print history. Restoring from the trash asks before it recreates a duplicate
Projects — Orders, Products, Customers & Stock
Four sections in the sidebar, with separate permissions — orders (what was asked for), products (how it is made), customers (who asked), stock (what is on the shelves). Orders open as cards unless this browser has saved another view; the other lists offer cards and tables too
Order page — price and margin in the header, headline figures, lines of product × quantity that expand into per-part progress, a purchased-parts checklist, the prints grouped by the line they belong to, the queue, a timeline, notes and attachments, and a banner offering to close the order once everything is printed
"What to print next" under the lines — plates chosen by useful parts per print hour until the shortfall is covered, with live filament / time / cost totals, alternative files per printer model and a split across them, and one click sends a row, a split or the whole plan to the auto-queue — a single row can also go straight to a chosen printer through the print dialog, which preselects the file sliced for that machine
Product page — composition (printed parts with per-unit counts, purchased parts with price and link), plates grouped by file, linked files and folders, free stock, and every order that asks for this product; every printed part with its picture, rendered on the server from the sliced G-code — or your own photo
Free stock of product parts — a movement ledger with a reason on every row, a bank-the-surplus button on the order, a hand correction with a note, and a per-line "from stock" reservation that every order figure counts as already done
The order is asked for where the print starts — the print and auto-queue dialogs offer the orders that still need this plate first — by priority, then deadline, then age, never by how much they still want — with how many prints each is still short; the archive editor and the order page can file (and un-file) a print afterwards
Count a past print into stock — a button in the archive editor for an order-less print whose parts are on the shelf but were never recorded
Finished-goods stock and free parts — positions per product configuration show on-hand, reserved, available and minimum quantities. Receive goods, assemble them from free parts, stocktake, reserve for an order and issue them to a customer; every movement has a journal entry, and each issue produces a dispatch note. The stock section also shows the free-parts shelf and both journals
Link folders or individual files from the File Manager to a product — many-to-many (a file or folder can belong to several products at once), with per-chip unlink
Duplicate an order — customer, lines, price, tags, notes, attachments and cover under a new name, always , leaving the prints, queue items, stock reservations and purchasing progress with the original
Telegram Bot
Full printer control: pause, resume, stop (asks first), light, speed, camera snapshot
Camera snapshot carries the print controls, from the button and from /camera
Skip Objects from the bot: rendered plate with numbered markers, paginated keyboard, confirmation by object name
Upload: send a document, choose a library folder, print or queue it
Printer calibration from bot: model-aware selection (bed leveling, vibration, motor noise, nozzle offset, high-temp heatbed)
Printer status with model tag, maintenance indicators
Edit printer hours, view/mark maintenance from bot
Clear plate confirmation for queue auto-dispatch
Print from Library: file → printer (model-filtered) → Print Now or Add to Queue
Add to Queue: file → target (specific printer or model) → confirm
A notification centre in the app, filled even with no channel configured — the Bell in the sidebar is a per-user inbox: every farm event you subscribe to (a failed print, a filament runout, an AMS alarm, queue trouble, a sensor past its limit) lands there with a live unread count, read/unread kept per person, and filters by level, printer and period. An alarm about hardware no longer waits for somebody to set up a bot or a mail server first. Each person picks their own events — warnings and errors by default — history retention is a farm setting (30 days), and the per-user e-mail switches that used to be the whole Notifications page are now one tab inside the centre
Telegram (auto-restart bot on config change), Discord, Email, Pushover, ntfy, CallMeBot, Bark (free iOS push, no account)
Home Assistant, custom webhooks, Signal CLI API (self-hosted via signal-cli-rest-api, numbers or a group; in Docker, docker-compose.signal.yml runs that server next to BamDude and docker-install.sh offers it)
Printer scope on every channel — all, one, or several printers per provider, and per Telegram chat (where it also scopes the bot itself: lists, cameras, queue, controls)
Progress-milestone duration floor — mute 25/50/75% for prints shorter than N minutes, per chat and per provider
Per-chat quiet hours & daily digest (Telegram)
Actionable buttons: clear plate, mark maintenance done, pause/stop on progress
Print finish photo, filament usage details
HMS error alerts, bed cooled alerts
Dedicated AI Failure Detection event (separate from hardware errors); finish photos embedded inline in completion / failure emails
Pause / resume events with classified reason — print_paused carries normalised {reason} (door / filament runout / presence-check / file-pause-command / AI defect / plate-objects / user) + matched {hms_code}; print_resumed carries {paused_for} (mm:ss). Default ON for new providers, included in default Telegram-chat event set
Queue events (waiting, skipped, failed)
Spool Inventory
Built-in inventory with AMS slot assignment
Spools link to a filament family — the same identity Bambu Studio uses (filament_id), picked from a built-in catalog of official filaments plus your own cloud/custom ones; slot assignment, K-profile auto-matching and slicing all key on it
Create your own filament family from the spool form or the Profiles page — Bambu-Studio-compatible identity, per-printer presets, optional push to Bambu Cloud
Runout-accurate consumption tracking — a filament runout closes the spent spool at exactly its label weight and splits the print at the runout layer between the old and the replacement spool (per-layer G-code accuracy, same-slot refills and AMS backup switches included); jams are never mistaken for runouts. Live "filament so far" on the printer card while a print runs; a filament-runout notification prompts you to assign the replacement
Two-way AMS weight sync for Bambu-tagged spools — the firmware's own remaining estimate can correct the books downward too, debounced against garbled post-reconnect reports
Automatic filament consumption tracking
Per-spool cost tracking
Bulk spool addition
Mass actions on the Filament tab — tick rows (or the whole page, or everything matching the filter) and Edit / Print labels / Reset usage / Archive / Restore / Delete in one go; works in both built-in and Spoolman modes
Spool catalog, color catalog, low-stock alerts
Spool labels you draw yourself — text, QR, barcode and a block of the spool's colour, placed by hand in Settings → Filament → Marking, with the live picture coming from the renderer that makes the printed file. Sheets of stock are a separate thing you can also draw, so any label prints on any paper; a design too big for a cell is refused rather than shrunk. The designs BamDude ships are a starting point you can redraw. Manual
Print straight to a label printer on a desk — BamDude renders and queues, the BamDude Bridge app on that machine comes and takes it; nothing is exposed and no port is opened. A design declares whether it is going out as colour through a driver or to a one-bit thermal head.
Managed storage-locations catalog — pick shelves/drawers/dryboxes from a managed list instead of free-text
Colour-aware reorder forecasting — per-colour runway with material/brand filters and lead-time overrides. Every row also shows what your active orders have already promised out of that colour, and the reorder date counts down from the free stock rather than from everything on the shelf; promise more than the shelf holds and the row says so. Spools you archived still count as while no longer counting as , so retiring an empty spool does not collapse the rate onto its fresh replacement; a material you have run out of entirely stays on the panel for 90 days, because that is precisely the one to reorder
Integrations
BamDude Cloud link (opt-in) — pair the farm to the cloud.bamdude.top portal and it reports outward: which of the printers you chose to publish are running, how far along, the events worth knowing, and a single camera frame on request. One-way by design — nothing prints from the portal, the request list is fixed in the version you installed, and the link can be cut from either side
Server-side slicing — OrcaSlicer + BambuStudio sidecar containers ship in the same Compose project (--profile orca / --profile bambu / --profile all); per-job slicer picker in the Slice modal with live reachability badges, bed-type override (Cool / Engineering / High-Temp / Textured PEI / SuperTack), inline multi-plate selection, owner-filter on preset dropdowns
Spoolman filament sync
MQTT publishing for Home Assistant
Prometheus metrics for Grafana
Local OrcaSlicer preset import
Orca Cloud profile sync & push — pair once (under BamDude's own registered app identity, via a device code) and use your Orca Cloud printer/process/filament presets as a preset tier in the slice dialog and AMS-slot picker; mirrored server-side into the filament family catalog alongside Bambu Cloud's. Authored filament families push back to Orca Cloud too, with explicit conflict resolution when a profile changed in the cloud
K-profiles (pressure advance)
Git backup (GitHub + GitLab)
API keys & webhooks
LDAP/Active Directory authentication
Virtual Printer & Remote Printing
Proxy Mode for remote printing via TLS relay
Four modes: File Manager (the default), Printer Queue, Auto-Queue, and Proxy
File Manager mode — saves received 3MF files into the library rather than archiving them, so the archive stays a record of prints that actually ran
Queue modes — hand a received file straight to one printer's queue, or to the Auto-Queue to be routed across the farm
SSDP discovery or manual IP
Per-VP G-code injection toggle for auto-eject / plate-clear rigs; Bambu Studio "Send all plates" queues one item per plate
Tailscale reach — when the host runs Tailscale, the VP card shows the tailnet IP and MagicDNS name to paste into the slicer. The CLI ships in the Docker image; mount /var/run/tailscale/tailscaled.sock (see docker-compose.yml) to enable it. Trust still goes through the one-time bbl_ca.crt import — slicers validate MQTT only against the bundled BBL CA store, so a publicly-signed cert can't replace it
SSO autologin and an option to disable local username/password login (lockout-guarded)
Admin session-lifetime ceiling (Settings → Users → Session Policy, up to 30 days)
LDAP/Active Directory with group mapping
Per-user Bambu Cloud accounts
Advanced Auth via Email (SMTP)
Per-user email notifications
Long-lived camera-stream tokens — per-user, named, revocable tokens with hard 365-day TTL for Home Assistant cards, Frigate inputs, and wall-mounted kiosks
Plus: Customizable themes, mobile responsive, multi-language (EN/UK), auto updates, database backup/restore, PostgreSQL support — bundled or your own
Quick Start
Requirements
Python 3.12+ (only for a native install — the Docker image bundles its own)
Windows (native): download the latest bamdude-windows-setup.exe from the Releases page and run it. It's a self-contained installer (embedded Python — no Python or Node install required) that sets up a data directory and registers BamDude as an NSSM-supervised Windows Service that autostarts on boot.
SmartScreen: the installer is not code-signed, so Windows shows "Windows protected your PC" on first run — click More info → Run anyway.
Choosing a database
BamDude uses SQLite by default — nothing to set up. One variable, DATABASE_URL, switches it:
DATABASE_URL
Backend
empty / unset
SQLite (default)
embedded
a PostgreSQL 18 that ships with BamDude and that BamDude starts and stops for you
postgresql+asyncpg://…
your own PostgreSQL server
The bundled server comes from our open-source embedded-postgres package (PostgreSQL 18 + pgvector + pg_stat_statements; Linux x86_64/aarch64/armv7l, macOS, Windows) and arrives with the Python dependencies — nothing to install by hand. It lives under DATA_DIR/postgres/, listens on 127.0.0.1 only, and generates its own password. Pin EMBEDDED_PG_PORT=6432 if you want to reach it with psql or DBeaver.
Every installer asks which one you want: install.sh --db sqlite|embedded|external, a Database page in the Windows installer (where the bundled server can run as its own BamDudePostgres service), and the same question in docker-install.sh. Switching from SQLite imports your existing database automatically on the next start.
For full diagnostics on an external server, enable pg_stat_statements in the database BamDude uses. The guide covers third-party images and host installations; changing only the BamDude image does not configure that server.
From Bambuddy — no longer supported since 0.6.0. BamDude forked at Bambuddy 2.2.2 and the two schemas have diverged too far for a one-time import; start BamDude with an empty data directory and re-add printers and spools.
From Bambuddy-HE / BamDude 0.2.x / 0.3.x (tested & supported) — Docker users run install/migrate-volumes.sh once to copy bambuddy_he_* → bamdude_*; native users just point the installer at the existing data dir.
In BamDude Settings > Notifications, add a Telegram provider with the bot token
Enable Registration Mode, send /start to the bot from your Telegram
In Settings > Telegram Chats, assign a role to your chat and enable it
Done! Use the reply keyboard or inline menus to control printers
Enabling Developer Mode
On printer: Settings > Network > LAN Only Mode > Enable
Enable Developer Mode
Note the Access Code and IP address
Tech Stack
Component
Technology
Backend
Python, FastAPI, SQLAlchemy, aiogram 3.x
Frontend
React 19, TypeScript, Tailwind CSS 4
Database
SQLite (default), your own PostgreSQL, or a bundled PostgreSQL 18 on native installs
3D Viewer
Three.js
Part thumbnails
Pinned Node.js (bundled in Docker and the Windows installer)
Communication
MQTT (TLS), FTPS
Telegram
aiogram 3.x, MarkdownV2, FSM
Supported Printers
Series
Models
X1
X1, X1 Carbon, X1E
H2
H2D, H2D Pro, H2C, H2S
P1
P1P, P1S
P2
P2S
X2
X2D
A2
A2L
A1
A1, A1 Mini
Development
# Backend
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
# --loop asyncio is not optional, in development either: uvicorn[standard]
# picks uvloop, whose TLS layer can silently truncate a file transfer.
DEBUG=true uvicorn backend.app.main:app --reload --loop asyncio --timeout-graceful-shutdown 15
# Frontend (separate terminal)
cd frontend && npm install && npm run dev
Want to contribute? CONTRIBUTING.md has the setup, the checks
CI runs and the house rules; SECURITY.md is for vulnerabilities.
Working with a coding agent? CLAUDE.md is the engineering guide it
should read first (AGENTS.md points there for other tools), and
each release attaches the repository's code graph (bamdude-code-graph-*.json.gz).
https://docs.bamdude.top/privacy/. BamDude talks to your printers on your own network. The only data it sends out is anonymised usage telemetry (on by default; opt out in Settings or with TELEMETRY_DISABLED=true) and the bug reports you file explicitly. Optional integrations you enable yourself (Telegram, Spoolman, Obico, an OIDC provider, …) send data to the services you configure, under those services' own policies.
Acknowledgments
Bambuddy by maziggy — the original project this is forked from
A product's spare parts have a shelf of their own. The plate that makes four lids for an order that wanted three leaves a fourth: bank it to the product's free stock, and the next order can use it instead of printing it again. Reservations can take both complete kits and loose parts; mixed stock/print receipts count each part once. It is a ledger of movements rather than a stock column — every reservation, release, correction and credit is a row you can read — and a print that belongs to no order lands there by itself. Kits taken from stock count as done everywhere: the line's progress, the plan and the "everything is printed" banner all see them. The Stock tab shows every shelf on the farm at once — kits and balances per product, which active orders hold kits in reserve, and one journal of every movement — so the question is "what do we have", not "what does this product have".
Defective parts still count against the target. An order for forty usable parts is not finished because forty came off the plates. Scrap is recorded per print and subtracted.
Planned spare parts are an obligation of their own (since 0.7.1). A printed BOM part can carry an extra percentage, rounded up once for the order line. The line keeps its saved percentage when the catalog default changes. Extras do not change the base kit composition: they are planned, received and issued separately, and a customer order must deliver them before closing. See additional printed parts.
Defects are recorded where you stand. Every completed print card on an order page shows printed and defective and offers Defects…; on the printer card the finished print's counters sit beside Clear plate and Repeat. In Telegram the complete assessment stays a short-lived, cancellable draft, bound to its bot, chat and operator, until the whole plate is confirmed; typed counts must reply to their own prompt, and the form refuses to overwrite an archive changed while it was open. Clear/Repeat buttons carry both the named run and its gate generation, so an old card cannot clear a newer plate. Statistics gain Defects by printer. A print already counted into free stock has its shelf credit corrected when defects are recorded later, in either direction.
A file or folder belongs to the product — many-to-many, so one shared file can feed several products, and each product then feeds however many orders ask for it.
Build plate empty detection
Printer control (stop, pause, resume, light, speed)
Skip Objects — cancel individual parts mid-print instead of losing the plate to one failure. The plate is shown from above with a clickable numbered marker on each object, positioned from the slicer's own pick data; already-skipped parts stay visible so nothing shifts under the cursor, and a skip raises the archive's defective-part count from the printer's own report. Available in the web and in the Telegram bot, from the same marker placement
Printer storage browser on both media — browse, download, preview plates, import into the library and delete on the SD card and on the built-in storage of printers that have it (X2D, P2S, H2C, H2D, H2D Pro, H2S), with a switch between the two and separate model / timelapse catalogues on the internal side
Timelapse pre-flight — the tick is checked against the printer before it is promised: a machine with no SD card, an unreadable one or a read-only one is named in the print dialog with which of the three it is, and a queue whose printer has run out of room pauses instead of quietly dropping the recording. Printers with internal storage or a timelapse kit skip the card question entirely
Timelapse target, chosen per print — on a printer with both built-in storage and a card, the print dialog offers which one records it, the way Bambu Studio does; the choice travels with the queue item and is re-checked against the card at dispatch, so a card removed in the meantime means the recording falls back to internal storage rather than the print failing. A print sent from a slicer to a Virtual Printer keeps the slicer's own pick
Motion control — a round Bambu-Studio-style pad for the toolhead (10 mm / 1 mm rings, Home in the middle), the nozzle-bed gap, manual extrude / retract with the extruder drawn from Studio's own artwork, and release-motors. Reads which axes the printer says are homed, refuses a cold extruder below 170 °C, and speaks the newer xyz_ctrl protocol where the machine offers it
Temperature control — set nozzle, bed and chamber (both nozzles on dual-nozzle machines), with the limits the printer itself reports: an X1 on 220 V mains accepts a lower bed temperature, and the chamber ceiling differs per model. Zero always means off
Fan and air-duct control on every model — per-fan speeds, air-duct mode and filtration, with each fan labelled the way your printer names it. Machines that describe no air duct (P1S / P1P / X1C / A1) get the same controls built from what they do report
Pause-state visualisation — yellow status pip in compact mode, inline Paused • {reason} · 14m chip with live elapsed counter in card header (compact + expanded), instant WebSocket toast on RUNNING↔PAUSE edges with classified reason (door / filament runout / AI defect / plate-detect / etc.)
AMS management (RFID re-read, slot config, Filament Backup status) and auto-drying — per-filament humidity thresholds + alarms, a badge showing the active filament + target temp, H2C support, and opt-in Continue drying while printing on capable firmware (H2D / H2C / H2S / P2S / X2D / A2L / X1C)
HMS error monitoring with history — actionable remediation buttons (Resume / Stop / Ignore & Resume / Stop Drying / Turn off Fire Alarm / …) that send the command straight to the printer over MQTT
Heater temperature history — per-printer nozzle / second-nozzle / bed / chamber charts with target overlays, current/avg/min/max stats, and 6h / 24h / 48h / 7d ranges (30-day retention, auto-pruned)
Quantity says what it means. With several printers picked, the Print dialog's number was always «on each of them». It now offers Per printer (still the default) or Total, dealt round-robin across the picked printers in list order, and a line under the field states the outcome: «4 × 3 printers = 12 in total» or «13 → A1-01: 5 · A1-02: 4 · A1-03: 4». Remembered per browser; the auto-queue's field was always a total.
Confirmed bulk printer actions — select printers and preview which can receive homing, supported calibrations, queue pause/resume, maintenance mode, lighting or print controls. Record completed maintenance tasks with a shared note. Each printer is checked again before its action, and the result distinguishes commands sent, changes saved, skips and failures.
Per-printer Maintenance Mode — park a printer out of service (drops out of dispatch, scheduler, auto-drying, and metrics, and disconnects MQTT) without deleting it
Archive a printer — soft-retire a sold/decommissioned printer: it disappears from the Printers page, every picker, queues, dispatch, the scheduler, and MQTT, while its full print history is kept. Blocked while printing; cancels the printer's pending queue items. Restore or permanently delete it under Settings → Printing → Archived printers. Distinct from Maintenance Mode, which only parks a printer temporarily and keeps its card visible
Auto error-pause on print failure (queue stops, user decides next step)
Staggered start for farms (limit concurrent heating — farm-wide or per electrical phase and room via printer tags and locations, each group with its own cap if needed; bed temp monitoring)
Printer tags with colours; the Printers page filters and groups by tag
Order print parameters by sliced model — save independent calibration, timelapse and preheat choices for each model in an order's print plan. New jobs retain those choices even when routed to a compatible model; replacing the sliced file selects the corresponding saved entry. Existing jobs and operator profiles keep their settings. See the guide.
Prepared-file auto-ejection for orders — an experimental opt-in for hardware and finish G-code prepared by the operator. New jobs snapshot the mode and camera policy; fresh camera checks normally guard the next dispatch. An explicit no-check option requires two warnings. BamDude adds no ejection motion, and ordinary, failed or uncertain predecessors still need manual plate confirmation.
Polygon plate-detection areas — draw and edit a contour on the original camera image or keep the rectangular ROI. Only the selected area is compared with empty-plate references; an unavailable polygon check pauses a normal print for inspection.
Swap macro auto-execution — swap_mode_start before print, swap_mode_change_table after print, with ACK + stg_cur completion tracking, queue pause on failure
Auto-Print G-code Injection — per-job toggle that splices operator-defined snippets into the gcode of the plate being printed, just before ; MACHINE_START_GCODE_END (start) and before ; EXECUTABLE_BLOCK_END (end), with {placeholder} substitution from the plate's 3MF header (incl. PrusaSlicer→Bambu aliases); the setting is read on every dispatch, and one that cannot be read skips the snippets, not the print. Snippets stored as per-printer-model JSON in settings; folded into the same single 3MF open/repack cycle as Quick Vibration Check so multi-plate 50+ MB files aren't unzipped twice
MQTT recording to a file — start and stop it from the printer's menu, keep it running with the tab closed, and download or attach it to a support bundle afterwards. What a printer actually says, without running a script beside BamDude
G-code macros — execute from printer menu, ACK-based MQTT confirmation, stg_cur completion tracking, real-time status on printer card
Bulk firmware updates — a console that takes a whole set of printers, groups them by model, fetches each model's firmware once into a shared store and fans the transfer out under a concurrency cap; printers that are mid-print are skipped rather than interrupted, and one failure does not abort the batch
Model-aware maintenance types with history tracking and Excel export
Clear plate confirmation between prints
Smart plug integration (Tasmota, HA, MQTT, REST/webhook, and Zigbee — BamDude drives the dongle itself, no Home Assistant or Zigbee2MQTT needed)
Zigbee environment sensors — pair temperature / humidity sensors onto the same dongle, name them, place them, and set how often each one reports. Battery devices are deliberately never polled, since a sleeper answers on its own schedule
Sensor alarms — a lowest and/or a highest value on anything a sensor measures, including its own battery. The two are independent rather than a range, so "never above 30" needs no invented floor
Measurement history — power draw and room conditions recorded as they arrive and kept for a month, charted over 6 h / a day / two days / a week per plug and per sensor. Written above the plug drivers, so all five plug types are covered
Energy consumption tracking, per print as well as over time
Nested locations — a workshop holds shelves, a shelf holds printers; printers, sensors and spool storage attach at whichever level fits, and the printers, queues and maintenance pages group by them
Auto power-on/off
Background print dispatch with WebSocket progress
Slicer Pipelines — save a slice setup (printer / process / per-slot filament presets + bed type) once, then slice-and-queue any library file or archive in one click; target a specific printer or a whole model class (fanned out across matching printers via the auto-queue distributor), with a pre-flight compatibility check, multi-copy fanout, a live per-copy runs dashboard, and retry-failed
Preheat & heat-soak — optionally hold the bed (and, on chamber-equipped printers, the chamber) at temperature before a queued print starts, so engineering filaments get the adhesion/warp soak Bambu's firmware won't wait for; per-print chamber target worked out from the loaded AMS filament types (editable map), three hardware tiers handled automatically (active heater / sensor-wait / timer) with airduct-flap control, plus a per-print Inherit/On/Off override
Duplicate detection
Trash bin with restore — soft-delete with configurable retention (default 30 days), background sweeper hard-deletes past the window, opt-in scheduled auto-purge for old library files + archives; trash UIs render thumbnails and a unified split-button (trash + caret dropdown for purge-old)
active
Duplicate a product — composition with its aliases, card, attachments, cover, file and folder links
Products import/export as ZIP — the product, its files and its attachments; a product cannot be deleted while an order line still asks for it
what you burned
what you have
A History view — the whole farm's filament ledger in one list. A third view mode beside Table and Cards: every consumption record there is, with what was printed, off which spool, on which printer, how many grams and what it cost. Search, filters (printer, material, brand, outcome, a date range, and the spool's own active/archived and in-printer/on-shelf state), sorting and paging are all computed by the server, and the running total is for the whole filter rather than the page on screen. Rows for spools you have since archived or deleted are kept and marked, not hidden — the grams they carry were still printed.
Inventory search matches the name you see. The list shows a name built from your own template, and the search box matches that composed name — so LU/PET finds a spool named SUNLU/PETG. A spool's id and lot number are searchable whatever the template says.
The manager remembers what you filtered to — material, brand, colour, category, name, the archived tab, the usage and stock chips, the search box and the view all survive leaving the page, and "Clear filters" clears the memory too
CSV import / export of the local inventory — export takes every spool matching the current list filters, not just the visible page
Opt-out toggle for auto-adding unknown RFID spools