Skip to main content
ansicode
Ruby

ANSI escape codes in Ruby

Ruby's double-quoted strings accept \e as the ESC literal (no need for \x1b or \033), and puts / print / STDOUT.write are byte-clean on every platform. Ruby 3.0+ on Windows auto-enables ENABLE_VIRTUAL_TERMINAL_PROCESSING on the standard streams, so \e[31m lights up Conhost and Windows Terminal without a colorama-style shim. For ergonomic styling: colorize monkey-patches String with chainable colour methods ("oops".red.bold), term-ansicolor (Florian Frank's classic — powers pry and rspec) offers both module-call (Term::ANSIColor.red(...)) and mixin styles, and pastel (from the TTY toolkit) ships isolated SGR helpers that auto-detect NO_COLOR and CLICOLOR_FORCE without polluting String. For full TUIs reach for the rest of the TTY toolkit — tty-prompt, tty-spinner, tty-cursor, tty-progressbar.

Recommended libraries

  • colorize

    Monkey-patches String with chainable colour methods — "oops".red.bold.on_white. ~30M downloads, the de facto choice for one-off scripts and Rakefile output. Supports 8 named colours + extended palette via colorize(color: :red, mode: :bold, background: :white).

  • term-ansicolor

    Florian Frank's classic gem (since 2009) — both module-call style (Term::ANSIColor.red("text")) and mixin style (include Term::ANSIColor; red("text")). Powers pry, rspec, cucumber, and a long tail of Ruby CLI tools. Honours NO_COLOR since 1.7.0.

  • pastel

    Module-scoped SGR helper — Pastel.new.red.bold("oops"). No String monkey-patching. The TTY toolkit's idiomatic colour layer; Pastel.new(enabled: nil) auto-detects via tty? + NO_COLOR + CLICOLOR_FORCE. Supports decorators (pastel.decorate("text", :red, :bold)) and 256-colour on_<color> chains.

  • tty-prompt

    Interactive prompts — select, ask, multi_select, mask (password), yes?/no?, with polished styling and keyboard navigation. Pairs with tty-spinner, tty-progressbar, tty-cursor for a full TUI stack. Used by Hanami, Pry, Bundler-style installers, and Foreman.

Idiomatic patterns

Direct puts — \e is Ruby's ESC literal
puts "\e[1;31merror:\e[0m permission denied"
Chainable colours with colorize
require 'colorize'

puts "error:".red.bold + " permission denied"
puts "ok".green
puts "deprecated".yellow.on_black
Capability-aware styling with pastel + NO_COLOR / CLICOLOR_FORCE
require 'pastel'

# Pastel.new(enabled: nil) auto-detects:
#   STDOUT.tty? AND NO_COLOR not set AND CLICOLOR != '0'
#   CLICOLOR_FORCE=1 forces colour even when redirected.
pastel = Pastel.new

puts "#{pastel.red.bold('error:')} permission denied"
puts pastel.decorate('lavender truecolor', :on_blue, :bold)

# Disable globally — e.g. in CI:
plain = Pastel.new(enabled: false)
puts plain.red('this prints as plain text')
In-place progress with CR + EL + cursor hide
STDOUT.print "\e[?25l"               # hide cursor
at_exit { STDOUT.print "\e[?25h" }   # restore on any exit path

100.times do |i|
  # \r returns to col 1, \e[K erases to end of line
  STDOUT.print "\r\e[K#{i + 1}% complete"
  STDOUT.flush
  sleep 0.02
end
puts

Related sequences

Other languages