Ansi.md

About

Ansi.md is my brain dump for creating modern command line apps. My intent is to gradually expand this guide with hard-won tricks, recommended apps and homegrown tools. My name is Adam Doppelt, feedback welcome at [email protected].

AI statement: I like my writing voice and I do not use LLMs to write.

Why

I don't claim to be an expert on command line apps, but I've written a few popular tools (like tennis) and it's not easy. I've also built literally hundreds of internal cli apps for various projects and I'm inordinately obsessed with color, progress bars, and spinners.

Why is this stuff so complicated? In order to answer this question, you have to dig into the history of the terminals and text output. Your little cli app runs inside something like Apple Terminal, Ghostty, iTerm, Alacritty, or even good ol' xterm. If you are using a web-based terminal like the thing inside Google Cloud, you are running a javascript terminal.

Terminals have a shared lineage dating back to the classic VT100 from 50 years ago. My dorm room actually had one of these. Your lovingly crafted app emits bytes like "hello world" and the terminal displays them.

Vintage hardware terminals were relatively straightforward, displaying text on screen and looking for \n to advance to the next line. Similar to typewriters of that era. In the pre-internet days we used modems to access our apps and data remotely using new kinds of software terminals. But modern terminals are capable of more, so much more. Too much, probably.

We've got truecolor RGB. We've got themes that are "light" and "dark". We've got mouse control, layout, and hints for double buffering. We've got window titles. We've got strange graphics protocols, built-in tiny progress bars, and hacks to make the icon bounce in the Dock.

Modern terminals carefully parse the stream of bytes printed from your app in order to support these features. Terminals also set environment variables to give hints to your app about what's supported. Tools like ssh or tmux have to understand these environment variables too, otherwise apps running over ssh have no idea what's supported. There are huge databases that try to capture which features are supported by which terminals. Brave apps can also query the terminal directly using obscure invisible codes.

I'll be honest with you, this system is a beautiful mess and probably should be burned in a fire. The complexity is made worse due to the various strata in the system - it's quite easy to encounter docs painstakingly written for older terminals, but in many cases you won't need that stuff. Software evolves quickly, and devs are eager to move on to modern terminals.

In the meantime, cli and library authors need to understand the ecosystem if they want to create nice cli apps. That's why I created ansi.md, to collect the latest and greatest ansi knowledge in one place.

Pages

  1. Home
    you are here
  2. ENV & Capabilities
    OMG why is this so hard
  3. Color Depth
    all about color palettes
  4. CLI Best Practices
    the difference between meh and awesome cli
  5. Progress Bars & Spinners
    the fun stuff
  6. The TUI
    pretty apps
  7. ANSI Escape Codes
    just the basics, ha
  8. Advanced ANSI Stuff
    don't read this
  9. Recommended Apps & Libs
    stuff I personally like

Tools

  1. Nearest Color
    nearest ANSI 256 and Tailwind matches
  2. Giant Contrast Table
    see lots of colors on light and dark

Palettes

  1. ANSI 256 Color Cube
    ansi 256 names-as-code
  2. Catppuccin Colors
    Catppuccin-as-code
  3. D3 Ordinal Scales
    d3 scales-as-code
  4. Tailwind Colors
    tailwind colors-as-code

Special Thanks

  • design inspo from Fil's lovely Fil-C doc site
  • nak for reading early (bad) drafts
  • site built with astro, thanks guys

Changelog

Aug 2026 - first public release