medialab/xanPublic

The CSV magician

AI summary: A blazingly fast CSV processing CLI written in Rust.

Stars
4.5K
+1 today
Forks
87
Watchers
21
Open issues
120
Open PRs
1
Contributors
~63
Commits
3.4K
Branches
90

RustUnlicenseCreated Jul 10, 2018Last push 7d agoLatest release 0.60.0+14 stars this week+19 this month

Star history

since Feb 4, 2024
02K4KFeb 2024Dec 2024Sep 2025Aug 2026
4.5K stars as of Aug 7, 2026, tracked back to Feb 4, 2024. Historical curve reconstructed from public GitHub event archives, calibrated to the current total.

Contribution activity

commits per day, last 52 weeks
AugSepOctNovDecJanFebMarAprMayJunJulAugMonWedFri2025-08-10: 0 commits2025-08-11: 0 commits2025-08-12: 0 commits2025-08-13: 0 commits2025-08-14: 0 commits2025-08-15: 0 commits2025-08-16: 0 commits2025-08-17: 0 commits2025-08-18: 0 commits2025-08-19: 0 commits2025-08-20: 0 commits2025-08-21: 0 commits2025-08-22: 1 commit2025-08-23: 0 commits2025-08-24: 0 commits2025-08-25: 0 commits2025-08-26: 0 commits2025-08-27: 0 commits2025-08-28: 0 commits2025-08-29: 0 commits2025-08-30: 0 commits2025-08-31: 0 commits2025-09-01: 5 commits2025-09-02: 8 commits2025-09-03: 2 commits2025-09-04: 0 commits2025-09-05: 0 commits2025-09-06: 0 commits2025-09-07: 0 commits2025-09-08: 0 commits2025-09-09: 0 commits2025-09-10: 0 commits2025-09-11: 0 commits2025-09-12: 0 commits2025-09-13: 0 commits2025-09-14: 0 commits2025-09-15: 3 commits2025-09-16: 0 commits2025-09-17: 2 commits2025-09-18: 0 commits2025-09-19: 1 commit2025-09-20: 0 commits2025-09-21: 0 commits2025-09-22: 0 commits2025-09-23: 1 commit2025-09-24: 0 commits2025-09-25: 0 commits2025-09-26: 1 commit2025-09-27: 1 commit2025-09-28: 0 commits2025-09-29: 2 commits2025-09-30: 1 commit2025-10-01: 0 commits2025-10-02: 1 commit2025-10-03: 2 commits2025-10-04: 0 commits2025-10-05: 0 commits2025-10-06: 1 commit2025-10-07: 2 commits2025-10-08: 8 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 0 commits2025-10-12: 0 commits2025-10-13: 4 commits2025-10-14: 1 commit2025-10-15: 5 commits2025-10-16: 1 commit2025-10-17: 15 commits2025-10-18: 5 commits2025-10-19: 4 commits2025-10-20: 6 commits2025-10-21: 2 commits2025-10-22: 6 commits2025-10-23: 15 commits2025-10-24: 11 commits2025-10-25: 4 commits2025-10-26: 0 commits2025-10-27: 0 commits2025-10-28: 11 commits2025-10-29: 13 commits2025-10-30: 10 commits2025-10-31: 7 commits2025-11-01: 0 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 12 commits2025-11-05: 2 commits2025-11-06: 2 commits2025-11-07: 1 commit2025-11-08: 0 commits2025-11-09: 0 commits2025-11-10: 3 commits2025-11-11: 0 commits2025-11-12: 3 commits2025-11-13: 1 commit2025-11-14: 9 commits2025-11-15: 4 commits2025-11-16: 2 commits2025-11-17: 8 commits2025-11-18: 0 commits2025-11-19: 1 commit2025-11-20: 0 commits2025-11-21: 0 commits2025-11-22: 0 commits2025-11-23: 0 commits2025-11-24: 0 commits2025-11-25: 5 commits2025-11-26: 5 commits2025-11-27: 3 commits2025-11-28: 1 commit2025-11-29: 0 commits2025-11-30: 0 commits2025-12-01: 0 commits2025-12-02: 0 commits2025-12-03: 0 commits2025-12-04: 0 commits2025-12-05: 0 commits2025-12-06: 0 commits2025-12-07: 0 commits2025-12-08: 0 commits2025-12-09: 0 commits2025-12-10: 0 commits2025-12-11: 0 commits2025-12-12: 0 commits2025-12-13: 0 commits2025-12-14: 0 commits2025-12-15: 0 commits2025-12-16: 0 commits2025-12-17: 0 commits2025-12-18: 0 commits2025-12-19: 9 commits2025-12-20: 0 commits2025-12-21: 0 commits2025-12-22: 0 commits2025-12-23: 0 commits2025-12-24: 2 commits2025-12-25: 0 commits2025-12-26: 0 commits2025-12-27: 0 commits2025-12-28: 0 commits2025-12-29: 0 commits2025-12-30: 0 commits2025-12-31: 0 commits2026-01-01: 0 commits2026-01-02: 0 commits2026-01-03: 0 commits2026-01-04: 0 commits2026-01-05: 0 commits2026-01-06: 0 commits2026-01-07: 0 commits2026-01-08: 0 commits2026-01-09: 0 commits2026-01-10: 0 commits2026-01-11: 0 commits2026-01-12: 0 commits2026-01-13: 0 commits2026-01-14: 0 commits2026-01-15: 0 commits2026-01-16: 0 commits2026-01-17: 0 commits2026-01-18: 0 commits2026-01-19: 0 commits2026-01-20: 0 commits2026-01-21: 0 commits2026-01-22: 0 commits2026-01-23: 0 commits2026-01-24: 0 commits2026-01-25: 0 commits2026-01-26: 0 commits2026-01-27: 0 commits2026-01-28: 0 commits2026-01-29: 0 commits2026-01-30: 2 commits2026-01-31: 0 commits2026-02-01: 0 commits2026-02-02: 0 commits2026-02-03: 2 commits2026-02-04: 4 commits2026-02-05: 10 commits2026-02-06: 6 commits2026-02-07: 0 commits2026-02-08: 0 commits2026-02-09: 1 commit2026-02-10: 1 commit2026-02-11: 3 commits2026-02-12: 11 commits2026-02-13: 5 commits2026-02-14: 1 commit2026-02-15: 0 commits2026-02-16: 2 commits2026-02-17: 3 commits2026-02-18: 1 commit2026-02-19: 6 commits2026-02-20: 12 commits2026-02-21: 1 commit2026-02-22: 0 commits2026-02-23: 0 commits2026-02-24: 2 commits2026-02-25: 0 commits2026-02-26: 1 commit2026-02-27: 1 commit2026-02-28: 0 commits2026-03-01: 0 commits2026-03-02: 2 commits2026-03-03: 0 commits2026-03-04: 0 commits2026-03-05: 0 commits2026-03-06: 0 commits2026-03-07: 0 commits2026-03-08: 0 commits2026-03-09: 0 commits2026-03-10: 0 commits2026-03-11: 0 commits2026-03-12: 0 commits2026-03-13: 0 commits2026-03-14: 0 commits2026-03-15: 0 commits2026-03-16: 0 commits2026-03-17: 0 commits2026-03-18: 4 commits2026-03-19: 9 commits2026-03-20: 6 commits2026-03-21: 4 commits2026-03-22: 0 commits2026-03-23: 2 commits2026-03-24: 7 commits2026-03-25: 10 commits2026-03-26: 12 commits2026-03-27: 17 commits2026-03-28: 0 commits2026-03-29: 0 commits2026-03-30: 17 commits2026-03-31: 6 commits2026-04-01: 10 commits2026-04-02: 10 commits2026-04-03: 10 commits2026-04-04: 8 commits2026-04-05: 1 commit2026-04-06: 0 commits2026-04-07: 0 commits2026-04-08: 5 commits2026-04-09: 11 commits2026-04-10: 0 commits2026-04-11: 0 commits2026-04-12: 0 commits2026-04-13: 0 commits2026-04-14: 0 commits2026-04-15: 9 commits2026-04-16: 0 commits2026-04-17: 6 commits2026-04-18: 1 commit2026-04-19: 0 commits2026-04-20: 1 commit2026-04-21: 8 commits2026-04-22: 16 commits2026-04-23: 9 commits2026-04-24: 8 commits2026-04-25: 1 commit2026-04-26: 8 commits2026-04-27: 7 commits2026-04-28: 11 commits2026-04-29: 10 commits2026-04-30: 17 commits2026-05-01: 3 commits2026-05-02: 3 commits2026-05-03: 3 commits2026-05-04: 13 commits2026-05-05: 13 commits2026-05-06: 10 commits2026-05-07: 11 commits2026-05-08: 2 commits2026-05-09: 4 commits2026-05-10: 1 commit2026-05-11: 26 commits2026-05-12: 15 commits2026-05-13: 18 commits2026-05-14: 2 commits2026-05-15: 16 commits2026-05-16: 2 commits2026-05-17: 0 commits2026-05-18: 16 commits2026-05-19: 3 commits2026-05-20: 0 commits2026-05-21: 4 commits2026-05-22: 3 commits2026-05-23: 3 commits2026-05-24: 4 commits2026-05-25: 4 commits2026-05-26: 6 commits2026-05-27: 0 commits2026-05-28: 7 commits2026-05-29: 1 commit2026-05-30: 0 commits2026-05-31: 0 commits2026-06-01: 0 commits2026-06-02: 4 commits2026-06-03: 3 commits2026-06-04: 4 commits2026-06-05: 4 commits2026-06-06: 2 commits2026-06-07: 0 commits2026-06-08: 0 commits2026-06-09: 3 commits2026-06-10: 0 commits2026-06-11: 17 commits2026-06-12: 13 commits2026-06-13: 6 commits2026-06-14: 1 commit2026-06-15: 6 commits2026-06-16: 9 commits2026-06-17: 11 commits2026-06-18: 2 commits2026-06-19: 1 commit2026-06-20: 0 commits2026-06-21: 0 commits2026-06-22: 0 commits2026-06-23: 0 commits2026-06-24: 0 commits2026-06-25: 0 commits2026-06-26: 1 commit2026-06-27: 0 commits2026-06-28: 0 commits2026-06-29: 0 commits2026-06-30: 0 commits2026-07-01: 5 commits2026-07-02: 12 commits2026-07-03: 1 commit2026-07-04: 2 commits2026-07-05: 0 commits2026-07-06: 0 commits2026-07-07: 5 commits2026-07-08: 0 commits2026-07-09: 0 commits2026-07-10: 6 commits2026-07-11: 0 commits2026-07-12: 0 commits2026-07-13: 0 commits2026-07-14: 0 commits2026-07-15: 0 commits2026-07-16: 0 commits2026-07-17: 0 commits2026-07-18: 0 commits2026-07-19: 0 commits2026-07-20: 0 commits2026-07-21: 1 commit2026-07-22: 0 commits2026-07-23: 0 commits2026-07-24: 0 commits2026-07-25: 0 commits2026-07-26: 0 commits2026-07-27: 0 commits2026-07-28: 2 commits2026-07-29: 0 commits2026-07-30: 0 commits2026-07-31: 2 commits2026-08-01: 0 commits2026-08-02: 0 commits2026-08-03: 0 commits2026-08-04: 0 commits2026-08-05: 0 commits2026-08-06: 0 commits2026-08-07: 0 commits2026-08-08: 0 commits
889 commits in the last yearLessMore

Signals and awards

derived from tracked data
  • Battle-tested

    8 years of history

  • Permissive license

    Unlicense

  • Continuous integration

    Automated checks passing

What xan does

xan is a high-performance command-line tool designed to process massive CSV files directly from the shell. Written in Rust, it leverages a novel SIMD-based CSV parser and multithreading to slice, filter, join, and aggregate gigabytes of data with minimal memory footprint. It goes beyond basic shell utilities by embedding a custom, highly-optimized expression language specifically tailored for tabular data, allowing users to perform complex evaluations far faster than dynamically-typed scripts.

Data engineers, analysts, and developers who frequently work with large CSV datasets in the terminal.

  • SIMD parsing: Utilizes a single-instruction, multiple-data parser for maximum throughput on large files.
  • Custom expression language: Embeds a minimalistic, typed language designed specifically for fast evaluation of CSV columns.
  • Multithreaded operations: Parallelizes computations across available cores to speed up aggregations and joins.
  • Low memory footprint: Streams data efficiently to handle files larger than available RAM.

Where teams use it

Data wrangling

Filtering and aggregating multi-gigabyte CSV exports from databases without loading them into memory.

Shell pipelines

Replacing slow Python or Awk scripts with a fast, compiled tool in data processing pipelines.

Complex transformations

Using the embedded expression language to mutate columns based on complex logic.

Getting started: Install via Cargo or download a pre-built binary, then run xan --help.

README

master branch

Build Status DOI

xan, the CSV magician

xan is a command line tool that can be used to process CSV files directly from the shell.

It has been written in Rust to be as fast as possible, use as little memory as possible, and can very easily handle large CSV files (Gigabytes). It leverages a novel SIMD CSV parser and is also able to parallelize some computations (through multithreading) to make some tasks complete as fast as your computer can allow.

It can easily preview, filter, slice, aggregate, sort, join CSV files, and exposes a large collection of composable commands that can be chained together to perform a wide variety of typical tasks.

xan also offers its own expression language so you can perform complex tasks that cannot be done by relying on the simplest commands. This minimalistic language has been tailored for CSV data and is way faster than evaluating typical dynamically-typed languages such as Python, Lua, JavaScript etc.

Note that this tool is originally a fork of BurntSushi's xsv, but has been nearly entirely rewritten at that point, to fit SciencesPo's médialab use-cases, rooted in web data collection and analysis geared towards social sciences (you might think CSV is outdated by now, but read our love letter to the format before judging too quickly).

xan therefore goes beyond typical data manipulation and expose utilities related to lexicometry, graph theory and even scraping.

Beyond CSV data, xan is able to process a large variety of CSV-adjacent data formats from many different disciplines such as web archival (.cdx) or bioinformatics (.vcf, .gtf, .sam, .bed etc.). xan is also able to convert to & from many data formats such as json, excel files, numpy arrays etc. using xan to and xan from. See this section for more detail.

Finally, xan can be used to display CSV files in the terminal, for easy exploration, and can even be used to draw basic data visualisations:

view command flatten command
view flatten
categorical histogram scatterplot
categ-hist correlation
categorical scatterplot histograms
scatter hist
parallel processing time series
parallel series
small multiples (facet grid) grouped view
small-multiples view-grid
correlation matrix heatmap heatmap
small-multiples view-grid

Summary

How to install

Cargo

xan can be installed using cargo (it usually comes with Rust):

cargo install xan --locked

Optional features

Some features are not built by default because they cost too much in compilation time or in executable size. Here is a list of those optional features:

  • parquet: enables xan from -f parquet

You can specify which optional features you want thusly:

# To enable all optional features
cargo install xan --locked --all-features
# To enable only specific features
cargo install xan --locked --features parquet

You can also tweak the build flags to make sure the Rust compiler is able to leverage all your CPU's features:

CARGO_BUILD_RUSTFLAGS='-C target-cpu=native' cargo install xan --locked

You can also install the latest dev version thusly:

cargo install --git https://github.com/medialab/xan --locked

Scoop (Windows)

xan can be installed using Scoop on Windows:

scoop bucket add extras
scoop install xan

Homebrew (macOS)

xan can be installed with Homebrew on macOS thusly:

brew install xan

Arch Linux

You can install xan from the extra repository using pacman:

sudo pacman -S xan

NetBSD

A package is available from the official repositories. To install xan simply run:

pkgin install xan

Nix

xan is packaged for Nix, and is available in Nixpkgs as of 25.05 release. To install it, you may add it to your environment.systemPackages as pkgs.xan or use nix-shell to enter an ephemeral shell.

nix-shell -p xan

Pixi (Linux, macOS, Windows)

xan can be installed in Linux, macOS, and Windows using the Pixi package manager:

pixi global install xan

Conda Forge

xan can be installed through conda-forge thusly:

conda install conda-forge::xan

Pre-built binaries

Pre-built binaries can be found attached to every GitHub releases.

Currently supported targets include:

  • x86_64-apple-darwin

  • x86_64-unknown-linux-gnu

  • x86_64-unknown-linux-musl

  • x86_64-pc-windows-msvc

  • aarch64-apple-darwin

  • aarch64-unknown-linux-gnu

ppc64le targets are not built by the CI yet but prebuilt binaries can still be found in the conda-forge package's files if you need them.

Feel free to open a PR to improve the CI by adding relevant targets.

Installing completions

Note that xan also exposes handy automatic completions for command and header/column names that you can install through the xan completions command.

Run the following command to understand how to install those completions:

xan completions -h

For zsh, you can add the completion file to ~/.zfunc:

mkdir -p ~/.zfunc
xan completions zsh > ~/.zfunc/_xan

Then add this before compinit in your ~/.zshrc:

fpath=(~/.zfunc $fpath)
autoload -Uz compinit
compinit

Quick tour

Let's learn about the most commonly used xan commands by exploring a corpus of French medias:

Downloading the corpus

curl -LO https://github.com/medialab/corpora/raw/master/polarisation/medias.csv

Displaying the file's headers

xan headers medias.csv
0   webentity_id
1   name
2   prefixes
3   home_page
4   start_pages
5   indegree
6   hyphe_creation_timestamp
7   hyphe_last_modification_timestamp
8   outreach
9   foundation_year
10  batch
11  edito
12  parody
13  origin
14  digital_native
15  mediacloud_ids
16  wheel_category
17  wheel_subcategory
18  has_paywall
19  inactive

Counting the number of rows

xan count medias.csv
478

Previewing the file in the terminal

xan view medias.csv
Displaying 5/20 cols from 10 first rows of medias.csv
┌───┬───────────────┬───────────────┬────────────┬───┬─────────────┬──────────┐
│ - │ name          │ prefixes      │ home_page  │ … │ has_paywall │ inactive │
├───┼───────────────┼───────────────┼────────────┼───┼─────────────┼──────────┤
│ 0 │ Acrimed.org   │ http://acrim… │ http://ww… │ … │ false       │ <empty>  │
│ 1 │ 24matins.fr   │ http://24mat… │ https://w… │ … │ false       │ <empty>  │
│ 2 │ Actumag.info  │ http://actum… │ https://a… │ … │ false       │ <empty>  │
│ 3 │ 2012un-Nouve… │ http://2012u… │ http://ww… │ … │ false       │ <empty>  │
│ 4 │ 24heuresactu… │ http://24heu… │ http://24… │ … │ false       │ <empty>  │
│ 5 │ AgoraVox      │ http://agora… │ http://ww… │ … │ false       │ <empty>  │
│ 6 │ Al-Kanz.org   │ http://al-ka… │ https://w… │ … │ false       │ <empty>  │
│ 7 │ Alalumieredu… │ http://alalu… │ http://al… │ … │ false       │ <empty>  │
│ 8 │ Allodocteurs… │ http://allod… │ https://w… │ … │ false       │ <empty>  │
│ 9 │ Alterinfo.net │ http://alter… │ http://ww… │ … │ <empty>     │ true     │
│ … │ …             │ …             │ …          │ … │ …           │ …        │
└───┴───────────────┴───────────────┴────────────┴───┴─────────────┴──────────┘

On unix, don't hesitate to use the -p flag to automagically forward the full output to an appropriate pager and skim through all the columns.

Reading a flattened representation of the first row

# NOTE: drop -c to avoid truncating the values
xan flatten -c medias.csv
Row n°0
───────────────────────────────────────────────────────────────────────────────
webentity_id                      1
name                              Acrimed.org
prefixes                          http://acrimed.org|http://acrimed69.blogspot…
home_page                         http://www.acrimed.org
start_pages                       http://acrimed.org|http://acrimed69.blogspot…
indegree                          61
hyphe_creation_timestamp          1560347020330
hyphe_last_modification_timestamp 1560526005389
outreach                          nationale
foundation_year                   2002
batch                             1
edito                             media
parody                            false
origin                            france
digital_native                    true
mediacloud_ids                    258269
wheel_category                    Opinion Journalism
wheel_subcategory                 Left Wing
has_paywall                       false
inactive                          <empty>

Row n°1
───────────────────────────────────────────────────────────────────────────────
webentity_id                      2
...

Searching for rows

xan search -s outreach internationale medias.csv | xan view
Displaying 4/20 cols from 10 first rows of <stdin>
┌───┬──────────────┬────────────────────┬───┬─────────────┬──────────┐
│ - │ webentity_id │ name               │ … │ has_paywall │ inactive │
├───┼──────────────┼────────────────────┼───┼─────────────┼──────────┤
│ 0 │ 25           │ Businessinsider.fr │ … │ false       │ <empty>  │
│ 1 │ 59           │ Europe-Israel.org  │ … │ false       │ <empty>  │
│ 2 │ 66           │ France 24          │ … │ false       │ <empty>  │
│ 3 │ 220          │ RFI                │ … │ false       │ <empty>  │
│ 4 │ 231          │ fr.Sott.net        │ … │ false       │ <empty>  │
│ 5 │ 246          │ Voltairenet.org    │ … │ true        │ <empty>  │
│ 6 │ 254          │ Afp.com /fr        │ … │ false       │ <empty>  │
│ 7 │ 265          │ Euronews FR        │ … │ false       │ <empty>  │
│ 8 │ 333          │ Arte.tv            │ … │ false       │ <empty>  │
│ 9 │ 341          │ I24News.tv         │ … │ false       │ <empty>  │
│ … │ …            │ …                  │ … │ …           │ …        │
└───┴──────────────┴────────────────────┴───┴─────────────┴──────────┘

Selecting some columns

xan select foundation_year,name medias.csv | xan view
Displaying 2 cols from 10 first rows of <stdin>
┌───┬─────────────────┬───────────────────────────────────────┐
│ - │ foundation_year │ name                                  │
├───┼─────────────────┼───────────────────────────────────────┤
│ 0 │ 2002            │ Acrimed.org                           │
│ 1 │ 2006            │ 24matins.fr                           │
│ 2 │ 2013            │ Actumag.info                          │
│ 3 │ 2012            │ 2012un-Nouveau-Paradigme.com          │
│ 4 │ 2010            │ 24heuresactu.com                      │
│ 5 │ 2005            │ AgoraVox                              │
│ 6 │ 2008            │ Al-Kanz.org                           │
│ 7 │ 2012            │ Alalumieredunouveaumonde.blogspot.com │
│ 8 │ 2005            │ Allodocteurs.fr                       │
│ 9 │ 2005            │ Alterinfo.net                         │
│ … │ …               │ …                                     │
└───┴─────────────────┴───────────────────────────────────────┘

Sorting the file

xan sort -s foundation_year medias.csv | xan view -s name,foundation_year
Displaying 2 cols from 10 first rows of <stdin>
┌───┬────────────────────────────────────┬─────────────────┐
│ - │ name                               │ foundation_year │
├───┼────────────────────────────────────┼─────────────────┤
│ 0 │ Le Monde Numérique (Ouest France)  │ <empty>         │
│ 1 │ Le Figaro                          │ 1826            │
│ 2 │ Le journal de Saône-et-Loire       │ 1826            │
│ 3 │ L'Indépendant                      │ 1846            │
│ 4 │ Le Progrès                         │ 1859            │
│ 5 │ La Dépêche du Midi                 │ 1870            │
│ 6 │ Le Pélerin                         │ 1873            │
│ 7 │ Dernières Nouvelles d'Alsace (DNA) │ 1877            │
│ 8 │ La Croix                           │ 1883            │
│ 9 │ Le Chasseur Francais               │ 1885            │
│ … │ …                                  │ …               │
└───┴────────────────────────────────────┴─────────────────┘

Deduplicating the file on some column

# Some medias of our corpus have the same ids on mediacloud.org
xan dedup -s mediacloud_ids medias.csv | xan count && xan count medias.csv
457
478

Deduplicating can also be done while sorting:

xan sort -s mediacloud_ids -u medias.csv

Computing frequency tables

xan frequency -s edito medias.csv | xan view
Displaying 3 cols from 5 rows of <stdin>
┌───┬───────┬────────────┬───────┐
│ - │ field │ value      │ count │
├───┼───────┼────────────┼───────┤
│ 0 │ edito │ media      │ 423   │
│ 1 │ edito │ individu   │ 30    │
│ 2 │ edito │ plateforme │ 14    │
│ 3 │ edito │ agrégateur │ 10    │
│ 4 │ edito │ agence     │ 1     │
└───┴───────┴────────────┴───────┘

Printing a histogram

xan frequency -s edito medias.csv | xan hist
Histogram for edito (bars: 5, sum: 478, max: 423):

media      |423  88.49%|━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━|
individu   | 30   6.28%|━━━╸                                                  |
plateforme | 14   2.93%|━╸                                                    |
agrégateur | 10   2.09%|━╸                                                    |
agence     |  1   0.21%|╸                                                     |

Computing descriptive statistics

xan stats -s indegree,edito medias.csv | xan transpose | xan view -I
Displaying 2 cols from 14 rows of <stdin>
┌─────────────┬───────────────────┬────────────┐
│ field       │ indegree          │ edito      │
├─────────────┼───────────────────┼────────────┤
│ count       │ 463               │ 478        │
│ count_empty │ 15                │ 0          │
│ type        │ int               │ string     │
│ types       │ int|empty         │ string     │
│ sum         │ 25987             │ <empty>    │
│ mean        │ 56.12742980561554 │ <empty>    │
│ variance    │ 4234.530197929737 │ <empty>    │
│ stddev      │ 65.07326792108829 │ <empty>    │
│ min         │ 0                 │ <empty>    │
│ max         │ 424               │ <empty>    │
│ lex_first   │ 0                 │ agence     │
│ lex_last    │ 99                │ plateforme │
│ min_length  │ 0                 │ 5          │
│ max_length  │ 3                 │ 11         │
└─────────────┴───────────────────┴────────────┘

Evaluating an expression to filter a file

xan filter 'batch > 1' medias.csv | xan count
130

To access the expression language's cheatsheet, run xan help cheatsheet. To display the full list of available functions, run xan help functions.

Evaluating an expression to create a new column based on other ones

xan map 'fmt("{} ({})", name, foundation_year) as key' medias.csv | xan select key | xan slice -l 10
key
Acrimed.org (2002)
24matins.fr (2006)
Actumag.info (2013)
2012un-Nouveau-Paradigme.com (2012)
24heuresactu.com (2010)
AgoraVox (2005)
Al-Kanz.org (2008)
Alalumieredunouveaumonde.blogspot.com (2012)
Allodocteurs.fr (2005)
Alterinfo.net (2005)

To access the expression language's cheatsheet, run xan help cheatsheet. To display the full list of available functions, run xan help functions.

Transform a column by evaluating an expression

xan transform name 'split(name, ".") | first | upper' medias.csv | xan select name | xan slice -l 10
name
ACRIMED
24MATINS
ACTUMAG
2012UN-NOUVEAU-PARADIGME
24HEURESACTU
AGORAVOX
AL-KANZ
ALALUMIEREDUNOUVEAUMONDE
ALLODOCTEURS
ALTERINFO

To access the expression language's cheatsheet, run xan help cheatsheet. To display the full list of available functions, run xan help functions.

Performing custom aggregation

xan agg 'sum(indegree) as total_indegree, mean(indegree) as mean_indegree' medias.csv | xan view -I
Displaying 1 col from 1 rows of <stdin>
┌────────────────┬───────────────────┐
│ total_indegree │ mean_indegree     │
├────────────────┼───────────────────┤
│ 25987          │ 56.12742980561554 │
└────────────────┴───────────────────┘

To access the expression language's cheatsheet, run xan help cheatsheet. To display the full list of available functions, run xan help functions. Finally, to display the list of available aggregation functions, run xan help aggs.

Grouping rows and performing per-group aggregation

xan groupby edito 'sum(indegree) as indegree' medias.csv | xan view -I
Displaying 1 col from 5 rows of <stdin>
┌────────────┬──────────┐
│ edito      │ indegree │
├────────────┼──────────┤
│ agence     │ 50       │
│ agrégateur │ 459      │
│ plateforme │ 658      │
│ media      │ 24161    │
│ individu   │ 659      │
└────────────┴──────────┘

To access the expression language's cheatsheet, run xan help cheatsheet. To display the full list of available functions, run xan help functions. Finally, to display the list of available aggregation functions, run xan help aggs.

Learning

If you speak French, here is a quick rundown of the tool by our friends from CERES.

Documented use-cases

For a sense of what can be achieved with xan, see this page summarizing a variety of complex but detailed pipelines that have been used in real-life by real people to solve their problems, using the tool: PIPELINES.

Available commands

  • help: Get help regarding the expression language

Explore & visualize

  • count (c): Count rows in file
  • headers (h): Show header names
  • view (v): Preview a CSV file in a human-friendly way
  • flatten: Display a flattened version of each row of a file
  • hist: Print a histogram with rows of CSV file as bars
  • plot: Draw a scatter plot or line chart
  • heatmap: Draw a heatmap of a CSV matrix
  • spark: Draw ascii sparklines (e.g. ▇▅▄▃▂▃) from CSV data
  • progress: Display a progress bar while reading CSV data

Search & filter

  • search: Search for (or replace) patterns in CSV data
  • filter: Only keep some CSV rows based on an evaluated expression
  • head: First rows of CSV file
  • tail: Last rows of CSV file
  • slice: Slice rows of CSV file
  • top: Find top rows of a CSV file according to some column
  • sample: Randomly sample CSV data
  • bisect: Binary search on sorted CSV data

Sort & deduplicate

Aggregate

  • frequency (freq): Show frequency tables
  • groupby: Aggregate data by groups of a CSV file
  • stats: Compute basic statistics
  • agg: Aggregate data from CSV file
  • bins: Dispatch numeric columns into bins
  • window: Compute window aggregations (cumsum, rolling mean, lag etc.)

Combine multiple CSV files

  • cat: Concatenate by row or column
  • join: Join CSV files
  • merge: Merge multiple similar already sorted CSV files

Add, transform, drop and move columns

  • select: Select columns from a CSV file
  • drop: Drop columns from a CSV file
  • map: Create a new column by evaluating an expression on each CSV row
  • transform: Transform a column by evaluating an expression on each CSV row
  • enum: Enumerate CSV file by preprending an index column
  • fill: Fill empty cells
  • complete: Add missing rows in a column of contiguous values
  • blank: Blank down contiguous identical cell values
  • separate: Split a single column into multiple ones

Format, convert & recombobulate

  • behead: Drop header from CSV file
  • rename: Rename columns of a CSV file
  • input: Read unusually formatted CSV data
  • fixlengths: Makes all rows have same length
  • fmt: Format CSV output (change field delimiter)
  • explode: Explode rows based on some column separator
  • implode: Collapse consecutive identical rows based on a diverging column
  • from: Convert a variety of formats to CSV
  • to: Convert a CSV file to a variety of data formats
  • scrape: Scrape HTML into CSV data
  • reverse: Reverse rows of CSV data

Transpose & pivot

  • transpose (t): Transpose CSV file
  • pivot: Split distinct values of a column into their own columns columns
  • unpivot: Stack multiple columns into fewer

Split a CSV file into multiple

  • split: Split CSV data into chunks
  • partition: Partition CSV data based on a column value

Parallelization

Generate CSV files

  • range: Create a CSV file from a numerical range

Lexicometry & fuzzy matching

  • tokenize: Tokenize a text column
  • vocab: Build a vocabulary over tokenized documents

Matrix & network-related commands

  • matrix: Convert CSV data to matrix data
  • network: Convert CSV data to network data

Scripting

  • run: Run a xan pipeline or script
  • eval: Evaluate/debug a single expression

General flags and IO model

Getting help

If you ever feel lost, each command has a -h/--help flag that will print the related documentation.

If you need help about the expression language, check out the help command itself:

# Help about help ;)
xan help --help

Regarding input & output formats

All xan commands expect a "standard" CSV file, e.g. comma-delimited, with proper double-quote escaping. This said, xan is also perfectly able to infer the delimiter from typical file extensions such as .tsv, .tab, .psv, .ssv or .scsv.

If you need to process a file with a custom delimiter, you can either use the xan input command or use the -d/--delimiter flag available with all commands.

If you need to output a custom CSV dialect (e.g. using ; delimiters), feel free to use the xan fmt command.

If your CSV file has a varying number of columns per row, use the xan fixlengths command before piping into other commands as xan expects well-behaved CSV data where rows all have the same number of columns.

Finally, even if most xan commands won't even need to decode the file's bytes, some might still need to. In this case, xan will expect correctly formatted UTF-8 text. Please use iconv or other utils if you need to process other encodings such as latin1 ahead of xan.

Working with headless CSV file

Even if this is good practice to name your columns, some CSV file simply don't have headers. Most commands are able to deal with those file if you give the -n/--no-headers flag.

Note that this flag always relates to the input, not the output. If for some reason you want to drop a CSV output's header row, use the xan behead command.

Regarding stdin

By default, all commands will try to read from stdin when the file path is not specified. This makes piping easy and comfortable as it respects typical unix standards. Some commands may have multiple inputs (xan join, for instance), in which case stdin is usually specifiable using the - character:

# First file given to join will be read from stdin
cat file1.csv | xan join col1 - col2 file2.csv

Note that the command will also warn you when stdin cannot be read, in case you forgot to indicate the file's path.

Regarding stdout

By default, all commands will print their output to stdout (note that this output is usually buffered for performance reasons).

In addition, all commands expose a -o/--output flag that can be use to specify where to write the output. This can be useful if you do not want to or cannot use > (typically in some Windows shells). In which case, - as a output path will mean forwarding to stdout also. This can be useful when scripting sometimes.

Supported file formats

xan is able to process a large variety of CSV-adjacent data formats out-of-the box:

  • .csv files will be understood as comma-separated
  • .tsv & .tab files will be understood as tab-separated
  • .scsv & .ssv files will be understood as semicolon-separated
  • .psv files will be understood as pipe-separated
  • .cdx files (an index file format related to web archive) will be understood as space-separated and will have its magic bytes dropped
  • .ndjson & .jsonl files will be understood as tab-separated, headless, null-byte-quoted, so you can easily use them with xan commands (e.g. parsing or wrangling JSON data using the expression language to aggregate, even in parallel). If you need a more thorough conversion of newline-delimited JSON data, check out the xan from -f ndjson command instead.
  • .vcf files (Variant Call Format) from bioinformatics are supported out of the box. They will be stripped of their header data and considered as tab-delimited.
  • .gtf & .gff2 files (Gene Transfert Format) from bioinformatics are supported out of the box. They will be stripped of their header data and considered as headless & tab-delimited.
  • .sam files (Sequence Alignment Map) from bioinformatics are supported out of the box. They will be stripped of their header data and considered as headless & tab-delimited.
  • .bed files (Browser Extensible Data) from bioinformatics are supported out of the box. They will be stripped of their header data and considered as headless & tab-delimited.

Note that more exotic delimiters can always be handled using the ubiquitous -d, --delimiter flag.

Some additional formats (e.g. .gff, .gff3) are also supported but must first be normalized using the xan input command because their cells must be trimmed or because they have comment lines to be skipped.

Note also that UTF-8 BOMs ara always stripped from the data when processed.

Compressed files

xan is able to read gzipped files (having a .gz extension). It is also able to leverage .gzi indices (usually created through bgzip) when seeking is necessary (constant time reversing, parallelization etc.).

xan is also able to read files compressed with Zstdandard (having a .zst extension).

Regarding color

Some xan commands print ANSI colors in the terminal by default, typically view, flatten, etc.

All those commands have a standard --color=(auto|always|never) flag to tweak the colouring behavior if you need it (note that colors are not printed when commands are piped, by default).

They also respect typical environment variables related to ANSI colouring, such as NO_COLOR, CLICOLOR & CLICOLOR_FORCE, as documented here.

Also, note that some xan commands (xan heatmap & xan spark notably) require a terminal able to display truecolor (24bits) ANSI colors (at least if you want them to be able to print continuous color gradients).

Sometimes you might want to explicitly set the COLORTERM env variable to truecolor, if you know your terminal supports them but your shell does not know it (e.g. sometimes when using screen, tmux or ssh).

Expression language reference

News

For news about the tool's evolutions feel free to read:

  1. the changelog
  2. the xan zines
  3. the roadmap

See also blog posts related to the tool:

How to cite?

xan is published on Zenodo as 10.5281/zenodo.15310200.

You can cite it thusly:

Guillaume Plique, Béatrice Mazoyer, Laura Miguel, César Pichon, Anna Charles, & Julien Pontoire. (2025). xan, the CSV magician. (0.50.0). Zenodo. https://doi.org/10.5281/zenodo.15310200

Frequently Asked Questions

How to display a vertical bar chart?

Rotate your screen ;)

View on GitHub

Recent activity

commits and pull requests

Recent open issues

view all

Discussions

all 2

Releases and announcements

39 total
  1. v0.60.00.60.0Jul 10, 20261.6K downloads

    *Breaking* * Renaming `xan from --path` to `--root`. * Renaming `xan separate -T/--txt` to `-L/--lines`. *Features* * Adding `xan count -c/--check-alignment & -H/--human-readable`. * Adding `xan sort -e -z/--compress`. * Adding `xan sample -g -S/--sorted`. * Adding `xan from -f=(json|ndjson) --model`. * Adding `xan cat rows -I/--intersection & -U/--union`. * Adding `xan top -g -S/--sorted`. * Adding the `sort`, `dedup`, `flatten` & `flat_map` moonblade function. * Adding support for `list` & `map` columns when using `xan from -f=parquet`. *Fixes* * Fixing text wrapping across tool, especially `xan flatten -w` & `xan flatten -F`. * Fixing `xan select -e` & `xan map` plural clause flattening given list. * Fixing `xan from -f=parquet` not emitting correct column names for list & map columns. *Performance* * Introducing a fast path for `xan sort -e` when input fits in a single chunk. * Faster `xan from -f=ndjson & -f=parquet`. * Amortizing `xan sample` allocations. * Improving performance of `xan freq` & `xan p freq`. *Quality of Life* * Better record size estimation for `xan sort -e`. * Better `xan flatten -c` when string width cannot be computed correctly (because of emojis

  2. v0.60.0-rc.10.60.0-rc.1Jun 26, 2026pre-release30 downloads
  3. v0.59.00.59.0Jun 17, 20263.3K downloads

    *Breaking* * Bumping MSRV to `1.85.0` and edition 2024. * Overhauling how `xan scrape` takes its inputs. It now targets HTML files on disk by default now. * `xan plot --density-scale` now defaults to `log`. * `xan freq -X/--approx-algo` & `xan p freq -X/--approx-algo` now default to `heavy-keeper`. * Dropping `xan eval -S/--serialize`. The default behavior of the command is now to output the serialized value. *Features* * Adding `xan search -x/--pattern-file`. * Adding `xan cat --glob`, `xan merge --glob`, `xan parallel --glob`. * Adding the `hostname` moonblade function. * Adding `xan scrape --paths, --path-column, --docs, --docs-column, -D/--stdin-doc & --glob`. * Adding `xan from -f=(json|ndjson) --path <path>`. * Adding `xan from -f toml` & `-f raw`. * Adding `xan spark --hide-all & --repeat-x-axis`. *Fixes* * Fixing moonblade string with bstring equality. * Fixing percentages shown by `xan spark -P`. * Fixing `xan complete` correctness in presence of duplicate values. * Fixing `xan spark -c` discretization & legend. *Performance* * Improving performance of `xan scrape`. * Improving performance of `xan from -f ndjson`. *Quality of Life* * Better legends & axis for `xan

  4. v0.59.0-rc.10.59.0-rc.1Jun 16, 2026pre-release33 downloads
  5. v0.58.00.58.0Jun 2, 20261.6K downloads

    *Breaking* * Stopping to serialize moonblade lists either as joined by some separator or JSON. This was awkard, error-prone & potentially lossy. Use the `join` function manually to format output when required. * As per previous point, dropping `xan scrape --sep`. * Dropping implicit unary function calls in moonblade pipelines. This feature was not well-known, confusing (an indentifier, could be understood as a call in a pipeline, only if not in first position...), and mostly useless now that moonblade has had a proper dot operator. * `xan plot -A/--aggregate` does not take an expression anymore but has an automatic selection of two modes: `sum` and `mean`. It should also be faster. * Renaming the `index` function as `row_index` for clarity. * `xan agg -C/--along-columns & -M/--along-matrix` & `xan groupby -C/--along-columns & -M/--along-matrix` will not map current column index to the result of the `index()` function. The `col_index()` can be now used instead for this very purpose. * `xan window -g/--groupby` does not require the file to be sorted anymore. This means using `-g/--groupby` will now require the whole file to be buffered into memory by the command. The old behavior ca

Commits per week

last 52 weeks
800Week of 2025-08-10: 0 commitsWeek of 2025-08-17: 1 commitsWeek of 2025-08-24: 0 commitsWeek of 2025-08-31: 15 commitsWeek of 2025-09-07: 0 commitsWeek of 2025-09-14: 6 commitsWeek of 2025-09-21: 3 commitsWeek of 2025-09-28: 6 commitsWeek of 2025-10-05: 11 commitsWeek of 2025-10-12: 31 commitsWeek of 2025-10-19: 48 commitsWeek of 2025-10-26: 41 commitsWeek of 2025-11-02: 17 commitsWeek of 2025-11-09: 20 commitsWeek of 2025-11-16: 11 commitsWeek of 2025-11-23: 14 commitsWeek of 2025-11-30: 0 commitsWeek of 2025-12-07: 0 commitsWeek of 2025-12-14: 9 commitsWeek of 2025-12-21: 2 commitsWeek of 2025-12-28: 0 commitsWeek of 2026-01-04: 0 commitsWeek of 2026-01-11: 0 commitsWeek of 2026-01-18: 0 commitsWeek of 2026-01-25: 2 commitsWeek of 2026-02-01: 22 commitsWeek of 2026-02-08: 22 commitsWeek of 2026-02-15: 25 commitsWeek of 2026-02-22: 4 commitsWeek of 2026-03-01: 2 commitsWeek of 2026-03-08: 0 commitsWeek of 2026-03-15: 23 commitsWeek of 2026-03-22: 48 commitsWeek of 2026-03-29: 61 commitsWeek of 2026-04-05: 17 commitsWeek of 2026-04-12: 16 commitsWeek of 2026-04-19: 43 commitsWeek of 2026-04-26: 59 commitsWeek of 2026-05-03: 56 commitsWeek of 2026-05-10: 80 commitsWeek of 2026-05-17: 29 commitsWeek of 2026-05-24: 22 commitsWeek of 2026-05-31: 17 commitsWeek of 2026-06-07: 39 commitsWeek of 2026-06-14: 30 commitsWeek of 2026-06-21: 1 commitsWeek of 2026-06-28: 20 commitsWeek of 2026-07-05: 11 commitsWeek of 2026-07-12: 0 commitsWeek of 2026-07-19: 1 commitsWeek of 2026-07-26: 4 commitsWeek of 2026-08-02: 0 commitsAug 10, 2025Aug 2, 2026
889 commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 14 commitsSun 1:00 — 8 commitsSun 2:00 — 0 commitsSun 3:00 — 0 commitsSun 4:00 — 0 commitsSun 5:00 — 0 commitsSun 6:00 — 0 commitsSun 7:00 — 0 commitsSun 8:00 — 2 commitsSun 9:00 — 11 commitsSun 10:00 — 8 commitsSun 11:00 — 14 commitsSun 12:00 — 13 commitsSun 13:00 — 20 commitsSun 14:00 — 13 commitsSun 15:00 — 24 commitsSun 16:00 — 13 commitsSun 17:00 — 7 commitsSun 18:00 — 3 commitsSun 19:00 — 5 commitsSun 20:00 — 18 commitsSun 21:00 — 17 commitsSun 22:00 — 3 commitsSun 23:00 — 0 commitsMon 0:00 — 0 commitsMon 1:00 — 0 commitsMon 2:00 — 0 commitsMon 3:00 — 0 commitsMon 4:00 — 0 commitsMon 5:00 — 0 commitsMon 6:00 — 0 commitsMon 7:00 — 0 commitsMon 8:00 — 0 commitsMon 9:00 — 3 commitsMon 10:00 — 39 commitsMon 11:00 — 64 commitsMon 12:00 — 10 commitsMon 13:00 — 36 commitsMon 14:00 — 73 commitsMon 15:00 — 55 commitsMon 16:00 — 61 commitsMon 17:00 — 73 commitsMon 18:00 — 24 commitsMon 19:00 — 16 commitsMon 20:00 — 21 commitsMon 21:00 — 30 commitsMon 22:00 — 23 commitsMon 23:00 — 1 commitsTue 0:00 — 2 commitsTue 1:00 — 0 commitsTue 2:00 — 1 commitsTue 3:00 — 0 commitsTue 4:00 — 1 commitsTue 5:00 — 0 commitsTue 6:00 — 1 commitsTue 7:00 — 0 commitsTue 8:00 — 0 commitsTue 9:00 — 7 commitsTue 10:00 — 23 commitsTue 11:00 — 64 commitsTue 12:00 — 13 commitsTue 13:00 — 17 commitsTue 14:00 — 56 commitsTue 15:00 — 57 commitsTue 16:00 — 75 commitsTue 17:00 — 111 commitsTue 18:00 — 22 commitsTue 19:00 — 7 commitsTue 20:00 — 17 commitsTue 21:00 — 19 commitsTue 22:00 — 18 commitsTue 23:00 — 4 commitsWed 0:00 — 0 commitsWed 1:00 — 0 commitsWed 2:00 — 0 commitsWed 3:00 — 0 commitsWed 4:00 — 1 commitsWed 5:00 — 0 commitsWed 6:00 — 0 commitsWed 7:00 — 1 commitsWed 8:00 — 0 commitsWed 9:00 — 6 commitsWed 10:00 — 50 commitsWed 11:00 — 96 commitsWed 12:00 — 27 commitsWed 13:00 — 52 commitsWed 14:00 — 34 commitsWed 15:00 — 60 commitsWed 16:00 — 85 commitsWed 17:00 — 122 commitsWed 18:00 — 33 commitsWed 19:00 — 7 commitsWed 20:00 — 5 commitsWed 21:00 — 16 commitsWed 22:00 — 20 commitsWed 23:00 — 3 commitsThu 0:00 — 0 commitsThu 1:00 — 0 commitsThu 2:00 — 0 commitsThu 3:00 — 0 commitsThu 4:00 — 2 commitsThu 5:00 — 0 commitsThu 6:00 — 1 commitsThu 7:00 — 1 commitsThu 8:00 — 7 commitsThu 9:00 — 19 commitsThu 10:00 — 51 commitsThu 11:00 — 57 commitsThu 12:00 — 27 commitsThu 13:00 — 41 commitsThu 14:00 — 88 commitsThu 15:00 — 66 commitsThu 16:00 — 85 commitsThu 17:00 — 67 commitsThu 18:00 — 37 commitsThu 19:00 — 17 commitsThu 20:00 — 21 commitsThu 21:00 — 23 commitsThu 22:00 — 16 commitsThu 23:00 — 6 commitsFri 0:00 — 8 commitsFri 1:00 — 1 commitsFri 2:00 — 1 commitsFri 3:00 — 0 commitsFri 4:00 — 0 commitsFri 5:00 — 0 commitsFri 6:00 — 0 commitsFri 7:00 — 0 commitsFri 8:00 — 2 commitsFri 9:00 — 14 commitsFri 10:00 — 57 commitsFri 11:00 — 87 commitsFri 12:00 — 34 commitsFri 13:00 — 30 commitsFri 14:00 — 70 commitsFri 15:00 — 80 commitsFri 16:00 — 79 commitsFri 17:00 — 80 commitsFri 18:00 — 34 commitsFri 19:00 — 5 commitsFri 20:00 — 10 commitsFri 21:00 — 17 commitsFri 22:00 — 12 commitsFri 23:00 — 10 commitsSat 0:00 — 3 commitsSat 1:00 — 1 commitsSat 2:00 — 0 commitsSat 3:00 — 0 commitsSat 4:00 — 0 commitsSat 5:00 — 0 commitsSat 6:00 — 1 commitsSat 7:00 — 0 commitsSat 8:00 — 1 commitsSat 9:00 — 4 commitsSat 10:00 — 13 commitsSat 11:00 — 10 commitsSat 12:00 — 9 commitsSat 13:00 — 14 commitsSat 14:00 — 18 commitsSat 15:00 — 21 commitsSat 16:00 — 21 commitsSat 17:00 — 9 commitsSat 18:00 — 5 commitsSat 19:00 — 2 commitsSat 20:00 — 11 commitsSat 21:00 — 20 commitsSat 22:00 — 19 commitsSat 23:00 — 5 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.
DateListRankStars gained
Jul 11, 2026daily#16+2
  • ultraworkers/claw-code

    An agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.

    195K stars · Rust

  • ultraworkers/claw-code

    An agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.

    194.9K stars · Rust

  • ultraworkers/claw-code

    An agent-managed museum exhibit, built in Rust with Gajae-Code / LazyCodex — developed and maintained with no human intervention.

    194.9K stars · Rust

  • yt-dlp/yt-dlp

    A feature-rich command-line audio/video downloader

    183K stars · Python

  • farion1231/cc-switch

    A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io

    125.4K stars · Rust

  • denoland/deno

    A modern runtime for JavaScript and TypeScript.

    108.2K stars · Rust