Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>Serial Port for VSCodeNew to Visual Studio Code? Get it now.
Serial Port for VSCode

Serial Port for VSCode

haleywang

|
101 installs
| (3) | Free
Full-featured serial port tool for VS Code: monitor, send/receive (hex or ASCII), RTS/DTR control, multiple ports in parallel, log-to-file, and reusable send templates. Works transparently from WSL windows against physical Windows ports.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Serial Port for VSCode

A full-featured serial port tool built right into VS Code: monitor a port's output live, send and receive data as hex or ASCII, toggle RTS/DTR, run multiple ports in parallel, log sessions to file, and save/reuse send templates — all from the Activity Bar, without leaving your editor.

Features

  • Live per-port terminal — an interactive terminal for each open port, color-coded by TX/RX direction, with optional per-line timestamps.
  • Device colors, preserved — ANSI/SGR escapes from the device (ESP-IDF's red/yellow/green log output, Zephyr's shell, anything using colored printf) render as colors, and a color set at the start of a burst still applies to the end of it.
  • Log-level detection — ESP-IDF, Zephyr, Linux printk, Android and generic [ERROR]-style prefixes are recognized on received lines and used to color the terminal row and fill in the log header's level column.
  • Hex or ASCII, independently for send and receive.
  • Configurable line ending per session (none / NL / CR / CRLF), so an ESP-IDF console, Zephyr shell or AT-command modem actually sees a completed command.
  • Raw input mode — every keystroke goes straight to the device, so Ctrl+C, Ctrl+D and arrow keys work against a MicroPython REPL or a device's own line editor.
  • Multiple ports open in parallel, each with its own session card: live config, byte counters, and controls.
  • RTS/DTR control per port — handy for boards that reset on a DTR/RTS edge (e.g. Arduino, ESP8266/ESP32).
  • Session logging to file — record a port's traffic to a timestamped log file in your workspace (or wherever serialPort.saveLogAt points), as readable annotated lines or as a byte-exact raw capture.
  • Syntax highlighting for the log — recorded logs open in the editor with the header, direction, timestamps and level tokens colored; see Log files below.
  • Reusable send templates — save frequently-sent hex/ASCII payloads and fire them at any open port with one click.
  • Works transparently from WSL — open a WSL-remote VS Code window and add a physical Windows COM port with zero manual configuration; see WSL support below.

Getting started

  1. Open the Serial Port view in the Activity Bar.
  2. Pick a port from the dropdown and click + to add it as a session.
  3. Click the session's toggle button to open it — a terminal appears; type and press Enter to send.
  4. Expand Default Settings to change baud rate, data bits, parity, stop bits, or hex send/receive defaults for newly-added sessions. Each session can also override these while open.

WSL support

If your VS Code window is connected to a WSL remote workspace, this extension still talks to physical Windows COM ports with no manual configuration. It declares extensionKind: ["ui"], so VS Code always runs it on the machine hosting the UI (Windows), while workspace-facing APIs (vscode.workspace.fs, integrated terminals) are transparently proxied to the actual WSL workspace. Practically: port I/O happens on Windows, and your logs/templates land in the WSL filesystem you're working in.

Sending to the device

Typing in a port's terminal and pressing Enter sends the line. What gets appended to it is the session's Line Ending setting — CRLF by default, which satisfies devices that accept only CR and devices that accept only NL. Set it to None if you need to send exactly the bytes you typed. Hex sends and hex templates never get a line ending appended.

The terminal is a line editor by default: it keeps a local history (Up/Down), supports cursor editing, and pins your in-progress line to the bottom row, so device output arriving mid-typing doesn't scramble what you are writing. Ctrl+L clears the screen and Ctrl+C clears the pending line.

Check Device Console (under Advanced on the session card) when you need the device itself to do the editing — a MicroPython REPL, a Zephyr shell, a bootloader menu, or any full-screen device TUI. It hands the terminal over: the pinned input row disappears, every keystroke (including Ctrl+C, Ctrl+D and the arrow keys) is sent to the device immediately, and the device's own cursor control is passed through untouched. Local history and Ctrl+L are line-mode features and are not available while it is on. Logging keeps running either way.

Log files

Check Record to File on a session card to record it. Two formats are available via serialPort.logFormat:

annotated (default) — <port>_<timestamp>.serial.log. One physical line per device line, so the file is greppable and diffable:

# --- COM8 recording started 2026-09-05T14:23:01.123+08:00 · 115200 8N1 ---
[09-05 14:23:01.140 ASC RX INFO ] I (301) cpu_start: Pro cpu up.
[09-05 14:23:01.142 ASC RX WARN ] W (318) spiram: no SPIRAM
[09-05 14:23:02.008 ASC TX      ] reboot
[09-05 14:23:02.311 ASC RX ERROR] E (402) wifi: connect failed

Every line is stamped with when the device started it and ANSI escapes are stripped (no ←[0;31m garbage in the editor). The timestamp carries no year and no UTC offset — both are constant for the whole session and are recorded once, in full, on the # --- banner; on every line they would only cost horizontal space. Turn on Compact Timestamps to drop the date too and keep just 14:23:01.140.

The bracketed header is fixed-width, and it is the only thing this extension adds to a line — everything after the closing ] is byte-for-byte what the device sent, so a device that labels its own output still reads unambiguously:

[09-05 14:23:42.738 ASC RX ERROR] [ERROR] sensor 3 offline
                            ↑       ↑
                      detected      the device's own text

The level column is filled in for received lines only — what you send is a command, not a log record, so a TX line is never classified and always renders in the configured TX colour. Turn detection off entirely with serialPort.detectSeverity; the column stays (blank) so the payload keeps starting at the same offset on every line, which is what makes cut -c35- and grep ' ERROR]' work.

raw — <port>_<timestamp>.raw.log. A byte-exact capture of the wire in arrival order: no headers, nothing stripped or transformed, both directions interleaved exactly as they happened. Use this when the capture has to be diffed against another tool's or replayed. Hex Receive and Show Timestamp do not affect it.

A received byte that cannot be displayed — a NUL, a BEL, a stray 0x7F — is written into an annotated line as a visible \xNN escape rather than being dropped, so a device answering a hex send with control bytes while the session is in ASCII receive still shows something instead of looking like a dead port. Tab, CR and LF keep their normal meaning, and raw captures are untouched.

A line the device never terminates (a esp32> prompt, or that same control-byte echo) is held briefly so the file gets whole lines, then written out anyway once it has been quiet for about ¾ of a second. If the device does continue it later, the continuation is written as its own line — an append-only file can't revise a line it has already written, and two lines beat a line that never appears.

The format is read when recording starts, so changing the setting mid- recording never leaves one file holding a mix of both; the new format applies the next time recording begins.

Highlighting in the editor

*.serial.log and *.raw.log open in a Serial Log language that layers serial-specific rules on top of VS Code's built-in Log grammar — so the ISO dates, quoted strings, MAC/GUID constants and stack frames the built-in grammar already colors still work, plus the [timestamp MODE DIRECTION LEVEL] header, RX/TX direction, hex-dump payloads, ESP-IDF/Zephyr tag prefixes and the # session banner. Plain *.log files (older recordings, or a custom saveLogAt naming) get the same serial rules via a grammar injection, while staying in the built-in Log language.

Every rule is anchored to the exact header shape this extension writes, so an unrelated .log file you happen to open is left alone. The reader accepts every header shape past versions wrote (ASCII as well as ASC, full ISO timestamps as well as the short ones), so an older recording still highlights.

Bracket-pair colourisation is off for *.serial.log / *.raw.log. Device output routinely contains an unbalanced [, and a single one shifts the nesting depth for the whole rest of the file — every header bracket below it is drawn in a different colour, which reads as a bug because it is one. Plain *.log files stay in VS Code's built-in Log language, whose configuration this extension does not control, so they still colourise brackets; set "[log]": { "editor.bracketPairColorization.enabled": false } if that bothers you.

To see it without a device, open samples/example.serial.log — a hand-written file covering every rule, with a checklist of what to look for at the bottom.

The level column ships with colors (red/yellow/blue/grey), because no VS Code theme styles the log.* scopes on its own. They are contributed as defaults, so if you already have an editor.tokenColorCustomizations of your own, it replaces them — add these back, or recolor anything else, the same way:

"editor.tokenColorCustomizations": {
  "textMateRules": [
    { "scope": "log.error.serial", "settings": { "foreground": "#f14c4c", "fontStyle": "bold" } },
    { "scope": "log.warning.serial", "settings": { "foreground": "#cca700" } },
    { "scope": "log.info.serial", "settings": { "foreground": "#6f9dc0" } },
    { "scope": "log.debug.serial", "settings": { "foreground": "#9d9d9d" } },
    { "scope": "log.verbose.serial", "settings": { "foreground": "#6e6e6e" } },
    { "scope": "storage.type.mode.log.serial", "settings": { "foreground": "#6e6e6e" } },
    { "scope": "support.class.direction.rx.log.serial", "settings": { "foreground": "#33cc33" } },
    { "scope": "keyword.control.direction.tx.log.serial", "settings": { "foreground": "#00cccc" } },
    { "scope": "entity.name.tag.log.serial", "settings": { "fontStyle": "italic" } }
  ]
}

In practice you rarely need to: these rules are only the baseline for the moment before the extension activates. Once it is running, the level token, the RX/TX token and the payload are painted from serialPort.severityColors and serialPort.txColor/rxColor instead (see below), which wins over any TextMate rule.

Run Developer: Inspect Editor Tokens and Scopes on any line to see which scopes apply to it.

Level colours

serialPort.severityColors holds one CSS hex colour per level, and together with serialPort.txColor/rxColor that palette drives both surfaces the same way — an open log reads like the terminal it came from:

Part of the line Colour
timestamp, ASC/HEX left to your theme (dimmed) — they repeat on every line
RX / TX serialPort.rxColor / serialPort.txColor
the level token serialPort.severityColors[level], bold for ERROR
the device's own text the level's colour, or the direction's when unclassified

Both surfaces update live — change a colour and every open terminal and log reflects it immediately, with no port reopen and no window reload. ERROR and WARN also get a mark in the editor's scrollbar overview ruler, so a failure is findable in a ten-thousand-line boot log without scrolling.

Level Default
ERROR #f14c4c (bold in the editor)
WARN #cca700
INFO #6f9dc0
DEBUG #9d9d9d
TRACE #6e6e6e

Set a level to "" to turn its override off: the terminal row falls back to the configured RX colour, and in the editor the level token is left to your theme while the payload takes the RX colour. Useful for INFO if you would rather only the unusual lines stand out.

The panel's Default Settings › Level Colours section has a picker for each level (each label drawn in its own colour, so the block doubles as a legend), a per-level button to turn the override off, Reset all, and a gear that opens the same settings in VS Code's Settings UI. A device that emits its own ANSI colours always wins over all of this — its bytes are passed through untouched.

Extension Settings

All settings are under serialPort.* and configurable via the Settings UI, settings.json, or the panel's own Default Settings section:

Setting Description
serialPort.defaultBaudRate Default baud rate for newly-added ports.
serialPort.defaultDataBits Default data bits (5/6/7/8).
serialPort.defaultParity Default parity (none/even/odd/mark/space).
serialPort.defaultStopBits Default stop bits (1/1.5/2).
serialPort.defaultHexSend / defaultHexRecv Default hex mode for send/receive.
serialPort.defaultLineEnding Terminator appended to ASCII sends: none/lf/cr/crlf (default crlf).
serialPort.defaultDeviceConsole Start new sessions with Device Console on (keystrokes go straight to the device).
serialPort.defaultShowTimestamp / compactTimestamps Show timestamps, and whether to render them as time-of-day only instead of month-day-and-time.
serialPort.detectSeverity Recognize device log-level prefixes on received lines and color/label them accordingly.
serialPort.logFormat annotated (readable, highlighted) or raw (byte-exact capture).
serialPort.messageGapMs Quiet time after which an unterminated line (a prompt) is surfaced anyway.
serialPort.saveLogAt Folder for session log files. Supports the ${workspaceFolder} token.
serialPort.txColor / serialPort.rxColor Colors (CSS hex) for sent/received bytes, in the terminal and in an open log.
serialPort.severityColors Per-level colors (CSS hex) for the terminal row and, in an open log, the level token and payload. "" turns a level's override off.
serialPort.sendTemplates Reusable send templates (usually managed via the panel UI).

Requirements

None beyond VS Code itself — the native serial bindings ship inside the extension.

Known limitations

  • RTS/DTR and reset-on-connect behavior varies by board; if your board resets unexpectedly on open, check its RTS/DTR wiring.
  • In line-editing mode the terminal deliberately drops the device's cursor-movement and screen-erase escapes (it keeps only color), so the pinned input row and the timestamp columns stay intact. Turn on Device Console for a device that needs full cursor control.
  • Colouring a log line's payload from the TX/RX and level colours paints over the finer-grained syntax colouring inside it, so the ESP-IDF/Zephyr tag prefixes, quoted strings and stack frames the grammar scopes are visible only where no payload colour applies (a level set to "", or a txColor/rxColor cleared to an empty string).

License

MIT — see LICENSE.


Development

npm install
npm run watch     # incremental esbuild build

Press F5 in VS Code to launch an Extension Development Host with the extension loaded — the Serial Port icon appears in the Activity Bar.

npm run lint       # eslint
npm test           # compiles + runs the extension test suite
npm run package    # production bundle (dist/extension.js)

Packaged with @vscode/vsce. Never commit a Marketplace personal access token; pass it via the VSCE_PAT environment variable to vsce publish instead.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft