The Modbus client for macOS, Windows and Linux.

Read and write devices over RTU serial, Modbus TCP and RTU over TCP, keep register maps as files, see the RS-485 bus as it runs and test against a built-in simulator. Native Rust, with no browser engine inside.

  • Version 0.1.0
  • macOS, Windows, Linux
  • Free and open source (MIT)
Mb Studio reading unit 10, a cold-room controller on the Bench RS-485 serial connection: the explorer grouped by site on the left, holding registers 0 to 19 in a grid with name, type and scale, raw hex and decimal, and the decoded value, temp_aux struck through as invalid because it reads the sentinel 7FFF, and the setpoint register open in the inspector with its address in three notations (3, 4 and 40004), its decoding from 0xFF4C to -18.0 °C, its bits, and a write preview with the raw value in two's complement and the FC06 frame.

From the value that looks wrong to the frame that explains it.

A dense, keyboard-first workspace where registers, bus timing and frames get the room and the chrome steps back. Every screen here is the app itself, running on fictional sample devices.

Every serial port has a scheduler, and the bus view shows it: a timeline of transmit, wait and receive per unit, bus occupancy, the t3.5 gap, timeouts, the backoff of a unit that stopped answering and what its silence costs the others, and the adapter's latency timer.

The bus view of Bench RS-485 on ttyUSB0 at 57600 8N1: cycle time, bus occupancy, the t3.5 gap of 1.75 ms, an adapter latency of 16 ms and 2,400 ms lost to timeouts; a banner saying unit 41, an EEV controller, does not answer and is backing off, a tip with the command that lowers the FTDI latency timer to 1 ms, a timeline of transmit, wait and receive per unit with unit 41's timeouts hatched in red, and that unit's scheduler settings.

Every device, on every line.

A USB adapter on the bench, a serial-to-Ethernet converter at a plant and a PLC on the network sit in one explorer, grouped by site, with the devices on each connection under it by unit ID.

Three transports
RTU over a serial port, Modbus TCP, and RTU over TCP for the serial-to-Ethernet converters in front of an RS-485 line. Each connection holds its devices by unit ID.
Function codes 01, 02, 03, 04, 05, 06, 15 and 16
Read coils, discrete inputs, holding and input registers; write a single coil or register, or many at once. Modbus terms are used as the spec writes them: unit ID, coil, exception code, broadcast, t3.5.
Grouped by site, colored by connection
Mark a connection as a live plant and its color tints the toolbar, the tab and the status bar, so it never looks like the bench, and every write asks first. A read-only connection hides writes entirely.
Serial ports that keep their names
On Linux, connections save the stable /dev/serial/by-id path, so a port keeps its name when the adapter is re-plugged; your user needs the dialout group (uucp on Arch). On macOS only /dev/cu.* ports are listed. On Windows, a port another program holds is reported as busy.
Nothing added to the protocol
Modbus has no authentication or encryption, and Mb Studio adds none. It stores no passwords.
The app's sample connections. Every name and address is fictional.

Serial ports on Linux

Join the dialout group once (log out and back in after). FTDI adapters hold every short reply for 16 ms by default; lowering the latency timer to 1 ms speeds up every transaction, until the adapter is re-plugged.

sudo usermod -aG dialout $USERecho 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB0/latency_timer

Light or dark, it is the same tool.

Twin dark and light themes, dark by default, built to sit next to your IDE. Drag to compare.

Unit 21, a three-phase meter, with a note that the manual's “Little Endian” means low word first: 32-bit voltages, currents, powers and energy in CDAB order, and the inspector showing current_l1 read in the four byte orders ABCD, CDAB, BADC and DCBA, where only CDAB gives a plausible 12.409 A.

And the rest of the toolbox

Scanner
Finds the unit IDs that answer on a line and the address ranges each one serves.
Live charts
Plot any registers of a device as they are polled, with now, min, average and max for each series.
Session recording
Record a session's values to CSV, to read later or hand to someone else.
Frame log export
Save the traffic log as CSV or text, to attach to a ticket or compare with another capture.
Validity rules
A map can mark sentinel values and status bits that make a reading invalid, so a dead sensor is not read as a temperature.
Problems first
Timeouts, exception codes, CRC errors and mute units surface before the normal traffic, counted in the status bar.
SSH tunnels
Reach a Modbus TCP device or a serial-to-Ethernet converter that only a bastion host can see. Host keys are pinned on first use; passwords and passphrases go to the system keychain.
Split editor
Up to four panes side by side or in a grid: the bus of one line next to a device on another, each keeping its own selection.
Import and export
Move connections between machines as one JSON file with every option, passwords only if you ask for them.
Test before saving
A new connection can be tested from its dialog before it joins the explorer.
Copy as mbpoll
The current read as an mbpoll command line, for a terminal.
Logs without values
A local log for when a connection fails or the app crashes. It holds connection names, hosts, errors and timings, never frame contents or register values.
Fonts and icons inside
Inter, JetBrains Mono and the Lucide icons are embedded in the app, so it looks the same on every system with nothing else to install.

Native Rust, no browser inside.

The interface is egui drawn with OpenGL. There is no WebKit process, no JavaScript heap and no network process, and the app repaints only when the data changed. Release build, measured on Linux, 2026-10-13.

First frame
70–107 ms
From launch to the first painted frame, 16 runs.
CPU, idle
0.00 %
Of one core with nothing connected, over 7 runs; one run read 0.15 %.
CPU, live
0.57 %
Simulator serving and a client polling 20 registers every second.
Memory
66–87 MB
PSS of the whole app, idle or live.
Binary
13.5 MiB
Fonts, icons, the whole interface, SSH and the keychain inside. The .deb is 6.2 MiB.

Next to its siblings, measured the same way

AppFirst frameIdle CPU one coreMemory PSS, all processesBinary
Postgres Studio Tauri–0.17 %249 MB16.8 MiB
Rabbit Studio Tauri196–263 ms0.03 %234–252 MB15.8 MiB
Mb Studio egui70–107 ms0.00 %66–87 MB13.5 MiB

Release builds with an idle window, CPU over 30 s after launch, memory as the PSS of every process 10 s after the first frame. AMD Ryzen 7 5700G, Linux 7.0, Wayland session. Postgres Studio's first frame was not measured.

Nothing leaves your machine.

Read the privacy policy
No account
Install it and connect. There is nothing to sign into.
No telemetry
No analytics and no update checks. The app talks only to the devices, gateways and serial adapters you set up, and to its own simulator.
Your files
Connections stay on your computer; register maps, CSV exports and recordings are saved where you choose.
MIT licensed
Native Rust with egui, from one codebase for macOS, Windows and Linux, with no runtime to install.

Download Mb Studio

Version 0.1.0, free and open source.

Mb Studio is not released yet. Installers for Windows, macOS and Linux appear here as soon as the first build is out.

Windows

x64 installer

Your system
Download .exe

The simulator serves TCP on Windows; RTU needs a virtual COM pair.

macOS

Apple silicon

Your system
Download .dmg

A disk image for Macs with Apple silicon. Only /dev/cu.* serial ports are listed.

Builds are not code-signed yet, so the first launch shows a Gatekeeper warning on macOS and a SmartScreen warning on Windows.