CLI tool
saulpw/visidata avatar
saulpw/visidata

VisiData splits format support across optional dependencies you never installed

A terminal spreadsheet multitool for discovering and arranging data

9,471 stars378 forksPythonGPL-3.0

At a glance

What is it?
A terminal spreadsheet for tsv, csv, sqlite, json, xlsx, and hdf5 where only python-dateutil is an unconditional requirement and many formats need an opt-in package. The recurring failure is not a broken loader, it is a vd on your PATH running from a different environment than the one you installed into.
Who is it for?
VisiData suits someone who lives in a terminal and wants to reshape CSVs, spreadsheets, SQLite, and HDF5 without a mouse, and who is comfortable adding Python packages as formats demand them.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • saulpw/visidata9,471 ★ · +179
Star history
Repository2026-09-222026-11-14
saulpw/visidata9.3k9.5k

179 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Every install path costs something different

Five routes are documented and they are not interchangeable. A plain PyPi install puts the package into whichever interpreter pip3 belongs to. The throwaway route runs the tool without installing anything, which is the fastest way to look at a file and the worst way to keep it. A permanent pipx install adds vd to your PATH in an isolated environment of its own. Format packages have to be requested at install time or injected afterwards, and the develop branch is a direct git install carrying an explicit no warranty note.

code
pip3 install visidata
code
pipx run visidata          # or: uvx visidata
code
pipx install visidata      # or: uv tool install visidata
code
pipx install visidata --preinstall openpyxl --preinstall lxml
# or: uv tool install visidata --with openpyxl --with lxml
code
pipx inject visidata openpyxl lxml
code
pip3 install git+https://github.com/saulpw/visidata.git@develop

A package X not installed message usually means the wrong interpreter

This is the failure to recognise first. If VisiData reports package X not installed after you installed it, the stated cause is almost never a bad install. The vd on your PATH is running from a different environment than the one you installed the package into. The prescribed diagnostic is to check which vd and then install into that environment, using pipx inject for a pipx install or the Homebrew Python for a brew install of VisiData. For a reader this reframes the error entirely: chasing a broken loader or a corrupt archive wastes time, because the archive is fine and the interpreter is wrong. Two other constraints bound the same run. Platforms are Linux, OS/X, or Windows with WSL, and the Python floor is 3.8.

requirements.txt is a catalogue of formats, not an install list

The hard requirement set is three entries, and only one of them is unconditional. Everything else in requirements.txt is commented as optional, and each line names the format it covers, which makes that file the closest thing the project has to a supported format matrix. openpyxl covers xlsx, xlrd and xlwt cover xls, h5py covers hdf5, psycopg2-binary covers postgres, boto3 covers rds, pyshp covers shapefiles, and so on through pdf, vcf, Arrow parquet, GeoParquet, ODS, and the .zst readers. setup.py reads requirements.txt to compute the dependency list but the actual install_requires block stays narrow, so formats such as xlsx and hdf5 need their optional packages installed separately.

code
install_requires = [
    "python-dateutil",
    'importlib_resources; python_version<"3.9"',
    'standard-mailcap; python_version>="3.13"',
]

Environment markers split the dependencies at 3.7, 3.9, 3.11, and 3.13

The marker expressions mean two people on the documented 3.8 floor do not get the same packages. pandas is requested at one floor on Python 3.11 and newer and at a lower floor below it, both times annotated as the Stata reader. tomli is pulled in only below 3.11, backports.zoneinfo only below 3.9, and importlib_resources only below 3.9 as well, matching the older-Python branch in install_requires. At the other end standard-mailcap is added only on 3.13 and newer. There is also a dead branch: pyarrow_hotfix and a bare pyarrow are gated on Python 3.7 and older, which no supported interpreter can satisfy given the stated 3.8 minimum. Reading the marker column before you debug an import error saves time.

code
pandas>=1.5.3; python_version >= '3.11' # dta (Stata)
pandas>=1.0.5; python_version < '3.11'  # dta (Stata)
pyarrow>=14.0.1; python_version >= '3.8' # arrow arrows parquet (Apache Arrow)
pyarrow_hotfix; python_version <= '3.7' # pyarrow security patch

Man pages became a hard packaging requirement after a bad v3.4 sdist

The build script carries a scar. It defines three expected man page files under visidata/man/, checks for them, and if they are missing shells out to dev/mkman.sh. If generation fails you get a printed warning and a package built without man pages, which was the old behaviour. The sdist command class was then changed to hard fail, with an inline note that a v3.4 sdist silently shipped without man pages. Now a missing man page aborts the build with an explicit instruction to install groff and man-db and rerun. For someone building from source that turns a silent packaging defect into a visible build error, and it also means the man page tooling, groff and man-db, is a prerequisite rather than a nicety.

code
raise SystemExit('man pages required for sdist; install groff and man-db and rerun')

The default branch is develop, but the GPLv3 grant names the stable branch

Two different branches are in play and the licensing sentence only covers one. The repository default branch is develop, which is also the branch named in the git install command. The license statement says code in the stable branch, including the main vd application, loaders, and plugins, is available for use and redistribution under GPLv3. It says nothing about develop. On versions, the README announces v3.5, setup.py declares 3.5, and the release history runs v3.5 on 2026-10-28, v3.4 on 2026-07-01, and v3.3 described as bugfixes mostly on 2025-09-08. If you are redistributing, resolve the branch question before you package, not after.

Batch tests replay recorded sessions through the vgit layer

The test surface is not a unit test suite you point at a file. A single target runs a shell script covering everything, while a dedicated vgit target drives the running application itself, pointing vd at a configuration file in tests/ and replaying recorded session files under visidata/apps/vgit/tests/ in batch mode with no prompts. A separate target cds into the vdsql app and runs its own script. Alongside those, make check runs the ruff linter and the pyright type checker together, and a diff-test target reports what changed since the last run. The helper targets configure the working tree as well, pointing git at dev/hooks and copying devcontainer configs into .vscode/. Install variants exist too: a plain pip3 install, an editable install with dev requirements, and extras-based installs for test and for all optional dependencies.

code
test-vgit:
	vd --config tests/.visidatarc -p visidata/apps/vgit/tests/*.vdx --batch

Windows support runs through WSL, so the file layer is Linux

The platform line is short and has a consequence attached. Supported systems are Linux, OS/X, and Windows with WSL, which means a Windows install is a Linux environment rather than a native port. That matters for the format list because the optional packages are ordinary Python wheels chosen by interpreter version, and the interpreter on a WSL setup is a Linux one. It also matters for the environment mismatch described earlier: the Homebrew Python advice for a brew install assumes a Mac, and the pipx inject advice assumes the isolated environment pipx actually created. The interfaces you interact with are equally minimal, since input is opened by passing it as an argument or piping it in, and quitting is Ctrl+Q.

code
$ vd <input>
$ <command> | vd

Inside the running tool, Ctrl+H brings up the quick reference listing commands and options, which is faster than the online manual when you need one binding.

Editorial conclusion

VisiData suits someone who lives in a terminal and wants to reshape CSVs, spreadsheets, SQLite, and HDF5 without a mouse, and who is comfortable adding Python packages as formats demand them. Before you rely on it, confirm which environment your vd binary actually lives in with which vd, install the format packages into that same environment, and read the licensing line carefully because the GPLv3 grant is stated for the stable branch while the repository default branch is develop.

Frequently asked questions

How do I install Visidata?

Install the latest release from PyPi with pip3 install visidata. Supported platforms are Linux, OS/X, and Windows with WSL, and Python 3.8 or newer is required.

How can I install Visidata for formats that need extra packages?

Use pipx install visidata --preinstall openpyxl --preinstall lxml at install time, or add packages to an existing pipx install with pipx inject visidata openpyxl lxml. The uv equivalents are uv tool install visidata --with openpyxl --with lxml.

How do I use Visidata once it is installed?

Pass an input as an argument with vd <input>, or pipe another command's output in with <command> | vd. Press Ctrl+Q to quit at any time and Ctrl+H inside the tool for the quick reference of commands and options.

Official sources

  1. License: GPL-3.0
  2. Project website
  3. README
  4. Releases
  5. saulpw/visidata on GitHub
Community

Where developers are discussing it

Posts on Hacker News, dev.to and Lobsters that link to this repository, found by our scan of those communities. 0 in the last 30 days; newest first.

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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/saulpw-visidata.svg)](https://hysenlabs.com/projects/saulpw-visidata)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/saulpw-visidata.svg)](https://hysenlabs.com/projects/saulpw-visidata)

Was this useful?