CLI tool
klaudiosinani/signale avatar
klaudiosinani/signale

Signale: a configurable Node.js logger with 19 built-in loggers and pluggable types

Highly configurable logging library

9,174 stars232 forksJavaScriptMIT

At a glance

What is it?
Signale is an MIT-licensed JavaScript logging library for Node.js CLIs and applications, with default loggers, custom types, scopes, timers and secret filtering. It is small, stable and largely unchanged since 2019.
Who is it for?
Signale fits Node.js CLI tools and small apps that want readable, colour-coded console output with per-type control, and teams that prefer a dependency-light library over a structured logging pipeline. It is the wrong choice if you need JSON log shipping, sampling, or a transport ecosystem.
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 177 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Signale solves for Node.js command-line tools

Most Node.js scripts start with console.log and end with a mess of prefixes, colours and inconsistent formatting. Signale targets that gap. The README describes it as usable for logging purposes, status reporting, and for handling the output rendering process of other node modules and applications. In practice that means a CLI can call signale.success, signale.warn or signale.pending instead of hand-rolling a prefix string, and get a consistent badge, label and colour per message type.

The audience is narrow but real: developers writing command-line tools, build scripts, generators and small services where console output is the primary interface. The package declares node >=6 in package.json, so it runs on old runtimes, and it ships only three runtime dependencies: chalk, figures and pkg-conf. That dependency count matters if you are publishing a CLI and care about install size. It is not a logging framework for servers that need log aggregation, sampling or transports; nothing in the README suggests those features exist.

How the logger types, scopes and streams fit together

The core object is a Signale instance. The default export is one such instance, preloaded with 19 loggers listed in the README: await, complete, error, debug, fatal, fav, info, note, pause, pending, star, start, success, wait, warn, watch and log. Calling signale.success('...') looks up the success type, renders its badge, label and colour, and writes the result to a stream.

Configuration flows through a single options object that a new Signale(options) call accepts. It can carry disabled, interactive, logLevel, secrets, stream, scope and types. Each entry under types can itself carry badge, label, color, logLevel and stream, so a single type can be routed to its own writable stream while the rest of the instance writes elsewhere. The stream option accepts a single Writable stream or an array of them, which is how the README describes multiple configurable writable streams.

Filtering is handled by logLevel, which is a scaled mechanism rather than a per-call flag. Setting logLevel to 'warn' on an instance means only warn, error and fatal messages render; 'error' narrows that further to error and fatal. The secrets array is the other cross-cutting feature: strings or numbers placed in it are stripped from the body and metadata of messages and replaced with the literal '[secure]'. That is a blunt substitution, not a pattern matcher, so it only removes exact values you already know.

Installing Signale and writing a first scoped logger

The README gives two install paths, Yarn and npm. Both add the package to your project:

bash
npm install signale

After installation, the default instance is available immediately. This snippet uses three of the built-in loggers, including the printf-style substitution the README shows for pending:

js
const signale = require('signale');

signale.success('Operation successful');
signale.pending('Write release notes for %s', '1.2.0');
signale.watch('Recursively watching build directory...');

You should see three lines with distinct badges and labels rather than three identical console lines. For anything beyond the defaults, create your own instance. The README's custom logger example defines a types object and passes it to the constructor:

js
const {Signale} = require('signale');

const options = {
  scope: 'custom',
  types: {
    remind: {
      badge: '**',
      color: 'yellow',
      label: 'reminder',
      logLevel: 'info'
    }
  }
};

const custom = new Signale(options);
custom.remind('Improve documentation.');

The scope value is what appears alongside each message, and the same options object accepts logLevel, secrets and stream if you need them at construction time. One detail worth knowing before you write config: package.json in this repository contains an options.default block with keys such as displayScope, displayBadge, displayLabel, underlineLabel and uppercaseLabel. The README states that configuration is globally configurable through package.json, so those display toggles are read from there rather than passed per call.

Where Signale stops being the right tool

Signale writes human-readable lines. It does not emit structured records. If your logs need to be parsed by a collector, correlated by request ID, or shipped off the machine, the library gives you no field-level output to work with. The stream option lets you point output at a Writable stream, so you could build that yourself, but nothing in the README describes serialisation, buffering behaviour or backpressure handling for a slow destination.

The secrets filter is the second sharp edge. It replaces exact values you list, so a token that is truncated, re-encoded, or embedded inside a larger string will pass through untouched. Treating it as a redaction system rather than a convenience for known constants is a mistake.

Version history is the third consideration. The most recent release listed is v1.4.0 from 2019-02-26, and the repository's last push was on 2026-04-06. The repository is not archived, but the release line has not moved in years, so features and fixes you might expect from an actively released logging library should not be assumed. The README does not document a deprecation policy or a support window. If your project needs a guaranteed upgrade path, this is a signal to look elsewhere.

Signale against pino and other structured loggers

The closest comparison in the search data is pino, and the difference is the output model. Pino is built around structured JSON records and a transport layer; Signale is built around rendered console lines with badges, labels and colours. If you choose pino, you get machine-parseable output and a plugin ecosystem, and you give up the out-of-the-box visual formatting that makes a CLI readable without extra work. If you choose Signale, you get the formatting and you give up the structure.

There is also a middle path inside Node itself. console.log with a small formatting helper covers a surprising amount of CLI output, and it adds no dependency at all. Signale's argument over that is the 19 predefined types, the per-type stream and logLevel overrides, the scoped instance model and the secrets substitution, all configured from one options object. Whether that is worth a dependency is a judgement about how much logging surface your tool actually has. A script with four messages does not need it. A CLI with twenty message types and a --verbose flag probably does.

Licence, maintenance and what an upgrade costs

The package is MIT licensed, and the repository carries a license.md file at the top level. MIT is permissive: it allows commercial use, modification and redistribution provided the copyright notice and permission notice are preserved. That is a description of the licence text, not legal advice; check how your organisation handles attribution for bundled dependencies.

Upgrade cost is low in one direction and uncertain in the other. Because the public surface is a constructor plus named methods, and because the dependency list is three packages, moving between 1.x versions is unlikely to require code changes. The uncertainty is forward-looking. With v1.4.0 dated 2019-02-26 and a last push on 2026-04-06, there is no published roadmap in the repository, and the README does not describe a migration guide. Pinning the version in package.json is the practical move if you depend on current behaviour, because there is no release cadence to plan around.

Editorial conclusion

Signale fits Node.js CLI tools and small apps that want readable, colour-coded console output with per-type control, and teams that prefer a dependency-light library over a structured logging pipeline. It is the wrong choice if you need JSON log shipping, sampling, or a transport ecosystem. Before adopting, check that the default logLevel and the package.json configuration block behave as your project expects, and confirm the last push date on the repository against your own maintenance policy.

Frequently asked questions

How do I install Signale in a Node.js project?

The README gives two options: yarn add signale or npm install signale. The package declares node >=6 in package.json, and it ships with chalk, figures and pkg-conf as runtime dependencies.

How do I create a custom logger type in Signale?

Define an options object with a types field and pass it to new Signale(options). Each type can set badge, label, color, logLevel and stream, and the README shows a remind type with a '**' badge and a yellow label.

How does Signale filter out sensitive values from log messages?

The secrets option takes an array of strings or numbers and replaces those exact values in the message body and metadata with the default '[secure]' string. It is a literal substitution, so values that are transformed or embedded in longer strings are not matched.

Can Signale write logs to a file instead of the console?

The stream option accepts a single Writable stream or an array of them, and it defaults to process.stdout. Individual logger types can also define their own stream, which the README lists as multiple configurable writable streams.

Official sources

  1. klaudiosinani/signale on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/klaudiosinani-signale.svg)](https://hysenlabs.com/projects/klaudiosinani-signale)