mrkeyoor.com_
Sat 08 Aug 20:58 UTC
npmCLI & Toolingupdated 08 Aug 2026

cli-table

cli-table turns arrays and small key-value objects into bordered text tables for Node command-line output. You construct a table, push rows because the object inherits from Array, and call `toString()` to render Unicode borders, padded columns, optional ANSI colors, alignment, truncation, multiline cells, horizontal tables, vertical key-value layouts, or cross tables. It is the original 2010 package, not the newer `cli-table3` fork.

Verdict

Do not install the original for a new CLI; use `cli-table3` unless a different data model fits better. Keep `cli-table` only when an existing tool relies on its exact legacy rendering behavior.

API stability4/5The constructor, array-like row model, `toString()` rendering, and core `head`, `colWidths`, `colAligns`, `chars`, and `style` options have changed little across a long lifetime. Existing snapshots are unlikely to shift, but that predictability comes with old implementation contracts and no published semantic compatibility policy.
Docs3/5The README demonstrates horizontal, vertical, and cross tables, initial rows, custom border characters, border removal, padding, and truncation-related options in compact examples. It does not document the complete option contract, Unicode width limits, null handling, cross-row mutation, TypeScript setup, ESM usage, or the exact `middle` alignment token.
Maintenance2/5npm lists 0.3.11 from December 2021 as the latest published version. GitHub reports a repository push in August 2024 and the project is neither archived nor deprecated, but the repository's default branch is named `v0.4.0` without a corresponding latest npm release. The maintained `cli-table3` fork is a clearer target for fixes.
Ecosystem3/5The package recorded 4,564,889 downloads for the measured week and has 2,297 GitHub stars, reflecting a large installed base in command-line dependency trees. Its practical ecosystem is legacy CommonJS with one color dependency; it has no plugin layer, declarations, terminal capability adapter, or modern module entry point.

Use it if

  • You maintain an existing CommonJS CLI that already depends on cli-table and its exact output is covered by snapshots
  • You need a dependency-light table with custom borders, fixed widths, alignment, truncation, and multiline cells
  • Your table data is short ASCII or simple ANSI-colored text where JavaScript string length is a sufficient width estimate
  • You want an array-like object that can be built incrementally with `push`, `unshift`, and `splice`
Skip it if

Setup reality

`npm install cli-table` is the whole installation. There are no native builds, peer dependencies, credentials, or config files; the only runtime dependency is the pinned `colors` 1.0.3 package. The API is CommonJS (`require('cli-table')`) and has no bundled TypeScript declarations, so typed projects need their own declaration or a community types package. Widths are the first practical surprise. Each `colWidths` number includes left and right padding plus the cell content, and values that exceed it are truncated with `…` by default. Without explicit widths, the renderer measures all rows and can produce a table wider than the terminal. Its measurement removes a limited ANSI SGR pattern but counts ordinary JavaScript string length, which is not display width for emoji, combining characters, and many CJK glyphs. Alignment uses `left`, `right`, or the implementation's `middle` value even though the README describes center alignment. Row cells are converted through `toString()`, so `null` and `undefined` are not safe cell values unless normalized first. Vertical rows are one-key objects; extra keys are ignored because rendering takes only `Object.keys(row)[0]`. Cross-table rendering calls `unshift` on the array stored as the object value, mutating that source array. Styling names are looked up on `colors/safe`, and invalid style names fail at render time. The table does not print by itself, wrap to terminal width, sanitize control characters, or stream rows; call `toString()` only after the complete in-memory table is ready.

Patterns

Render a basic horizontal tablerender-horizontal-table

const Table = require('cli-table');

const table = new Table({
  head: ['Name', 'Status'],
});
table.push(
  ['api', 'ready'],
  ['worker', 'stopped'],
);

console.log(table.toString());

Automatic widths inspect all rows and do not respect terminal width, so long values can create an extremely wide table.

Fix widths and truncate long cellsset-column-widths

const table = new Table({
  head: ['Package', 'Description'],
  colWidths: [18, 42],
  truncate: '...',
});

table.push(['cli-table', 'Render tables in terminal output']);

Each width includes both padding columns. The truncation marker also consumes part of the available content width.

Align numeric and centered columnsalign-columns

const table = new Table({
  head: ['Item', 'Count', 'State'],
  colWidths: [18, 10, 12],
  colAligns: ['left', 'right', 'middle'],
});

table.push(['jobs', 42, 'ok']);

The implementation recognizes `middle` for centered text, not the more common `center` spelling.

Render key-value rowsrender-vertical-table

const table = new Table();

table.push(
  { Runtime: process.version },
  { Platform: process.platform },
);

console.log(table.toString());

Use exactly one key per row object. If an object has several keys, only the first enumerated key is rendered.

Render row and column headersrender-cross-table

const table = new Table({
  head: ['', 'Passed', 'Failed'],
});

table.push(
  { Unit: [120, 0] },
  { Integration: [34, 2] },
);

console.log(table.toString());

Rendering prepends the row header with `unshift`, mutating each array supplied as an object value. Do not reuse those arrays afterward.

Provide rows in the constructorinitialize-with-rows

const table = new Table({
  head: ['Command', 'Duration'],
  rows: [
    ['lint', '1.2s'],
    ['test', '8.4s'],
  ],
});

process.stdout.write(table.toString() + '\n');

Constructor rows are pushed into the array-like table; later `push`, `splice`, and `unshift` calls still work.

Replace the border character setcustomize-borders

const 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: '|',
  },
});
table.push(['plain', 'ascii']);

Override every key for a consistent ASCII border; omitted keys retain their Unicode defaults.

Hide horizontal lines between rowsremove-row-separators

const table = new Table({
  chars: {
    mid: '',
    'left-mid': '',
    'mid-mid': '',
    'right-mid': '',
  },
});
table.push(['one', 'first'], ['two', 'second']);

Empty decoration lines are skipped, but the top, bottom, left, right, and vertical middle borders remain.

Create a compact borderless layoutrender-borderless-columns

const 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 },
});

The spaces needed for alignment still come from computed column widths; only borders and explicit padding disappear.

Render multiline cell contentrender-multiline-cell

const table = new Table({
  head: ['Service', 'Endpoints'],
  colWidths: [16, 32],
});

table.push(['api', 'GET /health\nPOST /jobs']);

The row height grows to the tallest cell and shorter cells are padded with blank lines; there is no automatic word wrapping.

Normalize missing values before renderingnormalize-null-cells

const rows = records.map((record) => [
  record.name ?? '(unnamed)',
  record.owner ?? '-',
]);

const table = new Table({ head: ['Name', 'Owner'], rows });

Cells are rendered through `item.toString()`, so passing `null` or `undefined` directly throws instead of displaying an empty value.

Alternatives

PackageRegistryPick it when
cli-table3npmYou want the maintained continuation with a familiar row model and better handling for modern Node projects
tablenpmYou need configurable word wrapping, spanning cells, border presets, and a functional rendering API
easy-tablenpmYou prefer building records column by column with automatic widths and simple formatters