🐱 sqmeow.nvim

Query your database from your favorite editor β€” fast, keyboard-driven, and Rust-powered.

Features β€’ Databases β€’ Installation β€’ Quick Start β€’ Configuration β€’ Contributing


✨ Features

  • ⚑ Rust engine β€” queries run off the editor thread with paged results; large results never freeze Neovim.
  • 🐘 Multiple connections β€” keep several databases open at once.
  • 🌲 Schema drawer β€” browse schemas, tables, views, routines and columns with types and keys.
  • πŸ“„ Scratchpads β€” persistent query buffers; press u on a connection to make it active.
  • ✏️ In-grid editing β€” edit cells, add or delete rows, review staged changes before applying.
  • πŸ”Ž Filter and sort β€” WHERE / ORDER BY bar runs on the database (or in-memory for Redis/ScyllaDB/SurrealDB).
  • ▢️ Flexible execution β€” run the statement under the cursor, a visual selection, or the whole buffer.
  • 🧭 EXPLAIN β€” query plans and errors render in the result window.
  • πŸ•˜ Query log β€” reopen any past result, even after restart.
  • πŸ“€ Export β€” to CSV, JSON or SQL INSERT (single or batched, with optional CREATE TABLE) β€” to file or clipboard.
  • πŸ” Secrets β€” passwords are masked; URLs can read {{ env "VAR" }}, {{ exec "cmd" }} or {{ file "path" }}.
  • ⌨️ Buffer-local keymaps β€” no global mappings; <Plug> for everything worth a global key.

πŸ—„οΈ Supported Databases

Database Notes
PostgreSQL / CockroachDB Full support, including EXPLAIN, TLS, postgres://
MySQL / MariaDB Full support, mysql://
SQLite sqlite:// / file: β€” zero-config
DuckDB duckdb: β€” local analytics
Redis / Valkey / Dragonfly Keys grouped by type; redis://, rediss://, redis+cluster://, redis+sentinel://
MongoDB Extended JSON commands, mongodb:// / mongodb+srv://
ScyllaDB / Cassandra CQL via scylla:// / cassandra://, ?ssl=true
SurrealDB SurrealQL via surrealdb:// / surrealdbs://
ClickHouse HTTP via clickhouse://, HTTPS via clickhouses://; results are read-only

πŸ‘€ Preview

Overview

✏️ In-grid editing

In-grid editing

πŸ” Table structure

Table structure

πŸš€ Installation

Requirements: Neovim 0.10+ and nui.nvim.

With lazy.nvim:

{
  "2giosangmitom/sqmeow.nvim",
  dependencies = { "MunifTanjim/nui.nvim" },
  version = "*",
  build = function()
    -- Downloads the matching release binary; pass 'curl', 'wget', 'powershell' or 'cargo' to choose.
    require("sqmeow").install()
  end,
  opts = {},
  cmd = "Sqmeow",
  keys = {
    { "<leader>Dd", "<cmd>Sqmeow toggle<cr>", desc = "Toggle" },
    { "<leader>Dc", "<cmd>Sqmeow cancel<cr>", desc = "Cancel" },
    { "<leader>Da", "<cmd>Sqmeow add<cr>", desc = "Add Connection" },
    { "<leader>Ds", "<cmd>Sqmeow scratch<cr>", desc = "New Scratchpad" },
  },
}

[!NOTE] To track master, remove version and build with install('cargo') (needs Rust toolchain + DuckDB). Run :checkhealth sqmeow to verify.

⚑ Quick Start

  1. :Sqmeow opens the drawer and result window.
  2. A in the drawer (or :Sqmeow add) adds a connection.
  3. <CR> on a connection connects; a creates a scratchpad; u makes it active.
  4. Write a query and press <CR> to run the statement under cursor (or a visual selection).

[!TIP] Press ? in the drawer or result window to list its keymaps. See :h sqmeow-keymaps for the full reference.

Dialect Notes

  • SQL β€” <CR> runs statement under cursor; <leader>E runs whole buffer.
  • Redis β€” one command per line, e.g. GET key. Drawer lists keys by type. Cluster: redis+cluster://host:7000,host:7001. Sentinel: redis+sentinel://host:26379,host:26380/mymaster/0.
  • MongoDB β€” database commands as Extended JSON, e.g. {"find": "users"}. use db_name switches database.
  • ScyllaDB β€” ?ssl=true for TLS, ?sslrootcert=/path/ca.pem for custom CA.
  • SurrealDB β€” surrealdb://user:pass@host:8000/namespace/database; leave out the database to list every one in the namespace. surrealdbs:// for TLS, ?auth=namespace or ?auth=database for a non-root user, ?sslrootcert=/path/ca.pem for custom CA. USE DB name switches database. Scratchpads ending in .surql get the surql filetype.

SSH Tunnels

Fill SSH in the connection dialog or add "ssh": "user@bastion" (or user@bastion:2222) to a saved connection. Uses your own ssh, so keys, agent and ~/.ssh/config all apply, and the URL host is resolved from the bastion.

Environment Connections

Define connections in SQMEOW_CONNECTIONS:

export SQMEOW_CONNECTIONS='[{"name": "dev", "url": "postgres://app:{{ env \"PGPASSWORD\" }}@localhost/dev"}]'

Safety

  • Tick Read only in the dialog or add "read_only": true to a connection (or connections.json) to allow only reads. PostgreSQL, MySQL, ClickHouse, SQLite and DuckDB enforce it in the database session (a server that speaks the PostgreSQL protocol without read-only sessions falls back to the check below, with a warning); Redis, MongoDB, ScyllaDB and SurrealDB only check commands against a list of reads, so use a read-only database user where it matters.
  • Before DELETE/UPDATE without WHERE, DROP, TRUNCATE, or emptying a Redis/MongoDB database, sqmeow asks first. Set query.confirm_destructive = false to disable.

⌨️ Commands

Command Description
:Sqmeow Open drawer and result window
:Sqmeow toggle Show or hide schema drawer
:Sqmeow drawer Show schema drawer
:Sqmeow open / close Show / hide result window
:Sqmeow add Add a connection
:Sqmeow save Save connection for next time
:Sqmeow edit [name] Edit a saved connection
:Sqmeow remove <name> Delete a saved connection
:Sqmeow use [name] Choose connection queries run against
:Sqmeow bind <name|none> Tie current buffer to a connection, or untie it
:Sqmeow disconnect Close current connection
:Sqmeow scratch [name] Create a scratchpad
:Sqmeow execute [sql] Run buffer, selection, or given SQL
:Sqmeow statement Run statement under cursor
:Sqmeow cancel Stop running query
:Sqmeow next / prev Next / previous page
:Sqmeow float Move result between split and float
:Sqmeow review Review and apply staged edits
:Sqmeow export <csv|json|sql> [path|clipboard] Export result to file or clipboard
:Sqmeow log [clear] Reopen past result, or clear log
:Sqmeow install [method] Install engine binary
:Sqmeow start / stop / restart Start, stop or restart engine
:Sqmeow messages Show engine log
:Sqmeow health Run health check

πŸ—ΊοΈ Keymaps

Drawer

Key Action
<CR>, o Expand or collapse node
u Run queries against this connection
p Preview relation's first page
K Show table's or key's structure
f Show only Redis keys matching a glob
r Reload subtree
y / s Yank qualified name / a SELECT
a Create a scratchpad
A / e Add / edit a connection
R Rename connection or scratchpad
d Delete connection/scratchpad, or clear log
? / q Show keymaps / close drawer

Result Window

Key Action
L / H Next / previous page
]H / [H Last / first page
K Show row's details
gK Show table's columns and indexes
]r / [r Next / previous statement's result
x Export result, or selected rows
gf / go Open filter bar on WHERE / ORDER BY
= Filter by cell's value
s / S Sort by column / add to sort
- / g- Hide column / show hidden columns
R Clear filters, sort and hidden columns
Z Move between split and float
? / q Show keymaps / close result window

Filter Bar

gf/go open a bar above the grid with WHERE and ORDER BY. The query reruns as a subquery; = adds cell value to WHERE, s fills ORDER BY. MongoDB takes filter/sort documents; Redis/ScyllaDB/SurrealDB and closed connections filter in-memory with AND/OR/NOT, IS NULL, LIKE/ILIKE, IN, BETWEEN.

Key Action
<CR> Run query with bar's content
q, <Esc> Close bar without filtering
<C-p> / <C-n> Older / newer filter
<C-x><C-o> Complete column name

Editing Results

A column is editable when it is a plain table column and its table's whole primary (or unique) key is in the result. Joined rows update each table by its own key; deleted row removes from first editable column's table; rows only addable to single-table results.

Key Action
i, <CR> Edit cell
X Set cell to NULL
g= Set cell to SQL expression, e.g. now()
o / D Add row / copy row without primary key
dd / d Delete row / selected rows
u / U Undo last change / discard all
gs, <C-s> Review staged changes; <C-s> in review applies
<C-c> Stop changes being applied, or a running query

Scratchpad

Key Action
<CR> Run statement under cursor
<CR> (visual) Run selection
<leader>E Run whole buffer
<C-c> Stop running query

βš™οΈ Configuration

setup() is optional. Defaults:

require('sqmeow').setup({
  sources = { { type = 'file' }, { type = 'env' } }, -- where connections are loaded from
  core = {
    path = vim.fs.joinpath(vim.fn.stdpath('data'), 'sqmeow'), -- engine, connections, scratchpads, log
    log_level = 'warn',
  },
  ui = {
    drawer = { width = 36 },
    result = { height = 16, page_size = 100, max_column_width = 48, column_icons = true, null_text = 'NULL' },
    border = 'default', -- 'default' follows 'winborder'; or a nui style such as 'rounded'
    winbar = true,
    persist_session = false, -- reopen last session's connections and drawer nodes
  },
  query = {
    max_rows = 100000,
    timeout_ms = 0, -- 0 disables timeout
    history_size = 32, -- results kept in memory
    persist_history = true, -- save log and results to disk
    history_limit = 500,
    confirm_destructive = true, -- ask before destructive statements
  },
  icons = {}, -- Nerd Font glyphs; recolour via SqmeowIcon* highlight groups
  keymaps = {},
  redact_urls = true, -- mask passwords wherever a URL is shown
})

See :h sqmeow-config for every option.

🀝 Contributing

Toolchain is pinned with mise and tasks are just recipes:

mise install   # rust, just, stylua, selene, lua-language-server
just db-up     # start test databases in Docker
just           # lint, test and check help file, as CI does
just docs      # regenerate doc/sqmeow.txt

Commit messages follow Conventional Commits.

πŸ“œ License

MIT. Thanks to all contributors πŸ’›

Contributors

πŸŽ–οΈ Acknowledgments

Inspired by vim-dadbod, vim-dadbod-ui, and nvim-dbee.