Plaintable app icon

A CSV that finally reads like a table.

Plaintable is a fast, native macOS viewer and editor for CSV, TSV and any other delimited text. It opens in View mode, so nothing changes by accident — and ⌘E turns the same table into a real editor.

Requires macOS 26. Sandboxed, no network access.

The Plaintable window showing a sales CSV: sticky header, line-number gutter, a pinned Order column, currency and percent formatting, a calculated Revenue column and conditionally coloured rows.

The view file

Everything about the view lives in a file you can read.

A CSV cannot hold a calculation, a colour or a hidden row. So Plaintable keeps those beside it. Open sales.csv and everything about how it is shown — column order and widths, what is hidden or pinned, number and date formats, calculated columns, hidden rows, conditional row colouring, the sort and the filters — is written to sales.csv.md.

It is plain markdown, written to be read: tables you can edit in any editor, diff in a pull request and commit next to the data. Save it from somewhere else and the open window follows along. Nothing written in it ever touches the CSV, and calculated columns are shown, never saved.

Read the view file syntax →

## Columns

| Column   | Show | Width | Format        | Formula             |
| -------- | ---- | ----- | ------------- | ------------------- |
| Units    | yes  | 85    | number        |                     |
| Price    | yes  | 110   | currency(EUR) |                     |
| Category | no   | 100   |               |                     |
| Revenue  | yes  | 140   | currency(EUR) | `[Units] * [Price]` |

## Rows

- Hidden: 6, 40-44

## Row formatting

| When                    | Style                   |
| ----------------------- | ----------------------- |
| `[Discount] >= 0.2`     | background amber        |
| `[Status] = "Refunded"` | strikethrough, text red |

## Sort

1. Revenue — descending

An excerpt from a real sales.csv.md.

sales-2026.csv.md open in TextEdit, showing the Columns table and the Row formatting table that produced the view.

The same file in TextEdit, sitting next to the CSV.

Calculations

Real formulas. Never written to your CSV.

Write a column's name in square brackets and go: [Units] * [Price] * (1 - [Discount]). Comparisons, and / or / not, & for joining text, about fifty functions, and whole-column summaries — so [Total] / SUM([Total]) works.

A calculated column sorts, filters and exports like any other, and is left out of the file. Formulas can also be pinned to a single cell. Errors are values, not failures: a bad formula shows #NAME? in its own cell and leaves the rest of the table alone.

The New Calculated Column sheet with a formula, a live preview of the computed values for several rows, and the palette of available columns.

Sorting & filtering

Filter like a spreadsheet.

A quick filter in the toolbar, per-column popovers whose contents follow the inferred type, and the familiar distinct-value checklist with counts. Filters stack in a removable chip bar with AND/OR and invert, and a set can be named and saved per file.

Click a header to cycle the sort three ways, shift-click for extra keys with priority numbers. Comparison is type-aware — numeric, chronological, boolean, localised text — stable, with empties pinned to one end.

Three filter chips with an All/Any switch, a descending sort on Revenue, and a column filter popover listing distinct product values with a count beside each.

Editing

⌘E turns the same table into an editor.

Inline editing with type-to-replace, range paste, fill down and right, case transforms, find and replace with a live count of what is about to change, insert and delete rows and columns, and unlimited undo with real action names.

Saving preserves your file's delimiter, quoting, line endings, encoding and BOM, and rewrites only the rows you actually touched. An unmodified document saves byte-identically — asserted by a property test over every fixture.

Edit mode: an inline cell editor open mid-typing, amber modified-cell markers, row change bars in the gutter, and a chip reading 3 cells changed, not yet written to the file.

Built for big files

Ten million rows, open in a blink.

The file is memory-mapped and never loaded as a string. A single quote-aware pass records where each record starts; cells are decoded only as they scroll into view. Sorting and filtering permute an array of row IDs over cached column projections, so the source bytes are never copied or reordered.

Files of 24 MB and up show their window immediately and finish indexing in the background, with the progress in the status bar.

A 953 MB file open at row 9,876,538, with the status bar reading 10,000,000 rows, UTF-8, comma, 953.6 MB, parsed in 11 ms.
Measured on a Release buildTime
Map and index 1,000,000 rows (55 MB)0.06 s
Map and index 10,000,000 rows (568 MB)0.60 s
10,000 scattered row reads0.005 s
Sort 1,000,000 rows on a numeric column0.73 s
Quick filter across all columns (1M rows)0.07 s
Serialize 1,000,000 rows with one edited cell0.10 s

Times vary with your Mac and your data; these are from the project's own benchmark suite.

And the rest

Everything else it does.

Opens anything delimited

.csv, .tsv, .tab, .psv, .txt and .csv.gz, with delimiter and encoding sniffing, header detection, and a re-import sheet to override every guess.

Encodings that actually work

BOM detection, UTF-8 validation, UTF-16/32 transcoding and a Windows-1252/1251 fallback. A file that arrived gzipped is written back gzipped.

A grid that keeps up

Sticky header, a frozen gutter showing source line numbers, pinned columns, drag to resize and reorder, auto-fit on a double-click, and full keyboard navigation.

Malformed rows, found

Rows with the wrong field count are marked, and ⌘⇧J steps to the next one. Go to Row with ⌘L, zoom with ⌘+ and ⌘−.

Row formatting

Rules of the form “when [Total] > 1000, bold on amber”. Every rule that matches applies, top to bottom, so they layer instead of multiplying.

Hidden rows

Hide one row or a selection by CSV line number, kept apart from the filters so clearing the filters does not bring them back. The status bar always says how many.

Column statistics

Type, row and empty counts, distinct values, min, max, sum, mean, median and standard deviation, with a distribution sparkline.

The row inspector

⌘I reads the focused row top to bottom — every field, hidden columns and calculated values included — and copies the whole row as JSON.

Export and Copy As

The current view — sorted, filtered, calculated — out to CSV, TSV, JSON, JSON Lines, Markdown or HTML.

Crash recovery

Unsaved edits are journalled a couple of seconds after you stop typing. A journal on disk means the session ended badly, and reopening the file offers the edits back.

Quick Look

An app extension previews delimited text through the same engine, with the sniffed dialect, a row-number gutter and markers for malformed rows.

VoiceOver

The grid publishes itself as a real accessibility table — rows, cells, and columns that announce their sort and filter state — built only for what is on screen.

The row inspector open beside the table, listing every field of row 12 — including the hidden Category and Channel columns and the calculated Revenue — with a per-column distinct and empty count at the bottom.

The row inspector, with the two hidden columns and the calculated Revenue in place.

Get Plaintable

A one-time purchase for macOS. No account, no subscription, no network access — your files never leave your Mac.

Requires macOS 26 or later · Apple silicon and Intel · Sandboxed, no network entitlement