BeautifulCLITerminal string styling done right — a chainable, zero-dependency library for adding color and style to Node.js CLI output.
Concept

Key Concepts

Core abstractions and design patterns


Overview

This page explains the core abstractions that underpin BeautifulCLI's two tools — degit and chalk. Understanding these concepts will help you make deliberate choices when scaffolding projects, styling terminal output, and composing both tools into larger workflows. Each concept maps directly to a behavior or design decision you will encounter as soon as you start integrating either tool into your code.


Content

Template Repositories

A template repository is any public git repository — hosted on GitHub, GitLab, BitBucket, or Sourcehut — that you treat as a starting point for a new project. When you run degit against one, it downloads the repository's files without carrying along any of the source repo's commit history. This keeps your new project's git history clean from the first commit and avoids the overhead of transferring refs and blobs you will never use.

Degit also supports subdirectory cloning: you can point it at a folder inside a repository by appending the path directly to the source argument (for example, user/repo/packages/my-template). Only the contents of that folder are downloaded, which is useful when a single repo hosts multiple independent templates.


The Tarball Cache

Every time degit downloads a repository, it stores the result as a compressed snapshot — a .tar.gz file — at ~/.degit/<user>/<repo>/<commithash>.tar.gz. This is the tarball cache.

The cache serves two purposes:

  1. Speed. If you scaffold the same commit a second time, degit skips the network request and extracts the file it already has.
  2. Offline use. Once a commit is cached, you can scaffold from it without a network connection.

The cache is keyed by commit hash, not by branch or tag name. That means degit always stores a precise, immutable snapshot rather than a mutable label — so two runs against the same branch name that resolve to different commits produce two separate cache entries.


Download Modes

Degit supports two modes that control how it fetches a repository:

ModeHow it worksWhen to use it
tar (default)Downloads a compressed snapshot over HTTPSPublic repositories; fastest option
gitClones via SSH then strips the .git directoryPrivate repositories that require SSH access

You select a mode with the --mode flag or the mode option in the programmatic API. For the vast majority of workflows — scaffolding from a public template — the default tar mode is the right choice. Switch to --mode=git only when HTTPS access is unavailable or the repository is private.


Post-Scaffold Actions

Degit's actions system lets you define post-scaffold steps in a degit.json file placed at the root of your working directory. After cloning the primary template, degit reads this file and executes each listed action in order.

Two action types are supported:

  • clone — Downloads an additional repository (or subdirectory) into the same destination folder, allowing you to compose a project from multiple template sources.
  • remove — Deletes specified files or directories from the scaffolded output, so you can ship a template with placeholder files that are stripped during scaffolding.

This makes it possible to build layered templates: a base project structure from one repo, a framework-specific configuration from another, with a handful of scaffolding-only files removed at the end — all described declaratively in degit.json without any custom scripting.


ANSI Styles and How Chalk Generates Them

ANSI styles are standard escape codes that terminals interpret as instructions to change the visual appearance of text — its foreground color, background color, or modifiers like bold, italic, underline, or strikethrough. Chalk generates these codes for you automatically; you never write raw escape sequences.

Chalk detects whether your terminal supports color and adjusts its output accordingly. This detection result is exposed as chalk.level:

LevelMeaning
0Colors disabled
1Basic 16-color support
2256-color support
3Truecolor (16 million colors)

You can read or override chalk.level globally, or create an isolated instance with a fixed level using new Chalk({ level: n }) to avoid affecting other consumers.


Style Chaining

Chaining is chalk's primary composition mechanism. Because each style accessor returns the same chalk instance, you can join multiple modifiers and colors with dots before calling the result as a function:

chalk.bold.red.bgWhite('text')

Order is flexible — later styles take precedence when there is a conflict. chalk.red.yellow.green is equivalent to chalk.green. This lets you build up style combinations incrementally and define reusable theme variables by storing partially-chained expressions:

const error = chalk.bold.red;
const warning = chalk.hex('#FFA500');

Chalk also supports nested styles: you can embed one styled expression inside another, and chalk correctly re-opens the outer style after the inner one closes.


256-Color and RGB Support

Beyond the standard 16 named colors, chalk provides three extended color models for both foreground and background:

  • rgb(r, g, b) / bgRgb(r, g, b) — Specify a color as red, green, and blue values (0–255).
  • hex('#RRGGBB') / bgHex('#RRGGBB') — Specify a color as a CSS-style hex string.
  • ansi256(n) / bgAnsi256(n) — Specify a color as an index from 0–255 in the 8-bit ANSI palette.

When the terminal does not support the requested color depth, chalk automatically downsamples the value to the closest color the terminal can render, based on chalk.level. This means you can write your styling code against the full RGB space and trust chalk to degrade gracefully on older terminals.


Examples

Scaffolding from a public GitHub template

Download a repository's files into a new directory. No git history is copied.

degit user/my-template my-new-project

After running this command, my-new-project/ contains the template's files, ready for git init.


Scaffolding from a subdirectory

Download only the packages/app folder from a monorepo template.

degit user/monorepo/packages/app my-app

Using git mode for a private repository

degit user/private-template my-project --mode=git

Degit clones via SSH and strips the .git directory from the result.


Composing templates with degit.json

Place a degit.json file in your template repository root to define post-scaffold actions:

[
  {
    "action": "clone",
    "src": "user/shared-config"
  },
  {
    "action": "remove",
    "files": ["degit.json", "TEMPLATE_README.md"]
  }
]

When a user scaffolds your template, degit first clones the primary repo, then merges in user/shared-config, then removes the listed files.


Basic chalk styling

import chalk from 'chalk';

console.log(chalk.blue('Hello world!'));
console.log(chalk.bold.red('Error: something went wrong'));
console.log(chalk.blue.bgWhite.underline('Highlighted text'));

Expected output (colors rendered by your terminal):

Hello world!                  ← blue
Error: something went wrong   ← bold red
Highlighted text              ← blue, white background, underlined

Defining reusable theme variables

import chalk from 'chalk';

const error   = chalk.bold.red;
const warning = chalk.hex('#FFA500');
const success = chalk.green;

console.log(error('Build failed'));
console.log(warning('Skipping optional step'));
console.log(success('Done'));

RGB and hex colors with automatic downsampling

import chalk from 'chalk';

// RGB foreground + modifier
console.log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));

// Hex foreground
console.log(chalk.hex('#DEADED').bold('Bold gray!'));

// 256-color background
console.log(chalk.bgAnsi256(194)('Honeydew, more or less'));

If the terminal only supports 16 colors (chalk.level === 1), chalk downsamples the RGB or hex value to the nearest ANSI color automatically.


Creating an isolated chalk instance with a fixed color level

Use this when you need to control styling in a reusable module without affecting other chalk consumers.

import { Chalk } from 'chalk';

const customChalk = new Chalk({ level: 2 }); // Force 256-color mode

console.log(customChalk.ansi256(201)('Purple text'));

Nesting styles

import chalk from 'chalk';

console.log(
  chalk.green(
    'I am green ' +
    chalk.blue.bold('with a blue bold section') +
    ' and green again'
  )
);

Chalk correctly reopens the outer green style after the inner blue-bold section closes.


Related concepts
  • Installation — How to add degit and chalk to your project before using any of the concepts described here.
  • Scaffold a new project from a template — A step-by-step workflow that puts template repositories, tarball caching, and download modes into practice.
  • Target a specific branch, tag, or commit — How ref resolution works and how the tarball cache stores results by commit hash rather than ref name.
  • Compose template actions — A deeper look at building degit.json files to merge multiple sources and clean up scaffolding artifacts.
  • Use degit programmatically — How to drive degit's clone and action system from JavaScript, including listening to info and warn events.
  • Style terminal output with chalk — End-to-end guide covering auto-detection, level overrides, and building a complete theme for a CLI tool.