If you've built a Node.js CLI tool, you've probably used cli-table3 or table to render terminal tables. They work fine — but both haven't been updated in over a year, and they're missing the features modern CLI tools need.
I built cmd-table as a standalone, TypeScript-first alternative. Here's why.
The problem
| cli-table3 | table | cmd-table | |
|---|---|---|---|
| Last updated | 2+ years ago | 1+ year ago | This week |
| Dependencies | 3 | 6 | 0 |
| Interactive TUI | No | No | Yes |
| Sparklines / Heatmaps | No | No | Yes |
| SQL / SQLite browsing | No | No | Yes |
| CSV / HTML parsing | No | No | Yes |
| Pivot tables | No | No | Yes |
| Progress bars | No | No | Yes |
| Tree view | No | No | Yes |
| Diff tables | No | No | Yes |
| Export (MD/CSV/JSON/HTML) | No | No | Yes |
| TypeScript-first | Partial | Yes | Yes |
The top two CLI table libraries have 23M+ weekly downloads combined, mostly from being transitive dependencies of other tools. They're stable but stagnant. If you're starting a new project in 2026, you deserve better.
Install
npm install cmd-table
No extra dependencies. That's it.
Quick start — under 30 seconds
import { Table } from 'cmd-table';
const table = new Table();
table.addColumn('Name');
table.addColumn('Role');
table.addColumn('Status');
table.addRow({ Name: 'Alice', Role: 'Dev', Status: 'Active' });
table.addRow({ Name: 'Bob', Role: 'PM', Status: 'Offline' });
console.log(table.render());
╭────────┬──────┬─────────╮
│ Name │ Role │ Status │
├────────┼──────┼─────────┤
│ Alice │ Dev │ Active │
│ Bob │ PM │ Offline │
╰────────┴──────┴─────────╯
Or pipe data directly from your terminal:
echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' | npx cmd-table
cat data.csv | npx cmd-table --interactive
5 features that cli-table3 doesn't have
1. Interactive TUI
Explore large datasets in your terminal. Search, filter, sort, select rows — all keyboard-driven:
import { Table, InteractiveTable } from 'cmd-table';
const table = new Table();
// ... add hundreds of rows ...
const interactive = new InteractiveTable(table, {
onSelect: (rows) => console.log('Selected:', rows),
onExit: () => process.exit(0)
});
interactive.start();
Controls:
-
Right/Left— page through results -
s— sort by column -
/— search and filter -
Space— select/deselect rows -
Enter— confirm selection
No external TUI framework needed. Just call .start().
2. SQL / SQLite browsing
Browse real database tables interactively — pagination, sorting, and search at the SQL level:
import Database from 'better-sqlite3';
import { Table, AsyncInteractiveTable, SqlDataSource } from 'cmd-table';
const db = new Database('mydata.db');
const source = new SqlDataSource(db, 'employees');
const template = new Table();
template.addColumn('id');
template.addColumn('name');
template.addColumn('department');
const app = new AsyncInteractiveTable(source, template);
await app.start();
It doesn't load your entire database into memory.
3. Sparklines, Heatmaps & Progress bars
Visualize trends directly inside table cells:
import { Table, Sparkline, Heatmap, ProgressBar } from 'cmd-table';
table.addColumn({
name: 'CPU trend', key: 'cpu',
formatter: (v) => Sparkline.generate(JSON.parse(v)) // ▂▄█▄▂
});
table.addColumn({
name: 'Coverage', key: 'coverage',
minWidth: 15,
formatter: (v) => ProgressBar.generate(Number(v), 100, { width: 10 })
// ████████░░ 82%
});
4. Pivot tables & diff comparison
Built-in data analysis:
import { PivotTable, CrossTab, Table } from 'cmd-table';
// Aggregate data
const pivot = PivotTable.create(salesData, {
groupBy: 'Region',
targetColumn: 'Amount',
algorithm: 'sum'
});
// Compare two datasets
const diff = Table.compare(oldData, newData, {
primaryKey: 'id',
columns: ['name', 'status', 'score']
});
// Added rows in green, removed in red, changed cells in yellow
5. Parse anything, export anywhere
import { CsvTable, HtmlTable } from 'cmd-table';
// CSV string -> Table
const t1 = CsvTable.from('name,age\nAlice,30\nBob,25');
// HTML table -> Table
const t2 = HtmlTable.from('<table><tr><td>Data</td></tr></table>');
// Export to any format
console.log(t1.export('md')); // Markdown
console.log(t1.export('csv')); // CSV
console.log(t1.export('json')); // JSON
Migrating from cli-table3
If you're already using cli-table3, switching is straightforward:
Before (cli-table3):
import Table from 'cli-table3';
const table = new Table({
head: ['Name', 'Age'],
colWidths: [20, 10]
});
table.push(['Alice', 30], ['Bob', 25]);
console.log(table.toString());
After (cmd-table):
import { Table } from 'cmd-table';
const table = new Table();
table.addColumn({ name: 'Name', minWidth: 20 });
table.addColumn({ name: 'Age', minWidth: 10 });
table.addRow({ Name: 'Alice', Age: 30 });
table.addRow({ Name: 'Bob', Age: 25 });
console.log(table.render());
What you gain: interactive TUI, sparklines, formatters, exports, themes, and everything else — for free.
Full feature list
- 7+ built-in themes (Rounded, Honeywell, DoubleLine, BoldBox, Dots, Void, etc.)
- ANSI colors for headers, columns, rows
-
colSpan,rowSpan, auto-sizing, word-wrap - Responsive column hiding by priority
- Tree view with automatic indentation
- Auto-merge identical adjacent cells
- Header groups (super-headers spanning columns)
- Footers and aggregation summaries
- Per-column formatter callbacks
- Conditional row coloring (
rowColor) - Transpose tables (flip rows and columns)
- Streaming renderer for large datasets
- JSX/React declarative syntax
- CLI tool for piping JSON/CSV data
- TypeScript-first with full type definitions
Links
- npm: npmjs.com/package/cmd-table
- GitHub: github.com/Aarul5/cmd-table
- Docs: aarul5.github.io/cmd-table
If this looks useful, a star on GitHub helps others find it. Contributions welcome
What do you use for CLI tables? Have you hit limitations with cli-table3 or table? Let me know in the comments.
Top comments (0)