
Serial
Scan, monitor, send, and log UART/USB serial traffic while bringing up embedded firmware without leaving the agent.
Overview
serial is an agent skill for the Build phase that scans, monitors, sends, and logs embedded UART/USB serial sessions from your coding agent.
Install
npx skills add https://github.com/zhinkgit/embeddedskills --skill serialWhat is this skill?
- Scans system serial ports when `port` is unset and picks the device automatically when only one is found
- Live text monitor with regex filters, timestamps, and binary Hex view
- Send plain text or Hex payloads including AT-command style debugging
- Export session logs as text, CSV, or JSON under configurable `log_dir`
- Resolves port and baud via CLI overrides, then `.embeddedskills/config.json`, then state file defaults
- Logs export in text, csv, and json formats
- Parameter stack: CLI, project config, state file, then defaults
Adoption & trust: 1 installs on skills.sh; 340 GitHub stars; 3/3 security scanners passed (skills.sh audits).
Who is it for?
Solo builders flashing ESP32, STM32, or modem modules who want the agent to run repeatable serial bring-up in-repo.
Skip if: Teams that need remote production serial gateways, protocol certification, or debugging without local USB access and drivers installed.
When should I use this skill?
User needs to scan ports, watch serial output, send text or Hex data, or save serial logs for embedded hardware debug.
What do I get? / Deliverables
After a session you have filtered live output, sent test traffic, and saved structured serial logs tied to your workspace config.
- Real-time serial capture with optional regex filtering
- Transmitted test payloads (text or Hex)
- Session logs under `.embeddedskills/logs/serial`
Recommended Skills
Journey fit
Serial debugging is part of wiring hardware and firmware during product build, before you can ship or operate a physical device confidently. Fits integrations because it connects the agent workspace to real boards via pyserial, socat multiplexing, and workspace `.embeddedskills` serial settings.
How it compares
Use instead of ad-hoc `screen`/`minicom` copy-paste when you want config-driven scans, logging, and agent-guided steps.
Common Questions / FAQ
Who is serial for?
Indie embedded and IoT developers using Claude Code who need structured serial port scan, monitor, send, and log workflows on their machine.
When should I use serial?
During Build integrations when a board is on USB, you need boot logs, AT tests, or Hex traces; less often in Operate when reproducing a field issue locally with the same `.embeddedskills` config.
Is serial safe to install?
It runs local Python and serial I/O on your hardware; review the Security Audits panel on this page before granting shell and filesystem access in your agent.
SKILL.md
READMESKILL.md - Serial
{} # serial Claude Code skill,用于嵌入式串口调试:端口扫描、实时监控、数据发送、Hex 查看和日志记录。 ## 功能 - 扫描系统可用串口 - 实时监控串口文本输出(支持正则过滤、时间戳) - 发送文本或 Hex 数据(支持 AT 命令调试) - 二进制流 Hex 查看 - 串口日志保存(text / csv / json 格式) ## 环境要求 - Python 3.x - [pyserial](https://pypi.org/project/pyserial/) — `pip install pyserial` - [socat](http://www.dest-unreach.org/socat/) — `apt install socat` / `pacman -S socat`(多路复用功能需要) - USB 转串口芯片驱动(CH340、CP2102、FT232 等,按硬件安装对应驱动) ## 配置 ### 环境级配置 (`config.json`) serial skill 的环境级配置目前为空对象 `{}`,因为串口参数属于工程级配置,统一在工作区的 `.embeddedskills/config.json` 中管理。 ### 工程级配置 (`.embeddedskills/config.json`) 工作区下的 `.embeddedskills/config.json` 存放工程级串口配置: ```json { "serial": { "port": "", "baudrate": 115200, "bytesize": 8, "parity": "none", "stopbits": 1, "encoding": "utf-8", "timeout_sec": 1.0, "log_dir": ".embeddedskills/logs/serial" } } ``` | 字段 | 必填 | 说明 | |------|------|------| | `port` | 否 | 串口号(如 `COM3`),为空时自动扫描 | | `baudrate` | 否 | 波特率,默认 115200 | | `bytesize` | 否 | 数据位,默认 8 | | `parity` | 否 | 校验位:`none` / `even` / `odd` / `mark` / `space` | | `stopbits` | 否 | 停止位:`1` / `1.5` / `2` | | `encoding` | 否 | 文本编码,默认 `utf-8` | | `timeout_sec` | 否 | 读写超时秒数,默认 1.0 | | `log_dir` | 否 | 日志输出目录,默认 `.embeddedskills/logs/serial` | ### 参数解析优先级 1. **CLI 参数** (`--port`, `--baudrate` 等) - 最高优先级 2. **工程级配置** (`.embeddedskills/config.json` 中的 `serial` 部分) 3. **状态文件** (`.embeddedskills/state.json` 中的历史记录) 4. **默认值** - 最低优先级 ### 自动扫描行为 当未指定 `port` 时,脚本会自动扫描系统串口: - 若只找到一个串口,自动使用该端口并写入工程配置 - 若找到多个串口,返回候选列表让用户选择(通过 `--port` 指定) - 若未找到串口,提示错误 { "usb_serial_chips": [ {"vid": "1A86", "pid": "7523", "name": "CH340"}, {"vid": "1A86", "pid": "55D4", "name": "CH9102"}, {"vid": "10C4", "pid": "EA60", "name": "CP2102"}, {"vid": "10C4", "pid": "EA70", "name": "CP2105"}, {"vid": "0403", "pid": "6001", "name": "FT232R"}, {"vid": "0403", "pid": "6010", "name": "FT2232"}, {"vid": "0403", "pid": "6014", "name": "FT232H"}, {"vid": "067B", "pid": "2303", "name": "PL2303"}, {"vid": "067B", "pid": "23A3", "name": "PL2303GS"}, {"vid": "2341", "pid": "0043", "name": "Arduino Uno"}, {"vid": "2341", "pid": "0001", "name": "Arduino Mega"}, {"vid": "1366", "pid": "0105", "name": "SEGGER J-Link (CDC)"}, {"vid": "0D28", "pid": "0204", "name": "DAPLink (CDC)"}, {"vid": "303A", "pid": "1001", "name": "ESP32-S2 (CDC)"}, {"vid": "303A", "pid": "4001", "name": "ESP32-S3 (CDC)"} ] } """串口 Hex Dump 查看""" import argparse import json import signal import sys import time from datetime import datetime from pathlib import Path from serial_runtime import ( get_serial_config, open_serial_port, save_project_config, update_state_entry, ) PARITY_MAP = {"none": "N", "even": "E", "odd": "O", "mark": "M", "space": "S"} IDLE_FLUSH_SEC = 0.2 def output_json(obj): sys.stdout.buffer.write(json.dumps(obj, ensure_ascii=False).encode("utf-8")) sys.stdout.buffer.write(b"\n") sys.stdout.buffer.flush() def error_exit(code, message, use_json): result = {"status": "error", "action": "hex", "error": {"code": code, "message": message}} if use_json: output_json(result) else: print(f"错误: {message}", file=sys.stderr) sys.exit(1) def hex_dump_line(data, offset, width, show_ascii): """格式化一行 hex dump""" hex_part = " ".join(f"{b:02X}" for b in data) hex_part = hex_part.ljust(width * 3 - 1) line = f"{offset:08X} {hex_part}" if show_ascii: ascii_part = "".join(chr(b) if 0x20 <= b < 0x7F else "." for b in data) line += f" |{ascii_part}|" return line def emit_chunk(data, offset, width, show_ascii, use_json): now = datetime.now().isoformat(timespec="milliseconds") if use_json: ascii_str = "".join(chr(b) if 0x20 <= b < 0x7F else "." for b in data) output_json({ "timestamp": now, "offset": offset, "length": len(data), "hex": data.hex(" "),