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

Usage Patterns

Common integration patterns and best practices


Overview

This page walks you through the most common integration patterns for BeautifulCLI's two tools: chalk for styling terminal output and degit for scaffolding projects from git repository templates. Whether you are building a polished CLI tool, spinning up a new project in seconds, or composing templates programmatically, the patterns here give you a practical starting point. Each section builds on the last, so you can follow along from installation to advanced programmatic use.


Prerequisites

Before you begin, make sure you have the following installed:

  • Node.js ≥ 8.0.0 — required by both chalk and degit
  • npm — used to install packages
  • git (optional) — only needed if you use --mode=git for private repository access with degit

Confirm your Node.js version before proceeding:

node --version

Installation

Install each tool according to how you plan to use it.

1. Install chalk as a project dependency

Chalk is a library you import into your scripts, so install it locally:

npm install chalk

Important: Chalk 5 is ESM-only. If you are using TypeScript or a CommonJS build tool, install Chalk 4 instead:

npm install chalk@4

2. Install degit as a global CLI tool

Degit is primarily used as a command-line scaffolding tool:

npm install -g degit

3. (Optional) Install degit as a local dependency for programmatic use

If you want to drive degit from a Node.js script, add it to your project as well:

npm install degit

Configuration

Chalk configuration

chalk.level

Controls the color depth used when generating ANSI escape codes. Chalk detects the terminal's color support automatically, but you can override it globally:

import chalk from 'chalk';

chalk.level = 1; // Force basic 16-color mode
LevelDescription
0All colors disabled
1Basic color support (16 colors)
2256-color support
3Truecolor support (16 million colors)

Overriding chalk.level applies globally to every Chalk consumer in the same process. If you are writing a reusable module, create an isolated instance instead to avoid affecting other consumers:

import { Chalk } from 'chalk';

const customChalk = new Chalk({ level: 2 });

Environment variable overrides

You can force a specific color level without changing code, which is useful in CI pipelines:

  • FORCE_COLOR=1 — enable basic color (level 1)
  • FORCE_COLOR=2 — enable 256-color mode (level 2)
  • FORCE_COLOR=3 — enable Truecolor mode (level 3)
  • FORCE_COLOR=0 — disable all color

The --color and --no-color CLI flags also override detection when passed to your Node.js process.


Degit configuration

--mode (default: tar)

Controls how degit downloads a repository:

ValueBehavior
tarFetches a compressed snapshot over HTTPS. Fastest option; works for public repos.
gitUses SSH-based git cloning. Required for private repositories. Slower than tar.
degit user/repo --mode=git

Tarball cache

Degit automatically caches downloaded snapshots at ~/.degit/<user>/<repo>/<commithash>.tar.gz. If you scaffold the same commit again, degit reuses the cached file — no network request needed. This also enables offline use after the first download.

https_proxy

If your environment routes HTTPS traffic through a proxy, set the https_proxy environment variable and degit will use it automatically.


JavaScript API configuration (degit)

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

const degit = require('degit');

const emitter = degit('user/repo', {
  cache: true,    // Use the local tarball cache when available
  force: true,    // Overwrite destination if it already exists
  verbose: true,  // Emit detailed info events
});

Usage

Scaffolding a new project with degit

The simplest use case downloads the default branch of any public repository into your current directory:

degit user/repo

To create a named folder for the project, pass a destination as the second argument:

degit user/repo my-new-project

Degit works with GitHub, GitLab, BitBucket, and Sourcehut out of the box:

degit github:user/repo
degit gitlab:user/repo
degit bitbucket:user/repo
degit git.sr.ht/user/repo

Targeting a specific branch, tag, or commit

Append a # fragment to pin the download to an exact point in the repository's history:

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

Downloading only a subdirectory

If you only need a subfolder of a repository, append its path to the argument:

degit user/repo/packages/my-template my-project

This fetches the entire repo as a tarball (using the cache) and extracts only the specified subdirectory, so you get exactly the files you need.


Styling terminal output with chalk

Import chalk and chain style modifiers to produce colored, formatted strings:

import chalk from 'chalk';

console.log(chalk.blue('Hello world!'));
console.log(chalk.bold.red('Error occurred'));
console.log(chalk.blue.bgRed.bold('Alert!'));

Combine styled segments with plain strings:

console.log(chalk.blue('Hello') + ' World' + chalk.red('!'));

Use chalk inside ES2015 template literals for inline substitution:

const cpuUsage = '90%';
console.log(`CPU: ${chalk.red(cpuUsage)}`);

Defining a consistent theme

Assign chalk expressions to named variables so your styling stays consistent across a CLI tool:

import chalk from 'chalk';

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

console.log(error('Build failed!'));
console.log(warning('Dependency is outdated.'));
console.log(success('Deployed successfully.'));
console.log(info('Listening on port 3000.'));

Using 256-color and RGB support

For terminals that support extended colors, use chalk.hex(), chalk.rgb(), chalk.ansi256(), and their bg-prefixed background equivalents:

import chalk from 'chalk';

console.log(chalk.hex('#DEADED').bold('Soft purple, bold'));
console.log(chalk.rgb(15, 100, 204).underline('Custom blue, underlined'));
console.log(chalk.bgHex('#DEADED').black('Background color'));
console.log(chalk.bgRgb(15, 100, 204).white('RGB background'));

Chalk automatically downsamples these values when a terminal supports fewer colors.


Using degit programmatically

When you need to scaffold from within a Node.js script — for example, as part of a custom CLI command — use the JavaScript API:

const degit = require('degit');

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

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

emitter.clone('path/to/dest').then(() => {
  console.log('Done scaffolding!');
});

Composing templates with degit actions

Place a degit.json file at the root of your working directory to run post-scaffold steps automatically. Two actions are supported: clone and remove.

Clone an additional repository into the same folder:

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

Remove unwanted files after scaffolding:

[
  {
    "action": "remove",
    "files": ["LICENSE"]
  }
]

You can combine both actions in a single degit.json array. Cloned repos can themselves contain a degit.json, allowing recursive composition.


Examples

Example 1 — Basic project scaffold

Download a template repository and place it in a new folder:

degit user/my-template my-new-app
cd my-new-app
npm install

Expected output:

> cloned user/my-template#abc1234 to my-new-app

Degit downloads only the file snapshot — no .git folder, no history.


Example 2 — Scaffold from a specific branch

Pin your scaffold to the next branch:

degit user/my-template#next my-next-app

Expected output:

> cloned user/my-template#next to my-next-app

Example 3 — Scaffold a subdirectory only

Download only the packages/cli folder from a monorepo:

degit user/monorepo/packages/cli my-cli-starter

Expected output:

> cloned user/monorepo/packages/cli to my-cli-starter

Example 4 — Simple chalk styling

import chalk from 'chalk';

const log = console.log;

log(chalk.blue('Hello') + ' World' + chalk.red('!'));
log(chalk.blue.bgRed.bold('Hello world!'));
log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));

Expected terminal output:

Hello World!            ← "Hello" in blue, "!" in red
Hello world!            ← blue text, red background, bold
Hello world!            ← "Hello" in red; "world" underlined with blue background

Example 5 — Chalk theme for a CLI tool

import chalk from 'chalk';

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

console.log(error('Error: file not found'));
console.log(warning('Warning: API key expires in 3 days'));
console.log(success('✔ Build complete'));
console.log(info('ℹ Listening on port 3000'));

Expected terminal output:

Error: file not found                  ← bold red
Warning: API key expires in 3 days     ← orange
✔ Build complete                       ← green
ℹ Listening on port 3000               ← cyan

Example 6 — RGB and hex colors

import chalk from 'chalk';

console.log(chalk.hex('#DEADED').underline('Hello, world!'));
console.log(chalk.rgb(15, 100, 204).inverse('Hello!'));
console.log(chalk.bgHex('#DEADED').black('Background color'));
console.log(chalk.bgRgb(15, 100, 204).white('RGB background'));

Expected terminal output (Truecolor terminal):

Hello, world!       ← underlined in #DEADED purple-grey
Hello!              ← foreground/background inverted with custom blue
Background color    ← #DEADED background, black text
RGB background      ← RGB(15,100,204) background, white text

Example 7 — Programmatic scaffold with chalk progress output

Combine both tools: scaffold a project programmatically and use chalk to surface status messages.

const degit = require('degit');
import chalk from 'chalk';

const emitter = degit('user/my-template', {
  cache: true,
  force: true,
  verbose: false,
});

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

console.log(chalk.bold('Scaffolding project...'));

emitter.clone('./my-project').then(() => {
  console.log(chalk.green('✔ Project scaffolded into ./my-project'));
}).catch(err => {
  console.error(chalk.bold.red('✖ Scaffold failed:'), err.message);
});

Expected terminal output:

Scaffolding project...
ℹ cloned user/my-template#abc1234
✔ Project scaffolded into ./my-project

Example 8 — Composing templates with degit.json actions

Place this degit.json in your working directory after running an initial scaffold:

[
  {
    "action": "clone",
    "src": "user/shared-config"
  },
  {
    "action": "remove",
    "files": ["LICENSE", ".travis.yml"]
  }
]

When degit processes the actions, it clones user/shared-config on top of the existing files and then removes LICENSE and .travis.yml.


Troubleshooting

Issue: No colors appear in the terminal

Symptom: Chalk output shows unstyled plain text instead of colors.

Likely cause: The terminal or environment does not support ANSI escape codes, or chalk.level has been set to 0.

Fix:

  1. Check whether your terminal supports color. Use FORCE_COLOR=1 (or 2 or 3) to override detection:
    FORCE_COLOR=3 node your-script.js
    
  2. If you are in a CI environment, check whether the CI service sets NO_COLOR or TERM=dumb.
  3. Verify that nothing in your codebase has set chalk.level = 0.

Issue: chalk.hex() or chalk.rgb() renders wrong colors

Symptom: Extended colors look different from expected, or fall back to basic colors.

Likely cause: The terminal does not support Truecolor (level 3), so chalk downsamples to the nearest supported color.

Fix: Check your terminal's color support level:

import chalk from 'chalk';
console.log('Color level:', chalk.level);

If it reports 1 or 2, either use a Truecolor-capable terminal (e.g., Windows Terminal, iTerm2) or accept the downsampled output.


Issue: SyntaxError: Cannot use import statement in a module when importing chalk

Symptom: Your script throws an ESM-related error immediately on startup.

Likely cause: Chalk 5 is ESM-only. Your project is using CommonJS (require).

Fix: Either add "type": "module" to your package.json to use ESM, or downgrade to Chalk 4 which supports CommonJS:

npm install chalk@4

Then use require:

const chalk = require('chalk');

Issue: degit command not found

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

Likely cause: Degit was not installed globally, or the global npm bin directory is not on your PATH.

Fix:

  1. Install degit globally:
    npm install -g degit
    
  2. Confirm the global bin folder is on your PATH:
    npm bin -g
    
    Add the printed path to your shell's PATH if it is missing.

Issue: Scaffold fails with a network or permission error on a private repository

Symptom: degit user/private-repo exits with an HTTPS 404 or authentication error.

Likely cause: Degit's default tar mode uses HTTPS and cannot authenticate with private repositories.

Fix: Use --mode=git to switch to SSH-based cloning, which uses your configured SSH credentials:

degit user/private-repo --mode=git

Ensure your SSH key is added to your git hosting provider before running this command.


Issue: Destination folder already exists and degit refuses to continue

Symptom: Degit exits with an error indicating the target directory is not empty.

Likely cause: The destination path already contains files and degit will not overwrite them by default.

Fix: Use the force option in the JavaScript API, or remove the target directory manually before re-running:

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

Issue: Scaffolded files are stale or do not reflect recent commits

Symptom: The scaffolded project does not include changes you know are in the repository.

Likely cause: Degit served the project from its local tarball cache at ~/.degit/<user>/<repo>/<commithash>.tar.gz.

Fix: Delete the relevant cache entry and re-run the scaffold:

rm -rf ~/.degit/user/repo
degit user/repo my-project