box-cli-maker draws terminal boxes with a fluent API and nine border styles
Render highly customizable boxes in the terminal
At a glance
- What is it?
- Box CLI Maker is a Go library for rendering configurable boxes in a terminal, with nine built in border styles, custom glyphs, three title positions, colour handling that respects terminal capability and NO_COLOR, and a Copy method for deriving a family of boxes from one base. The v3 line is a rewrite with its own major version path and a MIGRATION.md.
- Who is it for?
- Adopt box-cli-maker if you are writing a Go command line tool that needs bordered output rather than a full screen interface, since it gives you border styles, title placement, wrapping and colour handling without pulling in a TUI framework. Do not adopt it for interactive selection, live redraw or layout, since it renders a string and nothing else.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 35 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Nine border styles, and every glyph can be replaced
Box CLI Maker is a Go library for rendering highly customizable boxes in the terminal, and its feature list starts with the part that matters most for a CLI: the border. There are nine built in styles, named Single, Double, Round, Bold, SingleDouble, DoubleSingle, Classic, Hidden and Block, and the README shows a screenshot per style rather than describing them in prose.
A style is a starting point, not a constraint. Any glyph can be overridden after the style is chosen, so a box can be given plus signs at the corners and simple dashes and pipes for the edges regardless of which style it started from:
b.Style(box.Single).
TopLeft("+").
TopRight("+").
BottomLeft("+").
BottomRight("+").
Horizontal("-").
Vertical("|")That design has a practical consequence. Teams often need a house style, and the fact that the glyphs are just strings means a shared visual language across a suite of tools is a matter of one helper function rather than nine separate style constants. The Block and Hidden styles are worth noting separately, since block style borders are what you want for dense output and a hidden style is how you draw a box with no visible border at all, which is useful for spacing.
The library also handles width correctly for Unicode and emoji, which is not a small detail in a box renderer, since a naive character count misaligns every border on any line containing wide characters.
The API is a builder chain ending in Render
The shape of the library is a fluent builder. NewBox constructs a box with the default Single style, you configure it with chained methods, and you call Render to get a string back. The README's quick start shows the whole sequence in one expression:
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)
}The two arguments to Render are the title and the content. Padding and margin are both pairs, and the comments in the example are explicit that the first value is horizontal and the second is vertical.
Error handling is a deliberate part of the design rather than an afterthought. The feature list calls out explicit errors from Render, plus MustRender for panic-on-error. That gives you the choice: a library that returns an error from Render for a normal call site, and a MustRender variant for the case where a failure really is a bug rather than a runtime condition. The example above shows the plain form, returning the error and panicking on it.
The import path carries the major version, github.com/box-cli-maker/box-cli-maker/v3, and the module path in go.mod matches, which is the Go convention for a v3 release of a module whose first version was v2 or earlier.
Copy turns one configured box into a family of related boxes
The feature that saves the most repetition is Copy, described in the README as a way to build box families from a shared base with derived styles. The example is short:
base := box.NewBox().
Style(box.Single).
Padding(2, 1).
ContentAlign(box.Left)
info := base.Copy().Color(box.Green)
warn := base.Copy().Color(box.Yellow)The pattern is the point. A configured base box is built once, and each variant is a copy with one difference applied, so the padding, style and alignment stay identical across an entire set of output panels while the colour carries the meaning. This is what you want for an info, warning and error trio, or for a set of status lines in a long running command.
Note what is not happening. The copies are not sharing mutable state at render time in a way that would let one change bleed into the others; each copy is an independent configured box that produces its own string. The README presents Copy as a configuration convenience rather than as a live inheritance mechanism, and the two examples in the repository, examples/shared_styles/ and examples/ansi_styles_and_links/, are where you would look to see the pattern in a longer form.
One caution: nothing in the README documents whether the copy is deep or shallow for the internal style state, so if you mutate a base after copying, treat the result as unspecified and rebuild the base instead.
Titles have a position and an alignment, and they interact
Title handling is where a box renderer usually gets confusing, so this library splits it into two independent decisions. TitlePosition decides where the title goes: inside the box, on the top border, or on the bottom border, with box.Inside as the default. TitleAlign decides where the title sits within that position, across the box for an Inside title and along the border for a Top or Bottom title.
The two can be called in any order, and the README pairs them in a single chain:
b.TitlePosition(box.Top).TitleAlign(box.Center) // title centered on the top borderThe defaults are worth knowing because they are not symmetrical. If you do not set the alignment, Inside titles are centered while Top and Bottom titles are left aligned. That is a sensible choice, since a title sitting on a border reads better starting from the left, but it means a title on the border and the same title inside will not line up the same way unless you set the alignment explicitly.
The values for alignment are box.Left, box.Center and box.Right, and the README shows a screenshot for each combination of the two settings, which is the only reliable way to judge how a title on a border interacts with the corner glyphs.
Colour is negotiated with the terminal, and NO_COLOR wins
The colour support is more careful than a hardcoded ANSI escape. The library accepts the first 16 ANSI colour names, hex in #RGB and #RRGGBB form, and the rgb:RRRR/GGGG/BBBB and rgba:RRRR/GGGG/BBBB/AAAA forms. It then converts the colour to what the terminal can actually display, and the feature list states that the output is suppressed for NO_COLOR and for piped output.
That last part is the important behaviour for a library used in scripts. A command whose output is piped into another program should not be full of escape codes, and a CI log that honours NO_COLOR should not be coloured either. The detection depends on the terminfo capability, and the dependency list in go.mod shows github.com/xo/terminfo, which is the package that provides terminal capability information, alongside charmbracelet/colorprofile, charmbracelet/x/ansi and charmbracelet/x/term for the profile handling and the terminal queries.
The same set of dependencies explains how the library handles Unicode and emoji with proper width handling: github.com/mattn/go-runewidth is a direct dependency, with clipperhouse/displaywidth and clipperhouse/uax29/v2 as indirect ones, which is the package README ecosystems rely on for terminal character width.
The practical effect is that you can set a hex colour and trust that the same code produces readable output in a modern terminal, a limited one, and a redirected file. The README does not document a way to force colour on, so if you need raw escape codes regardless of environment, that is the gap to check.
Wrapping and spacing are explicit, and the width is yours to set
Content wrapping is opt in through the WrapContent and WrapLimit options, and the feature list pairs them as a single capability. The limit is what makes wrapping predictable: without a width, a long line either runs off the terminal or gets truncated at some internal default.
Spacing is split into two controls, and the README is careful to distinguish them. Padding is inner padding, the space between the border and the content. Margin is outer margin, the space between the box and whatever is around it. The quick start uses Padding(2, 1) and Margin(3, 1), and both take horizontal then vertical values.
These two together with the glyph overrides are what decide whether a box sits nicely inside a wider panel of text or crowds it. In a CLI that prints several boxes in sequence, the margin is what creates the breathing room, and the padding is what keeps the text off the border line.
The examples directory is where the intended usage patterns are visible. It holds folders named simple_box/, custom_box/, box_styles/, titles/, content_align/, content_wrap/, spacing/, colors_and_unicode/, ansi_styles_and_links/, ansi_art/, shared_styles/, lolcat/, ksctl/ and readme/. The last two are interesting because they show the library used the way a real tool uses it, a colourised character animation and a kubectl style output, rather than as isolated demos.
v3 is a rewrite, and the migration file is the first thing to read
The release history shows a major transition in February 2026, with v2.4.0 and v3.0.0 published on the same day, 2026-02-09, and v3.1.0 following on 2026-09-15. The last push was on 2026-09-18 and the repository is not archived.
That same-day v2 and v3 release is the signal that v3 is not a small increment. The repository root carries a MIGRATION.md, and the import path changed to include /v3, so upgrading is a deliberate migration with its own document rather than a version bump. If you are on the v2 line, read MIGRATION.md before touching your code, because the module path itself changes the import statement in every file that uses the library.
The licence is MIT, recorded in the LICENSE file at the repository root, so there is no copyleft obligation on a CLI you ship with it, which is a licensing note rather than legal advice. The README also records that the library is used by kubernetes/minikube, which is a stronger signal of production fitness than any feature list, and it was featured in Golang Weekly three times and in GitHub's Release Radar.
The module targets go 1.24.2, which is a floor worth checking if you support older toolchains. The repository also has a fuzz_test.go, a box_render_test.go and util_test.go, a testdata/ directory, a .golangci.yml, and a scripts/ directory, so the rendering path is covered by both unit and fuzz testing rather than only by the examples.
Editorial conclusion
Adopt box-cli-maker if you are writing a Go command line tool that needs bordered output rather than a full screen interface, since it gives you border styles, title placement, wrapping and colour handling without pulling in a TUI framework. Do not adopt it for interactive selection, live redraw or layout, since it renders a string and nothing else. Verify first which major version path you are on, because the import path carries /v3 and MIGRATION.md documents the change from earlier lines, then check that the terminal colour detection matches your deployment, since output is intentionally converted to the terminal's capability and suppressed for NO_COLOR and piped output.
Frequently asked questions
How do I install box-cli-maker and render a first box in Go?
Run go get github.com/box-cli-maker/box-cli-maker/v3, then build a box with NewBox, configure it with the fluent methods and call Render, which returns the box as a string plus an error. MustRender is the panic-on-error variant.
Which border styles does box-cli-maker provide?
Nine built in styles: Single, Double, Round, Bold, SingleDouble, DoubleSingle, Classic, Hidden and Block. Any glyph can be overridden afterwards with TopLeft, TopRight, BottomLeft, BottomRight, Horizontal and Vertical.
How do I set the title position and alignment in box-cli-maker?
TitlePosition takes box.Inside, box.Top or box.Bottom, with Inside as the default, and TitleAlign takes box.Left, box.Center or box.Right. If you do not set the alignment, Inside titles are centered and Top and Bottom titles are left aligned.
Does box-cli-maker respect NO_COLOR and piped output?
Yes. Colours are converted to the terminal's own colour capability, and the output is suppressed for NO_COLOR and for piped output. The library accepts the first 16 ANSI colour names, #RGB, #RRGGBB, rgb:RRRR/GGGG/BBBB and rgba:RRRR/GGGG/BBBB/AAAA forms.
What changed between box-cli-maker v2 and v3?
v2.4.0 and v3.0.0 were both published on 2026-02-09, and the v3 import path adds the /v3 suffix to github.com/box-cli-maker/box-cli-maker. The repository includes a MIGRATION.md file describing the change, and the module now targets go 1.24.2.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/box-cli-maker-box-cli-maker)Was this useful?