Render markdown, images, diagrams, and pixel graphics in the terminal. Browse the filesystem with keyboard navigation.
markdown – render .md files with headings, lists, code blocks, imagesgraph – flowcharts, sequence diagrams, class diagramsimg – PNG, JPEG, GIF (animated), WebP with aspect-correct scalingcanvas – pixel drawing, shapes, SVG paths, text overlayssegment-display – 7-segment digits and pixel font textfile-browser – directory listing with filter, selection, keyboard navRender markdown files in the terminal. Headings, lists, code blocks, tables, links, and images.
Welcome to Melker Melker Engine renders rich terminal UIs from an HTML-inspired document model. Features • Tables, charts, and heatmaps • Markdown with syntax highlighting • Mermaid diagrams • File browser with fuzzy search Quick Start bash melker hello.melker ▎ Melker apps run in any ANSI terminal. ▎
Load a file with the src prop, or pass inline content with text.
The onLink handler fires when a user clicks a link, letting you
navigate between documents or open URLs in the browser.
<markdown id="md" src="README.md" onLink="$app.handleLink(event)" style="text-wrap: wrap" /> <script type="typescript"> export function handleLink(event: { url: string }) { if (event.url.startsWith('http')) { $melker.openBrowser(event.url); return; } // Navigate to another .md file within the app const md = $melker.getElementById('md'); md.props.src = event.url; } </script>
Markdown supports GFM extensions (tables, strikethrough), syntax-highlighted code blocks,
blockquotes, and images. Images referenced in markdown ()
are rendered inline using the same pixel graphics as the
<img> component. Code blocks with ```mermaid
are rendered as interactive diagrams (see next section).
Reference: Component reference
Flowcharts, sequence diagrams, and class diagrams rendered with Unicode box drawing.
Git Workflow ┌───── Local ─────┐ ┌──── Remote ─────┐ │ │ │ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ Working Dir │ │ │ │ Remote Repo │ │ │ └─────────────┘ │ │ └─────────────┘ │ │ │ │ │ ▲ │ │ │git add │ └────────│────────┘ │ │ │ │ │ ▼ │ │ │ ┌─────────┐ │ │ │ │ Staging │ │ │ │ └─────────┘ │ git pull │ │ │ │ │ │ │git commit │ │ │ │ │ │ ▼ │ │ │ ┌────────────┐ │ │ │ │ Local Repo │◀────────────────┘ │ └────────────┘ │ │ │ └─────────────────┘
The <graph> component parses Mermaid syntax and renders it
using Unicode box-drawing characters. Place the Mermaid definition directly
as the element's text content. Melker can also render .mmd files directly
from the command line: melker diagram.mmd.
<graph style="overflow: scroll; flex: 1"> flowchart LR subgraph Local WD[Working Dir] -->|git add| SA[Staging] SA -->|git commit| LR[Local Repo] end subgraph Remote RR[Remote Repo] end LR -->|git push| RR RR -->|git pull| LR </graph>
Mermaid blocks inside markdown code fences (```mermaid) are also
rendered as diagrams automatically. Nodes in the diagram are focusable and
keyboard-navigable.
```mermaid sequenceDiagram Client->>Server: GET /api/data Server->>DB: Query DB-->>Server: Results Server-->>Client: JSON response ```
Reference: Mermaid support · Graph architecture
Display PNG, JPEG, GIF, and WebP images using Unicode sextant characters (2x3 pixels per cell).
Image Component Format: PNG 🬞🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬏 Mode: sextant (2x3 pixels/cell) 🬞🬩🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬓 Fit: contain (preserves aspect) 🬯🬰🬰🬰🬞🬭🬭🬏🬭🬰🬰🬰🬞🬭🬭🬏🬮🬰🬰🬮 🬋🬋🬋🬋▐🬋🬋🬺🬱🬚🬹🬞🬵🬋🬋▌🬋🬋🬋🬋 🬰🬰🬰🬰▐🬰🬕🬊🬡🬲🬭🬰🬝🬨🬰▌🬐🬰🬰🬰 🬋🬋🬋🬋▐🬋🬃🬌🬉🬬🬋🬄🬎▐🬋▌🬃🬋🬋🬋 🬂🬂🬡🬁▐🬒▌▌🬂🬂🬂🬂🬨▐🬂▌🬐🬕🬂🬂 🬬🬍🬍🬬🬉🬎🬎🬄🬎🬎🬎🬎🬉🬉🬎🬄🬄🬌🬛🬛 🬁🬬🬬🬎🬎🬎🬎🬎🬎🬎🬎🬎🬎🬊🬎🬆🬆🬆🬎🬆 🬁🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬆🬂🬀
The <img> component renders images using Unicode block characters.
The default sextant mode gives 2x3 pixels per cell, and quadrant mode gives 2x2
pixels per cell with near-universal font support. Supports PNG, JPEG, WebP, and animated GIFs.
GIF animation plays automatically and can be disabled with --no-animate-gif.
A separate <video> component exists for MP4, RTSP streams, and other
video formats (requires FFmpeg).
<!-- Fixed size with aspect-correct scaling --> <img src="logo.png" width="20" height="10" style="object-fit: contain" /> <!-- Responsive: fills container width --> <img src="photo.jpg" width="100%" height="20" /> <!-- Animated GIF --> <img src="animation.gif" width="40" height="20" /> <!-- Load and error callbacks --> <img src="image.png" width="30" height="15" onLoad="$app.loaded()" onError="$app.failed()" />
The object-fit style controls scaling: "contain" preserves
aspect ratio, "fill" stretches to fill (default), "cover"
fills and crops. Use setSrc(url) to change the image at runtime.
Reference: Component reference
Pixel-level drawing with shapes, lines, text labels, and SVG paths.
Canvas Drawing 🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭 🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬭🬏 🬞🬭🬭🬭🬭🬭🬭🬭 ████40%████████ ███30%██████▌ ▐███20%█ 🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂🬂 🬞🬙🬎🬆🬂🬂🬂🬂🬎🬎🬰🬂🬂🬀 🬁🬂🬂🬂🬂🬂🬂🬂 🬞🬋🬀 🬈🬢 🬞🬄 🬣 🬔 🬁🬓 ▌ ▌ 🬉🬏 🬘 🬈🬭 🬞🬖🬀 🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬌🬩🬹🬚🬋🬋🬋🬋🬹🬹🬋🬌🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋🬋 🬁🬂🬂🬂🬂
The onPaint handler provides a canvas object with drawing methods.
Use fillRect, drawLine, drawCircleCorrected,
and drawText for basic shapes. SVG path strings are also supported
for curves and complex shapes.
<canvas id="c" width="40" height="12" gfxMode="sextant" onPaint="$app.draw(event.canvas)" /> <script type="typescript"> export function draw(canvas: any) { canvas.clear(); canvas.setColor('#3b82f6'); canvas.fillRect(2, 2, 30, 5); canvas.setColor('#ffffff'); canvas.drawText(10, 4, 'Label'); canvas.setColor('#6366f1'); canvas.drawCircleCorrected(45, 18, 12); } </script>
Canvas also supports per-pixel shaders via the onShader prop for
animated effects (requires "shader": true in the policy), named SVG overlay
layers via setSvgOverlay(), and tooltips via onTooltip.
The <img> component extends canvas, so all canvas methods
are available on images too.
Reference: Component reference
LCD/LED-style digits and pixel font text using Unicode characters.
7-Segment Display ━━━━ ━━━━ ━━━━ ━━━━ ┃ ┃ ● ┃ ┃ ┃ ● ┃ ┃ ┃ ━━━━ ━━━━ ━━━━ ━━━━ ┃ ┃ ● ┃ ┃ ● ┃ ┃ ┃ ━━━━ ━━━━ ━━━━ ━━━━ Pixel Font █ █ ████ █ █ ██ █ █ █ █ █ █ █ ████ ███ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ████ ████ ████ ██
Four renderers are available. The box-drawing renderer (default) draws
clean 7-segment digits with thin lines. rounded adds rounded corners.
geometric uses chunky block characters for an LCD look. The
pixel renderer uses bitmap font glyphs and supports the full ASCII
character set, including accented characters.
<!-- 7-segment clock --> <segment-display value="12:45:30" style="height: 5; color: green" /> <!-- Pixel font with custom characters --> <segment-display value="HELLO" renderer="pixel" style="height: 7; color: cyan" /> <!-- LCD effect with visible off-segments --> <segment-display value="88:88" style="color: #00ff00; off-color: #003300" /> <!-- Scrolling marquee --> <segment-display value="HELLO WORLD" scroll="true" scrollSpeed="24" style="width: 50" />
Height can be 5 or 7 rows. The pixel renderer uses
3x5 glyphs at height 5 and 5x7 glyphs at height 7. Set off-color
to make inactive segments visible (classic LCD panel look). Use
pixel-char and off-pixel-char styles to change the
fill characters.
Reference: Component reference
A filesystem navigator with fuzzy filtering, keyboard navigation, and single or multiple selection.
┌──────────────────────────────────────────────────────┐ │ Open File │ ├──────────────────────────────────────────────────────┤ │┌────────────────────────────────────────────────────┐│ ││ Path: /home/wistrand/melker ││ ││ Filter: type to filter... ││ ││┌──────────────────────────────────────────────────┐││ │││ [^] .. █││ │││ [D] agent_docs/ ░││ │││ [D] apps/ ░││ ││└──────────────────────────────────────────────────┘││ ││ [ Cancel ] [ Open ] ││ │└────────────────────────────────────────────────────┘│ └──────────────────────────────────────────────────────┘
The file browser is typically placed inside a <dialog>. It shows
a breadcrumb path, a filter input, a scrollable file list, and action buttons.
The onChange handler fires with the selected file path. Requires
"read" permission in the policy.
<policy>{ "permissions": { "read": ["*"] } }</policy> <dialog id="dlg" title="Open File" open="false" modal="true" width="60" height="18"> <file-browser id="fb" selectionMode="single" selectType="file" onChange="$app.pick(event)" onCancel="$app.closeDialog()" maxVisible="10" /> </dialog> <script type="typescript"> export function openDialog() { $melker.getElementById('dlg').props.open = true; } export function pick(event: { path: string }) { $melker.getElementById('dlg').props.open = false; $melker.getElementById('result').setValue(event.path); } </script>
Keyboard: arrows to navigate, Enter to open directory or select file, Backspace to go up, Escape to cancel, any character to start filtering. Space toggles selection in multiple mode.
Reference: File browser architecture
Configuration options for the markdown component.
<!-- Load from file --> <markdown src="docs/README.md" /> <!-- Inline content --> <markdown text="# Hello\n\nThis is **bold**." /> <!-- GFM tables, text wrapping, link handler --> <markdown src="file.md" enableGfm="true" style="text-wrap: wrap" onLink="$app.handleLink(event)" /> <!-- Light theme for code blocks --> <markdown src="file.md" codeTheme="light" />
The src prop loads from a file path or URL. Use text for inline markdown.
enableGfm (default true) enables GitHub Flavored Markdown
extensions like tables and strikethrough. The onLink event provides
event.url and optional event.title.
Change the source at runtime by updating the prop:
const md = $melker.getElementById('md'); md.props.src = 'other-file.md';
Reference: Component reference
Three Mermaid diagram types are supported.
<graph> flowchart TD A[Input] --> B{Valid?} B -->|Yes| C[Process] B -->|No| D[Error] D --> A </graph>
<graph> sequenceDiagram Client->>Server: Request Server->>DB: Query DB-->>Server: Results Server-->>Client: Response </graph>
<graph> classDiagram class Animal { +name: string +speak() } class Dog { +fetch() } Animal <|-- Dog </graph>
Flowcharts support subgraphs, decision nodes ({}), and edge labels.
The graph component can also load content from a URL with src,
or you can run .mmd files directly: melker diagram.mmd.
Reference: Mermaid support
Configuration for selection mode, file type filtering, and display.
<!-- Directory picker --> <file-browser selectType="directory" selectLabel="Choose Folder" onChange="$app.setWorkspace(event.path)" /> <!-- Multiple file selection --> <file-browser selectionMode="multiple" selectType="file" onChange="$app.handleFiles(event.paths)" /> <!-- Filter by extension --> <file-browser extensions="['.ts', '.js']" showHidden="true" onChange="$app.openFile(event.path)" /> <!-- Standalone without buttons --> <file-browser path="/home/user/docs" showButtons="false" maxVisible="15" onChange="$app.openFile(event.path)" />
The selectType prop controls what can be selected: "file",
"directory", or "both". The filter prop accepts
the same modes as combobox: "fuzzy" (default), "prefix",
"contains", "exact", or "none".
The onChange event provides event.path (full path),
event.name (filename), event.isDirectory, and
event.paths (array, for multiple selection).
The onError event fires with event.code (PERMISSION_DENIED,
NOT_FOUND) and event.message.
Reference: File browser architecture