A dead-simple CLI for reading and writing Modbus registers. Like curl, but for Modbus.
Project description
modbus-cli
__ __ ___ ___ ___ _ _ ___ ___ _ ___
| \/ |/ _ \| \| _ )| | | / __| ___ / __| | |_ _|
| |\/| | (_) | |) | _ \| |_| \__ \ |___| (__| |__ | |
|_| |_|\___/|___/|___/ \___/|___/ \___|____|___|
Like curl, but for Modbus.
A dead-simple command-line tool for reading and writing Modbus TCP and RTU registers. Beautiful terminal UI. No GUI, no config files, no bloat.
pip install modbus-cli
Features
- Styled output -- color-coded panels, value bars, gradient theme
- Live dashboard -- full-screen TUI with sparkline history, change detection, and keybindings (powered by Textual)
- Smart addressing -- auto-detects register type from standard Modbus notation (40001 = holding, 30001 = input, etc.)
- TCP + Serial RTU -- works with network devices and serial RS485 buses
- Multiple formats -- decimal, hex, binary, signed 16-bit
- Progress bars -- animated scan and dump with real-time feedback
- CSV export -- dump register maps straight to file
- JSON output -- pipe read/scan/dump output into jq and automation tools
Quick Start
# Read 5 holding registers
modbus read 192.168.1.10 40001 --count 5
# Write a value
modbus write 192.168.1.10 40001 1234
# Scan for devices on the bus
modbus scan 192.168.1.10 --range 1-10
# Open live monitoring dashboard
modbus watch 192.168.1.10 40001 --count 8
# Dump 200 registers to CSV
modbus dump 192.168.1.10 40001 40200 --csv registers.csv
Why?
Every Modbus device ships with register maps. To test them, you currently need:
- A Windows GUI tool (QModMaster, ModRSsim, Simply Modbus)
- Or a throwaway Python script with pymodbus boilerplate
Neither works well when you're SSH'd into a headless gateway, debugging a PLC at 2am, or just want a quick sanity check.
modbus-cli gives you one command. That's it.
Install
pip install modbus-cli
Requires Python 3.8+. No binary dependencies. Works on Linux, macOS, and Windows.
Docker
# Build local image
docker build -t 19bk/modbus-cli .
# Run a command inside the container
docker run --rm 19bk/modbus-cli read 192.168.1.10 40001 -c 10
Commands
modbus read -- Read registers
# Read a single holding register
modbus read 192.168.1.10 40001
# Read 10 holding registers with value bars
modbus read 192.168.1.10 40001 --count 10
# Read input registers in hex
modbus read 192.168.1.10 30001 --count 4 --format hex
# Read coils
modbus read 192.168.1.10 1 --count 8 --type coil
# Read via serial RTU
modbus read --serial /dev/ttyUSB0 40001 --slave 2 --baudrate 19200
# Signed 16-bit values
modbus read 192.168.1.10 40001 -c 5 -f signed
# JSON output for scripting
modbus read 192.168.1.10 40001 -c 5 --json | jq '.registers[].value'
Output includes styled panels, connection status, and visual value bars showing register magnitude at a glance.
Address notation: Uses standard Modbus addressing. 40001-49999 = holding registers, 30001-39999 = input registers, 10001-19999 = discrete inputs, 1-9999 = coils. Or pass raw 0-based addresses with --type.
modbus write -- Write registers
# Write a single holding register
modbus write 192.168.1.10 40001 1234
# Write multiple registers
modbus write 192.168.1.10 40001 100 200 300
# Write a coil ON
modbus write 192.168.1.10 1 1 --type coil
modbus scan -- Find active devices
# Scan all slave IDs (1-247) with animated progress bar
modbus scan 192.168.1.10
# Scan a specific range
modbus scan 192.168.1.10 --range 1-10
# Scan serial bus
modbus scan --serial /dev/ttyUSB0 --range 1-50
# JSON output
modbus scan 192.168.1.10 --range 1-10 --json
Devices are reported as they're found, with a progress bar showing scan completion.
modbus watch -- Live monitoring dashboard
# Watch 4 registers with full-screen TUI
modbus watch 192.168.1.10 40001 --count 4
# Watch at 500ms intervals in hex
modbus watch 192.168.1.10 40001 -c 8 -i 0.5 -f hex
Opens a full-screen Textual dashboard with:
- Live data table with zebra-striped rows
- Sparkline history per register (up to 60 samples)
- Change detection showing deltas between polls
- Stats bar with poll count, change count, and polling rate
Keybindings:
| Key | Action |
|---|---|
q |
Quit |
r |
Reset stats and history |
f |
Cycle format (decimal / hex / bin / signed) |
p |
Pause / resume polling |
modbus dump -- Export register ranges
# Dump 100 registers to terminal with progress bar
modbus dump 192.168.1.10 40001 40100
# Export to CSV
modbus dump 192.168.1.10 40001 40200 --csv registers.csv
# Dump in hex format
modbus dump 192.168.1.10 40001 40200 -f hex
# Dump as JSON
modbus dump 192.168.1.10 40001 40020 --json
Reads in chunks of 125 registers (Modbus protocol max). Shows an animated progress bar for large ranges.
Options
| Flag | Short | Description |
|---|---|---|
--port |
-p |
TCP port (default: 502) |
--serial |
-s |
Serial port (e.g. /dev/ttyUSB0), overrides TCP |
--baudrate |
-b |
Serial baud rate (default: 9600) |
--slave |
-u |
Slave/unit ID (default: 1) |
--count |
-c |
Number of registers to read (default: 1) |
--type |
-t |
Register type: holding, input, coil, discrete |
--format |
-f |
Output format: decimal, hex, bin, signed |
--timeout |
Connection timeout in seconds (default: 3) |
Common Workflows
Quick register check on a field device:
modbus read 10.0.0.50 40001 -c 20 -f hex
Find all devices on a serial bus:
modbus scan --serial /dev/ttyUSB0 --range 1-50 --timeout 0.3
Monitor a sensor value live:
modbus watch 192.168.1.10 40010 -i 0.5
Dump a full register map for documentation:
modbus dump 192.168.1.10 40001 40500 --csv device_map.csv
Compare before/after a config change:
modbus dump 192.168.1.10 40001 40050 --csv before.csv
# ... make changes ...
modbus dump 192.168.1.10 40001 40050 --csv after.csv
diff before.csv after.csv
Built With
- pymodbus -- Modbus protocol implementation
- Click -- CLI framework
- Rich -- Terminal formatting and styled output
- Textual -- TUI framework for the watch dashboard
Development
git clone https://github.com/19bk/modbus-cli.git
cd modbus-cli
python -m venv .venv
source .venv/bin/activate
pip install -e .
modbus --help
Contributing
Issues and PRs welcome. If you work with Modbus devices and want a feature, open an issue describing your use case.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file modbus_curl-0.1.0.tar.gz.
File metadata
- Download URL: modbus_curl-0.1.0.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3c9677963fb51e55ef3399c780621fb3dfe5516de699a0f19fe580cebe51cd0
|
|
| MD5 |
ea7b6fa7cc945343cae9c01fcc8d1678
|
|
| BLAKE2b-256 |
a7eb18e11be86659d26c4f95af5ff0c068d7f7549bc0633f6cd27f06032d28a1
|
File details
Details for the file modbus_curl-0.1.0-py3-none-any.whl.
File metadata
- Download URL: modbus_curl-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c61c3ce4418fc05b715a6775da059ec4afe294246b893eeef9eb1d05b25880d
|
|
| MD5 |
d950c8cc6c2cdc631bb40178a3755f4c
|
|
| BLAKE2b-256 |
1b793498f600a5f4853e1fb5ed01fcaf3275c6da05508e90b9e692a302031418
|