CSV files are everywhere. Server exports, billing dumps, database snapshots, Grafana data. You can open them in Excel, or you can stay in the terminal and work at actual speed.

What It Is

xan is a command-line CSV processor written in Rust. It started as a fork of the classic xsv by BurntSushi — but it's been so thoroughly rewritten at this point it's essentially its own tool. It uses a SIMD-accelerated CSV parser, can parallelize operations with multithreading, handles multi-gigabyte files without a sweat, and exposes a composable set of commands that feel like natural Unix extensions.

It also does something no other tool in this space does as cleanly: it can draw data visualizations directly in your terminal. Histograms, scatterplots, time series. No Python. No Jupyter. Pipe and go.

Why It's Worth Your Time

Most CSV tools fail in one of two places. Tools like csvkit are Python-based and choke once files get large. xsv is fast but has been largely unmaintained. Reaching for awk or pandas for basic slicing and counting is overhead you don't need.

xan threads the needle: fast by default, readable command names, and a small expression language (moonblade) for when the simple subcommands aren't enough. It also handles CSV-adjacent formats — you can feed it Excel files, JSON, VCF, SAM, and more via xan from.

The philosophy is pure Unix: every command reads from stdin, writes to stdout, and chains naturally with the rest of your pipeline.

Hands On

Install on Arch Linux:

sudo pacman -S xan

Or via Cargo on any distro:

cargo install xan --locked

Pre-built binaries are also available on the releases page if you'd rather not compile.

Start by exploring a file:

# What columns does this CSV have?
xan headers data.csv

# How many rows?
xan count data.csv

# Pretty-print the first 10 rows
xan view data.csv

xan view renders a proper aligned table in your terminal. It truncates long values and shows you exactly how many columns exist. Much more useful than head.

Filter and search:

# Find rows where a column matches a pattern
xan search -s status "^5" access.csv | xan view

# Filter with an expression
xan filter 'count > 100' stats.csv | xan count

The histogram command is the killer feature:

xan frequency -s status_code access.csv | xan hist

Output:

Histogram for status_code (bars: 3, sum: 1247, max: 891):
200 |891 71.5%|━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━|
404 |247 19.8%|━━━━━━━━━━╸                              |
500 |109  8.7%|━━━━╸                                    |

That's a frequency distribution rendered in your terminal in milliseconds — even on files with millions of rows.

Stats at a glance:

xan stats -s response_time data.csv | xan transpose | xan view -I

You get count, mean, stddev, min, max — all without leaving your shell.

The expression language (moonblade) handles anything the simple commands can't:

# Compute a derived column
xan map 'len(path) as path_length' access.csv | xan filter 'path_length > 200'

# Format values
xan map 'fmt("{} ({})", name, year) as label' data.csv | xan select label

The cheatsheet is one command away: xan help cheatsheet.

Honest Verdict

xan is a focused tool. It doesn't try to replace pandas or become a general-purpose data platform. That restraint is what keeps it fast and composable.

The rough edges: the expression language has a learning curve, and the docs — while solid — assume you're willing to read them. A few advanced subcommands are under-documented. If your CSV use case is simple, xsv still works fine. If your files are large, your logic is non-trivial, or you want terminal charts without spinning up a Python environment, xan earns its place in your toolkit.

Run it once on a real dataset. The speed will make the decision for you.

Go Try It

cargo install xan --locked
xan --help

Then skim the quick tour in the README — it walks through twenty real commands on a real dataset.

Project: github.com/medialab/xan