A blazingly fast terminal UI for CSV files. Open a 10GB file instantly. Query it with SQL. Convert between any format. Edit cells with a full vim editor inside. All from your terminal, zero config needed.
Inspired by lazygit, lazydocker, and lazysql.
- Billions of rows, instant open - memory-mapped lazy loading. No loading screen, no waiting. Scroll through files larger than RAM like they're empty
- SQL on CSV -
:sqlopens a full query editor backed by DuckDB. JOIN across files, aggregate, filter, INSERT, UPDATE, DELETE — your data, your queries - Edit like vim - insert mode for quick fixes, magnifier mode for a full vim editor inside any cell. Macros, visual mode, undo/redo. It's vim, in your data
- Your keys, your way - ships with vim, emacs, and excel presets. Customize every binding to match your workflow
- File explorer - browse all CSVs in a directory with a 3-column file picker. Switch files like Excel sheets, no
cdrequired - Multi-format powerhouse - open CSV, TSV, XLSX, ODS, JSON, Parquet. Export to any of them. Convert from the CLI:
lazycsv data.xlsx -o out.json - CLI superpowers - sort, dedup, generate synthetic data, query non-interactively, grab stats — all without opening the TUI
- Highly configurable, great defaults - works out of the box. 11 theme presets (Gruvbox, Dracula, Nord, Catppuccin, Tokyo Night...), 3 keybinding presets, and deep config when you want control. If you don't — it just works
- Lazy loading - files under 10MB load into memory for instant access. Larger files use memory-mapped I/O with an LRU row cache, so you can open files bigger than your RAM
- 60 FPS rendering - virtual scrolling only draws visible cells (O(1) per frame). Files with 100K+ rows render at 2500+ FPS
- Parallel search - regex search across 100K rows in ~20ms using rayon multi-core
- DuckDB-backed queries - SELECT on 100K rows in under 50ms, JOINs in under 200ms
Open a full SQL editor inside the TUI with :sql:
- Full DuckDB SQL - SELECT, WHERE, ORDER BY, GROUP BY, HAVING, JOINs, aggregates, string functions, math operators
- DML support - INSERT, UPDATE, DELETE, ALTER, DROP, CREATE
- Multi-file JOINs - all supported files in the same directory are auto-loaded as tables
- SQL IntelliSense - context-aware auto-completion for table names, column names, and SQL keywords
- Fuzzy error suggestions - mistyped column name? Levenshtein distance suggests the right one
- Query history - persisted to
~/.config/lazycsv/sql_history, browse with Up/Down - Cancellable - hit Esc to kill long-running queries
- Results as virtual table - query output appears as a new tab in the file switcher
Insert mode (i, a, s) - quick single-line cell editing for fixes and updates:
Tabsaves and moves right,Entersaves and moves down,EsccancelsCtrl+wdeletes word,Ctrl+udeletes to start,Ctrl+hbackspaces
Magnifier mode (Enter) - a full vim editor embedded inside any cell:
- All vim motions:
hjkl,w/b/e,0/$,gg/G,f/F/t/T - All vim operators:
d,c,y,p,r,x,J,>>/<< - Visual mode, search (
/,n,N), undo/redo (u,Ctrl+r) Alt+hjklto navigate to adjacent cells without closing- Perfect for JSON, multi-line text, or any cell that needs real editing power
Row and column operations:
dddelete row,yyyank row,p/Ppaste row,5dddelete 5 rows,dddelete column,,yyyank column,,p/,Ppaste columno/Oinsert row below/above,,o/,Oinsert column right/leftccclear row,gj/gkswap rows, drag with mouse to reorder
Cell transforms:
~toggle case,gUuppercase,gulowercase,g~title caseg.toggle boolean values (yes/no, true/false, 1/0, on/off)s/old/new/gfind and replace — in a cell, a range, or across all data
vcell-by-cell selection,Vrow selection,,vcolumn selectionddelete,yyank,cchange,ppasteotoggle selection corner,gvre-select last visual rangegsshow statistics for selected cells
/opens regex search with live results as you typen/Nnext/previous match,*search for current cell value- Match counter shows
[current/total]in status bar - Case-insensitive by default with automatic regex fallback
uundo,Ctrl+rredo — up to 1000 steps, configurable.repeats the last edit operationqa...qrecords a macro into register a-z,@areplays,@@repeats last- Per-file undo history preserved across file switches
:files opens a yazi-inspired 3-column file browser:
- Parent | Current | Preview layout
- Type to filter,
j/kto navigate,Enterto open - File operations: rename (
r), delete (d), copy (y), move (m), new file (n) :opens a shell prompt with$CWD,$FILE,$NAME,$EXTvariable substitution- Navigate directories, spot-preview files before opening
- Quick switching between files with
[and]
Read: CSV, TSV, CSV.GZ, TSV.GZ, XLSX, XLS, ODS, JSON, NDJSON/JSONL, Parquet, SQLite
Write/Export: CSV, TSV, JSON, Markdown, XLSX, ODS, Parquet
From the TUI: :export json or :export data.xlsx
From the CLI: lazycsv data.xlsx -o out.json, lazycsv data.csv -o out.parquet
Pipe support: cat data.csv | lazycsv or lazycsv -q "SELECT * FROM stdin"
Everything the TUI can do, you can do from the command line:
# SQL query non-interactively
lazycsv data.csv -q "SELECT * FROM data WHERE amount > 100"
# Sort by column
lazycsv data.csv --sort Name
# Print stats (type, min, max, mean, stddev, median, mode, cardinality)
lazycsv data.csv --stats
# Print headers, row count, or column count
lazycsv data.csv --headers
lazycsv data.csv --rows
lazycsv data.csv --columns
# Deduplicate with primary key support
lazycsv data.csv --dedup --keep-first
# Split a large file into smaller ones
lazycsv data.csv --split 10000
# Generate realistic synthetic data
lazycsv --generate customer --rows 10000 -o customers.csv
# Convert formats
lazycsv spreadsheet.xlsx -o data.json
lazycsv data.csv -o out.parquet
# Extract Excel sheets
lazycsv spreadsheet.xlsx -x
# Add headers to a headerless file
lazycsv data.csv --add-header "Name,Age,City"
# Clipboard integration
lazycsv data.csv -C # copy output to clipboard
lazycsv -P # paste from clipboard into lazycsv
# Locale-aware number formatting
lazycsv data.csv --formatExcel-compatible formula engine for spreadsheet power users:
- Aggregates:
=SUM(A1:A5),=AVERAGE(A1:A5),=MIN(...),=MAX(...),=COUNT(...) - Math:
=POWER(),=CEILING(),=FLOOR() - Text:
=CONCAT(),=TRIM(),=UPPER(),=LOWER(),=PROPER(),=LEFT(),=RIGHT(),=MID(),=SUBSTITUTE() - Logic:
=IF(condition, true_val, false_val)with comparison operators - Lookup:
=VLOOKUP(),=HLOOKUP() - Date:
=NOW(),=TODAY(),=DATEDIF() - Formula bar displays the formula when cursor is on a formula cell
- Auto-completion popup for function names and cell references
- Imports formulas from XLSX spreadsheets
Color columns based on conditions:
:bgcolor Amount red ">1000" # red background where Amount > 1000
:bgcolor Status green "=active" # green where Status equals "active"
:fgcolor Name blue "~^admin" # blue text where Name matches regex
:bgcolor # green "and(>0,<=100)" # compound conditions
:clearview # remove all custom colors
Colors persist across sessions in ~/.config/lazycsv/views.json.
:sort Namesort ascending by column,:sort! Namedescending, multi-column::sort Dept,Name:statsshow column statistics overlay (count, sum, avg, min, max, distinct),:stats Afor one column:sum,:avg,:count,:distinctfor quick single-stat lookupss/old/new/replace in current cell,%s/old/new/greplace everywhere,5,10s/old/new/gin a row range,B,Ds/old/new/gin a column range
:wsave,:Wsave all,:wqsave and quit,:q!force quit- Dirty file indicator (
*after filename) - External modification detection — polls every 2 seconds, prompts to reload
- View state (column widths, types, colors, frozen columns) saved per file across sessions
:freeze A,Bpin columns,:freeze 1,3pin rows,:unfreezeto remove:type A numberannotate column types for proper formatting
Default config location: ~/.config/lazycsv/config.toml
Per-directory overrides: .lazycsv.toml in any directory
[defaults]
delimiter = ","
encoding = "utf-8"
zebra_striping = true
max_column_width = 50
undo_limit = 1000
# Full theme customization with 11 presets
[ui]
bg = "#282c34"
fg = "#abb2bf"
# Every keybinding remappable, 199 named actions
# Three presets: vim (default), emacs, excelHot-reload — save your config and changes apply instantly. No restart needed.
11 built-in themes: Gruvbox (dark/light), Dracula, Nord, Catppuccin (Mocha/Macchiato/Frappe/Latte), Solarized (dark/light), Tokyo Night
3 keybinding presets: inherit = "vim" (default), inherit = "emacs", inherit = "excel", or inherit = "none" for a blank slate. Every key in every mode is remappable.
- Click to select cells, click headers to select columns, click row gutters to select rows
- Double-click enters insert mode
- Right-click context menu (cut, copy, paste, clear, insert, delete)
- Drag column headers to reorder columns
- Drag row gutters to reorder rows
- Mouse wheel for scrolling
Download the latest release for your platform from GitHub Releases.
macOS (Apple Silicon)
curl -L https://github.com/funkybooboo/lazycsv/releases/latest/download/lazycsv-v0.24.4-aarch64-apple-darwin.tar.gz | tar xz
sudo mv lazycsv /usr/local/bin/macOS (Intel)
curl -L https://github.com/funkybooboo/lazycsv/releases/latest/download/lazycsv-v0.24.4-x86_64-apple-darwin.tar.gz | tar xz
sudo mv lazycsv /usr/local/bin/Linux (x86_64)
curl -L https://github.com/funkybooboo/lazycsv/releases/latest/download/lazycsv-v0.24.4-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv lazycsv /usr/local/bin/Windows
Download lazycsv-v0.24.4-x86_64-pc-windows-msvc.zip from the releases page, extract, and add to your PATH.
Requires the Rust toolchain. Install it first if you don't have it:
macOS
brew install rustor
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shLinux (Debian/Ubuntu)
sudo apt install cargoor for the latest Rust version:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shWindows
Download and run rustup-init.exe from the official site.
Then build lazycsv:
git clone https://github.com/funkybooboo/lazycsv.git
cd lazycsv
cargo install --path .# Open current directory (scans for CSV files)
lazycsv
# Open specific file
lazycsv data.csv
# Open a directory
lazycsv ./data/
# With options
lazycsv data.csv --delimiter ';' --no-headers
# Non-interactive query mode
lazycsv data.csv --query "SELECT * FROM data WHERE amount > 100"
# Locale-aware number formatting
lazycsv data.csv --format| Key | Action |
|---|---|
hjkl or arrows |
Move around (with count: 5j, 10h) |
gg / G |
Jump to first / last row |
5G / :5 |
Jump to row 5 |
:B / :A5 |
Jump to column B or cell A5 |
w / b / e |
Next/prev/last non-empty cell |
i / a / s |
Quick edit cell (Insert mode) |
Enter |
Magnifier — full vim editor inside the cell |
o / O |
Insert row below/above |
dd / yy / p |
Delete/yank/paste row |
,dd / ,yy / ,p |
Delete/yank/paste column |
v / V / ,v |
Visual select (cell/row/column) |
/ |
Search (regex, live results) |
n / N |
Next/previous match |
u / Ctrl+r |
Undo / Redo |
. |
Repeat last edit |
~ / gU / gu / g~ |
Toggle/upper/lower/title case |
g. |
Toggle boolean (yes/no, true/false) |
gj / gk |
Swap row down/up |
:sql |
SQL query mode (DuckDB-backed) |
:sort / :sort! |
Sort ascending/descending |
:stats |
Column statistics overlay |
:files |
File explorer (browse, open, manage files) |
:export |
Export to JSON, TSV, Markdown, XLSX, ODS, Parquet |
s/old/new/g |
Find and replace in cells |
qa...q / @a |
Record / replay macro (26 registers) |
Esc |
Cancel loading/queries |
zt / zz / zb |
Scroll row to top/center/bottom |
? |
Show help |
:w / :q |
Save / Quit |
Press ? in the app for the full keybinding reference.
- Keybindings - Every keyboard shortcut by version
- Design - How it looks and feels
- Architecture - How it works
- Development - How to contribute
# Using mise (recommended)
mise run run # run with sample.csv
mise run test # run tests
mise run ci # format, lint, test
# Or with Cargo
cargo run -- sample.csv
cargo testSee docs/development.md for contributing guidelines.
LazyCSV follows the "lazy tools" design:
- Keyboard first - mouse optional, every action has a key
- Fast - instant response, lazy-loaded for infinite scale
- Simple - no configuration required, sensible defaults
- Powerful - vim-style efficiency, SQL queries, format conversion
- Vim-first - if it works in vim, it should work here
MIT License - see LICENSE file for details.
Built with:
Inspired by the excellent "lazy" tools: lazygit | lazydocker | lazysql | lazyssh
Have fun exploring your data!