[Bug] Long text responses in CLI display with repeated blocks of text

Resolved 💬 2 comments Opened Apr 22, 2026 by doingnz Closed May 27, 2026

Bug Description
long text answer to a prompt (e.g. when planning new feature) in the CLI are not displayed correctly (they were correct in the past). Full response is available at the top of the CLI screen buffer, then below that are multiple partial copies of the lower portion of the response text, possibly the bit of text displayed in the visible portion of the CLI.

See example below with the repeated text. Note I deleted a block of repeats to fit constraints of the issue system.

Easily 6 copies of this truncated text displayed in the CLI. I can work around by scrolling way back to the top of the buffer to read the full response, however it's awkward as when I type a response, it is added below the last copy of the input field below the 6 repeated blocks of text and the information I am referring way back at the top is not not visible.

Environment Info

  • Platform: win32
  • Terminal: visualstudio
  • Version: 2.1.117
  • Feedback ID: 9fea0acb-d1c5-4c00-b871-c9885a4750b6

Errors

Note how some of the response text is repeated.

D:\BPplus\BleUartBridge>claude
 ▐▛███▜▌   Claude Code v2.1.117
▝▜█████▛▘  Opus 4.7 (1M context) with xhigh effort · Claude Pro
  ▘▘ ▝▝    D:\BPplus\BleUartBridge

❯ is there a standard method to do firmware updates via an "AT" command interface? Could you think about and plan for a
   potential new feature for BleUartBridge that would permit firmware updates and configuration settings control via an
   "AT" command interface that is enabled on the UART when the BleUartBridge is not connected. do not make changes,
  plan and ask questions as I am not sure if we should implement this feature. please suggest pro and cons. the main
  reason I am considering this approach is the speed of firmware updates via BLE is in practice a bit slow. Adding this
   feature will make the software bigger which would make it slower, so there is a trade-off. thoughts please.

● Standard AT-based firmware update patterns

  There's no one standard, but there's a small cluster of well-worn conventions:

  1. Espressif's own AT firmware uses AT+CIUPDATE — HTTP OTA triggered by a one-shot command.
  2. Cellular modem world (Quectel, u-blox, SIMCom, Telit): AT+QFUPL / AT+QFOTA / AT+FUMO — file upload via an AT
  command that then switches the line into a raw binary transfer, usually XMODEM-1K or YMODEM. That's the closest thing
  to a de-facto standard.
  3. Custom framed DFU: AT+DFU_START, AT+DFU_DATA=<seq>,<hex>, AT+DFU_APPLY. Common in smaller in-house products.

  YMODEM is the one I'd highlight — TeraTerm, ExtraPutty, Kermit, and sz/rz all speak it, so operators get file-transfer
   for free, and its 1 KB blocks + CRC handle flaky lines.

  The speed premise — worth testing first

  The whole motivation rests on UART being meaningfully faster than BLE. That's only true at the right baud rate:

  ┌───────────────────────────────┬──────────────────────┬─────────────────────────┐
  │           Transport           │ Realistic throughput │       1 MB image        │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ BLE (BP+ Mgmt today)          │ ~20–80 KB/s          │ 15–50 s                 │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ UART @ 115200                 │ ~11 KB/s             │ ~90 s — slower than BLE │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ UART @ 921600                 │ ~90 KB/s             │ ~12 s                   │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ UART @ 2 Mbaud                │ ~200 KB/s            │ ~5 s                    │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ USB-CDC                       │ line-rate            │ <2 s                    │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ esptool.py @ 921600 (factory) │ —                    │ a few seconds           │
  └───────────────────────────────┴──────────────────────┴─────────────────────────┘

  So the win depends on what baud your host connection actually sustains, and on whether the transfer is raw-binary
  (YMODEM) or hex/base64-encoded in AT frames (which eats 33–100% of the bandwidth back).

  Pros

  - Potentially faster — but only if the UART link is ≥921600 and uses a binary sub-protocol, not hex-in-AT.
  - Recovery path — works when BLE is broken, misconfigured, or the device won't advertise. Nice safety net.
  - Scriptable for IT / manufacturing — one COM port, no BLE stack on the host, no pairing dance.
  - Reuses the existing security primitives — signed image + HMAC auth can be dropped in unchanged; only the transport
  frame differs.
  - Config management via AT is almost free once you have the parser — mirrors CFG_CONTROL TLVs.

  Cons

  - Two DFU paths to maintain — every change to the DFU state machine now has to be tested over both transports.
  - Mode arbitration is the hard part — UART is currently a transparent NUS pipe. When is it AT vs. passthrough? The
  classic +++ Hayes guard collides with arbitrary NUS payloads. Auto-switching based on BLE connection state is cleaner
  but has edge cases (what if the user wants AT mode while something is BLE-connected, e.g. monitoring?).
  - Attack surface — anyone with physical UART access can drive the management channel. If UART is exposed as a service
  port on the enclosure, that changes the threat model.
  - Auth friction on bench — if you reuse HMAC, every manufacturing script needs the master key. If you skip HMAC and
  trust physical presence, you've created a bypass around the BLE security.
  - Binary size argument is weak — AT parser + YMODEM is ~5–10 KB. On ESP32-S3 with multi-MB flash that's nothing.
  Firmware size doesn't meaningfully slow runtime (caches aside); it slows OTA transfer, which is the thing you're
  trying to speed up — mildly ironic but probably not enough to matter.

  Questions before committing

  1. Who's the user? Factory bring-up / service techs, or end-users? That drives the auth decision and the UX for mode
  switching.
  2. Is UART physically exposed on the deployed product, or only on dev/service hardware? Drives threat model.
  3. What baud rate can you actually run? If you're stuck at 115200, UART DFU is slower than BLE and there's no project.
   Worth confirming what the host side supports before any firmware work.
  4. Is esptool.py over the ROM bootloader already an option for the scenario you care about? If the target is
  factory/service and the device can be reset into bootloader, that's ~5 s for a full image and needs zero firmware
  changes. AT DFU only wins over esptool when you can't reset into bootloader (sealed unit, remote host, can't toggle
  BOOT/EN).
  5. Mode switch preference? My default would be: "UART is AT when no BLE central is subscribed to NUS TX; transparent
  bridge when it is." Simple, automatic, no +++ guard. But it means you can't do AT mode during an active BLE session —
  is that OK?
  6. Do you want config-over-AT too, or just DFU? Config is the cheap half; DFU is where the design decisions live.
  7. Keep the HMAC auth on UART, or gate it by physical presence only? Strong opinion either way is fine, but it needs
  deciding early.

  My instinct

  If the answer to Q4 is "esptool is available" — skip this. If it's "no, the unit is sealed and only the application
  UART is exposed," then it's a real feature and worth doing, but I'd scope it tightly:

  - YMODEM for the image, not hex-in-AT.
  - Auto mode-switch on BLE connection state.
  - Reuse HMAC auth verbatim — the master-key distribution problem already exists for the BLE path.
  - Ship DFU first, add config-over-AT only if there's demand.

  Want me to sketch a more concrete design around one of these paths, or dig into a specific question (baud-rate
  measurement, mode arbitration options, YMODEM vs. custom framing)?

✻ Brewed for 1m 12s

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
❯ 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ? for shortcuts
  4. Is esptool.py over the ROM bootloader already an option for the scenario you care about? If the target is
  factory/service and the device can be reset into bootloader, that's ~5 s for a full image and needs zero firmware
  changes. AT DFU only wins over esptool when you can't reset into bootloader (sealed unit, remote host, can't toggle
  BOOT/EN).
  5. Mode switch preference? My default would be: "UART is AT when no BLE central is subscribed to NUS TX; transparent
  bridge when it is." Simple, automatic, no +++ guard. But it means you can't do AT mode during an active BLE session —
  is that OK?
  6. Do you want config-over-AT too, or just DFU? Config is the cheap half; DFU is where the design decisions live.
  7. Keep the HMAC auth on UART, or gate it by physical presence only? Strong opinion either way is fine, but it needs
  deciding early.

  My instinct

  If the answer to Q4 is "esptool is available" — skip this. If it's "no, the unit is sealed and only the application
  UART is exposed," then it's a real feature and worth doing, but I'd scope it tightly:

  - YMODEM for the image, not hex-in-AT.
  - Auto mode-switch on BLE connection state.
  - Reuse HMAC auth verbatim — the master-key distribution problem already exists for the BLE path.
  - Ship DFU first, add config-over-AT only if there's demand.

  Want me to sketch a more concrete design around one of these paths, or dig into a specific question (baud-rate
  measurement, mode arbitration options, YMODEM vs. custom framing)?

✻ Brewed for 1m 12s

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
❯ 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ? for shortcuts
  3. What baud rate can you actually run? If you're stuck at 115200, UART DFU is slower than BLE and there's no project.
   Worth confirming what the host side supports before any firmware work.
  4. Is esptool.py over the ROM bootloader already an option for the scenario you care about? If the target is
  factory/service and the device can be reset into bootloader, that's ~5 s for a full image and needs zero firmware
  changes. AT DFU only wins over esptool when you can't reset into bootloader (sealed unit, remote host, can't toggle
  BOOT/EN).
  5. Mode switch preference? My default would be: "UART is AT when no BLE central is subscribed to NUS TX; transparent
  bridge when it is." Simple, automatic, no +++ guard. But it means you can't do AT mode during an active BLE session —
  is that OK?
  6. Do you want config-over-AT too, or just DFU? Config is the cheap half; DFU is where the design decisions live.
  7. Keep the HMAC auth on UART, or gate it by physical presence only? Strong opinion either way is fine, but it needs
  deciding early.

  My instinct

  If the answer to Q4 is "esptool is available" — skip this. If it's "no, the unit is sealed and only the application
  UART is exposed," then it's a real feature and worth doing, but I'd scope it tightly:

  - YMODEM for the image, not hex-in-AT.
  - Auto mode-switch on BLE connection state.
  - Reuse HMAC auth verbatim — the master-key distribution problem already exists for the BLE path.
  - Ship DFU first, add config-over-AT only if there's demand.

  Want me to sketch a more concrete design around one of these paths, or dig into a specific question (baud-rate
  measurement, mode arbitration options, YMODEM vs. custom framing)?

✻ Brewed for 1m 12s

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
❯ 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
...  deleted for brevity ...

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
❯ 
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ? for shortcuts
  │ BLE (BP+ Mgmt today)          │ ~20–80 KB/s          │ 15–50 s                 │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ UART @ 115200                 │ ~11 KB/s             │ ~90 s — slower than BLE │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ UART @ 921600                 │ ~90 KB/s             │ ~12 s                   │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ UART @ 2 Mbaud                │ ~200 KB/s            │ ~5 s                    │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ USB-CDC                       │ line-rate            │ <2 s                    │
  ├───────────────────────────────┼──────────────────────┼─────────────────────────┤
  │ esptool.py @ 921600 (factory) │ —                    │ a few seconds           │
  └───────────────────────────────┴──────────────────────┴─────────────────────────┘

  So the win depends on what baud your host connection actually sustains, and on whether the transfer is raw-binary
  (YMODEM) or hex/base64-encoded in AT frames (which eats 33–100% of the bandwidth back).

  Pros

  - Potentially faster — but only if the UART link is ≥921600 and uses a binary sub-protocol, not hex-in-AT.
  - Recovery path — works when BLE is broken, misconfigured, or the device won't advertise. Nice safety net.
  - Scriptable for IT / manufacturing — one COM port, no BLE stack on the host, no pairing dance.
  - Reuses the existing security primitives — signed image + HMAC auth can be dropped in unchanged; only the transport
  frame differs.
  - Config management via AT is almost free once you have the parser — mirrors CFG_CONTROL TLVs.

  Cons

  - Two DFU paths to maintain — every change to the DFU state machine now has to be tested over both transports.
  - Mode arbitration is the hard part — UART is currently a transparent NUS pipe. When is it AT vs. passthrough? The
  classic +++ Hayes guard collides with arbitrary NUS payloads. Auto-switching based on BLE connection state is cleaner
  but has edge cases (what if the user wants AT mode while something is BLE-connected, e.g. monitoring?).
  - Attack surface — anyone with physical UART access can drive the management channel. If UART is exposed as a service
  port on the enclosure, that changes the threat model.
  - Auth friction on bench — if you reuse HMAC, every manufacturing script needs the master key. If you skip HMAC and
  trust physical presence, you've created a bypass around the BLE security.
  - Binary size argument is weak — AT parser + YMODEM is ~5–10 KB. On ESP32-S3 with multi-MB flash that's nothing.
  Firmware size doesn't meaningfully slow runtime (caches aside); it slows OTA transfer, which is the thing you're
  trying to speed up — mildly ironic but probably not enough to matter.

  Questions before committing

  1. Who's the user? Factory bring-up / service techs, or end-users? That drives the auth decision and the UX for mode
  switching.
  2. Is UART physically exposed on the deployed product, or only on dev/service hardware? Drives threat model.
  3. What baud rate can you actually run? If you're stuck at 115200, UART DFU is slower than BLE and there's no project.
   Worth confirming what the host side supports before any firmware work.
  4. Is esptool.py over the ROM bootloader already an option for the scenario you care about? If the target is
  factory/service and the device can be reset into bootloader, that's ~5 s for a full image and needs zero firmware
  changes. AT DFU only wins over esptool when you can't reset into bootloader (sealed unit, remote host, can't toggle
  BOOT/EN).
  5. Mode switch preference? My default would be: "UART is AT when no BLE central is subscribed to NUS TX; transparent
  bridge when it is." Simple, automatic, no +++ guard. But it means you can't do AT mode during an active BLE session —
  is that OK?
  6. Do you want config-over-AT too, or just DFU? Config is the cheap half; DFU is where the design decisions live.
  7. Keep the HMAC auth on UART, or gate it by physical presence only? Strong opinion either way is fine, but it needs
  deciding early.

  My instinct

  If the answer to Q4 is "esptool is available" — skip this. If it's "no, the unit is sealed and only the application
  UART is exposed," then it's a real feature and worth doing, but I'd scope it tightly:

  - YMODEM for the image, not hex-in-AT.
  - Auto mode-switch on BLE connection state.
  - Reuse HMAC auth verbatim — the master-key distribution problem already exists for the BLE path.
  - Ship DFU first, add config-over-AT only if there's demand.

  Want me to sketch a more concrete design around one of these paths, or dig into a specific question (baud-rate
  measurement, mode arbitration options, YMODEM vs. custom framing)?

✻ Brewed for 1m 12s

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗