# vex-tui: a spreadsheet that lives in the terminal

> vex is a Go program for reading, editing and profiling CSV and Excel files without leaving the keyboard, with an expression filter, a column profiler, a formula engine and chart export to PNG. Its formula coverage and chart pipeline are narrower than a real spreadsheet app, and the last push was on 2026-04-17.

**CodeOne45/vex-tui** — A beautiful, fast, and feature-rich terminal-based Excel and CSV viewer & editor built with Go.

- Repository: https://github.com/CodeOne45/vex-tui
- Stars: 945 · Forks: 42
- Language: Go
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/codeone45-vex-tui

## Why a terminal spreadsheet instead of a browser tab

The usual way to look at a CSV is to open it in a spreadsheet, which means a browser, a download, or a desktop app that fights the keyboard. vex is a Go program for the opposite case. It opens CSV and Excel files in the terminal, renders a grid with a status bar, and keeps every action on the keyboard with vim-style bindings.

That audience is specific: people working over SSH, people who want to poke at a file in a pipeline context, and teams that would rather not upload data to a web service. The file support listed is Excel (.xlsx, .xlsm, .xls) and CSV, with multiple sheets and format preservation on save, so a file opened as xlsx is written back as xlsx rather than silently downgraded to text.

The architecture behind that grid is visible in the module file. The program is built on the Charm stack: `github.com/charmbracelet/bubbletea` for the event loop, `bubbles` for widgets, and `lipgloss` for styling. Excel parsing goes through `github.com/xuri/excelize/v2`, and clipboard access through `github.com/atotto/clipboard`. The module path is `github.com/CodeOne45/vex-tui` and it requires Go 1.24.0 with a 1.24.5 toolchain. A compiled single binary, no runtime to install.

## Filtering by expression instead of by spreadsheet dialog

The filter is the feature that makes vex feel different from a text preview. Press `f`, type an expression, press Enter to apply, press Esc to clear. The documented expressions are deliberately small in number, which is the point.

A bare word such as `apple` matches rows containing that text, case-insensitively. `>1000` keeps rows where the current column is greater than 1000, `<=50.5` keeps rows at or below that value, and `=Canada` is an exact match that works for text or numbers.

Two details make it usable. Pressing Tab while typing toggles between searching the current column and all columns, so you can narrow quickly and then widen. The active filter is shown in the title bar with a marker and the expression, which matters when a filtered view looks complete. Esc clears the filter and the original data is always preserved in memory, so filtering is a view change, not a destructive operation on the rows.

The limitation is that this is a small expression language, not a query language. There is no AND, OR, or grouping syntax documented, and no way to filter on a computed formula result. If your filtering needs compound conditions, you will end up exporting and using something else.

## Column profiling on demand and live stats under the cursor

Press `W` and vex renders a column-by-column breakdown of the current dataset. The documentation compares this to `pandas.describe()` in a terminal, and the output shape is close to that idea: a table with one row per column.

Columns are auto-detected as number, text or mixed. For numeric columns you get sum, average, min and max; for text columns you get a unique count and a sample of values. The column currently under the cursor is highlighted in the profile, so you can move and re-read.

A second, quieter version of the same idea lives in the status bar. Whenever the cursor rests on a numeric column, the bar fills in automatically, with no selection required.

This is the feature that changes daily use. Moving down a column tells you its distribution without any extra keystroke, which is a good way to spot a stray zero or a column that was imported as text. Note that the text and mixed case does not get a full statistical treatment, so profiling a mostly-text sheet tells you less than profiling a numeric one.

## Chart export depends on a separate PNG tool

Select a range with `V`, press `v` and a chart viewer opens. The documented chart types are a bar chart that supports negative values, a line chart drawn with the Bresenham algorithm, a sparkline, and a pie chart with a legend. The bar chart is described as responsive in width and drawn with an unfilled track, and the line chart actually connects points rather than plotting them in isolation.

The export step is where the design gets interesting. Inside the chart viewer you press `p`, and the file is written next to your data file.

The rendering of that PNG is not done by vex itself. The README states that the export goes through `freeze` at github.com/charmbracelet/freeze, and that if `freeze` is not installed, vex shows the install command rather than failing quietly. So chart export has an external dependency that the Go module file does not list, because it is a separate binary, not a library.

That is a reasonable trade for a TUI application, since rendering a PNG from a terminal grid is not something a text renderer can do well. It also means the export path is the part of vex most likely to break in a new environment, and the file is written next to your data, which is worth knowing before you run it over a read-only mount.

## Building the binary when the install section is incomplete

The README on this repository is cut off right after the heading for installation, and the section for Homebrew never appears, so there is no documented one-line install to copy. The repository does contain an INSTALL.md file and a Makefile with working targets, and the Makefile is the more reliable source.

The build target compiles a binary named `vex` and stamps the version into it:

```
@go build -ldflags="-s -w -X main.version=$(VERSION)" -o $(BINARY_NAME) .
```

The `build-release` target adds `-trimpath` to the same build flags, and the `install` target depends on it and then runs:

```
@go install
```

The repository also carries a `run` target that builds and starts the program on `sample_data.csv`, which is a quick way to see the grid without supplying your own data.

Other useful targets are `test`, which runs the Go test suite with the race detector and coverage, `fmt` for `go fmt./...`, and `lint` for golangci-lint. A `release` target exists as well, and the repository has a `.goreleaser.yml`, so cross-platform binaries are produced by GoReleaser rather than by a shell script. Version detection for local builds falls back to `git describe --tags --always --dirty`, and to `2.0.2` when that fails, which is a hint that a shallow clone without tags will report a stale version string.

## Editing, formulas and the file formats vex will not open

The editing side is where the gaps show. You can edit cells with values or formulas, insert and delete rows and columns, copy and paste ranges, fill down or right, and apply a formula across a range with reference adjustment. Formulas recalculate on every edit. The function set is documented as fifteen or more built-ins, with SUM, AVERAGE and AVG, COUNT, MAX and MIN, IF, CONCAT and CONCATENATE, UPPER and LOWER, LEN, ROUND, and the math group ABS, SQRT and POWER. Arithmetic such as `=A1+B1` and `=C1*D1/E1` is supported too.

Fifteen functions is a short list compared with any spreadsheet application. There is no lookup function, no date handling, no text search, no conditional aggregation, and no pivot table in the documented feature list. Cells are typed as numbers, formulas or text, and the type drives the colouring.

CSV handling is the flexible part. The first line of every CSV is read and the most likely delimiter is picked from comma, semicolon, tab and pipe, and you can override it on the command line:

```bash
vex data.csv                   # auto-detect
vex data.csv -d ';'            # semicolon
vex data.tsv -d '\t'           # tab
vex data.csv --delimiter '|'   # pipe
```

The first line heuristic has an obvious failure mode: a file whose header row contains quoted delimiters, or a single-column file, can be sniffed wrongly, which is exactly why the explicit flag exists. The documented file formats are xlsx, xlsm, xls and CSV, and there is no mention of ODS, Parquet, or database connections, so anything outside that list needs converting first.

## Release cadence and what a stale last push means

The release history is short and recent in terms of version numbers: v2.1.0 on 2026-04-17, v2.0.2 on 2026-02-13, and v2.0.1 on 2025-12-14. The last push to the repository was on 2026-04-17, the same day as the v2.1.0 release. The default branch is `develop`, not `main`.

Since the last push was on 2026-04-17, treat the project as quiet rather than actively developed. That matters in practice for a tool like this, because spreadsheet file formats and library behaviour both drift, and an unmaintained binary against a newer excelize or a newer Go toolchain is where surprises appear. The version fallback in the Makefile, which echoes 2.0.2 when git tags are missing, means a source build from an untagged clone will not even report the version you think it is.

The licence field on the repository says MIT, which covers the source and lets you build and redistribute the binary, including the `install` target that puts it on your PATH. The repository also carries SECURITY.md, CONTRIBUTING.md, ARCHITECTURE.md and a CHANGELOG.md, so the parts of the project you are most likely to need, the internal architecture and the change history, are documented in-tree rather than on a separate site. A CHANGELOG.md is also the file to read first when upgrading from an older vex.

## Conclusion

vex suits analysts who live in a shell and want to inspect or reshape a CSV or xlsx without a browser, and it is a good fit for scripted triage work on a server. It is not a replacement for Excel when you need pivot tables, many more than fifteen functions, or charts you can present as-is, and chart export depends on the separate freeze tool being present. Check first that your file is one of the formats it lists, that your formulas stay inside the documented function set, and that the 2026-04-17 release of v2.1.0 behaves as you need on the data you actually have.

## FAQ

### How do I install vex-tui on my machine?

The README section on installation is cut off before the package manager instructions, so the reliable path is the repository Makefile, which has build, build-release and install targets and a goreleaser configuration for cross-platform builds. Building from source requires Go 1.24.

### Which file formats can vex open and edit?

The documented formats are Excel (.xlsx, .xlsm, .xls) and CSV, with multiple sheet support and the original file format preserved when saving. CSV delimiters are auto-detected from comma, semicolon, tab and pipe, or can be set with the delimiter flag.

### Does vex-tui need a spreadsheet application to export charts?

Chart rendering to PNG goes through the separate freeze tool, and the export is triggered with p inside the chart viewer. If freeze is not installed, the program shows the install command instead of failing.

### How do I filter rows in vex-tui without using the mouse?

Press f, type an expression and press Enter, then press Esc to clear it. A plain word matches rows containing that text, comparison operators such as >1000 and <=50.5 apply to the current column, and = gives an exact match. Pressing Tab while typing switches between the current column and all columns.

### Can vex-tui handle formulas from a real Excel workbook?

The formula engine recalculates on every edit and applies references across a range, but the documented set is fifteen or more built-in functions covering sums, averages, counts, extremes, IF, CONCAT, case changes, LEN, ROUND and basic maths. The documentation does not describe lookup, date or pivot functions.

## Sources

- [CodeOne45/vex-tui on GitHub](https://github.com/CodeOne45/vex-tui)
- [Issues](https://github.com/CodeOne45/vex-tui/issues)
- [License: MIT](https://github.com/CodeOne45/vex-tui/blob/develop/LICENSE)
- [README](https://github.com/CodeOne45/vex-tui/blob/develop/README.md)
- [Releases](https://github.com/CodeOne45/vex-tui/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/codeone45-vex-tui
