Awesome-omni-skill serial-terminal
Safely interact with serial ports (send/receive data). Use when the user needs to communicate with serial devices like Arduino, ESP32, or other microcontrollers. CRITICAL - Never read /dev/tty* devices directly.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/tools/serial-terminal" ~/.claude/skills/diegosouzapw-awesome-omni-skill-serial-terminal && rm -rf "$T"
skills/tools/serial-terminal/SKILL.mdSerial Terminal Skill
Safely interact with serial ports without directly reading /dev/tty* devices (which would crash Claude Code).
CRITICAL SAFETY RULES
- NEVER read from
devices directly using/dev/tty*
,cat
,head
, or any other commandtail - NEVER use the Read tool on
files/dev/tty* - ALWAYS use the Python wrapper script for ALL serial operations
Device Identification
IMPORTANT: Always use
paths when available!/dev/serial/by-id/
When multiple devices are connected, raw paths like
/dev/ttyACM0 can change between reboots or when devices are reconnected. The /dev/serial/by-id/ directory provides stable, descriptive paths that include the device serial number.
Example
/dev/serial/by-id/ entries:
/dev/serial/by-id/usb-SEGGER_J-Link_001057754341-if00 -> ../../ttyACM2 /dev/serial/by-id/usb-SEGGER_J-Link_001057754341-if02 -> ../../ttyACM3
When the user asks to connect to a device:
- First run
to show available devices with their serial numberslist - Ask the user which device/serial number they want to use if multiple are present
- Use the
path for the connection/dev/serial/by-id/
Available Commands
The script is located at
~/.claude/skills/serial-terminal/scripts/serial_terminal.py
List Available Ports
python3 ~/.claude/skills/serial-terminal/scripts/serial_terminal.py list
This will show devices from
/dev/serial/by-id/ with their serial numbers, making it easy to identify which device is which.
Send Data
python3 ~/.claude/skills/serial-terminal/scripts/serial_terminal.py send <port> "<message>" [options]
Options:
: Baud rate (default: 115200)--baud <rate>
: Append newline to message (useful for command-line interfaces)--newline
Example:
python3 ~/.claude/skills/serial-terminal/scripts/serial_terminal.py send "/dev/serial/by-id/usb-SEGGER_J-Link_001057754341-if02" "AT" --newline --baud 9600
Receive Data
python3 ~/.claude/skills/serial-terminal/scripts/serial_terminal.py receive <port> [options]
Options:
: Baud rate (default: 115200)--baud <rate>
: How long to wait for data (default: 2.0)--timeout <secs>
: Max bytes to read (default: 4096)--bytes <n>
: Display data as hex dump--hex
Example:
python3 ~/.claude/skills/serial-terminal/scripts/serial_terminal.py receive "/dev/serial/by-id/usb-SEGGER_J-Link_001057754341-if02" --timeout 5 --baud 115200
Send and Receive (most common)
Send a command and wait for response in one operation:
python3 ~/.claude/skills/serial-terminal/scripts/serial_terminal.py sendrecv <port> "<message>" [options]
Example:
python3 ~/.claude/skills/serial-terminal/scripts/serial_terminal.py sendrecv "/dev/serial/by-id/usb-SEGGER_J-Link_001057754341-if02" "help" --newline --timeout 3
Troubleshooting
Permission denied
The user may need to add themselves to the
dialout group:
sudo usermod -a -G dialout $USER # Then logout and login again
Or use sudo for a quick test:
sudo python3 ~/.claude/skills/serial-terminal/scripts/serial_terminal.py list
No response received
- Check baud rate matches the device
- Increase timeout with
--timeout - Verify the device is connected with
list - Try adding
if the device expects CR/LF--newline
Device busy
Another program may have the port open. Close any serial monitors or other tools.
Script Details
The Python script uses only standard library modules:
- Low-level file operationsos
- Serial port configurationtermios
- Non-blocking I/O (safe timeout handling)select
- File descriptor controlfcntl
It safely handles serial I/O by:
- Using
to wait for data with timeout (never blocks indefinitely)select() - Setting non-blocking mode to prevent hangs
- Properly restoring terminal settings on exit