Skip to content

Profiles

Profiles are named serial-connection settings: port, baud, framing, and the various per-session toggles. Baudrun stores every profile in a single JSON file, which makes them easy to hand-edit, version- control, or generate programmatically from inventory data.

All profiles live in one file:

  • macOS: ~/Library/Application Support/Baudrun/profiles.json
  • Windows: %APPDATA%\Baudrun\profiles.json
  • Linux: $XDG_CONFIG_HOME/Baudrun/profiles.json (usually ~/.config/Baudrun/profiles.json)

The file is a JSON array, and the array order is the sidebar order — drag rows in the sidebar to reorder (the file is rewritten on drop), or rearrange the array in a hand-edit. Baudrun loads the file once at startup; changes made while the app is running are not picked up until the next launch. Use the app UI for interactive edits, hand-edit only while the app is closed.

The sidebar is more than a list:

  • Click a profile to open its editor; the editor’s Connect button starts the session.
  • Right-click for the context menu — connect in a new window, move a live session to a new window, delete.
  • Drag to reorder. Drop a row on another row to insert before it, or below the last row to move it to the end. The new order persists to profiles.json.
  • Drag to tear off. Drop a row anywhere outside the sidebar — onto the terminal pane or past any window edge — and the profile opens in a new window at the drop point, already connected. Tearing off the profile you’re connected to moves the live session instead: scrollback, port, and DTR/RTS state travel with it, and the source window returns to the welcome screen.

With several windows open, profile edits, additions, deletions, and reordering made in any window appear in every other window’s sidebar immediately.

[
{
"id": "8c6b3d4f-...",
"name": "Core-SW-01 (Aruba)",
"portName": "/dev/cu.usbserial-AU04CDLV",
"baudRate": 9600,
"dataBits": 8,
"parity": "none",
"stopBits": "1",
"flowControl": "none",
"lineEnding": "cr",
"localEcho": false,
"highlight": true,
"themeId": "",
"dtrOnConnect": "default",
"rtsOnConnect": "default",
"dtrOnDisconnect": "default",
"rtsOnDisconnect": "default",
"hexView": false,
"timestamps": false,
"lineNumbers": false,
"logEnabled": false,
"autoReconnect": true,
"backspaceKey": "del",
"createdAt": "2026-04-17T10:15:22Z",
"updatedAt": "2026-04-17T10:15:22Z"
}
]
Field Type Required Notes
id string yes* UUID. Generated automatically when the app creates a profile. Required for the in-app update path. Hand-written profiles can set any unique string.
name string yes Display name shown in the sidebar. Must be non-empty.
portName string yes OS device path. macOS /dev/cu.usbserial-..., Linux /dev/ttyUSB0 or /dev/ttyACM0, Windows COM7. Must match what the app enumerates.

* id is only required when round-tripping through the app UI. A hand-added profile with a blank id will be loaded but can’t be updated through the form until it gets one.

Field Type Required Valid values Default
baudRate int yes Any positive integer. Common: 9600, 19200, 38400, 57600, 115200. none
dataBits int yes 5, 6, 7, 8 8
parity string yes "none", "odd", "even", "mark", "space" "none"
stopBits string yes "1", "1.5", "2" (strings, not numbers) "1"
flowControl string yes "none", "rtscts", "xonxoff" "none"

Shorthand “8N1” = dataBits: 8, parity: "none", stopBits: "1". Network gear is overwhelmingly 9600 8N1.

Field Type Valid values Default Purpose
lineEnding string "cr", "lf", "crlf" "cr" Byte(s) the Enter key sends. Most network gear wants CR; Linux consoles want LF; legacy/Windows sometimes CRLF.
localEcho boolean true / false false Echo typed characters locally. Enable when the device doesn’t echo.
highlight boolean true / false true Run the line-buffered regex colorizer over incoming text.
enabledHighlightPresets string array | null any subset of pack ids ("baudrun-default", "cisco-ios", "junos", "aruba-cx", "arista-eos", "mikrotik-routeros", "user") null Per-profile highlight-pack subset. null (or absent) inherits the global enabled list from Settings. An empty array means “no highlighting at all” for this profile even when highlight: true. Only consulted when highlight is true.
backspaceKey string "del", "bs" "del" What the Backspace key sends. DEL (0x7f) matches VT100/xterm; BS (0x08) for some older Cisco/Foundry gear. Wrong setting surfaces as ^H echoed on screen.
hexView boolean true / false false Render incoming bytes as a hex dump (16 per line, ASCII sidebar). Binary protocols, firmware loaders.
timestamps boolean true / false false Prefix each line with [HH:MM:SS.mmm].
lineNumbers boolean true / false false Prefix each line with a session-local counter. Resets to 1 on every reconnect.
themeId string any theme ID or "" "" Per-profile theme override. Empty = use the global default theme from Settings.

UARTs on the receiving end of a paste are easy to overrun — even modest multi-line blobs can outpace a switch’s input buffer at 9600 baud. Two complementary defences, both on by default.

Field Type Default Purpose
pasteWarnMultiline boolean true Show a confirmation dialog before pasting anything containing a newline. Catches the “I meant to paste one line” copy-paste mistake.
pasteSlow boolean true Pace pasted bytes one at a time with pasteCharDelayMs between each, instead of writing the whole buffer at once.
pasteCharDelayMs int | null 10 Per-byte delay in milliseconds when pasteSlow is on. 10 ms = 100 bytes/s = effectively 1000 baud — slow enough for any device’s input buffer to drain between bytes. Bump higher (20–50 ms) for known-fragile UARTs, or lower (1–5 ms) when you’ve confirmed the target keeps up. Ignored when pasteSlow is false.

The Send Hex… path doesn’t use the slow-paste throttle — hex sends write the whole parsed byte vector through in one go, paced only by what the UART itself can absorb. If your target can’t keep up with that, paste the equivalent bytes from the keyboard buffer instead so they go through pasteSlow / pasteCharDelayMs.

Four policies for when the app asserts/deasserts the DTR and RTS lines on connect/disconnect. All four accept the same enum:

Value Meaning
"default" Leave the line in the OS default state (both asserted on Unix; RTS asserted on Windows).
"" Same as "default". Treated as unset.
"assert" Force the line high at the bookend.
"deassert" Force the line low at the bookend.
Field Applies at
dtrOnConnect Port open
rtsOnConnect Port open
dtrOnDisconnect Port close
rtsOnDisconnect Port close

Common uses:

  • RS-485 direction. Some adapters use RTS to toggle TX/RX; pin it.
  • Arduino DTR reset. Deassert DTR on connect to avoid auto-reset on port open.
  • Device state gating. Some firmwares require a specific DTR state to accept input.

Live DTR/RTS toggle pills in the session header let you flip the lines mid-session regardless of the connect-time policy.

Field Type Default Purpose
logEnabled boolean false Record raw incoming bytes to a timestamped file. Directory configured in Settings → Advanced (defaults to <support>/logs/).
autoReconnect boolean true On disconnect (port disappeared), poll for the port to reappear (1s interval, 30s timeout) and reopen with the same config. Preserves the scrollback backlog across the gap.
Field Type Notes
createdAt RFC3339 string Managed by the app. Preserved on update. Don’t touch in hand-edits unless you’re forging history.
updatedAt RFC3339 string Managed by the app. Bumped on every UI edit.

For a complete reference with every field set to a representative value, see docs-next/public/examples/profile.example.json. The task-focused snippets below omit fields they don’t need to make their point — the app fills defaults from the table above for anything missing.

Standard network switch (Cisco, Aruba, etc.)

Section titled “Standard network switch (Cisco, Aruba, etc.)”
{
"name": "Edge-SW-02",
"portName": "/dev/cu.usbserial-AU04CDLV",
"baudRate": 9600,
"dataBits": 8,
"parity": "none",
"stopBits": "1",
"flowControl": "none",
"lineEnding": "cr",
"highlight": true,
"backspaceKey": "del"
}

USB-C consoles (RuggedCom RST2228, newer Cisco, HPE/Aruba) are CDC-ACM, so the port name looks different (cu.usbmodem... on macOS). Otherwise the same:

{
"name": "RST2228-Plant-A",
"portName": "/dev/cu.usbmodem00000000001A1",
"baudRate": 57600,
"dataBits": 8,
"parity": "none",
"stopBits": "1",
"flowControl": "none",
"lineEnding": "crlf"
}

Deassert DTR on connect so the port open doesn’t reset the board:

{
"name": "Uno-Prototype",
"portName": "/dev/cu.usbmodem14201",
"baudRate": 115200,
"dataBits": 8,
"parity": "none",
"stopBits": "1",
"flowControl": "none",
"lineEnding": "lf",
"localEcho": true,
"dtrOnConnect": "deassert",
"autoReconnect": true
}

Hex view for binary protocol inspection, RTS/CTS for half-duplex adapters, auto-reconnect for flaky USB, slow-paste tuned wider than default since small embedded targets often need it:

{
"name": "Modbus-PLC",
"portName": "/dev/cu.usbserial-0001",
"baudRate": 19200,
"dataBits": 8,
"parity": "even",
"stopBits": "1",
"flowControl": "rtscts",
"lineEnding": "cr",
"hexView": true,
"timestamps": true,
"autoReconnect": true,
"pasteSlow": true,
"pasteCharDelayMs": 25
}

Because the file is a plain JSON array, generating many profiles at once is a scripting job. Two common approaches:

Given switches.csv with columns name,port,baud:

Terminal window
tail -n +2 switches.csv | \
jq -Rs 'split("\n") | map(select(length > 0)) |
map(split(",")) |
map({
name: .[0],
portName: .[1],
baudRate: (.[2] | tonumber),
dataBits: 8,
parity: "none",
stopBits: "1",
flowControl: "none",
lineEnding: "cr",
highlight: true,
backspaceKey: "del",
dtrOnConnect: "default",
rtsOnConnect: "default",
dtrOnDisconnect: "default",
rtsOnDisconnect: "default"
})' > profiles.json
import json, uuid
from datetime import datetime, timezone
inventory = [
("Core-01", "/dev/cu.usbserial-A1", 9600),
("Core-02", "/dev/cu.usbserial-A2", 9600),
("Edge-01", "/dev/cu.usbserial-B1", 115200),
]
now = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
profiles = [
{
"id": str(uuid.uuid4()),
"name": name,
"portName": port,
"baudRate": baud,
"dataBits": 8,
"parity": "none",
"stopBits": "1",
"flowControl": "none",
"lineEnding": "cr",
"localEcho": False,
"highlight": True,
"backspaceKey": "del",
"dtrOnConnect": "default",
"rtsOnConnect": "default",
"dtrOnDisconnect": "default",
"rtsOnDisconnect": "default",
"hexView": False,
"timestamps": False,
"lineNumbers": False,
"logEnabled": False,
"autoReconnect": True,
"pasteWarnMultiline": True,
"pasteSlow": True,
"pasteCharDelayMs": 10,
"enabledHighlightPresets": None,
"createdAt": now,
"updatedAt": now,
}
for name, port, baud in inventory
]
with open("profiles.json", "w") as f:
json.dump(profiles, f, indent=2)

Close the app, drop profiles.json into the config dir, relaunch.

  • Quit Baudrun first. The app reads once at startup and rewrites the whole file on every save. Hand-edits during a running session will be clobbered on the next UI edit.
  • Validation is strict. The app refuses to load a profile whose baud rate ≤ 0, data bits outside 5-8, or parity/stopBits/flowControl/ lineEnding outside the enum. Fix typos before relaunching.
  • IDs must be unique within the file. Duplicates cause ambiguity on update and may get deduped unpredictably.
  • Don’t bump createdAt. Not dangerous, but future sorting features might rely on it.

A natural workflow for shared environments: keep profiles.json in a private git repo, symlink it into <support>/profiles.json on each workstation. Hand-edits become commits; diffs show who changed what when.

The file has no secrets (passwords aren’t stored, since this is a serial terminal, not SSH), so a shared team repo works without additional encryption.

There’s no per-profile file format today. Workarounds:

  • Copy a single object out of the JSON array and paste into a gist / email. Recipient merges it into their own profiles.json.
  • Keep a shared JSON snippets file alongside profiles.json and import by hand.

A profiles export/import UI is a candidate feature if this becomes a real workflow. File an issue with the use case.