A lightweight terminal UI for viewing and querying tabular data — data files and live databases — with SQL, fuzzy search, plotting and theming built in. Written in Go on top of Bubble Tea v2.
- Open anything tabular — csv, tsv, dsv, json, jsonl, parquet, excel,
sqlite, fwf, logfmt, markdown, html; stdin (
-) and http(s) URLs too - SQL everywhere — an embedded in-memory SQL engine over loaded files, or live statements against MySQL / PostgreSQL / SQLite / Redis
- Tabs + frame stack — every table is a tab; every operation (filter,
sort, query, search, cast) layers a new frame you can pop off with
q - Fuzzy & exact search with live preview as you type — and every picker (schema browser, columns, themes, redis keys) is type-to-filter
- Command palette with fuzzy matching and inline shortcuts (
:f price > 3) - Context-aware SQL completion — tables after
FROM, columns afterWHERE,alias.resolution, functions, case-following - Histogram & scatter plots rendered right in the terminal
- Export to csv, tsv, json, jsonl, parquet, markdown
- Copy & paste —
y/Ycopy cell/row over OSC52 (works through SSH), bracketed paste into any input, terminal text selection stays untouched - 40+ built-in themes with live preview (default:
sorbet, a warm pastel scheme), on a transparent background that blends with your terminal, plus$EDITORround-trip editing
Table view — stripes, gutter, status tags |
Command palette ( :) |
SQL editor with autocompletion |
Theme selector with live preview |
Histogram ( :histogram) |
Scatter plot grouped by column |
go build -o sqltui .Try it right away with the bundled sample data:
./sqltui examples/employees.csv examples/demo.dbsqltui data.csv # open one file
sqltui a.csv b.parquet c.xlsx # multiple files -> multiple tabs
sqltui database.db # every sqlite table becomes a tab
cat data.csv | sqltui - # stdin
sqltui https://example.com/x.csv # remote file
sqltui data.txt -f csv # override format detection
sqltui --multiparts p1.csv p2.csv # concatenate parts verticallyParsing flags: --separator, --quote-char, --no-header,
--ignore-errors, --infer-schema no|fast|safe, --infer-types,
--truncate-ragged-lines, --widths, --separator-length,
--no-flexible-width, --sqlite-key.
Database mode is for server databases that need connection credentials.
SQLite databases are just files — open them directly in file mode
(sqltui app.db), no subcommand needed.
| Database | Command | Driver |
|---|---|---|
| MySQL | sqltui mysql |
go-sql-driver/mysql |
| PostgreSQL | sqltui postgres |
jackc/pgx |
| Redis | sqltui redis |
redis/go-redis |
A connection form opens first (prefilled from the config file): enter
connects, tab/arrows move between fields, ctrl+s saves, esc quits.
After connecting, the schema browser opens with the connected database
expanded and the others collapsed (lazy-loaded on enter); type to filter
tables. enter loads a table into a tab, and :query runs statements
against the live connection.
Database mode is organized as a stack of full-screen pages — connection
form, schema browser, table — and esc always goes back one page: from a
table it first pops applied frames, then returns to the schema browser;
from the browser it returns to the connection form; from the form it exits.
q in the browser jumps straight back to the open table instead.
In Redis mode a key browser (grouped by type) replaces the schema browser —
including in the esc chain above — and the query prompt executes raw
commands with inline argument hints and completion for 230+ commands.
| Key | Action |
|---|---|
k/↑, j/↓ |
move up / down |
h/←, l/→ |
move column cursor (both column modes) |
g/home, G/end |
first / last row |
ctrl+u / ctrl+d |
half page up / down |
pgup/ctrl+b, pgdown/ctrl+f |
page up / down |
_ / $ |
first / last column |
enter |
open row detail sheet |
w |
toggle fit / wide column mode (auto-picked per table) |
y / Y |
copy current cell / current row |
i |
table info |
R |
random row |
1-9 |
go to row |
/ , s |
fuzzy / exact search |
: |
command palette |
t |
tab switcher |
H/shift+←, L/shift+→ |
previous / next tab |
q |
pop frame / close tab / back |
esc |
back one level (never closes a tab or quits) |
Q |
quit |
F1 / ? |
help |
In the sheet view: j/k (or shift+j/shift+k) scroll, c copies the
row, q/esc return to the table.
Open the palette with : and type. Short aliases take the rest of the line
as an argument (:f age > 30 filters immediately).
| Command | Alias | Effect |
|---|---|---|
query |
q |
full SQL editor with autocompletion |
select |
s |
inline column selection |
filter |
f |
inline WHERE clause |
order |
o, sort |
inline ORDER BY |
search / fuzzysearch |
exact / fuzzy search | |
schema |
browse open tabs and live tables | |
info |
table schema and stats | |
export / import |
file export / import wizards | |
cast |
change a column's type | |
register |
name the current frame for SQL | |
histogram / scatterplot |
terminal plots | |
edit |
edit the table in $EDITOR |
|
theme |
theme selector with live preview | |
toggleborders / togglerownumbers |
view toggles | |
reset |
back to the base frame | |
reloadconfig |
reload the config file |
In file mode every loaded table is queryable by its tab name and the current
frame is always available as _:
select department, count(*) as headcount, cast(avg(salary) as int) as avg_pay
from employees group by department order by avg_pay descFull query results open in a new tab; inline select/filter/order
results stack onto the current tab (pop with q).
~/.config/sqltui/config.yaml stores connection settings per engine plus UI
preferences:
mysql:
userName: root
password: "123456"
host: 127.0.0.1
port: "3306"
dbName: test_db
ui:
theme: aurora
showBorders: true
showRowNumbers: trueA config.json left over from an older version is migrated to config.yaml
automatically on first start (the JSON file is kept, but no longer used).
Logs go to ~/.config/sqltui/sqltui.log.
- The column cursor (
h/l) works in both column modes: the header highlights it, the status barcol:tag tracks it,ycopies the cell under it, and wide mode scrolls to keep it visible. - Every filter, sort, query or search layers a frame onto the tab's stack;
the breadcrumb in the status bar shows the chain.
qpops one layer,escsteps back too, and:resetjumps straight to the base table. - In SQL,
_always means the current frame;:registergives a frame a real name so you can join it against other tables. y/Yand the sheet view'sccopy via OSC52, so the clipboard works over SSH. Bracketed paste works in every input, and the mouse is never captured — plain terminal text selection keeps working.- Type to filter in every picker: schema browser, theme selector, column pickers, tab switcher, redis keys.
1-9opens the go-to-row prompt with that digit prefilled, andRjumps to a random row.- The theme selector previews live as you move the highlight —
enterkeeps it,escreverts to the previous theme.







