1.7 KiB
Transcript
Status: Implemented · Code: Scripts/transcript.js
Nova sidebars hold only tree rows, so the readable conversation lives in an editor tab as Markdown.
Where it lives
<workspaceStoragePath>/Claude Transcript.md (global storage when the window
has no workspace). A real file rather than an untitled document so the tab has a
name, survives restarts, and can be saved without a dialog.
Incremental rendering
build() produces the whole document; _render() diffs it against the previous
render, finds the common prefix, and replaces only the differing tail:
edit.replace(new Range(prefix, current.length), text.slice(prefix));
Because output is append-mostly, the common prefix is usually the entire previous
text — one small edit at the end. This is what keeps scroll position and
selection stable while tokens stream in. Renders are throttled to 140ms;
flush() forces one and saves.
The viewport is only auto-scrolled when the caret was already at the end, so a user reading earlier history is not yanked around.
Format notes
- Tool results are fenced and truncated to 12 lines / 1200 chars.
Readresults are replaced by<sub>read N lines</sub>— echoing file contents Claude just read buries the conversation.- Fences widen past any backtick run in the body, so fenced content can't break out.
- Thinking is rendered as a blockquote, controlled by
claudenova.showThinking.
Gotchas
- The document is user-editable.
_render()diffs against the document's current text, not a cached copy, so manual edits are overwritten rather than corrupting the diff. editor.onDidDestroyclears the cached editor; the nextshow()reopens it.