prindeck: the Linux control panel my Brother printer needed
I published the first release of prindeck this week: an open-source Linux control panel for the Brother MFC-L2710DW. One native window holds toner and drum levels, scanning, printing and the job list, and a tray icon keeps watch. Three evenings of work, open protocols only, and version 0.1.0 ships as a .deb and an AppImage.
Why does a Linux printer need a client?#
Brother's desktop client is called iPrint&Scan, and the help pages for it name their platforms up front: "Applies to: Windows or Macintosh" (Brother support). Linux gets a different deal. The official download list for the MFC-L2710DW, with Linux selected, offers a printer driver, a scanner driver, a scan-key-tool and a PC-FAX driver, all as deb packages, plus an install tool and a mass deployment helper (download list). Everything on that list is a driver or an admin utility. A desktop application for the person at the printer is not on it.
Printing and scanning were never the blocker on Linux: CUPS takes the print jobs, and SANE finds the scanner. The blocker was everything around them. Toner level lives in the device's web panel, scans go through simple-scan or scanimage, the queue answers to lp, and no single window puts status, supplies, scan, print and history next to each other. The PRD I wrote before the first line of code states the goal in one sentence: "an equivalent of Brother iPrint&Scan (Windows/Android/iOS), which does not officially exist for Linux". I wanted that equivalent on my desktop.
How it talks to the printer#
Status runs over SNMP, one batched GET per poll. Brother keeps toner, drum and page counters in a compact OID table whose values arrive as length-prefixed binary records; the snmp2 crate handles the wire format, and a small parser turns the records into toner percent, drum percent, page and duplex counters and drum pages remaining. The values land in local SQLite, which is where the 90-day history chart comes from, along with a toner-pages estimate calculated from the cartridge yield you configure.
Scanning runs over eSCL, the HTTP scanning protocol with a public spec, the same one sane-airscan speaks. prindeck POSTs a scan job, fetches pages as they arrive, and sends a DELETE when you cancel. Platen or the 50-sheet feeder, 100 to 600 dpi, colour or grayscale, output as JPEG or a multi-page PDF.
Printing does the least work of the three. prindeck does not replace system printing: it hands your file to the existing CUPS queue with copies and duplex set, then shows the job list with a cancel button per job. The queue was already configured, so the app leaves it alone.
The shell is Tauri 2: Rust for everything that touches the device, TypeScript for the window, WebKitGTK for rendering. One instance only, a tray icon with a status colour, background polling, notifications for low supplies and outages, optional autostart, and closing the window hides it to the tray.
What the printer taught me#
The spec is public, but the device had opinions of its own.
- 150 dpi does not exist: the scanner advertises 100, 200, 300 and 600 dpi, and silently returns 300 when asked for 150. prindeck offers only the resolutions the capabilities actually list.
- BlackAndWhite1 with JPEG returns 409: the combination is representable in the job XML, and the device rejects it anyway. The app validates the pair before a job leaves the machine.
- An ADF stack is one document: the firmware assembles the whole feeder stack into a single PDF, so a cancelled job still keeps the pages already received.
- A tray icon needs a menu: on Linux the icon stays invisible until a menu is attached, and Tauri's documentation notes that an empty one is enough (docs.rs).
The three evenings split cleanly: one for a discovery spike against the live printer, one for the application, one for packaging and the release.
One printer, so far#
Version 0.1.0 supports exactly one device, the MFC-L2710DW, because that is the printer on my desk and the one every device behaviour in this article was checked against. The README is open about what comes next: support for more Brother MFC and DCP models "arrives sooner with every star". Stars are the only demand signal a solo maintainer gets. If people need prindeck on their devices, the support table grows. If nobody does, it stays a very good client for one printer.
The release notes list the rough edges by name: the offline screens need a cleanup pass planned for v0.1.x, Fedora users run the AppImage until the .rpm lands in v0.1.1, and seven of the ten interface languages are community drafts, with English, Russian and Ukrainian maintainer-verified. The deb weighs 5.0 MB, the AppImage 86.7 MB, and both are built on Ubuntu 26.04. The license is MIT, and the project is not affiliated with Brother: the trademarks appear "only to indicate compatibility".
How to run it#
Install from the releases page with sudo apt install ./prindeck_0.1.0_amd64.deb, or make the AppImage executable and run it. On first start, Settings asks for the printer's address, and that is the whole setup. Scans land in ~/Documents/scans, the config in ~/.config/prindeck. The repository also carries the PRD, the OID notes and read-only probe scripts for eSCL and SNMP, useful for talking to the device without the app. The case study on this site collects the architecture in one place: prindeck.
This is the second project on this blog where skipping the vendor layer and speaking the open protocol was the entire product. The first was searxng-mcp-server, which turned a self-hosted metasearch into the search backend for coding agents. The pattern repeats: talk to the thing directly, in the protocol it already speaks.