Repository navigation
Input history (command-history-state.json) is last-writer-wins across concurrent copilot processes; prompts typed in one session are erased #5265
Description
Describe the bug
~/.copilot/command-history-state.json is shared by every interactive copilot process, and the last process to write it wins. Each process loads the file once at startup and keeps the list in memory. Each time it saves a prompt, it writes the whole list back to the file, without re-reading or merging. When two or more copilot processes are open, whichever one writes last erases every entry the others added after it started. Those prompts then disappear from Up arrow and Ctrl+R in every later session.
Evidence (one machine, 2026-10-27, UTC): three interactive processes were running at once.
- Process A (1.0.103) had been running since 23:34 the previous day.
- Process C (1.0.103) started at 02:57.
- Process B (1.0.104) started at 03:01, so it loaded the history file at that point.
- The final history file has 50 entries, newest first. B last wrote it at 14:29:54, when B submitted a prompt. It contains:
- B's prompts from 14:19 to 14:29.
- C's prompts from 02:58 and 03:00, which were before B started.
- A's prompts up to 02:43, also before B started.
- It's missing C's 14:15:13 prompt. That prompt was submitted normally while the session was idle, with no error, so C's success path should have saved it. B's next write at 14:19:47 erased it.
- A's later prompts (03:00:55, 04:58, 05:00 and 14:12) are also missing. Each came right after a
Submission failed, so they don't prove this bug either way. If the 04:58, 05:00 and 14:12 messages were late deliveries of "failed" prompts, the CLI never saved them (Prompt is discarded after 'Submission failed' (host-ack timeout): composer cleared, not saved to history, delivered late or never #5264). If they were retypes, B's later writes would have erased them anyway, because B started at 03:01. The 03:00:55 message came before B started, and Prompt is discarded after 'Submission failed' (host-ack timeout): composer cleared, not saved to history, delivered late or never #5264 explains why the history file indicates it was most likely never saved.
Code (shipped cli-main.js, 1.0.103 and 1.0.104): the history manager's initialize() loads the file once. addCommand() puts the new entry at the front of the in-memory array, then saveHistory() writes the whole array through cliCommandHistoryWrite. Nothing re-reads or merges the file before writing.
Affected version
1.0.103 and 1.0.104. The code is the same in both.
Steps to reproduce the behavior
The steps below follow from the code. I haven't run this minimal version yet; the evidence above comes from normal use.
- Open terminal 1 and run
copilot. Open terminal 2 and runcopilot. - In terminal 1, submit
alpha. - In terminal 2, submit
beta. - Without exiting the first two, start a third
copilotand press Up.betais there, butalphais missing.
Expected behavior
Concurrent sessions shouldn't erase each other's history. Either option would work:
- Under a file lock, re-read the file, merge the new entry by recency, remove duplicates, trim to
commandHistoryMaxSize, then write. - Store history as an append-only log and compact it when reading.
Additional context
- macOS 27.0.1 (26A434), arm64. Ghostty, zsh.
- Several interactive
copilotprocesses usually run at the same time on this machine. - We found this while trying to recover a prompt that the CLI had discarded (Prompt is discarded after 'Submission failed' (host-ack timeout): composer cleared, not saved to history, delivered late or never #5264). Because of this bug, input history can't be relied on as a safety net for lost prompts.
Activity