/paste — Clean content for any destination
Cleans terminal output (ANSI, box-drawing, prompt artifacts, etc.) and reformats per destination rules. Reads clipboard by default, writes back to clipboard + previews in chat.
Step 1 — Get the content
In order:
- If the user included content in the prompt (pasted, or referenced from earlier in the conversation), use that.
- Else, read clipboard:
pbpaste
- If both empty, ask the user what to paste.
Step 2 — Parse destination
| Invocation |
Destination |
/paste |
plain (default) |
/paste plain |
plain |
/paste slack |
slack |
/paste notion |
notion |
/paste twitter or /paste x |
twitter |
/paste linkedin or /paste li |
linkedin |
/paste email |
email (plain) |
/paste email rich or /paste email html |
email (rich/HTML) |
/paste github or /paste gh |
github |
/paste markdown or /paste md |
markdown render |
/paste html |
render to HTML file + open in browser |
If ambiguous, ask. Per-destination rules live in references/destinations.md.
Step 3 — Scan for secrets
Before any cleaning or copying, scan against patterns in references/secret-patterns.md.
If any match:
- Stop. Don't copy yet.
- Report what was detected with the value masked (first 4 + last 4 chars only — e.g.
sk-12...wxyz).
- Ask: "Spotted [type] in the content. Continue, redact (replace with
[REDACTED]), or abort?"
- Default to abort if no clear answer.
Step 4 — Universal cleaning
Strip from the content:
- ANSI escape codes —
\x1b\[[0-9;]*[a-zA-Z] and related (color codes, cursor movement, screen control)
- Box-drawing chars —
╭ ─ ╮ │ ╰ ╯ ╞ ╡ ╤ ╧ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ ━ ┃ ┏ ┓ ┗ ┛ etc. Replace with simpler equivalents (-, |) or remove entirely depending on context.
- Terminal prompt artifacts — leading
$ , > , ❯ , % , # (when first non-whitespace on a line that looks like a shell prompt)
- Carriage returns (
\r) — replace with \n or delete
- Trailing whitespace per line
- Excess blank lines — collapse 3+ consecutive blank lines to 2
Step 5 — Apply destination rules
Read references/destinations.md and apply the relevant transform.
Step 6 — Output
| Destination |
Output behavior |
| plain / slack / notion / twitter / linkedin / email / github |
(a) Show preview in a code fence in chat. (b) Copy clean version to clipboard via pbcopy. |
| email rich |
Render to HTML, write to /tmp/paste-<timestamp>.html, open it in browser. Skip clipboard (the user copies from browser to preserve rich text). |
| markdown |
Render the cleaned markdown directly in chat (Claude Code renders it). Also copy raw markdown to clipboard. Offer: "Open as HTML too?" — if yes, write and open. |
| html |
Render to HTML, write to /tmp/paste-<timestamp>.html, open it. Skip clipboard. |
After output, report a one-line summary of what was cleaned (e.g., "Stripped 12 ANSI codes, 4 box-drawing chars, 1 prompt artifact. Character count: 248 / 280 (X).").
Length warnings
Twitter and LinkedIn have practical limits. the user said "let me trim" — don't refuse or auto-truncate.
- Twitter/X: warn if >280 chars. Note the overage.
- LinkedIn: warn if >400 chars (comfort line, not hard limit).
- Other destinations: no length warning.
URL handling for social destinations
If the content has URLs and destination is twitter or linkedin:
- Surface the URLs separately (don't include them in the body)
- Remind the user: links go in a first comment (LinkedIn) or reply (X), not the body
- See
makerskills:jab-hook and ~/.claude/memory/feedback_social_link_placement.md
Examples
/paste slack
→ Reads clipboard, strips ANSI, converts **bold** to *bold*, copies to clipboard, shows preview.
/paste twitter
[pasted error log]
→ Uses pasted content (ignores clipboard), strips everything, warns at 412/280 chars, copies, asks if the user wants to trim or pick a different destination.
/paste html
[pasted markdown table]
→ Renders table as HTML, opens in browser. the user selects + copies into Notion/email with formatting preserved.
/paste
[pasted output with sk-anthropic-key in it]
→ Stops. "Spotted what looks like an Anthropic API key: sk-an...3kf9. Continue, redact, or abort?"
Composes with
jab-hook — clean output for pasting into Typefully drafts when the MCP path doesn't fit; also enforces the link-placement rule for X/LinkedIn destinations
social-fetch — clean a fetched post before quoting it in a draft or newsletter
second-brain — paste output can be captured cleanly into raw/note-<slug>.md for future compilation
watch-video — transcript / summary output often flows through paste for platform-specific reformatting
Notes on quality
- Secret detection runs first, always. Before any formatting or destination logic,
paste scans for sk-*, AKIA*, xoxb-*, JWT-shaped strings, and long-hex tokens. Prompts before proceeding on any hit. Better to false-positive occasionally than to leak a real key.
- Destination-aware transforms, not one-size-fits-all. Slack wants
*bold*; LinkedIn wants unicode-styled bold; email wants HTML. Same input, 9 different valid outputs. The destination flag is not optional.
- ANSI codes get stripped for every destination. Terminal escapes (
\033[31m etc.) render as garbage everywhere except the source terminal.
- Character limits are enforced, not warnings. X at 280, LinkedIn at 3000, Twitter at 25000 — paste refuses to copy over-limit output and offers a trim strategy.
- Links go in first comments for social destinations — not the body. Enforced when destination is
twitter or linkedin. Documented in ~/.claude/memory/feedback_social_link_placement.md.
- HTML destination opens in a browser tab, not the clipboard. Formatted tables + code blocks need a rendered surface to select-and-copy from with formatting preserved. Copying raw HTML to the clipboard produces garbage in Notion/email.
1---2name: paste3description: When you want to clean and reformat content (usually from your terminal) for pasting into Slack, Notion, Twitter/X, LinkedIn, email, GitHub, or plain text. Strips ANSI codes, box-drawing chars, terminal prompt artifacts, and applies destination-specific formatting. Default input is the clipboard (read via `pbpaste`); default output is both the clipboard (`pbcopy`) and a chat preview. Triggers on "/paste", "/paste [destination]", "clean this for X," "format for slack/notion/twitter/linkedin/email/github," "render as markdown," "paste-ready," "strip formatting," "make this copy-pastable." Default destination is plain. Also scans for secrets (API keys, tokens, .env values) and warns before copying anything sensitive.4---5
6# /paste — Clean content for any destination
7
8Cleans terminal output (ANSI, box-drawing, prompt artifacts, etc.) and reformats per destination rules. Reads clipboard by default, writes back to clipboard + previews in chat.
9
10## Step 1 — Get the content
11
12In order:
131. If the user included content in the prompt (pasted, or referenced from earlier in the conversation), use that.
142. Else, read clipboard: `pbpaste`
153. If both empty, ask the user what to paste.
16
17## Step 2 — Parse destination
18
19| Invocation | Destination |
20|---|---|
21| `/paste` | **plain** (default) |
22| `/paste plain` | plain |
23| `/paste slack` | slack |
24| `/paste notion` | notion |
25| `/paste twitter` or `/paste x` | twitter |
26| `/paste linkedin` or `/paste li` | linkedin |
27| `/paste email` | email (plain) |
28| `/paste email rich` or `/paste email html` | email (rich/HTML) |
29| `/paste github` or `/paste gh` | github |
30| `/paste markdown` or `/paste md` | markdown render |
31| `/paste html` | render to HTML file + open in browser |
32
33If ambiguous, ask. Per-destination rules live in `references/destinations.md`.
34
35## Step 3 — Scan for secrets
36
37Before any cleaning or copying, scan against patterns in `references/secret-patterns.md`.
38
39If any match:
401. **Stop.** Don't copy yet.
412. Report what was detected with the value **masked** (first 4 + last 4 chars only — e.g. `sk-12...wxyz`).
423. Ask: *"Spotted [type] in the content. Continue, redact (replace with `[REDACTED]`), or abort?"*
434. Default to **abort** if no clear answer.
44
45## Step 4 — Universal cleaning
46
47Strip from the content:
48
49- **ANSI escape codes** — `\x1b\[[0-9;]*[a-zA-Z]` and related (color codes, cursor movement, screen control)
50- **Box-drawing chars** — `╭ ─ ╮ │ ╰ ╯ ╞ ╡ ╤ ╧ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ ━ ┃ ┏ ┓ ┗ ┛` etc. Replace with simpler equivalents (`-`, `|`) or remove entirely depending on context.
51- **Terminal prompt artifacts** — leading `$ `, `> `, `❯ `, `% `, `# ` (when first non-whitespace on a line that looks like a shell prompt)
52- **Carriage returns** (`\r`) — replace with `\n` or delete
53- **Trailing whitespace** per line
54- **Excess blank lines** — collapse 3+ consecutive blank lines to 2
55
56## Step 5 — Apply destination rules
57
58Read `references/destinations.md` and apply the relevant transform.
59
60## Step 6 — Output
61
62| Destination | Output behavior |
63|---|---|
64| plain / slack / notion / twitter / linkedin / email / github | (a) Show preview in a code fence in chat. (b) Copy clean version to clipboard via `pbcopy`. |
65| email rich | Render to HTML, write to `/tmp/paste-<timestamp>.html`, `open` it in browser. Skip clipboard (the user copies from browser to preserve rich text). |
66| markdown | Render the cleaned markdown directly in chat (Claude Code renders it). Also copy raw markdown to clipboard. Offer: *"Open as HTML too?"* — if yes, write and open. |
67| html | Render to HTML, write to `/tmp/paste-<timestamp>.html`, `open` it. Skip clipboard. |
68
69After output, report a one-line summary of what was cleaned (e.g., *"Stripped 12 ANSI codes, 4 box-drawing chars, 1 prompt artifact. Character count: 248 / 280 (X)."*).
70
71## Length warnings
72
73Twitter and LinkedIn have practical limits. the user said "let me trim" — don't refuse or auto-truncate.
74
75- **Twitter/X**: warn if >280 chars. Note the overage.
76- **LinkedIn**: warn if >400 chars (comfort line, not hard limit).
77- Other destinations: no length warning.
78
79## URL handling for social destinations
80
81If the content has URLs and destination is **twitter** or **linkedin**:
82- Surface the URLs separately (don't include them in the body)
83- Remind the user: links go in a first comment (LinkedIn) or reply (X), not the body
84- See `makerskills:jab-hook` and `~/.claude/memory/feedback_social_link_placement.md`
85
86## Examples
87
88```
89/paste slack
90```
91→ Reads clipboard, strips ANSI, converts `**bold**` to `*bold*`, copies to clipboard, shows preview.
92
93```
94/paste twitter
95[pasted error log]
96```
97→ Uses pasted content (ignores clipboard), strips everything, warns at 412/280 chars, copies, asks if the user wants to trim or pick a different destination.
98
99```
100/paste html
101[pasted markdown table]
102```
103→ Renders table as HTML, opens in browser. the user selects + copies into Notion/email with formatting preserved.
104
105```
106/paste
107[pasted output with sk-anthropic-key in it]
108```
109→ Stops. *"Spotted what looks like an Anthropic API key: `sk-an...3kf9`. Continue, redact, or abort?"*
110
111## Composes with
112
113- `jab-hook` — clean output for pasting into Typefully drafts when the MCP path doesn't fit; also enforces the link-placement rule for X/LinkedIn destinations
114- `social-fetch` — clean a fetched post before quoting it in a draft or newsletter
115- `second-brain` — `paste` output can be captured cleanly into `raw/note-<slug>.md` for future compilation
116- `watch-video` — transcript / summary output often flows through `paste` for platform-specific reformatting
117
118## Notes on quality
119
120- **Secret detection runs first, always.** Before any formatting or destination logic, `paste` scans for `sk-*`, `AKIA*`, `xoxb-*`, JWT-shaped strings, and long-hex tokens. Prompts before proceeding on any hit. Better to false-positive occasionally than to leak a real key.
121- **Destination-aware transforms, not one-size-fits-all.** Slack wants `*bold*`; LinkedIn wants unicode-styled bold; email wants HTML. Same input, 9 different valid outputs. The destination flag is not optional.
122- **ANSI codes get stripped for every destination.** Terminal escapes (`\033[31m` etc.) render as garbage everywhere except the source terminal.
123- **Character limits are enforced, not warnings.** X at 280, LinkedIn at 3000, Twitter at 25000 — paste refuses to copy over-limit output and offers a trim strategy.
124- **Links go in first comments for social destinations** — not the body. Enforced when destination is `twitter` or `linkedin`. Documented in `~/.claude/memory/feedback_social_link_placement.md`.
125- **HTML destination opens in a browser tab, not the clipboard.** Formatted tables + code blocks need a rendered surface to select-and-copy from with formatting preserved. Copying raw HTML to the clipboard produces garbage in Notion/email.