The pain
Half of my work happens in a terminal — Claude Code, logs, utility output, tabular views, progress bars, spinners. Constantly I want to grab a chunk of that output and paste it somewhere else: into the IDE, a ticket, a chat, a doc.
Every time, the same ritual.
I select a line from claude code or kubectl get, copy, paste — and in the IDE/ticket I get:
│ src/auth/middleware.ts:42
│ function validateToken(token)
│ if (token.exp < Date.now())
└─────────────────────────────────Then the cleanup starts. Drop the leading vertical bars │. Drop the bottom border └─. Drop the trailing whitespace — there's a wagon-load of it, because the terminal pads lines to column width. Drop ANSI escape sequences when the source was less tidy. Sometimes fish out invisible zero-width characters that quietly break JSON parsing or regex matching downstream.
It's 10–30 seconds each time. Tolerable. But I do this dozens of times a day. On long blocks of text, cleaning bars line by line by hand is minutes, and each pass is faintly nauseating.
With Claude Code the pain is especially loud: tool-output blocks draw frames, progress runs spinners from Braille (⠋⠙⠹⠸), status bars are stuffed with block elements █▌▏░ for progress meters. Copy an answer — and the clean markdown ends up full of debris.
The fix
A Raycast Script Command that:
- Reads the current clipboard via
pbpaste - Pipes through
perl -CSD(this matters — macOSsedmishandles UTF-8 multibyte characters;perlwith the-CSDflag does Unicode correctly) - Strips noise with regex by Unicode ranges
- Writes back to the clipboard via
pbcopy - Synthesizes
Cmd+Vviaosascript— pastes into the active app
One hotkey instead of manual cleanup.
What gets stripped
The regex hits ranges, not specific characters — broader coverage, more resilient:
| What | Unicode range | Why |
|---|---|---|
| ANSI escape sequences | \x1b\[...m | color codes from ls --color, grep --color, bat, etc. |
| Box-drawing | U+2500–U+257F | frames │ ├ └ ─ ┌ ┐ ╔ ╗ ║ ═ of every flavour |
| Block elements | U+2580–U+259F | progress bars █ ▌ ▏ ░ ▒ ▓ |
| Braille patterns | U+2800–U+28FF | Claude Code spinners ⠋ ⠙ ⠹ ⠸ ⠼ |
| Zero-width | U+200B–U+200D, U+FEFF | invisible ZWSP, ZWNJ, ZWJ, BOM |
| Trailing whitespace | [ \t]+$ | trailing spaces and tabs at line ends |
The leading border gets a separate, careful pass: s/^[\x{2500}-\x{257F}]+[ \t]?//mg strips the border together with one separator space after it. Otherwise │ code, after removing │, would keep an orphan leading space — and indentation in the IDE would drift.
What is not touched: bullets •, arrows → ← ↑ ↓, emoji, Cyrillic, normal code indentation. That's meaning, not debris.
The final script
~/raycast-scripts/smart-paste.sh:
#!/bin/bash
# @raycast.schemaVersion 1
# @raycast.title Smart Paste
# @raycast.mode silent
# @raycast.icon ✨
# @raycast.packageName Clipboard
# @raycast.description Strip box-drawing, spinners, progress bars, ANSI escapes, zero-width chars and trailing whitespace from the clipboard, then paste
pbpaste | \
perl -CSD -pe '
s/\x1b\[[0-9;?]*[a-zA-Z]//g;
s/^[\x{2500}-\x{257F}]+[ \t]?//mg;
s/[\x{2500}-\x{257F}\x{2580}-\x{259F}\x{2800}-\x{28FF}]//g;
s/[\x{200B}-\x{200D}\x{FEFF}]//g;
s/[ \t]+$//mg;
' | \
pbcopy
osascript -e 'tell application "System Events" to keystroke "v" using command down'Wiring it up
Raycast:
- Add
~/raycast-scripts/as a Script Directory in Raycast settings (Extensions → Script Commands →+) - Bind a hotkey. Mine is
⌘⌥B(cmd + option + b) - System Settings → Privacy & Security → Accessibility → enable Raycast (required for
osascriptkeystroke)
Stream Deck: on every profile I pinned a button in the top-right corner — System → Open pointing at the script path. Now both a keyboard hotkey and a one-press deck button do the same thing. Stream Deck also needs its own Accessibility permission in Privacy & Security.
Outcome
A 30-second manual ritual replaced by one keystroke. On long pastes out of Claude Code or kubectl, the savings are larger — line-by-line border cleanup by hand was honest suffering.
If anyone wants to tweak it — the ranges in the regex extend trivially. For example, if you copy a lot of markdown tables and want to keep | (that's ASCII U+007C, not box-drawing — it does not live in 2500–257F, so the script doesn't touch it) — nothing to do. If conversely you want to drop ASCII pipes too — add s/^\|//mg or similar.
Right now it covers all my cases. If some new artifact ever leaks out of Claude Code, a range gets added with a single line.
