Every polished CLI tool has one. You run neofetch and get a beautiful system info display with an ASCII logo. You start vim and see a startup screen. You launch a development server and the framework name appears in block letters. It's a small touch that makes a tool feel finished, and it takes almost no effort to add.
I add ASCII banners to every CLI tool I ship. Here's how I do it and why it matters more than you'd think.
Why banners matter for CLI tools
Terminal interfaces lack visual hierarchy. Everything is the same size monospace text scrolling down a black background. A banner creates a visual anchor -- it tells the user "the tool started successfully, here's what you're running." Without it, the first line of output bleeds into whatever was on screen before.
Banners also communicate identity. When a tool outputs its name in block letters, it's immediately recognizable in screenshots, documentation, and screen recordings. This is branding, and it works in the terminal the same way it works everywhere else.
The manual approach
You can hardcode a banner as a multiline string. Here's a Node.js example:
const banner = `
__ __ _____ _
| \\/ | |_ _| | |
| \\ / |_ _ | | ___ ___| |
| |\\/| | | | | | | / _ \\ / _ \\ |
| | | | |_| | | || (_) || __/ |
|_| |_|\\__, | \\_/ \\___/ \\___|_|
__/ |
|___/
`;
console.log(banner);
This works, but maintaining it is tedious. If you rename the tool, you have to regenerate the entire block. If you want a different font style, you're starting from scratch.
The figlet approach
The figlet package generates ASCII banners from text at runtime:
import figlet from 'figlet';
console.log(figlet.textSync('MyTool', { font: 'Standard' }));
This is flexible but adds a dependency. The figlet npm package includes all its font files and adds about 700KB to your node_modules. For a CLI tool where bundle size matters, that might be too much for a cosmetic feature.
In Python:
import pyfiglet
print(pyfiglet.figlet_format("MyTool", font="slant"))
The pyfiglet library works the same way. Font name in, ASCII art out.
The pre-generated approach (my preference)
I generate the banner text once, save it as a constant, and include it directly in the source code. No runtime dependency. No file I/O. Just a string literal.
// Generated with figlet "Standard" font
const BANNER = `
______ __ __ __ __ __ __
/\\ ___\\ /\\ \\_\\ \\ /\\ \\/\\ \\ /\\ "-.\\ \\
\\ \\ \\____ \\ \\ __ \\ \\ \\ \\_\\ \\ \\ \\ \\-. \\
\\ \\_____\\ \\ \\_\\ \\_\\ \\ \\_____\\ \\ \\_\\\\"\\_\\
\\/_____/ \\/_/\\/_/ \\/_____/ \\/_/ \\/_/
`;
function main() {
console.log(BANNER);
console.log(' v1.2.0 | https://github.com/user/tool\n');
// ... rest of tool
}
This approach costs zero dependencies and zero runtime computation. The banner is just bytes in the source file.
Choosing the right font
Not all figlet fonts work well at every size. Here are my go-to fonts and when I use each:
Standard -- The default. Clean, readable, works for most tool names up to about 10 characters.
Slant -- Italicized look. Good for tool names that should feel dynamic or fast.
Big -- Larger than Standard, good when the tool name is short (4-6 characters).
Small -- Compact. When terminal real estate is limited or the name is long.
Banner3 -- Thick block letters. High visual impact but takes up a lot of vertical space.
ANSI Shadow -- Modern, clean, popular in current CLI tools.
The rule of thumb: shorter tool names can use larger fonts. If your tool is called "api" you can use Banner3. If it's called "configuration-manager," use Small or you'll have a banner that's wider than most terminals.
Adding color
A monochrome banner works fine, but color makes it pop. Most terminals support ANSI escape codes:
const chalk = require('chalk');
console.log(chalk.hex('#6C5CE7')(BANNER));
console.log(chalk.gray(' v1.2.0 | MIT License\n'));
Or without a dependency, using raw ANSI codes:
const PURPLE = '\x1b[38;2;108;92;231m';
const RESET = '\x1b[0m';
console.log(`${PURPLE}${BANNER}${RESET}`);
The 38;2;R;G;B sequence sets a 24-bit foreground color. Most modern terminals support this. For broader compatibility, stick to the 16 standard ANSI colors.
Common mistakes
Banners that are wider than 80 columns. The traditional terminal width is 80 characters. Many developers use wider terminals, but 80 columns is still the safe maximum for content that needs to be portable. Test your banner at 80 columns.
Using tab characters in banner strings. Tabs render at different widths in different terminals. Banners should use spaces only.
Missing the blank line after the banner. Without whitespace separating the banner from the tool's output, they visually merge. Always add at least one empty line after the banner.
Printing the banner on every invocation. If your tool is called frequently in scripts or piped into other programs, a banner on every run is noise. Common pattern: show the banner when running interactively (stdout is a TTY), skip it when piped:
if (process.stdout.isTTY) {
console.log(BANNER);
}
For quick banner generation without installing figlet or fiddling with font files, I built a tool at zovo.one/free-tools/ascii-banner-generator that lets you type text, pick a font, and copy the output. I use it every time I start a new CLI project.
A good banner takes 30 seconds to create and makes your tool feel professional from the first character of output.
I'm Michael Lip. I build free developer tools at zovo.one. 350+ tools, all private, all free.
Top comments (0)