# mdwire > Send LLM-generated Markdown to chat channels without it breaking. mdwire does not render Markdown into finished output; it tailors the Markdown an agent wrote to each channel: it repairs it, rewrites it into the syntax each channel accepts, and splits it within the channel's length limit, in one shot or while tokens stream in. Pipeline: normalize → render for channel → split safely → send. Channels (the name each API takes): - `telegram-html` — Telegram `parse_mode: "HTML"` (nine tags, 4096-character limit) - `slack-markdown` — Slack `markdown_text` (standard Markdown, 12,000) - `github-markdown` — GitHub comments, GFM (65,536); a `~` or `<` meant as a character is escaped - `notion-markdown` — Notion page body, Notion-flavored Markdown (65,536); inline HTML Notion cannot draw is stripped - `plain` — plain text - `html` — HTML for the browser, safe to set as `innerHTML`: text is escaped and, by default, only `http(s)`/`mailto` links become `` (line breaks, images and allowed schemes are options) Use mdwire when: - a bot or agent posts model output to Telegram, Slack, GitHub or Notion — instead of a regex converter or escaping everything by hand - Telegram answers `Bad Request: can't parse entities` for an LLM answer (unclosed `**` or code fence, an unescaped `<`) - a streamed answer shows stray `**` or half-drawn formatting, or a Telegram message passes 4,096 characters and must be split without cutting through a tag - streaming LLM Markdown into React without `innerHTML` - Korean (or other CJK) text puts a particle right after bold (`**52%**다`), which CommonMark renderers leave unclosed Things that are easy to get wrong: - Streaming is append-only: what `push` returns is final and `finish` only appends the tail, so the pieces concatenated equal a one-shot `render` (unless the document is long enough to be split into parts). - A channel that rewrites the whole message (Telegram edit) sends the accumulated output plus `preview()`. An append-only channel (Slack `appendStream`) sends each `push` piece as is and never calls `preview()`. - The repair report counts what the normalizer fixed: closed emphasis, closed code fences, backtick runs kept as text, dropped `**` — and what the channel rewrote: escapes, tag emphasis, stripped HTML, bullets, tables, converted markers. - One Rust core with no dependencies. The CLI, the npm package (WASM) and the Go implementation are held to the same test cases. - `SPEC.md` and `DESIGN.md` are written in Korean. ## Docs - [README](https://raw.githubusercontent.com/minjun0219/mdwire/main/README.md): install and usage for the CLI, Rust, npm, React and Go - [README (Korean)](https://raw.githubusercontent.com/minjun0219/mdwire/main/README.ko.md): the same in Korean - [SPEC](https://raw.githubusercontent.com/minjun0219/mdwire/main/SPEC.md): what v0.1 covers and what was deliberately deferred (Korean) - [DESIGN](https://raw.githubusercontent.com/minjun0219/mdwire/main/DESIGN.md): the measurements behind each decision (Korean) ## For agents - [Agent skill](https://raw.githubusercontent.com/minjun0219/mdwire/main/skills/mdwire/SKILL.md): when to use mdwire, which channel and entry point to pick, and copyable code for each language (Agent Skills format). In Claude Code: `/plugin marketplace add minjun0219/mdwire`, then `/plugin install mdwire@mdwire` - WebMCP: pages on this site register a `mdwire_render` tool (`markdown`, `channel`, optional `limit`) that runs mdwire in the page and returns the parts and the repair report ## Packages - [npm `@minjun0219/mdwire`](https://www.npmjs.com/package/@minjun0219/mdwire): `render`, `renderWithReport`, `Streamer`; `@minjun0219/mdwire/react` (`Markdown`, `useMarkdownStream`), `@minjun0219/mdwire/events`, and `@minjun0219/mdwire/lezer` (`koreanEmphasis`, a `@lezer/markdown` extension that reads emphasis the way mdwire does) - [crates.io `mdwire-core`](https://crates.io/crates/mdwire-core): the Rust library, imported as `mdwire` - [crates.io `mdwire-cli`](https://crates.io/crates/mdwire-cli): the `mdwire` command — `mdwire --channel [--stream] [--report]` - [Go `github.com/minjun0219/mdwire/go`](https://pkg.go.dev/github.com/minjun0219/mdwire/go): the Go implementation, library and CLI ## Site Docs pages are Markdown at the page path plus `.md` (`/docs/npm/` → `/docs/npm.md`, `/ko/docs/` → `/ko/docs.md`). - [Overview](https://mdwire.minjun.dev/index.md): what mdwire does - [Why another one](https://mdwire.minjun.dev/why.md): three gaps in existing tools (emphasis across lines, Korean notation, streaming) - [Cases](https://mdwire.minjun.dev/why/cases.md): real failures (emphasis across lines, bold before a Korean particle, tildes, masked numbers, unclosed fences, Korean tables, splitting) and what mdwire sends instead - [Demos](https://mdwire.minjun.dev/demo/), all in the browser: [Telegram vs. Slack](https://mdwire.minjun.dev/demo/channels/) (one agent answer converted for both), [Streaming](https://mdwire.minjun.dev/demo/streaming/) (token by token into react-markdown, Streamdown, mdwire in front of Streamdown, and mdwire's React hook), [Before and after repair](https://mdwire.minjun.dev/demo/repair/) (broken agent output next to what mdwire sends, with the repair report) - [Korean](https://mdwire.minjun.dev/ko/): the site in Korean - [Docs: concepts](https://mdwire.minjun.dev/docs.md): channels, options, the repair report, the streaming contract - [Docs: npm](https://mdwire.minjun.dev/docs/npm.md) · [Rust](https://mdwire.minjun.dev/docs/rust.md) · [Go](https://mdwire.minjun.dev/docs/go.md) · [CLI](https://mdwire.minjun.dev/docs/cli.md): the API of each - [Docs: emphasis before Korean particles](https://mdwire.minjun.dev/docs/emphasis.md): why CommonMark parsers leave `**설정(config)**을` unclosed, the reading rule mdwire uses, and what GitHub, Slack and Notion need on output - [Full docs](https://mdwire.minjun.dev/llms-full.txt): the overview, why, cases and every docs page above in one file ## Optional - [Test cases](https://github.com/minjun0219/mdwire/tree/main/corpus/cases): input and expected output per channel, each a failure that actually happened - [Changelog](https://raw.githubusercontent.com/minjun0219/mdwire/main/CHANGELOG.md) - [Source](https://github.com/minjun0219/mdwire)