---
title: Export a raw thread (troubleshooting)
---

# Export a raw thread (troubleshooting)

## What it is

The raw thread export is a troubleshooting file for one session. It holds every message the
session stored, exactly as stored, and labels each one with where the session window actually put
it: shown on screen, folded away behind a control the user could open, or never drawn at all.

It exists to settle the first question in almost every "it never answered me" report: did the agent
never write the answer, or did it write it and the app hide it? The ordinary exports cannot tell you,
because they deliberately copy only what was on screen. This one copies everything and says, message
by message, what the user could and could not see.

Because it copies everything, the file is **unredacted**. Tool output, system reminders, hidden
instructions, automatic messages and anything pasted into the conversation all appear word for word.
Treat it as sensitive, and share it only with someone troubleshooting that session.

## Where to find it

Open the session, click the **⋯** menu in its header (or right-click the session in the sidebar),
and open **Exports**. **Export raw thread** is the last item in the save-to-file group, marked with a
bug icon; hovering it says it is for troubleshooting and unredacted.

- **On the desktop app** a Save dialog titled "Export Raw Thread (troubleshooting)" opens with the
  file name filled in: the session's name and the date, ending in `-raw-thread.md`.
- **On the phone** (the mobile web client) the same file downloads, or opens your phone's share
  sheet. A conversation too large to send to the phone shows a message asking you to export it from
  the desktop app instead.

The file is always Markdown, whichever surface you use, and the two surfaces produce the same file.

## How it behaves

### What the file contains

The file opens with a warning that it is unredacted, then the session's name, project, engine, status
and start time. Four short sections come before the messages:

- **How to read this** — every label (see the table below) and what it means.
- **Render context** — the display settings the labels were worked out with, such as whether system
  messages are shown for this session.
- **Row census** — how many messages received each label, so you see at a glance whether anything
  was hidden or dropped.
- **What this export cannot show** — the gaps, stated plainly (see "Limits" below).

Then every message, oldest first. Each has a heading with its number, who wrote it and its label;
a few facts about it (its id, time and length, how many tool calls and results it holds, which
markers it carries); and then its full text in a code block, unchanged.

For a reply the session drew as a bubble, the row also shows **the exact text the bubble displayed**
above the full stored text, whenever the two differ. For the final-message marker, the row states
where the marker sits (how many characters above it and below it) rather than guessing what the user
read.

### The labels

| Label | What it means |
| --- | --- |
| VISIBLE · agent reply | Drawn as the reply bubble. |
| VISIBLE · your message | A message the user sent; it opens a turn. |
| VISIBLE · system landmark | Drawn inline — a compaction divider or a status notice. |
| VISIBLE · aside (collapsed group) | A side question, in its own collapsible group. |
| FOLDED · behind the activity pill | On screen only if the user expanded the "N actions" line. |
| FOLDED · inside a compaction expander | On screen only if the user expanded the compaction divider. |
| HIDDEN · drawn nowhere, no toggle | Part of a turn, but nothing on screen draws it; the reason is on the row. |
| DROPPED · never rendered | Stored, but never shown; the reason is on the row. |
| UNKNOWN · placement unavailable | The export could not work out where it went; the reason is given. |

A **turn fold** line on a message describes how its whole turn was drawn, for example collapsed to a
single line that one click expands. Read it first: a message can be its turn's reply and still sit
behind a one-line collapse.

### How the labels are worked out

The labels are not guessed. The export runs the session window's own layout rules over the same
messages the window loads, with this session's display settings, and records where each message
landed. If the app changes how it folds messages, the export follows automatically. A turn that was
still running when the file was made is labelled the way it looks once it finishes.

If that replay fails, the file is still written: every message appears in full, each labelled
UNKNOWN, and the header says why.

### Limits

The file names what it cannot show, so nobody hunts for data that was never kept:

- The text of extended thinking is thrown away when a message is saved; only a placeholder with its
  length survives.
- Tool labels and tool details are shortened when they are saved, and the file shows the shortened
  forms.
- The full structured tool inputs and results are not in Omniscio's database, so they are not in
  the file.
- Display settings are read as they are now. If one changed since the problem happened, the view at
  the time may have differed.
- Two settings fold whole turns after layout — hiding background acknowledgements, and hiding
  automatic "waiting" replies unless they are final. The file reports their values but does not
  apply them to the labels.
- Scroll position is not recorded: VISIBLE means the message was drawn, not that it was on screen at
  a particular moment.
- A very long session is cut to its newest 99,999 messages. The header then says so and how many
  messages the session holds; the oldest are left out.

### Who can export what

Anyone who can open the session in the app can export it. A session hidden from the phone cannot be
exported from the phone. An agent running in its own session can read only its own session's raw
file, never another's.

## For agents

- **Headless read:** `GET /session/:id/raw-thread` on the local control server returns
  `{ ok, data: { approxTokens, truncated, classifierError, markdown } }`, the same Markdown file the
  menu saves. Add `?format=json` to receive `rows` (one structured object per message: placement,
  reason, bubble text, markers, counts) instead of `markdown`; never both, because they carry the
  same content. A session-scoped token reads only its own session.
- **Where it is built:** `assembleRawThreadExport` in `src/main/services/session/session-raw-thread.ts`.
  It reads the full history for the verbatim text and the window's own lightweight history for the
  replay, then places every row with `buildRealConversationTurns` and the shared bubble-versus-pill
  rule the window uses.
- **The menu paths:** the desktop Save dialog is `SESSION_EXPORT_MARKDOWN` and the phone download is
  `SESSION_EXPORT_BUFFER`, each with `variant: 'raw'`; both return the same bytes under the same file
  name. The `exported_markdown` audit event carries `variant: 'raw'`, so a raw export is never logged
  as a visible one; no content rides it.
- **The rules it must keep** (every row verbatim, labels replayed never re-derived, nothing called
  dropped that the layout placed, limits said out loud) are in
  `.claude/memory/contracts/session-raw-thread-export-contract.md`.

## Related

The ordinary exports (copy as Markdown, save as Markdown, Word or PDF, publish to Google Docs) copy
only what was on screen; they are on the [copy / export a session as Markdown](copy-session-as-markdown.md)
page. How the session window decides what to show and what to fold is on the
[real conversation layout](real-conversation-layout.md) page, and the side questions that appear as
asides are on the [asides](asides.md) page.
