← Learnings

Glow, a markdown reader that fills your terminal

Glow renders a markdown file in your terminal instead of showing you the source. By default it uses 80 columns, no matter how wide your window is.

Hand the whole thing to Claude Code
PROMPTCLAUDE CODE
Set up Glow so it renders markdown at my terminal's full width instead of
wrapping at 80 columns. Work on my actual machine and verify the result — do not
just append a line to my shell config and declare it done.

1. INSTALL. Check whether `glow` is on PATH (`command -v glow`). If not, install
   it with whatever package manager this machine uses — `brew install glow` on
   macOS; on Linux see github.com/charmbracelet/glow for apt/pacman/etc. Report
   the version you end up with.

2. CONFIRM THE PROBLEM. Find Glow's config — `glow --help` prints the default
   path on the "--config" line (macOS: ~/Library/Preferences/glow/glow.yml,
   Linux: ~/.config/glow/glow.yml). Glow writes this file itself on first run.
   Show me the `width:` value in it. Do not bother deleting that key as a fix:
   on glow 3.0.0 removing it changes nothing, because 80 is Glow's compiled-in
   default and it does not auto-detect terminal width. The `-w` flag is the only
   thing that widens the render.

3. CHECK FOR A PINNED COLUMNS — do not skip this, it is the step that makes the
   obvious fix fail silently. `tput cols` reads the COLUMNS environment variable
   before asking the terminal. Grep my shell startup files (~/.zshrc, ~/.zshenv,
   ~/.zprofile, ~/.bashrc, ~/.bash_profile, ~/.profile) for anything that sets
   or exports COLUMNS. If something does, `tput cols` returns that fixed number
   forever, and any width fix built on it renders at the wrong size with no error
   and no clue why. The function below is written to be immune either way, but
   tell me if you find such a line — it also makes every other COLUMNS-aware
   tool on this machine (less, fold, python rich, many TUIs) believe my terminal
   is a fixed width, which is worth deciding about separately.

4. INSTALL THE WRAPPER. Append this to the rc file for my login shell (`echo
   $SHELL` — ~/.zshrc for zsh, ~/.bashrc or ~/.bash_profile for bash). It works
   in both. It shadows `glow` itself, so my existing habits keep working:

       # Glow wraps at 80 columns (`width: 80` in the config it writes itself),
       # and deleting that key does not help, so -w is the only way to fill a
       # wider window. `COLUMNS=` clears any pinned COLUMNS so tput reads the
       # real terminal; it is read on every call, so it follows a resize.
       glow() {
         if [ ! -t 1 ]; then command glow "$@"; return; fi
         local w f
         w=$(COLUMNS= tput cols)
         for f in "$@"; do
           if [ -f "$f" ]; then command glow -w "$w" -p "$@"; return; fi
         done
         command glow -w "$w" "$@"
       }

   The `-t 1` guard keeps piped output (`glow x.md | head`) byte-identical to
   the raw binary. The `-f` loop adds the pager only when an argument is a real
   file, so `glow .` and bare `glow` still open the TUI normally.

5. VERIFY, and note this is harder than it looks: shells you spawn from your
   tools have no controlling terminal, so glow always falls back to 80 there and
   every setting looks identical — measure casually and you will "confirm" that
   nothing changed. Either render inside a pty of a known size (python's
   pty.openpty plus a TIOCSWINSZ ioctl on the slave fd before spawning, and
   clear COLUMNS from the child's environment first), or confirm the two halves
   separately: that `COLUMNS= tput cols` reports my real width, and that
   `glow -w N` renders at exactly N for a couple of values of N.

6. Check my rc file still parses (`zsh -n <file>` or `bash -n <file>`), then tell
   me to run `source <file>` or open a new terminal, and report what you actually
   verified versus what you did not.

One known limitation to mention to me rather than try to fix: Glow wraps at
print time, so text already on screen is cut rather than re-wrapped if I resize
the window afterwards. Resize first, then run.

Glow renders the file, not the source

cat shows the source. glow shows the rendered document. Same file, both ways:

zsh · 56 columns
$ cat sample.md
# Release checklist

| Step      | Owner | State |
| --------- | ----- | ----- |
| Sign      | dg    | done  |
| Notarize  | dg    | wait  |

- Run `appstore.sh check` before anything
- The build number is the commit count

$ glow sample.md

   Release checklist

   Step            │ Owner           │ State
  ─────────────────┼─────────────────┼────────────────
   Sign            │ dg              │ done
   Notarize        │ dg              │ wait

  • Run  appstore.sh check  before anything
  • The build number is the commit count
FIG 1 · THE SAME FILE THROUGH CAT, THEN THROUGH GLOW

github.com/charmbracelet/glow is Charm's terminal markdown reader. The second block above is its real output. It takes a file, a directory, or a URL. Installing is one line on macOS, and the same page lists packages for Arch, FreeBSD, Windows and Snap.

zsh · macos
$ brew install glow

$ glow notes.md      # render one file
$ glow .             # browse a directory of them
$ glow -p notes.md   # ...in a pager, for anything over a screen
FIG 2 · INSTALL, AND THE THREE COMMANDS YOU NEED

It only uses 80 columns

My terminal is 192 columns wide, but Glow renders into 80 of them. The width comes from a config file that Glow writes the first time you run it. Deleting that setting changes nothing: 80 is Glow’s built-in default, not just the number written into the file. With the width key removed the text still wraps at 80 in a 100-column window, a 150-column one and a 190-column one alike — Glow never measures the terminal for itself. No setting gives you the full window.

DEFAULT78 COLS CONFIG KEY DELETED78 COLS -w $(tput cols)187 COLS WINDOW EDGE · 190 COLS
FIG 3 · TEXT WIDTH FROM EACH SETTING, MEASURED IN A 190-COLUMN WINDOW

One line in .zshrc fixes it

A number in a config file cannot change when you resize the window, so the width has to be measured each time you run the command. tput cols does that. One trap: tput cols reads the COLUMNS environment variable before it asks the terminal, so if anything in your shell config exports COLUMNS it hands back that pinned number and the function renders at the wrong width, with no error to tell you why. Clearing COLUMNS for the length of the call is what makes it immune. Put that in a function in your .zshrc.

~/.ZSHRCZSH
# Glow always wraps at 80 — that is its built-in default, and deleting the
# width key from its config does not change it — so -w is the only way to fill
# a wider window. COLUMNS= makes tput measure the terminal instead of trusting
# a pinned variable. tput runs on each call, so the width follows a resize.
glowf() { command glow -w "$(COLUMNS= tput cols)" -p "$@"; }
FIG 4 · THE WHOLE FIX

The function is called glowf, not glow, so typing glow out of habit still gives you 80 columns and looks like the fix did nothing. Name it glow() instead if you would rather every call be wide — the command prefix is what stops it calling itself.

One caveat: the output does not change after it is printed. If you resize the window afterwards, the text already on screen is cut rather than re-wrapped. Resize first, then run.

A table in my notes went from nine wrapped lines per row to three, and the Source and Model column headers stopped being cut short to Sou… and Mod….