Fast, vim-native SQL client.
No Electron. No JVM. No bullshit.
Native Rust. Instant startup. Terminal-native. MySQL, Postgres, SQLite, DuckDB.
> analytics > billing v shop v users id: bigint(20) email: varchar name: varchar status: varchar created_at: timestamp > orders > products > sessions > mysql > information_schema
select * from shop.users
select * from shop.users id is_active first_name last_name email status 101 true Ada Lovelace ada@sample.com active 102 true Grace Hopper grace@sample.com active 103 false Alan Turing alan@sample.com pending 104 true Linus Torvalds linus@sample.com active 105 false Margaret Hamilton mh@sample.com inactive
why
Everything a keyboard-driven DB jockey wants.
Native Rust
Instant startup. No JVM, no Node, no runtime tax. Small binary, small RSS.
First-class vim
Normal/insert/visual/command modes. Search, leader chords, query history via Ctrl+P/Ctrl+N.
Terminal UI
sqeel — ratatui terminal client. Instant startup, no
Electron, no JVM.
MySQL · Postgres · SQLite · DuckDB
Powered by sqlx + duckdb-rs. Per-file TOML connections, live switcher. A
duckdb: URL (file or duckdb::memory:) puts
DuckDB's own reach at your fingertips —
SELECT * FROM 'data.csv'
over CSV / Parquet, no import step.
Per-tab connections
Each editor tab binds to its own database. Switching tabs swaps warm
connection pools without reconnecting, in-flight queries on other
connections keep running, and bindings survive a restart. Tabs pointed
somewhere other than the active connection carry a dim
[conn] suffix, so "which database is this about to hit" is
a glance, not a guess.
OS keyring credentials
Passwords land in Secret Service / Keychain / Credential Manager — never
plaintext on disk. :migrate-secrets walks existing
connections and moves inline passwords into the keyring.
sqls integration
Completions, inline diagnostic underlines, and gutter signs from any SQL
LSP, with an auto-generated sqls config from the active
connection. K hovers (markdown + GFM tables),
gd goes to definition, errors jump the editor to
line:col. No sqls on $PATH?
:Anvil install sqls fetches it into a local store — or turn
the offer off with editor.lsp_auto_install = false.
tree-sitter highlighting
Dialect-aware. Fast, accurate, no regex soup.
Editor tabs + history picker
Lazy load, 5-minute RAM eviction. Auto-save SQL buffers. Query history is kept per connection; <leader>h opens a fuzzy picker over it and drops the selection in a fresh scratch tab.
Vim-native results pane
Cell cursor with counts, / search, visual-line and
visual-block selection with TSV yank, mouse drag-select. SQL
NULL stays distinct from empty text in the table, JSON, and
CSV output.
Destructive-statement guard
UPDATE/DELETE with no top-level
WHERE, plus DROP and TRUNCATE,
ask for an explicit y/N first. Ctrl+C cancels a running query
or batch mid-flight.
-e for scripts and CI
sqeel -e "SELECT 1" --format table|csv|json runs statements
with no TUI. Summaries go to stderr so stdout stays pure data for pipes;
first error exits 1.
:export · :describe · :refresh
:export csv|json [path] writes the active result tab to
disk. :describe <table> dumps dialect-aware column
schema. :refresh / <leader>R busts the
schema cache without reconnecting.
tmux-aware nav
Ctrl+HJKL across schema / editor / results. Mouse works everywhere too.
Schema browser
Expand DB → tables → columns with types inline. Click or keyboard, fuzzy search across objects.
--sandbox to try it
Launches in a fresh tempdir that never touches your real config, seeded
with a SQLite connection and a sample buffer. Bare
sqeel with $DATABASE_URL set prompts y/N
(password masked) instead of showing the picker.
Auto-LIMIT on bare SELECTs
A SELECT that doesn't limit itself gets
LIMIT 100 appended, so a fat table never freezes the pane.
When the cap is what you're seeing, the result tab says
first N rows — auto LIMIT and headless mode notes it on
stderr. Tune or disable with editor.default_row_limit.
install
Prebuilt binaries on every tagged release.
macOS via Homebrew tap, Arch via AUR, crates.io, or grab a prebuilt binary.
Linux (x86_64, aarch64, musl), macOS (Apple Silicon, Intel), Windows
(x86_64). Arch users: AUR sqeel-bin. Alpine: the musl tarball
is a static drop-in (the .apk is built by the same pipeline but
didn't make the last tag). SHA-256 sidecars on every artifact, plus a
completions-man tarball — bash, zsh, fish, powershell, elvish,
and nushell completions and a man page, all generatable from the binary
itself (sqeel --completions zsh, sqeel --man).
$ brew install kryptic-sh/tap/sqeel $ sqeel
$ yay -S sqeel-bin $ paru -S sqeel-bin
# grab sqeel-<tag>-x86_64-unknown-linux-musl.tar.gz from # https://github.com/kryptic-sh/sqeel/releases/latest — static, no libc chase $ tar xzf sqeel-*-x86_64-unknown-linux-musl.tar.gz $ install -m755 sqeel /usr/local/bin/sqeel
# crates.io — the published crate can trail the newest tag $ cargo install sqeel # or build from the repo $ git clone https://github.com/kryptic-sh/sqeel $ cd sqeel $ cargo build --release # binary in target/release/sqeel