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

Examples

Real-world code examples


Overview

This page collects real-world, runnable examples for both BeautifulCLI tools — chalk and degit. You will find copy-paste-ready code snippets that demonstrate the most useful patterns: scaffolding projects from templates, targeting specific refs, composing templates with actions, styling terminal output with colors and themes, using extended RGB and hex colors, and animating strings in the terminal. Work through the examples in order for a guided tour, or jump directly to the pattern you need.


Prerequisites

Before running any example on this page, make sure you have the following in place:

  • Node.js ≥ 8.0.0 — both chalk and degit require it; check with node --version
  • npm — used to install packages; check with npm --version
  • git (optional) — only required when using --mode=git for private repositories
  • degit installed globally (for CLI examples):
npm install -g degit
  • chalk installed in your project (for chalk examples):
npm install chalk

Note: Chalk 5 is ESM-only. All chalk examples on this page use ES module import syntax. If your project uses CommonJS, use Chalk 4 instead.


Installation
  1. Install degit globally so the degit command is available in your terminal:
npm install -g degit
  1. Verify the installation:
degit --help
  1. Create or navigate to your project directory:
mkdir my-project && cd my-project
  1. Install chalk as a dependency of your Node.js project:
npm install chalk
  1. Confirm chalk is available by creating a quick smoke-test file:
// test.js
import chalk from 'chalk';
console.log(chalk.green('chalk is working!'));
node test.js

You should see chalk is working! printed in green.


Configuration

degit options

When using degit programmatically, you can pass an options object as the second argument:

OptionDefaultValid valuesEffect
cachetruetrue, falseWhen true, degit reuses a previously downloaded tarball from ~/.degit/<user>/<repo>/<commithash>.tar.gz instead of fetching it again. Set to false to always fetch fresh.
forcefalsetrue, falseWhen true, degit will overwrite files in the destination directory. When false, it stops if the destination is non-empty.
verbosefalsetrue, falseWhen true, degit emits detailed info events during cloning, useful for debugging.
--mode (CLI)tartar, gittar fetches a compressed snapshot over HTTPS — fastest option. git uses SSH-based cloning and is required for private repositories.

Example — programmatic options:

import degit from 'degit';

const emitter = degit('user/repo', {
  cache: true,
  force: true,
  verbose: true,
});

chalk — color level

Chalk auto-detects your terminal's color support, but you can override it with chalk.level:

LevelDescription
0All colors disabled
1Basic color support (16 colors)
2256 color support
3Truecolor support (16 million colors)

Overriding chalk.level applies globally. To avoid affecting other consumers, create a scoped instance instead:

import { Chalk } from 'chalk';

const chalk = new Chalk({ level: 2 }); // 256-color mode for this instance only

You can also force color support at the environment level without code changes:

FORCE_COLOR=3 node my-script.js   # force truecolor
FORCE_COLOR=0 node my-script.js   # disable all color

Usage

Scaffold a project from a GitHub template

The simplest degit command downloads the default branch of any public repository into your current directory:

degit user/repo

To create a named folder at the same time:

degit user/repo my-new-project

Degit stores the downloaded snapshot at ~/.degit/user/repo/<commithash>.tar.gz. The next time you scaffold from the same commit, degit reuses that local cache — no internet connection required.


Style terminal output with chalk

Import chalk and chain style modifiers to produce colored output:

import chalk from 'chalk';

console.log(chalk.blue('Hello world!'));
console.log(chalk.bold.red('Error: something went wrong'));
console.log(chalk.blue.bgRed.bold('Alert!'));

Passing multiple arguments joins them with a space:

console.log(chalk.blue('Hello', 'World!', 'from', 'chalk'));
// => Hello World! from chalk  (all in blue)

Define reusable style themes

Assign chalk chains to variables to create a consistent style system across your CLI:

import chalk from 'chalk';

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

console.log(error('Build failed!'));
console.log(warning('Deprecated API in use'));
console.log(success('Deployment complete'));
console.log(info('Listening on port 3000'));

Use chalk in template literals

Template literals let you mix styled and plain strings cleanly:

import chalk from 'chalk';

const cpu  = 90;
const ram  = 40;
const disk = 70;

console.log(`
CPU:  ${chalk.red(`${cpu}%`)}
RAM:  ${chalk.green(`${ram}%`)}
DISK: ${chalk.yellow(`${disk}%`)}
`);

Examples

Example 1 — Scaffold from GitHub, GitLab, and Bitbucket

Degit accepts multiple URL forms for each host. All of the following commands are equivalent for GitHub:

degit user/repo my-project
degit github:user/repo my-project
degit git@github.com:user/repo my-project
degit https://github.com/user/repo my-project

For GitLab and Bitbucket:

# GitLab
degit gitlab:user/repo my-project
degit https://gitlab.com/user/repo my-project

# Bitbucket
degit bitbucket:user/repo my-project
degit https://bitbucket.org/user/repo my-project

# Sourcehut
degit git.sr.ht/user/repo my-project

Expected result: A new my-project/ directory containing the repository's files — no .git folder, no commit history.


Example 2 — Target a specific branch, tag, or commit

Append #ref to pin the scaffold to an exact point in history:

degit user/repo#dev           # a branch named 'dev'
degit user/repo#v1.2.3        # a release tag
degit user/repo#1234abcd      # a specific commit hash

Expected result: The files from that exact ref are downloaded, not the latest default branch.


Example 3 — Clone only a subdirectory

When a template repository contains multiple project starters, you can download just one folder:

degit user/repo/packages/template-svelte my-svelte-app

Expected result: Only the contents of packages/template-svelte/ are extracted into my-svelte-app/.


Example 4 — Use a private repository with git mode

For SSH-accessible private repositories, switch to --mode=git:

degit --mode=git git@github.com:your-org/private-repo my-project

Expected result: Degit uses git over SSH to clone the repository, then strips the history, producing a clean working directory. Note this is slower than the default tar mode.


Example 5 — Compose templates with degit.json actions

Place a degit.json file at the root of your working directory to run post-scaffold steps automatically. You can clone additional repositories into the same folder and remove unwanted files:

[
  {
    "action": "clone",
    "src": "user/shared-configs"
  },
  {
    "action": "remove",
    "files": ["LICENSE"]
  }
]

What this does:

  1. After the primary scaffold completes, degit clones user/shared-configs into the same working directory, merging its files.
  2. The LICENSE file is then deleted from the result.

Expected result: Your project directory contains files from both repositories, minus LICENSE.


Example 6 — Use degit programmatically inside a Node.js script

import degit from 'degit';

const emitter = degit('user/repo', {
  cache: true,
  force: true,
  verbose: true,
});

emitter.on('info', info => {
  console.log(info.message);
});

await emitter.clone('path/to/dest');
console.log('Scaffold complete!');

Expected output:

cloned user/repo#abc1234 to path/to/dest
Scaffold complete!

Example 7 — Basic chalk colors and styles

import chalk from 'chalk';

// Single color
console.log(chalk.blue('Hello world!'));

// Combine styled and plain strings
console.log(chalk.blue('Hello') + ' World' + chalk.red('!'));

// Chain multiple styles
console.log(chalk.blue.bgRed.bold('Hello world!'));

// Nest styles
console.log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));

Expected output: Each line is printed with the corresponding ANSI colors and styles applied.


Example 8 — RGB and hex colors

For terminals that support 256 or truecolor, you can specify exact colors:

import chalk from 'chalk';

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

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

// Background hex
console.log(chalk.bgHex('#DEADED').underline('Hello, world!'));

// Background RGB with inverse
console.log(chalk.bgRgb(15, 100, 204).inverse('Hello!'));

// ansi256
console.log(chalk.bgAnsi256(194)('Honeydew, more or less'));

Expected output: Each string is rendered with the specified extended color in terminals that support it. On terminals with lower color support, chalk automatically downsamples the color to the closest available match.


Example 9 — Animated rainbow string

This example (adapted from examples/rainbow.js) combines chalk's hex() method with HSL color cycling to animate a rainbow across a string in the terminal. It depends on the color-convert and log-update packages:

npm install color-convert log-update
import { setTimeout as delay } from 'node:timers/promises';
import convertColor from 'color-convert';
import updateLog from 'log-update';
import chalk from 'chalk';

const ignoreChars = /[^!-~]/g;

function rainbow(string, offset) {
  if (!string || string.length === 0) return string;

  const hueStep = 360 / string.replaceAll(ignoreChars, '').length;
  let hue = offset % 360;
  const characters = [];

  for (const character of string) {
    if (ignoreChars.test(character)) {
      characters.push(character);
    } else {
      characters.push(chalk.hex(convertColor.hsl.hex(hue, 100, 50))(character));
      hue = (hue + hueStep) % 360;
    }
  }

  return characters.join('');
}

async function animateString(string) {
  for (let index = 0; index < 360 * 5; index++) {
    updateLog(rainbow(string, index));
    await delay(2);
  }
}

console.log();
await animateString('We hope you enjoy Chalk! <3');
console.log();

Expected output: The string We hope you enjoy Chalk! <3 cycles through the full color spectrum for approximately 3.6 seconds, with each character rendered in a distinct, smoothly shifting hue.


Example 10 — Input validation with style name arrays

Chalk exposes arrays of valid style names you can use to validate user input in your own wrappers:

import { modifierNames, foregroundColorNames } from 'chalk';

console.log(modifierNames.includes('bold'));          // => true
console.log(foregroundColorNames.includes('pink'));   // => false
console.log(foregroundColorNames.includes('cyan'));   // => true

Expected output:

true
false
true

Troubleshooting

Issue: degit command not found

Symptom: Running degit user/repo produces command not found: degit.

Cause: degit was not installed globally, or your npm global bin directory is not on your PATH.

Fix:

npm install -g degit

If the command is still not found, check your npm global prefix and ensure it is on PATH:

npm config get prefix
# Add <prefix>/bin to your PATH in your shell profile

Issue: Destination directory is not empty

Symptom: degit exits with an error saying the destination directory already contains files.

Cause: By default, degit will not overwrite an existing non-empty directory.

Fix: Pass force: true when using the programmatic API, or delete / empty the target folder before running degit:

const emitter = degit('user/repo', { force: true });

Or from the CLI, ensure your target directory does not exist yet:

degit user/repo fresh-folder   # 'fresh-folder' must not already exist

Issue: Private repository download fails with tar mode

Symptom: degit user/private-repo returns an authentication or access error.

Cause: The default tar mode fetches over HTTPS without authentication and cannot access private repositories.

Fix: Switch to git mode, which uses SSH authentication:

degit --mode=git git@github.com:your-org/private-repo my-project

Ensure your SSH key is loaded and authorised for the repository.


Issue: chalk produces no color output

Symptom: chalk calls print plain text with no color or styling.

Cause: Chalk detected that your terminal does not support color (chalk.level is 0). This can happen in CI environments, when output is piped, or when running in a terminal with no color support.

Fix: Force a color level using the FORCE_COLOR environment variable:

FORCE_COLOR=1 node my-script.js   # 16 colors
FORCE_COLOR=3 node my-script.js   # truecolor

Or create a chalk instance with an explicit level:

import { Chalk } from 'chalk';
const chalk = new Chalk({ level: 3 });

Issue: import chalk from 'chalk' fails with a module error

Symptom: Node.js throws ERR_REQUIRE_ESM or a similar module error when loading chalk.

Cause: Chalk 5 is ESM-only. If your project uses CommonJS (require()), it cannot import Chalk 5 directly.

Fix: Either migrate your project to ESM by adding "type": "module" to your package.json, or downgrade to Chalk 4 which supports CommonJS:

npm install chalk@4

Issue: degit.json actions do not run

Symptom: After scaffolding, the additional clone or file removal steps defined in degit.json are not executed.

Cause: The degit.json file must be located at the root of the working directory that degit is writing into — not inside the source template repository.

Fix: Ensure degit.json exists at the top level of your destination folder and is valid JSON matching the expected action schema:

[
  { "action": "clone", "src": "user/another-repo" },
  { "action": "remove", "files": ["LICENSE"] }
]