.-"""""-. ╭─────╮ ╭─────╮ ╭──────╮ ╭─────╮
.-' _ _ '-. │ You │ │ CLI │ │ Core │ │ TTY │
.' (o) (o) '. ╰──┬──╯ ╰──┬──╯ ╰───┬──╯ ╰──┬──╯
/ .-. \ │ │ │ │
; .--./___\.--. ; │ │ │ │
| / /_____\ \ | │ Mermaid in, terminal art out │
| \__/ '-' \__/ | │ │ │ │
; /| |\ ; │ merman diagram.mmd │ │ │
\ /_|_|_\ / ├───────────────────────▶ │ │
'. | | .' │ │ │ │
'-. | | .-' │ ├──────────────╮ │ │
'--|_|--' │ │ detect kind │ │ │
/| |\ │ ◀──────────────╯ │ │
/_|_|_\ │ │ │ │
.' | | '. │ │ parse │ │
/ | | \ │ ├──────────────────▶ │
; .--| |--. ; │ │ │ │
| / | | \ | │ │ ├─────────────────╮ │
| \__.| |.__/ | │ │ │ layout + route │ │
; | | ; │ │ ◀─────────────────╯ │
\ /| |\ / │ │ │ │
'-' | | '-' │ │ grid │ │
| | │ ◀──────────────────┤ │
___| |___ │ │ │ │
_.-' | | '-._ │ │ print │ │
.-' __| |__ '-. │ ├────────────────────────────────────────▶
/ | | \ │ │ │ │
; | | ; │ diagrams! │ │ │
| / \ | ◀────────────────────────────────────────────────────────────────┤
'._ _.' │ │ │ │
"""Mermaid diagrams for the terminal — flowcharts, sequence diagrams, and state diagrams as plain text, ANSI-colored output, or a live OpenTUI renderable.
Status: experimental. APIs may shift before
1.0.
Install merman globally when you just want diagrams on your $PATH:
bun add -g @kitlangton/merman
# or
npm install -g @kitlangton/mermanRender Mermaid from stdin, a positional argument, or a file:
echo "flowchart LR
A[Mermaid] --> B[Terminal]
B --> C[OpenTUI]" | merman --no-color╭─────────╮ ╭──────────╮ ╭─────────╮
│ Mermaid ├─────────▶│ Terminal ├─────────▶│ OpenTUI │
╰─────────╯ ╰──────────╯ ╰─────────╯More ways to run it:
# Read from a file
merman --file diagram.mmd
# Plain text (no ANSI escapes) for piping into docs
merman --file diagram.mmd --no-color > rendered.txtThe CLI is shipped as a Bun executable, so Bun must be available on your
$PATH.
Flowchart:
╭──────╮ ╭───────╮ ╭────────╮ ╭──────────╮
│ Idea ├─────────▶│ Parse ├─────────▶│ Render ├─────────▶│ Terminal │
╰──────╯ ╰───────╯ ╰────────╯ ╰──────────╯Sequence diagram:
╭──────╮ ╭────────╮ ╭──────────╮
│ User │ │ merman │ │ Terminal │
╰───┬──╯ ╰────┬───╯ ╰─────┬────╯
│ │ │
│ diagram.mmd │ │
├─────────────────▶ │
│ │ │
│ │ ANSI art │
│ ├─────────────────▶
│ │ │
│ ship it │ │
◀───────────────────────────────────┤
│ │ │State diagram:
╔═══════════╗ ╔═══════════════════╗
╔═══╣ edit loop ║ ╔═══╣ terminal snapshot ║
║ ╚═══════════╝ ║ ╚═══════════════════╝
║ ║
║ ║
╭───────╮ render ╭─────────╮ ship ╭───────────╮
●────────────▶│ Draft ├────────────▶│ Preview ├────────────▶│ Published ├────────────▶◎
╰──┬────╯ ╰──┬──────╯ ╰───┬───────╯
│ ▲ type │ ▲ tweak │ ▲ share
╰──╯ ╰────╯ ╰────╯Install the package with its OpenTUI peer dependency:
bun add @kitlangton/merman @opentui/core
# or
npm install @kitlangton/merman @opentui/coreESM only. The library requires Node >=20 or any current Bun.
render takes any Mermaid string — the leading flowchart/sequenceDiagram/
stateDiagram-v2 line picks the right renderer for you.
import { render } from "@kitlangton/merman"
// ANSI-colored string, ready for stdout.
console.log(
render(`flowchart LR
Cart([Cart]) --> Address[Address]
Address --> Payment[Payment]
Payment -->|approved| Orders[(Orders DB)]
Payment -->|declined| Retry([Retry])
Retry --> Payment`),
)
console.log(
render(`sequenceDiagram
Alice->>Bob: Hello
Bob-->>Alice: Hi`),
)
console.log(
render(`stateDiagram-v2
[*] --> Editing
Editing --> Submitted: submit`),
)
// Plain text (no escapes) — handy for snapshots and pipes.
render(content, { color: false })
// Override the palette.
render(content, { theme: { node: "#86E1C8", edge: "#5D766B" } })Two more top-level helpers:
import { parse, isMermaid } from "@kitlangton/merman"
isMermaid(content) // boolean — looks like any supported diagram?
const diagram = parse(content) // discriminated union
switch (diagram.kind) {
case "flowchart":
diagram.nodes.forEach(/* ... */)
break
case "sequence":
diagram.steps.forEach(/* ... */)
break
case "state":
diagram.states.forEach(/* ... */)
break
}Live, themeable, animatable diagrams are kind-specific (each has its own theme/animation surface). Pick the matching namespace:
import { createCliRenderer } from "@opentui/core"
import { Flowchart } from "@kitlangton/merman"
const renderer = await createCliRenderer({ targetFps: 30 })
const diagram = new Flowchart.Renderable(renderer, {
id: "diagram",
content: `flowchart TD
A[Start] --> B{Decide}
B -->|yes| C[Do it]
B -->|no| D[Skip]`,
})
renderer.root.add(diagram)Sequence.Renderable and State.Renderable follow the same pattern. Each
exposes theme setters, active-node/edge highlighting, and a pulseFrame for
animated edge pulses. See the demos in examples/.
Coming soon as a separate package: @kitlangton/merman-react.
Interactive demos (themes, active-node animation, scrolling, drag-to-pan) live
in examples/:
bun run examples # master demo: pick a sub-demo, Esc to go back
bun run examples:flowchart # individual demos
bun run examples:state
bun run examples:sequencebun install
bun run test # vitest-style suite via bun:test
bun run typecheck # tsc on src + examples
bun run build # tsdown -> dist/
bun run validate # build + publint + attw (pre-publish gate)See AGENTS.md for the codebase map and conventions.
MIT © Kit Langton