@josharsh/xeli
v0.3.0
Published
Excel for the Terminal — interactive TUI spreadsheet with AI-powered queries
Maintainers
Readme
xeli
Excel for the terminal. An interactive TUI spreadsheet with natural language queries.
Open CSV, JSON, Parquet, and Excel files in a fast TUI spreadsheet. Filter, sort, pivot, and export visually. Ask questions in plain English and let xeli write the SQL.
Try it without installing
→ xeli.josharsh.com/playground
DuckDB-WASM in your browser. Drop a CSV, ask a question, nothing leaves the tab.
Install
# npm (one-off, no install)
npx @josharsh/xeli examples/employees.csv
# npm (global)
npm install -g @josharsh/xeli
# Homebrew
brew install josharsh/tap/xeliOr grab a prebuilt binary.
Supported on macOS (Apple Silicon, Intel) and Linux (arm64, x86_64). Windows isn't supported yet, see #help-wanted.
Quick start
xeli sales.csv # open a CSV
xeli data.parquet # or Parquet, JSON, JSONL, Excel
cat events.json | xeli # pipe anything
psql -c "..." | xeli # query results, browsable
xeli # no args opens a file picker for the current dirPress Ctrl+K and ask something:
- "top 10 employees by salary"
- "average revenue by city for active customers"
- "signups per week last quarter"
xeli sends your schema plus the question to OpenAI or Anthropic, runs the returned SQL on DuckDB, and shows the rows.
Features
| | |
|---|---|
| Multi-format | CSV, TSV, JSON, JSONL, Parquet, xlsx |
| AI queries | Ctrl+K, plain English to SQL via OpenAI or Anthropic |
| SQL mode | Ctrl+Q, direct DuckDB queries with history |
| Filter | f, visual builder with 12 operators (=, >, contains, regex, ...) |
| Sort | s, cycle current column ASC / DESC / off |
| Search | /, regex across all columns, n and N to walk matches |
| Group-by + pivot | g, multi-column grouping wizard with COUNT, SUM, AVG, MIN, MAX |
| Join | J, pick a second file, choose INNER / LEFT / RIGHT / FULL |
| Computed columns | c, derive new columns from expressions (price * qty) |
| Formula bar | =, one-shot expressions (SUM(amount), MEDIAN(salary)) |
| Histograms | v, sparkline distribution for any numeric column |
| Column stats | Ctrl+I, min / max / mean / median / nulls / unique count |
| Export | e, write filtered result back out as CSV / JSON / Parquet |
| Themes | t, Dracula, Nord, Catppuccin, Tokyo Night, Solarized |
| Command palette | Ctrl+P, fuzzy-search every command |
| Undo | u, full view-state stack |
| File picker | run xeli with no args for a fuzzy list of supported files in cwd |
| Mouse | click, scroll, drag to resize columns |
Full keybinding list lives in the in-app help (?) or in src/handlers/input.rs.
How is this different from VisiData / csvkit / xsv / sc-im?
They're all great. Here's how xeli finds its niche:
| Tool | Best for | What xeli does differently |
|---|---|---|
| VisiData | Mature, scriptable Python TUI | DuckDB engine plus an AI natural-language query layer |
| csvkit | Pipeline transforms | Interactive browsing instead of one-shot scripts |
| xsv | Blazing fast CSV processing | Multi-format (Parquet, JSON, xlsx) plus TUI plus SQL |
| Miller | Streaming transforms across formats | Interactive table, group-by wizard, joins by point-and-click |
| sc-im | Classic spreadsheet UX | Less Excel-cell-editing, more "browse + query large data" |
| q | SQL over CSVs from the shell | Same idea, plus a TUI, plus NL queries, plus more file formats |
If you live in a notebook for ad-hoc data exploration, xeli is the "I just want to look at this CSV without spinning up Python" tool.
AI setup
xeli works without AI. Every feature except Ctrl+K runs offline. To turn natural language queries on, set an API key:
# OpenAI
export OPENAI_API_KEY=sk-...
# or: xeli config set-key openai sk-...
# Anthropic (Claude)
export ANTHROPIC_API_KEY=sk-ant-...
# or: xeli config set-key anthropic sk-ant-...If you press Ctrl+K with no key set, xeli walks you through it inline. Pick a provider, paste your key, hit Enter. No restart needed.
Examples
Sample datasets live in examples/:
xeli examples/employees.csv # 30 rows x 7 columns
xeli examples/departments.csv # join target
xeli examples/employees.json # same data, JSONTry this in the AI bar (Ctrl+K):
top 3 highest-paid people in engineeringaverage salary by department, ordered by amountwho has been here the longest in each city?
Or join two files (J):
- Open
examples/employees.csv - Press
J, enterexamples/departments.csv - Pick
INNERjoin, both on thedepartmentcolumn
Building from source
cargo build --release
./target/release/xeli examples/employees.csvTests (release mode is required on macOS):
cargo test --releaseTech stack
- Rust. Single static binary, ~3k LOC, no runtime dependencies.
- Ratatui for the terminal UI.
- DuckDB as the embedded vectorized SQL engine.
- clap for CLI parsing.
- tokio as the async runtime for the one AI request.
Demo
A short, deterministic walk-through. Open a CSV, navigate, sort by salary, then run the group-by wizard for AVG(salary) per department.
Contributing
PRs welcome. See CONTRIBUTING.md for the build and test loop and the open help-wanted list (Windows, Ollama backend, streaming, themes).
License
MIT. See LICENSE.
