It only saves agents started through unsent. It can't see the Claude Desktop app or the VS Code extension's chat panel, which don't run in a terminal.
Pasted images show as [Image #1] and come back as that placeholder. So does audio, as [Audio #1].
Claude Code shows a draft over 10,000 characters with its middle cut out, as [...Truncated text #1 +137 lines...]. unsent puts the middle back from the draft it saved just before, but only when the whole cut box, its first 500 characters, the placeholder and its last 500, fits on screen at once. That takes a tall window: in an 80 by 24 one it never does, and line breaks near either end make it harder. It also can't when an image sat in the cut middle, because Claude Code moves [Image #N] next to the cut. Otherwise it saves what the box shows and keeps the full draft in history.
A screen can't tell a wrapped line from a line you ended by hand exactly where the row was full. In that one case the line break comes back as a space. Lines that start a list item, heading, quote or code block are kept on their own line.
If a whole long draft lands in the box between two saves, only the part on screen is recovered. Typing never goes that fast.
In a draft taller than the box, a few edits can't be read off the screen for certain: for example, typing a word identical to the next word hidden below the box, or typing, deleting and scrolling at the edge of the box within one 0.4-second save. Then the live draft can come out slightly wrong. In simulation that's about 1 save in 100 with ordinary text, a little more with heavily repeated words or with Ctrl+W. Thanks to the one promise (unsent never throws away text you didn't delete), the correct text is still in history.
A draft that changes wholesale, like a prompt recalled with the Up arrow, is saved from what's on screen, and the old draft goes to history.
The sent log holds the box as the agent last drew it before your Enter. A key typed so fast before Enter that the agent never drew it can be missing: measured on Codex 0.158.0, a key 10 to 20 ms before Enter was missing in 3 of 4 messages, and none was missing at 30 ms or more. Enter and Ctrl+Enter count as a send, in whatever form the terminal sends them. A remapped submit key, or Ctrl+X Ctrl+S, reads as a clear, and the message goes to history instead.
Pressing Esc while Claude Code works on a message can put that message back in the box. The sent log still holds it, although Claude Code didn't answer it.
A draft with a tab in it isn't pasted back, because Claude Code's box turns each tab into four spaces. It goes to the clipboard instead, and the line under the box says so.
A conversation you typed in but never sent can't be resumed, since neither Claude Code, Codex nor pi keeps anything to resume for it. Its draft only comes back through the notice and unsent restore.
A draft goes back into the box only when the command line reads as a chat start: claude with its own options. Started with a prompt (claude "fix it") or a subcommand, it gets the notice instead. With --as or UNSENT_AGENT the command's arguments are read the same way, so a launcher started bare or with Claude Code's options restores, and npx @anthropic-ai/claude-code gets the notice. For Codex a chat start is codex with its own options, codex resume or codex fork; a prompt (codex "fix it"), an image to attach with -i, or any other subcommand gets the notice.
The line saying a draft was put back is drawn under the box only when Claude Code runs on the alternate screen. Otherwise the line printed after exit says it.
A draft goes back into a reopened Codex conversation only when unsent can tell which conversation the running Codex is in. With -c, --enable, --disable, --search or --no-daemon, Codex runs the conversation itself and names it. A plain codex hands it to a shared background server, which names it only when that codex started the server; one left running by an earlier codex names none. After /new or /resume one Codex holds two conversations and names neither. In those cases the notice and unsent restore reach the draft.
Codex draws a tab as one space and spaces at the end of a line as blank cells, so a draft saved from its box has spaces there.
Codex started with --no-alt-screen draws its box in a layout unsent doesn't read, and unsent says so after it exits.
An entry of Codex's history brought back with Up isn't saved as a draft until you edit it: Codex keeps it. Sending it puts it in the sent log. The same goes for pi.
pi draws spaces at the end of a line as blank cells, so a draft saved from its box has none there, and two or more spaces where a row wraps come back as one.
pi's editorPaddingX setting, when it isn't 0, puts spaces at the start of every row of the box, and they end up in the saved draft.
A pi draft cleared with Ctrl+C and brought back with Ctrl+- is saved again, but a paste placeholder in it stays the placeholder in the live draft; the draft history kept at the Ctrl+C has the pasted text.
pi's fullscreen mode (--tui-mode fullscreen) was not measured, and neither was a paste pi reads from the clipboard itself (Ctrl+V, or a right-click in fullscreen), which never crosses the terminal: such a paste over pi's placeholder threshold stays the placeholder in the saved draft.
agy draws no combining mark, so a decomposed accent (e and U+0301) is saved as the bare letter, although agy itself holds the whole character. A precomposed é is saved as it is.
agy shows a line break typed at the end of a row the text filled exactly, before a word too long to have fitted there, as nothing at all: those two rows are what one long word broken at the edge draws. That break is lost from the saved draft.
An agy draft with a tab, or one ending in a line break, is not pasted back: agy turns a tab into four spaces and drops that break. It goes to the clipboard instead, and the line after agy exits says so.
An agy conversation has no id until its first message is sent, so that message is in the sent log of the run that sent it, and the conversation's own log starts with the second.
macOS and Linux, including WSL. Native Windows has no pseudo-terminals of this kind.