Awesome Go

box-cli-maker

CategoryCommand Line
SubcategoryAdvanced Console UIs
Stars667

Render highly customizable boxes in the terminal

About box-cli-maker

Box CLI Maker

Go Reference Go GitHub release Mentioned in Awesome Go

Box CLI Maker is a Go library for rendering highly customizable boxes in the terminal.

Used by kubernetes/minikube · Featured in Golang Weekly (×3) and GitHub's Release Radar

Features

  • 9 built‑in styles (Single, Double, Round, Bold, SingleDouble, DoubleSingle, Classic, Hidden, Block)
  • Custom glyphs for all corners and edges
  • Title positions: Inside, Top, Bottom
  • Title and Content alignment: Left, Center, Right
  • Inner padding and outer margin
  • Optional content wrapping with WrapContent and WrapLimit
  • Color support with:
    • First 16 ANSI color names
    • #RGB, #RRGGBB, rgb:RRRR/GGGG/BBBB, rgba:RRRR/GGGG/BBBB/AAAA
    • Automatic conversion to the terminal's color capability; suppressed for NO_COLOR and piped output
  • Unicode and emoji support with proper width handling
  • Derived styles with Copy() for building box families from a shared base
  • Explicit errors from Render, plus MustRender for panic‑on‑error

Installation

go get github.com/box-cli-maker/box-cli-maker/v3

Quick Start

package main

import (
    "fmt"

    box "github.com/box-cli-maker/box-cli-maker/v3"
)

func main() {
    b := box.NewBox().
        Style(box.Single).  // single-line border
        Padding(2, 1).      // inner padding: x (horizontal), y (vertical)
        Margin(3, 1).       // outer margin: x (horizontal), y (vertical)
        TitlePosition(box.Top).
        ContentAlign(box.Center).
        Color(box.Cyan).
        TitleColor(box.BrightYellow)

    out, err := b.Render("Box CLI Maker", "Render highly customizable boxes\nin the terminal")
    if err != nil {
        panic(err)
    }
    fmt.Println(out)
}

NewBox constructs a box with the default Single style.
Configure it via fluent methods, then call Render (or MustRender) to get the box as a string.

API Overview

Construction

b := box.NewBox()

You can clone a configured box and tweak it:

base := box.NewBox().
        Style(box.Single).
        Padding(2, 1).
        ContentAlign(box.Left)

info := base.Copy().Color(box.Green)
warn := base.Copy().Color(box.Yellow)

Styles

Select a built‑in style:

b.Style(box.Double)

Styles showcase

You can override any glyph after choosing a style:

b.Style(box.Single).
  TopLeft("+").
  TopRight("+").
  BottomLeft("+").
  BottomRight("+").
  Horizontal("-").
  Vertical("|")

Titles and Alignment

Title position:

TitlePosition decides where the title goes: inside the box, on the top border, or on the bottom border. The default is box.Inside.

b.TitlePosition(box.Inside)
b.TitlePosition(box.Top)
b.TitlePosition(box.Bottom)

Title Position showcase

Title alignment:

TitleAlign decides where the title sits: across the box for Inside titles, or along the border for Top and Bottom titles. It works together with TitlePosition, and the two can be called in any order:

b.TitlePosition(box.Top).TitleAlign(box.Center) // title centered on the top border

The values are box.Left, box.Center, and box.Right. If you don't set it, Inside titles are centered and Top/Bottom titles are left‑aligned.

Title Alignment showcase

Content alignment:

ContentAlign decides whether content lines sit on the left, in the center, or on the right of the box. The box is as wide as its longest line, so it's the shorter lines that move. The default is box.Left.

b.ContentAlign(box.Left)
b.ContentAlign(box.Center)
b.ContentAlign(box.Right)

Content Alignment showcase

Padding

Padding adds space inside the box borders, between the border and the content: px columns of spaces on both the left and right of every line, and py blank rows above and below the content.

b.Padding(px, py) // set both: horizontal (px), then vertical (py)
b.HPadding(px)    // horizontal only
b.VPadding(py)    // vertical only

Horizontal comes first — the reverse of CSS's padding: vertical horizontal shorthand.

Padding defaults to 0. Setting negative padding causes Render to return an error.

Margin

Margin adds space outside the box borders — horizontal margin prepends spaces to every line, vertical margin adds blank lines above and below.

b.Margin(mx, my) // horizontal (mx) and vertical (my) margin
b.HMargin(mx)    // horizontal only
b.VMargin(my)    // vertical only

The argument order matches Padding: horizontal first.

Margin defaults to 0. Setting negative margin causes Render to return an error.

Wrapping

Long content can wrap automatically to fit the terminal, or at an exact width with WrapLimit. Wrapping is off by default.

b.WrapContent(true)       // enable wrapping (default: 2/3 of terminal width, minus any HMargin)
b.WrapLimit(40)           // set explicit wrap width (enables wrapping)
b.WrapContent(false)      // disable wrapping

Tabs are expanded (at 8‑column stops) before wrapping, so the configured limit is honored even for tab‑heavy content.

Render returns an error if the wrap limit is not positive or the terminal width cannot be determined when wrapping is enabled without a limit.

Colors

Colors can be applied to:

  • Title: TitleColor
  • Content: ContentColor
  • Border: Color

Accepted formats:

  • The 16 ANSI color names: box.Black, box.Red, box.Green, box.Yellow, box.Blue, box.Magenta, box.Cyan, box.White — each also available with a Bright prefix (e.g. box.BrightYellow) or its Hi alias (e.g. box.HiRed).
  • Hex and XParseColor formats (TrueColor and 8-bit): #RGB, #RRGGBB, rgb:RRRR/GGGG/BBBB, rgba:RRRR/GGGG/BBBB/AAAA

Example:

b.TitleColor(box.BrightYellow)
b.ContentColor("#00FF00")
b.Color("rgb:0000/ffff/0000")

Invalid colors cause Render to return an error.

Colors automatically adapt to what the terminal supports (TrueColor, 256‑color, or 16‑color). When the output can't show color at all — NO_COLOR set, TERM=dumb, or output piped to a file — colors are dropped entirely, so logs stay free of escape codes.

Styled Content and ANSI Safety

Your text may already be styled before it reaches the box — by your logger, a color library, or your own escape codes. That's fine: pass it in as-is, and the box renders correctly around it.

styled := "\x1b[31mthis red part is long enough to wrap\x1b[0m and this part is plain"
out, _ := box.NewBox().WrapLimit(24).Render("", styled)

What you can rely on:

  • Colors and styles in your text never leak into the borders or padding.
  • Styling survives wrapping: when a colored sentence breaks across lines, every line keeps its color.
  • Clickable hyperlinks (OSC 8) stay clickable — and the borders never become part of the link.
  • This works together with Color / ContentColor: your styling and the box's styling don't fight.

There is nothing to enable — this is how Render always behaves. (For the curious: every rendered line is made self‑contained by closing any open styling at the line's end and re‑opening it on the next line.)

Rendering

out, err := b.Render("Title", "Content")
if err != nil {
    // handle invalid style, colors, padding, wrapping, etc.
}

fmt.Println(out)

Render returns an error if:

  • The BoxStyle is invalid
  • The TitlePosition is invalid
  • The TitleAlign or ContentAlign is invalid
  • The wrap limit is not positive
  • Padding or margin is negative
  • A multiline title is used with a non‑Inside title position
  • Any configured colors are invalid
  • Terminal width detection fails when needed for wrapping

For convenience:

out := b.MustRender("Title", "Content") // panics on error

Examples

The examples directory contains small, focused programs that showcase different features:

  • simple_box – minimal single box with title and content.
  • content_align – compare Left, Center, and Right content alignment.
  • content_wrap – demonstrate WrapContent / WrapLimit with long text.
  • titles – every title position (Inside, Top, Bottom) with every alignment (Left, Center, Right).
  • spacing – inner padding vs outer margin, separately and combined.
  • box_styles – render all built‑in border styles and colors.
  • custom_box – build boxes using fully custom corner/edge glyphs.
  • ansi_styles_and_links – use bold/underline/blink/strikethrough and OSC 8 hyperlinks.
  • colors_and_unicode – mix hex/ANSI colors with CJK, emoji, and wrapping.
  • ansi_art – render more decorative/"artistic" boxes.
  • shared_styles – derive multiple boxes from a shared base style with Copy.
  • ksctl – real‑world example from ksctl showing wide titles vs narrow content.
  • lolcat – rainbow color demo using custom ANSI styling helpers.
  • readme – code used to generate the screenshot at the top of this README.

Unicode, Emoji, and Width Handling

This library uses mattn/go-runewidth and github.com/charmbracelet/x/ansi to handle:

  • Wide characters (e.g., CJK)
  • Emojis and other multi‑cell glyphs
  • Stripping ANSI sequences when measuring widths

Note:

  1. Rendering quality depends on the terminal emulator and font. Some combinations may misalign visually.
  2. Indic scripts and complex text may not display correctly in most terminals.
  3. Online playgrounds and many CI environments often use basic fonts and may not render Unicode/emoji correctly, so boxes may look misaligned there.

Migration from v2

v3 is a new major version with a redesigned API.

Key changes:

  • Config struct and New(Config) have been replaced with:

    b := box.NewBox().
        Style(box.Single).
        Padding(2, 1).
        TitlePosition(box.Top).
        ContentAlign(box.Left)
    
  • String‑based fields (Type, ContentAlign, TitlePos) are now strongly typed:

    • "Single" → box.Single
    • "Top" → box.Top
    • "Center" → box.Center
  • Colors:

    • No more interface{} colors (uint, [3]uint, etc.).
    • Use ANSI names or the documented hex/rgb formats instead.
    • Invalid colors now error at Render time.
  • Print / Println behavior can be replicated by fmt.Println(b.MustRender(...)) or your own helper.

Read more at Migration guide.

The old v2 API remains available at:

go get github.com/Delta456/box-cli-maker/v2

but is no longer actively developed.

Using Box CLI Maker in your project? Add it to the adopters list — we'd love to feature it.

Sponsors

Thanks to CodeRabbit for sponsoring my open source work.

Acknowledgements

Thanks to:

for inspiration, and to all contributors who have improved this library over time.

License

Licensed under MIT.

Frequently Asked Questions

What is box-cli-maker?

box-cli-maker is a Command Line library for the Go programming language. Render highly customizable boxes in the terminal

How do I install box-cli-maker?

Install box-cli-maker with the Go module system using `go get box-cli-maker/box-cli-maker`. Check the repository for the current installation instructions.

What category does box-cli-maker belong to?

box-cli-maker is listed under Command Line, specifically Advanced Console UIs.

← Back to Advanced Console UIs