tennis: stylish CSV tables that fit your terminal
stylish CSV tables in your terminal
At a glance
- What is it?
- A small Rust CLI that prints CSV, JSON or SQLite data as a bordered table sized to your window, with themes, sorting, filtering and a big column option. Rows are truncated rather than wrapped.
- Who is it for?
- tennis suits anyone who works with tabular files in a shell and wants to look at one without leaving the terminal, especially when the file is wide or the numbers need aligning. It does not suit a workflow that needs to transform data rather than view it, since the tool only selects, sorts, filters and formats, and the README points to miller and qsv for that work.
- 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 26 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A table that is cut to fit rather than wrapped
tennis is a small command line tool for printing CSV tables in a terminal, written in Rust. The design decision that defines it is that rows are truncated to fit, so you get a table whose shape matches the terminal rather than a wrapped mess that is hard to scan. Alongside that, the tool picks colours to match the terminal, formats numbers automatically and, according to the README, works with JSON, JSONL and SQLite as well as CSV. The options list shows the shape of the tool:
Usage: tennis [OPTIONS] [FILE]
Popular options:
-n, --row-numbers Turn on row numbers
-t, --title <string> Add a title to the table
--border <border> Table border style (rounded|thin|double|...)
-p, --pager Send output through $PAGER or less
--peek Show csv shape, sample, and handy stats
-z, --zebra Turn on zebra stripesThe dependency list in the manifest explains the implementation. The csv crate does the parsing, simd-json handles JSON with runtime detection and swar number parsing, terminal_size and unicode-width and unicode-truncate handle the layout budget, and terminal-colorsaurus is what reads the terminal background colour to pick a theme.
It sniffs the delimiter and the format
The format detection is the part worth understanding before you fight it. Tennis supports CSV-like files, JSON and SQLite, and it infers the format using both the filename when there is one and the first few bytes of input. For CSV it sniffs the correct delimiter from the first few rows, so tabs, semicolons and pipes work without configuration, and the delimiter can also be forced with the -d or --delimiter option, which accepts any character or the word tab. JSON is flexible: it can be a full array of objects, JSONL or NDJSON, or even a single JSON object, in which case the pairs become rows. SQLite files are read through the external sqlite3 command line program rather than through a linked driver, and the table is chosen with --table, or automatically if you do not say. There is also a numeric formatting switch, --vanilla, which disables the automatic number formatting.
Themes follow the terminal, and NO_COLOR still works
On appearance, tennis picks a colour theme based on the colour of your terminal, with a --theme option to force auto, dark or light. Colour is on by default, and the README says so with a bit of personality, that tennis likes to be colorful. The environment variable NO_COLOR=1 is honoured, and the fix for it landed in the 0.7.0 release. The border styles match the ones in nushell, and the bling options are --border, --row-numbers, --title and --zebra, with the 0.8.0 release improving the zebra striping so it blends with the terminal background. Two more scale options apply to data rather than chrome, --scale adds a red-to-green colour scale across a column and --rscale does the same in the opposite direction, which is a fast way to spot outliers in a numeric column.
Big, bigger, biggest, and a width budget
The layout engine works to a budget. Terminal width is taken from the terminal, defaulting to 80 when it cannot be worked out, and --width overrides it with a number or with min or max. The three column size flags are the memorable part. With -b the table still fits inside the terminal width, while -bb makes a column bigger, described as the 90th percentile, and -bbb makes it the biggest it can be, taking the full width. Both of those usually push the table past the edge of the screen, which the README says is intentional and suggests pairing with --pager. The pager option sends output through $PAGER or less and is described as the right choice for tables with many rows or for wide tables. The README points at src/middleware/layout.rs for the autolayout details, and calls that file the hairy part.
Peek, select, sort, filter
For the case where you only want a quick look at an unfamiliar file, the --peek flag shows the shape of the data, a sample, fill rate and formats. For actual work there is a set of display controls rather than data transformation. --select and --deselect choose and reorder columns by header name, --sort orders rows by comma-separated headers and -r reverses them, and --shuffle puts rows into random order. --head and --tail limit the output to the first or last N rows, and --filter keeps only rows containing a given string. The important limitation is that these are display operations. Nothing is written back, and tennis does not join or reshape data, which is why the README lists miller for CSV processing and transformation, qsv for filter, sort, combine and join, and visidata for exploring large files. It also lists csvlens, tabiew and the tidy viewer as viewers it considers good, which is generous about its competition.
Installation, and a rewrite from Zig to Rust
macOS users can install with Homebrew:
$ brew install gurgeous/tap/tennisOn Linux the README suggests downloading a binary from the releases page and copying it into a directory on the PATH, and it mentions optional bash and zsh completions and a man page in the extra directory. Building from source uses mise for the toolchain and cargo:
$ mise trust && mise install
$ cargo build # or use `just build`The most interesting item in the changelog is the 0.7.0 release, where the project moved from Zig to Rust and brought in a new and greatly improved autolayout. The 0.8.0 release added typed cells that honour the locale, column arguments by index, crude support for ANSI escapes inside cells and static Linux builds with musl and mimalloc, and it merged an unreleased crate back into the application. The manifest shows a Rust edition of 2024 with a minimum rust-version of 1.96, plus a small profile that trades speed for size with opt-level z, fat LTO and panic abort. The licence is MIT, and the project describes itself as based on the author's earlier table_tennis work.
Editorial conclusion
tennis suits anyone who works with tabular files in a shell and wants to look at one without leaving the terminal, especially when the file is wide or the numbers need aligning. It does not suit a workflow that needs to transform data rather than view it, since the tool only selects, sorts, filters and formats, and the README points to miller and qsv for that work. Before adopting, note that the project was rewritten from Zig to Rust in version 0.7.0, so older install instructions may not match, and that colour output defaults to on unless you set NO_COLOR=1.
Frequently asked questions
How do I install tennis?
On macOS run brew install gurgeous/tap/tennis. On Linux the README suggests downloading a binary from the releases page and putting it on your PATH, and to build from source run mise trust && mise install followed by cargo build.
Which file formats can tennis read?
CSV-like files with sniffed delimiters, JSON including JSONL and NDJSON, and SQLite files read through the external sqlite3 CLI. The format is inferred from the filename and the first bytes of input.
How do I make one column wider in tennis?
Use -b for big, -bb for bigger and -bbb for biggest. With -b the table still fits the terminal width, while -bb and -bbb usually make it overflow, so you may want --pager alongside them.
How do I disable colours in tennis?
Colour is on by default, so pass --color off or set the NO_COLOR=1 environment variable. The --theme option forces auto, dark or light rather than following the terminal background.
What does the tennis peek option show?
The --peek flag gives a quick summary of the file, showing the shape of the data, a sample, the fill rate and the formats present, without printing the whole table.
Official sources
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.
[](https://hysenlabs.com/projects/gurgeous-tennis)Was this useful?