tsql

April 18, 2026 ยท View on GitHub

A modern, keyboard-first PostgreSQL and MongoDB CLI with a TUI interface.

CI Crates.io License Discord

If you like this crate show some support by following fcoury (me) on X

tsql screenshot

Join us on Discord

Features

  • Full-screen TUI - Split-pane interface with query editor and results grid
  • Vim-style keybindings - Navigate and edit with familiar modal commands
  • Syntax highlighting - SQL and JSON highlighting powered by tree-sitter
  • Smart completion - Schema-aware autocomplete for tables, columns, and keywords
  • Results grid - Scrollable, searchable data grid with column resizing, multi-row selection, and flexible yank (TSV/CSV/JSON/Markdown)
  • Inline editing - Edit cells directly in the grid with automatic SQL generation
  • JSON support - Detect, format, and edit JSON/JSONB columns with syntax highlighting
  • Postgres + MongoDB - Connect with postgres://... or mongodb://... URLs
  • Schema commands - psql-style commands plus Mongo helpers (:show dbs, :show collections, :describe)
  • Query history - Persistent history with fuzzy search, pinning, and deletion
  • AI query assistant - Draft DB-aware queries with follow-ups and one-key accept (:ai / Ctrl+G)
  • External editor - Open the current query in $VISUAL / $EDITOR with vv
  • 1Password integration - Store an op:// secret reference per connection instead of a plain password
  • Update checks - Notify of new versions with install-method specific upgrade hints, plus optional in-app apply for standalone installs when updates.mode = "auto"
  • Configurable - Customize keybindings and appearance via config file

Installation

Homebrew (macOS/Linux)

brew tap fcoury/tap
brew install tsql

Cargo (from source)

cargo install tsql

Binary Download

Download pre-built binaries from the GitHub Releases page.

Quick Start

# Connect with a connection URL
tsql postgres://user:password@localhost:5432/mydb
tsql mongodb://user:password@localhost:27017/mydb

# Or set DATABASE_URL environment variable
export DATABASE_URL=postgres://user:password@localhost:5432/mydb
tsql

# Or configure a default connection in ~/.tsql/config.toml
tsql

Once connected:

  1. Type a SQL query in the editor pane
  2. Press Enter to execute
  3. Use Tab to switch between editor and results grid
  4. Press ? for help with all keybindings (type / inside the help popup to filter)

Keybindings

Global

KeyAction
TabSwitch focus between query editor and results grid
?Toggle help popup (/ to filter inside)
Ctrl+Shift+B / Ctrl+\ / Ctrl+4Toggle sidebar
Ctrl+OOpen connection picker
Ctrl+Shift+C / gmOpen connection manager
qQuit application
EscReturn to normal mode / close popups

Query Editor (Normal Mode)

KeyAction
h/j/k/lMove cursor
i/a/I/AEnter insert mode
o/OOpen line below/above
ddDelete line
yyYank (copy) line
p/PPaste after/before
uUndo
vEnter visual mode
vvOpen query in $VISUAL / $EDITOR, reload on exit
/Search
Ctrl-rFuzzy history search
Ctrl-gOpen AI query assistant
EnterExecute query
:Command mode

Results Grid

KeyAction
h/j/k/lNavigate cells
H/LScroll horizontally
gg/GFirst/last row
SpaceToggle row selection and advance cursor
aSelect all rows (press again to deselect all)
AInvert selection
EscClear selection
yy / yYYank row(s) as TSV / TSV with headers
yjYank row(s) as JSON
yc / yCYank row(s) as CSV / CSV with headers
ymYank row(s) as Markdown table
cCopy cell
eEdit cell
oOpen row detail view
/Search in results
+/-Widen/narrow column
=Fit/collapse column

Yank commands operate on all selected rows when a selection is active, or the cursor row otherwise.

Row Detail (o to open)

KeyAction
j/kNext/previous field
g/GFirst/last field
yy / yYCopy row as TSV / TSV with headers
yjCopy row as JSON
yc / yCCopy row as CSV / CSV with headers
ymCopy row as Markdown table
e / EnterEdit selected field
q / EscClose

History Picker (Ctrl-r or gh)

KeyAction
EnterLoad selected query into editor
Ctrl-bPin / unpin selected entry (pinned entries are never auto-pruned, shown with โ˜…)
Ctrl-dDelete selected entry
Ctrl-tToggle between full history and pinned-only view
EscClose picker

Troubleshooting keybindings

If a key combo isn't working in your terminal, you can inspect what tsql is actually receiving:

tsql --debug-keys

To also print mouse events:

tsql --debug-keys --mouse

Commands

CommandDescription
:connect <url>Connect to database
:disconnectDisconnect
:ai [prompt]Open AI query assistant
:export csv|json|tsv <path>Export results
:update [check|status|apply]Check/apply updates
:sbt / :sidebar-toggleToggle sidebar
:q / :quitQuit
:\dtList tables
:\d <table>Describe table
:\dnList schemas
:\diList indexes
:\lList databases
:\duList roles
:show dbsMongo: list databases
:show collectionsMongo: list collections
:describe <collection>Mongo: describe collection
:use <database>Mongo: switch database

:update apply is only available in updates.mode = "auto" and only for standalone binary installs.

Configuration

tsql looks for configuration at ~/.tsql/config.toml by default. On Linux/macOS startup, legacy config folders are auto-migrated to ~/.tsql.

[connection]
# Default connection URL (can be overridden by CLI arg or DATABASE_URL)
default_url = "postgres://localhost/mydb"
# Enable 1Password CLI support for `password_onepassword` refs
enable_onepassword = false

[updates]
# Update checks + optional in-app apply for standalone installs
enabled = true
check_on_startup = true
channel = "stable"
mode = "auto"
interval_hours = 24
allow_apply_for_standalone = true
github_repo = "fcoury/tsql"

[ai]
# Enable AI query assistant (`:ai`, `Ctrl+G`)
enabled = false
# provider:
# - "open_ai"
# - "open_ai_compatible"
# - "ollama"
# - "anthropic"
# - "google"
# - "openrouter"
provider = "open_ai"
model = "gpt-4o-mini"
api_key_env = "OPENAI_API_KEY"
# base_url = "http://localhost:1234/v1"
# provider defaults when omitted:
# ANTHROPIC_API_KEY / GEMINI_API_KEY / OPENROUTER_API_KEY

[keymap]
# Custom keymap overrides (see config.example.toml for options)

See config.example.toml for all available options.

1Password integration

1Password support is currently gated behind connection.enable_onepassword = true in your config.

Connection entries support an optional 1Password ref field (op://vault/item/field). When enabled, tsql calls op read at connect time to resolve the password, inheriting your shell's PATH and active op session token. Configure it via the connection manager (Ctrl+Shift+C or gm).

Requires the 1Password CLI (op) to be installed and an active authenticated session (for example via op signin).

Requirements

  • PostgreSQL 12 or later, or MongoDB 6.0+
  • Terminal with 256-color support recommended

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

This project is licensed under the MIT License - see the LICENSE file for details.