Back to Articles

Glow: Why Rendering Markdown in the Terminal Shouldn't Require a Browser

[ View on GitHub ]

Glow: Why Rendering Markdown in the Terminal Shouldn't Require a Browser

Hook

Most developers read more markdown in terminals than in browsers, yet we've normalized piping READMEs through cat like it's 1995. Glow's 25,000+ stars suggest the terminal deserves better typography.

Context

The terminal has always been where developers live, but documentation reading has been stuck in a peculiar limbo. You can syntax-highlight code with tools like bat, pretty-print JSON with jq, and visualize diffs with delta—but markdown, the lingua franca of developer documentation, has historically rendered as plain text with visible markup noise. Reading a README meant either opening a browser (context switch, slow), using GitHub's web interface (requires internet, breaks flow), or squinting at raw markdown where **bold** and [links](url) clutter the actual content.

This gap became more pronounced as projects adopted docs-as-code practices. Modern repositories contain dozens of markdown files—contributing guides, architecture decisions, API references—and developers needed to navigate this content without leaving their terminal environment. Glow emerged from Charm's ecosystem to solve this: a purpose-built markdown renderer that respects terminal constraints while delivering browser-quality typography. It's not just about pretty colors—it's about making documentation a first-class citizen in CLI workflows, with smart discovery, intuitive navigation, and rendering that adapts to your terminal's capabilities.

Technical Insight

TUI Components

Rendering

Detection

selected file

Markdown Input

File/stdin/URL

CLI Mode

Render Pipeline

TUI Mode

Bubble Tea Framework

Background Color

Detection

Theme Selector

dark/light/custom

Glamour Library

Markdown Engine

Stylesheet

JSON/YAML

File Browser

Git Scan

Interactive Pager

less-like keys

Terminal Output

TUI Display

System architecture — auto-generated

Glow's architecture revolves around two distinct operational modes, each serving different use cases. The traditional CLI mode acts as a rendering pipeline: input markdown (from file, stdin, or URL), apply styling, output to terminal or pager. The TUI mode transforms Glow into an interactive documentation browser, complete with file discovery, filtering, and navigation. Both modes share the same rendering engine—Charm's Glamour library—but expose radically different interfaces.

The rendering pipeline demonstrates Glow's attention to developer experience. Most terminal tools force you to manually specify themes, but Glow automatically detects your terminal's background color and selects an appropriate stylesheet. This happens through terminal escape sequence queries that probe the background RGB values. If your terminal responds, Glow calculates luminance and picks dark or light themes accordingly. If detection fails (some terminals don't support the query), it falls back to environment variable inspection or user configuration. This layered detection strategy means zero-configuration prettiness for 90% of users:

# Automatic theme detection - just works
glow README.md

# Override for screenshots or preferences
glow -s dark README.md

# Custom theme from JSON stylesheet
glow -s custom-theme.json README.md

The TUI mode reveals Glow's architectural sophistication. Built on Bubble Tea (Charm's Elm-inspired framework), it implements a full Model-View-Update cycle. The model tracks discovered markdown files, current selection, filter state, and scroll position. Updates respond to keypresses and file system events. The view renders a file browser with live filtering and preview panes. This isn't just a fancy file picker—Glow actively traverses your directory tree and Git repositories to build a markdown inventory, then presents it with fuzzy search and instant rendering.

Here's what the file discovery looks like in practice. When you run glow without arguments, it:

  1. Scans the current directory recursively for .md files
  2. Checks if you're inside a Git repository and includes tracked markdown files
  3. Reads your Glow configuration for custom file locations (like ~/Documents/notes)
  4. Presents everything in a filterable list with file paths and metadata
# Launch TUI in current directory
glow

# Launch TUI in specific directory
glow ~/projects/my-repo

# Add custom sources to config
echo 'sources:
  - ~/Documents/notes
  - ~/wiki' >> ~/.config/glow/glow.yml

The rendering engine itself leverages Glamour's AST-based approach. Markdown parsing produces an abstract syntax tree, which Glamour walks to apply styles defined in JSON stylesheets. Each node type—headings, lists, code blocks, tables—maps to specific rendering rules with configurable colors, padding, and borders. This separation between parsing and rendering allows Glow to support custom themes without touching the markdown engine. The stylesheet format is verbose but powerful:

{
  "document": {
    "block_prefix": "\n",
    "block_suffix": "\n",
    "color": "252",
    "background_color": "235"
  },
  "heading": {
    "block_suffix": "\n",
    "color": "39",
    "bold": true
  },
  "code_block": {
    "color": "244",
    "background_color": "236",
    "margin": 2
  }
}

One subtle but critical design decision: Glow's pager implementation. Rather than shelling out to less or more, Glow includes its own pager with markdown-aware navigation. This matters because external pagers don't understand ANSI escape sequences consistently, leading to rendering artifacts. The built-in pager handles styled output correctly and adds markdown-specific shortcuts—jump to next heading with n, previous with p, scroll by sections rather than lines. It's a small detail that dramatically improves the reading experience for long documents.

Glow also handles remote content gracefully. You can pass GitHub URLs directly, and Glow extracts the raw markdown, handles authentication if needed (via GitHub CLI tokens), and renders it locally. This eliminates the "open in browser" reflex when someone Slacks you a documentation link:

# Render from GitHub URL
glow https://github.com/charmbracelet/glow/blob/master/README.md

# Works with GitLab, raw GitHub URLs, any HTTP markdown
glow https://raw.githubusercontent.com/user/repo/main/docs/api.md

# Pipe remote content through glow
curl -s https://example.com/docs.md | glow -

The piping support integrates Glow into existing Unix workflows. Generate markdown programmatically, pipe it through Glow for presentation. Pull API documentation from a web service, render it locally. Chain Glow with grep, sed, or awk for filtered document viewing. This composability is where CLI tools earn their keep, and Glow respects the Unix philosophy while adding modern rendering capabilities.

Gotcha

Glow's biggest limitation stems from its strength: it's a viewer, not a converter or editor. If you need to transform markdown to PDF, HTML, or other formats, you'll still reach for Pandoc. Glow renders beautifully to ANSI-capable terminals but doesn't output anything else. This narrow focus is intentional—Charm builds single-purpose tools that do one thing well—but it means Glow can't replace your entire markdown toolchain, only the viewing part.

The custom styling system, while powerful, has a steep learning curve. The JSON stylesheet format requires understanding terminal color codes (256-color palette or RGB), box model concepts (margin, padding, border), and the specific node types Glamour recognizes. There's no visual editor or style preview tool, so customization involves editing JSON, running Glow, tweaking values, and repeating. The built-in dark and light themes cover most needs, but if you want precise brand colors or unusual layouts, expect an afternoon of experimentation. Documentation for stylesheet authoring is sparse, often requiring you to read Glamour's source code to understand available properties.

Performance can degrade in large repositories with thousands of markdown files. The TUI's file discovery is synchronous, so if you launch Glow in a monorepo with deep directory structures, you'll wait several seconds for the initial scan. There's no background indexing or caching between sessions, meaning every launch repeats the traversal. For everyday use in normal projects, this is imperceptible, but power users with extensive documentation trees might find the startup lag frustrating. Additionally, the fuzzy search operates on the full file list in memory, so filtering remains fast, but the initial load time is the bottleneck.

Verdict

Use if: You spend significant time reading documentation in the terminal, work with repos that have extensive markdown docs, want beautiful rendering without browser context switches, or need to integrate markdown viewing into CLI scripts and workflows. Glow excels for developers who live in terminal multiplexers, frequently browse API documentation, or give terminal-based demos. It's also perfect for quickly scanning unfamiliar repositories—launch the TUI, filter by keyword, and preview multiple docs without touching your mouse. Skip if: You rarely read markdown files, prefer web-based documentation browsers with search and navigation features Glow lacks, need document conversion rather than viewing, or work in environments without ANSI color support. Also skip if your markdown workflow involves heavy editing—Glow is read-only, so you'll still need a separate editor. For one-off README viewing where cat is sufficient, Glow's features may be overkill.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/cybersecurity/charmbracelet-glow.svg)](https://starlog.is/api/badge-click/cybersecurity/charmbracelet-glow)