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
Metadata
Release files for modbus-curl 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| modbus_curl-0.1.0.tar.gz | 16.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| modbus_curl-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.8 kB
Release files / modbus_curl-0.1.0.tar.gz
| Download URL | modbus_curl-0.1.0.tar.gz |
|---|---|
| Size | 16.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e3c9677963fb51e55ef3399c780621fb3dfe5516de699a0f19fe580cebe51cd0
|
|
BLAKE2b-256 checksum How to use checksums |
a7eb18e11be86659d26c4f95af5ff0c068d7f7549bc0633f6cd27f06032d28a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / modbus_curl-0.1.0-py3-none-any.whl
| Download URL | modbus_curl-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2c61c3ce4418fc05b715a6775da059ec4afe294246b893eeef9eb1d05b25880d
|
|
BLAKE2b-256 checksum How to use checksums |
1b793498f600a5f4853e1fb5ed01fcaf3275c6da05508e90b9e692a302031418
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|