Repository navigation
Clipboard: clean the text of a note pinned or pasted from a terminal: join the lines that the coding agent wrapped, remove the indentation and the trailing spaces #572
Description
The problem
When the developer adds a note to the Clipboard sidebar section from the text of a terminal (the shortcut ⇧⌘P), or pastes a text copied from a terminal into a note, the text keeps the line breaks and the indentation of the terminal. A coding agent such as Claude Code or Codex wraps its own answer at the width of the pane, and starts each next line with two spaces. A paragraph of the answer is then several lines in the note, and each line after the first one starts with spaces.
Example, a text copied from a pane of Claude Code (the dots show the spaces):
There are 6 open merge requests that nobody checked since January: !175, !173, !160, !159, !147 and
··!133. They are about the phone field, the OAuth login, and the move from Bootstrap 4 to 5. Two of them
··do not even target develop (!160 and !133). They are almost surely dead merge requests.
··We should decide whether we close them all at once.
The note must show one paragraph:
There are 6 open merge requests that nobody checked since January: !175, !173, !160, !159, !147 and !133. They are about the phone field, the OAuth login, and the move from Bootstrap 4 to 5. Two of them do not even target develop (!160 and !133). They are almost surely dead merge requests. We should decide whether we close them all at once.
Today, pinText in notes.ts only removes the spaces at the end of each line (text.replace(/\s+$/gm, "")). The regular expression \s also matches the line break, so it can also remove the empty lines between two paragraphs.
The proposal: an algorithm, with no language model
The cleaning is a pure function, cleanTerminalText(text, columns), in a new file of packages/apps/web_frontend/src/lib. It is fast, it works with no network, and it gives the same result every time. A language model is not needed for this.
- Remove the spaces and the tabs at the end of each line, but keep the empty lines.
- Find the common indentation of the block (the smallest indentation of the lines that are not empty, the first line excepted when it has none) and remove it from every line.
- Join a line to the next one, with one space, when the line is a cut of the terminal and not a real line break:
- the line is long: its length reaches the width of the pane,
columns, less a small margin (the width of the last word that did not fit). The width of the pane is known when the text is pinned, from xterm.js. This is the strongest sign. - and the next line is not empty, does not start a list item (
-,*,•,1.,1)), a heading (#), a table row (|), or a quote (>), and is not in a code block.
- the line is long: its length reaches the width of the pane,
- Never change the inside of a code block (between two lines of three backquotes), and never join the lines of a table or of a list. The continuation line of a list item is joined to its item.
- Remove the empty lines at the start and at the end, and keep at most one empty line between two paragraphs.
When the width of the pane is not known (a text pasted from another program), step 3 uses the longest line of the block as the width.
Where it applies
- The shortcut ⇧⌘P and the command of the command palette that pins the selection:
pinTextcleans the text before it saves the note. - The text of a note that the developer pastes in the large window of a note: the paste is cleaned in the same way.
- Optional: the same cleaning for ⌘C in a pane, behind a setting "Clean the copied text" in the section General of the Settings window, off by default.
Keep the raw text
- The note keeps the raw text in a new field
rawText, next totext. A button "Show the raw text" in the large window of a note shows the text as the terminal gave it, and a button "Clean again" runs the cleaning again. - A note saved by an older version has no
rawText. A button "Clean the text" in the large window cleans it.
The rules to update
- sidebars.md, section "Clipboard": the cleaning of the text of a note, and the raw text.
Tests
A Vitest test file next to the new function, with one test for each case:
- the example of this issue, from Claude Code, with its indentation of two spaces;
- a text from Codex;
- two paragraphs separated by an empty line, which stay two paragraphs;
- a list with a continuation line;
- a code block, a table, and a heading, which do not change;
- a short line followed by a line of the same paragraph, which stays a real line break;
- a text with no known width;
- the spaces at the end of the lines.
And a test of pinText in notes.ts that keeps rawText and keeps the empty lines between two paragraphs.
Activity
edefiez commentedon Oct 22, 2026
Added on 22 October 2026, after a discussion with the developer.
claude -pwith a small model, or by Codex), with its settings (coding agent, model, instruction), is a separate issue, because it sends the text out of the computer and needs its own choices. It builds on this issue.