How to use
- Paste the Markdown (an answer from ChatGPT, Claude, Copilot or Cursor, a README, a Notion export) into the left box.
- Pick Output for: Plain text drops every symbol; Slack, WhatsApp and Google Chat rewrite the formatting in that app's own markup so it renders bold and italic there.
- Choose how Links are written: the text with the URL in brackets, the URL alone, or the text alone.
- Copy to clipboard (or Ctrl+Enter in the input box) and paste into the chat, form or email.
What survives and what goes
AI assistants answer in Markdown. Paste that answer into Microsoft Teams, Google Chat, a Jira ticket, a CRM note or a web form and you get the raw symbols: ** around every emphasised phrase, # in front of each heading, |---| rows under each table. This tool parses the Markdown the way a renderer would and writes it back out as text a person would type: the structure stays, the syntax goes.
Kept: the words of every heading, bullet and numbered lists with their nesting, quoted lines, the full contents of code blocks, tables with their columns lined up, link addresses, image addresses, and the checked or unchecked state of task items. Removed: emphasis markers, heading hashes, backticks, link brackets, fence lines, horizontal rules and backslash escapes. Raw HTML in the input is left exactly as typed, because a chat box would show it literally either way. The AI Text Cleaner is the sibling tool for the other approach: strip the symbols in place and also fix smart quotes, em dashes and hidden characters.
Example
Load sample inserts a deploy checklist with 1 heading, 3 lists (one nested, one of tasks), 1 table, 1 code block and 3 links. In Plain text mode it becomes:
Deploy checklist
Run the full test suite before tagging a release: npm test takes about two minutes.
1. Bump the version in package.json
2. Update the changelog
• Group entries under Added, Changed and Fixed
• Link each entry to its pull request
3. Tag and push: git tag v2.4.0 && git push --tags
Environment | URL | Owner
------------|-----------------------------|------
Staging | https://staging.example.com | Priya
Production | https://example.com | Marco
> Production deploys happen only between 09:00 and 16:00 UTC.
npm run build && npm run deploy -- --env production
• ☑ Smoke test passed
• ☐ Release notes sent to #announcements (https://example.com/chat/announcements)Switch to Slack and the same input starts *Deploy checklist*, the heading as a bold line, with *full test suite* and _two minutes_ in Slack's own markup, the table and the command wrapped in ``` so they stay monospace. WhatsApp writes the task list as - ☑ Smoke test passed, using its "- " list syntax instead of the • character.
Options explained
- Output for: Plain text removes all formatting. Bullets are • characters, numbered items keep their numbers, quotes keep a
>prefix, tables are aligned in columns, code is written as-is with no fences. - Output for: Slack writes
*bold*,_italic_,~strike~,`code`,```blocks and>quotes, as Slack documents for its markup mode. Slack has no list syntax in that mode, so bullets stay • characters:• one. Headings become a bold line:*Release notes*. - Output for: WhatsApp uses the same bold, italic, strikethrough and code markup, plus WhatsApp's own list syntax, which renders
- oneas a bulleted list, and1.for numbered items. - Output for: Google Chat matches WhatsApp: Google Chat documents
-bullets and>quotes alongside the same emphasis characters. - Links: Text (URL) writes
See the docs (https://example.com/docs).; URL only writesSee the https://example.com/docs.; Text only writesSee the docs.. A link whose text is already its address is written once:https://example.com. - Load sample inserts the checklist shown above; Clear empties both boxes.
- Copy to clipboard and Download .txt take the right-hand box as it is. Ctrl+Enter in the input box copies.
Edge cases and common errors
- Nested lists keep their depth by indentation:
- a / - b / (two spaces) - b1 / (four) 1. deep / - cbecomes• a ⏎ • b ⏎ • b1 ⏎ 1. deep ⏎ • c, so a chat message still reads as an outline. - Underscores inside words are not emphasis.
snake_case_namestays as written, as the CommonMark rules require;__init__on its own, however, is bold in Markdown, so it comes out asinit:use snake_case_name and init here. - An unclosed marker stays literal.
a **never closed and *this* is finegivesa **never closed and this is fine: the lone**is kept because nothing closes it, exactly as GitHub would show it. - Task lists become
• ☑ done ⏎ • ☐ todo, using ☑ and ☐ so the state survives without brackets. - Images have no text form, so
becomesLogo (https://example.com/logo.png). - Code blocks: plain text keeps the code and drops the fences (
const x = 1;); the chat modes keep the fences because the apps render them as monospace:``` ⏎ const x = 1; ⏎ ```. The language tag after the opening fence is dropped in every mode. - Tables are padded so columns line up in a monospace font, and the chat modes wrap them in a code block for that reason. In a proportional font the columns drift; that is the trade-off for a table with no pipes and dashes to strip.
- Horizontal rules disappear.
---between two paragraphs is a pause, not content:before ⏎ ⏎ after. - Line breaks follow Markdown's rules: two trailing spaces or a backslash make a real break; a bare newline inside a paragraph is a space.
line one ⏎ line two line three. - HTML tags in the input are not interpreted:
<b>kept</b> as typed. - No Markdown at all gives the input back unchanged, and the status line says so rather than leaving you to compare two identical boxes. Empty input gives empty output.
- Size: half a megabyte of Markdown (thousands of headings, lists and tables) parses and renders in well under a second; typing is debounced so keystrokes never wait on it.
Do the same thing in code
Shell (pandoc)
pandoc -f gfm -t plain answer.md # plain text, structure kept
pandoc -f gfm -t plain --wrap=none answer.md # no re-wrapping of long linesPython
import markdown
from bs4 import BeautifulSoup
html = markdown.markdown(text, extensions=["tables", "fenced_code"])
plain = BeautifulSoup(html, "html.parser").get_text("\n")JavaScript (Node.js)
import { marked } from "marked";
import { convert } from "html-to-text";
const plain = convert(marked.parse(text), { wordwrap: false });Each of those goes through HTML and loses the chat-markup step; for Slack, WhatsApp or Google Chat markup use the modes above. If the pasted text is not going into a chat but into a document, Markdown to Google Docs keeps the formatting instead of removing it, and if the text needs its curly quotes and dashes straightened as well, run it through the AI Text Cleaner afterwards. Lists that come out one item per line can be joined with the column to comma separated list tool.