# cli-table3: unicode tables for Node command line tools

> cli-table3 renders unicode aided tables from Node scripts, and is API compatible with the unmaintained original cli-table while adding row and column spans, per cell styles, vertical alignment and word wrapping. It is MIT licensed and has only two runtime dependencies.

**cli-table/cli-table3** — Pretty unicode tables for the command line

- Repository: https://github.com/cli-table/cli-table3
- Stars: 639 · Forks: 55
- Language: JavaScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/cli-table-cli-table3

## A maintained fork of two abandoned libraries

cli-table3 lets you render unicode aided tables on the command line from your Node scripts, and its lineage explains why it exists. It is based on and API compatible with the original cli-table and with cli-table2, and the documentation states plainly that both of those are unmaintained. cli-table3 includes all the additional features from cli-table2, so the fork of a fork is the combination of the two. That compatibility is the practical argument, because it means the original documentation still applies and the README copies it in, including the horizontal, vertical and cross table sections, The project is MIT licensed, the primary language is JavaScript, and the package declares only two runtime dependencies, `ansis` for colour and `string-width` for measuring text that contains escape sequences.

## The first table, and the shape of the API

The API is deliberately array-like. You require the module, instantiate a table with a head and column widths, push rows onto it, and print the result:

```javascript
var Table = require('cli-table3');

// instantiate
var table = new Table({
    head: ['TH 1 label', 'TH 2 label']
  , colWidths: [100, 200]
});

// table is an Array, so you can `push`, `unshift`, `splice` and friends
table.push(
    ['First value', 'Second value']
  , ['First value', 'Second value']
);

console.log(table.toString());
```

The comment about the table being an Array is the important part of the design. Because the table object behaves like an array, you can build it up with the array methods you already know rather than through a dedicated row API, and rows can be added in any order. The `head` option sets the header row and `colWidths` fixes the column widths, which is what makes a table line up in a terminal. The `colWidths` values are in characters, and the two values in the example, 100 and 200, are wider than a standard terminal, so this example is aimed at output that will be piped or viewed wide.

## Vertical and cross tables are the same push

The vertical table is the same API with a different row shape, where each pushed item is an object of key and value pairs:

```javascript
var Table = require('cli-table3');
var table = new Table();

table.push(
    { 'Some key': 'Some value' }
  , { 'Another key': 'Another value' }
);

console.log(table.toString());
```

The cross table, where you have a header row and a header column at the same time, needs two adjustments. It requires a `head` setting when instantiated that has an empty string as the first header, and the rows take the general form of an object mapping the left header to an array of values:

```javascript
var Table = require('cli-table3');
var table = new Table({ head: ["", "Top Header 1", "Top Header 2"] });

table.push(
    { 'Left Header 1': ['Value Row 1 Col 1', 'Value Row 1 Col 2'] }
  , { 'Left Header 2': ['Value Row 2 Col 1', 'Value Row 2 Col 2'] }
);

console.log(table.toString());
```

The empty first header is the detail that is easy to miss and produces a visibly broken table if you omit it. The cross table is the shape you want for a matrix, and it is the one the row and column span features were added for.

## Border characters are the whole theming system

The `chars` property controls how the table is drawn, and it is a flat map of named positions to single characters. The full set covers top, top-mid, top-left, top-right, bottom and its three counterparts, left, left-mid, mid, mid-mid, right, right-mid and middle, and setting them produces a double-line box. The compact variant sets the four horizontal separators to the empty string, which the documentation says avoids vertical separator rows, and the minimal variant sets everything to empty except `middle`, which becomes a single space, with padding also set to zero, giving a table with no decorations at all:

```javascript
var table = new Table({
  chars: { 'top': '' , 'top-mid': '' , 'top-left': '' , 'top-right': ''
         , 'bottom': '' , 'bottom-mid': '' , 'bottom-left': '' , 'bottom-right': ''
         , 'left': '' , 'left-mid': '' , 'mid': '' , 'mid-mid': ''
         , 'right': '' , 'right-mid': '' , 'middle': ' ' },
  style: { 'padding-left': 0, 'padding-right': 0 }
});

table.push(
    ['foo', 'bar', 'baz']
  , ['frobnicate', 'bar', 'quuz']
);

console.log(table.toString());
```

That last variant is the one to remember if your output is going into a log file or a terminal without unicode support, since the default decoration is box drawing characters and a plain ASCII environment will show them as noise.

## Colour, truecolor and the head style option

Colour is applied through the `style` option, and the library uses ansis for it. The table head and the table border are styled separately, with `style.head[]` for the header text and `style.border[]` for the border colour. There are 16 named colours and styles, and truecolor via a hex code, with the format `hex(CODE)` for foreground and `bgHex(CODE)` for background, where CODE is a 3 or 6 digit hexadecimal value, and the documentation gives `hex(#FFA500)`, `hex(#A7E)`, `bgHex(#FF69B4)` and `bgHex(#49B)` as examples. The head style takes an array, so a colour and a style combine, and the example sets the header text in green and bold:

```js
var table = new Table({ 
  head: ['Name', 'Age'], 
  style: { 
    head: ['green', 'bold'],
  } 
});

table.push(['Walter White', '50']);

console.log(table.toString());
```

The truecolor variant uses the same array slot, with `style: { head: ['hex(#FFA500)', 'italic'] }` for orange italic headers. The dependency list shows the history here, since the README originally pointed at colors.js and now points at ansis, and the dev dependencies still carry `@colors/colors` for the test suite. That matters because colour handling with escape sequences is where the fork added real improvements, namely more dependable truncation of cell text containing ANSI colour characters and better handling of text colour that spans multiple lines.

## What the fork added over the original

The feature list that the original cli-table does not have is the reason to use cli-table3 rather than cli-table, and it is specific. Cells can span columns and rows. Styles can be set per cell, meaning border characters, colours and padding for one cell rather than the whole table. Vertical alignment is available with top, bottom and center. There are word wrapping options, documented in the basic usage guide under setting wordwrap to true to wrap text on word boundaries. The two ANSI handling improvements are listed above. The compatibility guarantee is API compatible with the original cli-table, and the test suite is described as exhaustive and including the entire original cli-table test suite. The examples are auto-generated from those tests, and they live in two files, basic-usage.md for the basic cases and advanced-usage.md for the column and row span features, with a scripts directory containing the update-docs script that regenerates them.

## Where this is the wrong choice

The limits are worth naming. The first is that the output is decorative by default. The default characters are unicode box drawing, and the table is meant to be read by a person in a terminal, so if you are printing something that a script will parse, or running in an environment without unicode support, you want the minimal chars configuration from the start rather than discovering the problem later. The second is the release state. The newest tagged release is v0.6.5 from 2024-05-12, while the package metadata declares version 0.7.0, and the last push was on 2026-04-19, so the working tree is ahead of what is on npm and the two are not the same artefact. The third is the Node version floor, where the engines field allows 10 or 12 and later, which excludes Node 11 and pins you to a version line that is itself out of support. The fourth is scope. This library draws a table; it does not compute alignments, sort rows, paginate output or handle terminal width detection, so a CLI that must adapt to the width of the window it is running in still has to compute column widths itself. And the last is dependency weight in a small project, since even two runtime dependencies matter if you are keeping a bundle size budget for a tiny script.

## Conclusion

cli-table3 fits a Node CLI that needs to print a table that people will actually read, since the per cell styling, spans and word wrapping cover the cases the original library left to the caller, and the API compatibility means the switch from cli-table is a dependency change. It is the wrong choice if you need a plain ASCII table for a machine to parse, since the output is decorated by default and the border characters are configurable but not absent. Before you adopt it, check the Node version, since the engines field allows 10 or 12 and later, and read the per cell style documentation rather than assuming the original cli-table options all apply unchanged. The last push was on 2026-04-19, the newest tagged release is v0.6.5 from 2024-05-12, and the package metadata declares version 0.7.0.

## FAQ

### How do I install cli-table3?

Install it with `npm install cli-table3`. The package is MIT licensed, its main entry is `index.js`, and it declares only two runtime dependencies, ansis for colour and string-width for measuring text.

### Is cli-table3 compatible with the original cli-table?

Yes. The README states that cli-table3 is based on and API compatible with the original cli-table and with cli-table2, both of which are unmaintained, so the original documentation still applies and the package includes all the additional features from cli-table2.

### What does cli-table3 add over cli-table?

Cells can span columns and rows, styles can be set per cell including border characters, colours and padding, vertical alignment supports top, bottom and center, there are word wrapping options, and ANSI colour handling is more robust for truncation and for colour spanning multiple lines.

### How do I draw a cli-table3 table without any borders?

Set every character in the `chars` option to the empty string except `middle`, which is set to a single space, and set the style padding-left and padding-right to 0. The README notes this produces the most compact layout with no decorations.

## Sources

- [cli-table/cli-table3 on GitHub](https://github.com/cli-table/cli-table3)
- [Issues](https://github.com/cli-table/cli-table3/issues)
- [License: MIT](https://github.com/cli-table/cli-table3/blob/master/LICENSE)
- [README](https://github.com/cli-table/cli-table3/blob/master/README.md)
- [Releases](https://github.com/cli-table/cli-table3/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cli-table-cli-table3
