Connection Management
Tabularis stores connection profiles as JSON (non-sensitive fields) and delegates all secrets to the OS keychain — Keychain Access on macOS, Windows Credential Manager on Windows, and libsecret (GNOME Keyring / KWallet) on Linux.

Supported Drivers
The following drivers are registered at startup and available natively, with no plugin required:
| Driver ID | Database | Default Port | Multi-database |
|---|---|---|---|
postgres |
PostgreSQL | 5432 | — (uses schemas) |
mysql |
MySQL / MariaDB | 3306 | Yes |
sqlite |
SQLite | (file path) | — (file-based) |
Each built-in driver renders with its own branded icon in the Connections page — the PostgreSQL elephant, MySQL dolphin, and SQLite cylinder — displayed in the driver's official color. Plugin drivers use any icon declared in their manifest, or a generic fallback.
Additional drivers can be added via the Plugin System.
Connections Page
The Connections page (Cmd/Ctrl + Shift + C) lists all saved profiles and supports two display modes, switchable from the toolbar:
- Grid — each connection is a card with the driver icon, status badge, host/database info, and SSH indicator.
- List — the same information in compact rows, better suited for large numbers of connections.
A search bar filters by name or host in real time.
Double-click a card or row to connect immediately.
Connection Profile Fields
When creating a connection (+ button in the sidebar or Cmd/Ctrl + Shift + N):
| Field | Required | Description |
|---|---|---|
| Name | Yes | Display label in the sidebar |
| Driver | Yes | Selects the database type |
| Host | Yes* | Hostname or IP address |
| Port | Yes* | Auto-filled from the driver default |
| Database | Yes* | The database name to connect to |
| Username | Yes* | Database user |
| Password | No | Stored in OS keychain; never written to disk |
| Save in keychain | — | Controls whether the password persists after closing |
| SSH enabled | No | Activates the SSH tunnel for this connection |
| SSH profile | — | Which saved SSH profile to use for the tunnel |
| Allow interactive prompts | No | Lets the SSH tunnel prompt in-app for a key passphrase, security-key PIN, or password when it can't authenticate silently. See SSH Tunneling → Interactive Authentication. |
| Startup script | No | SQL run on every new pooled connection (see Startup Script below). |
| Kubernetes | No | Tunnels the connection through a managed kubectl port-forward. Mutually exclusive with SSH. See Kubernetes Tunneling. |
| CA Certificate | No | Path to a PEM bundle to trust for TLS (PostgreSQL only). See TLS & CA Certificates below. |
| Detect JSON in text columns | No | Per-connection toggle: when enabled, plain TEXT / VARCHAR values that parse as JSON are routed through the JSON cell renderer in the data grid (chevron, viewer window, diff). The same flag also enables native array detection for text[] / int[] (PostgreSQL) and Firestore arrays. See Data Grid → JSON & long text cells. |
*Not required for SQLite, which takes a file path instead.
TLS & CA Certificates (PostgreSQL)
Tabularis terminates Postgres TLS with tokio-postgres-rustls and verifies the server certificate via rustls-platform-verifier, so the platform's trust store (macOS Keychain, Windows certificate store, Linux CA bundle) is honored automatically.
If your database uses a CA the system store doesn't trust — typical for AWS RDS, GCP Cloud SQL with private CAs, or self-hosted Postgres behind a private PKI — paste the path to a PEM bundle into the connection's CA Certificate field. The bundle is loaded as an additional trust anchor only for that connection.
AWS RDS in particular: download the global certificate bundle from https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem and point the field at it. Tabularis intentionally does not vendor the bundle — AWS rotates these CAs every one to three years, and a vendored copy would silently break released apps the moment the next rotation lands.
MySQL/MariaDB connections continue to use native-tls and the system trust store; the ssl_ca field is a Postgres-only option for now. As of v0.13.0 the selected MySQL SSL Mode is honored on every code path — including the test-connection path, which previously attempted TLS even with ssl_mode=disabled — and connection pools are keyed by their TLS settings, so editing a connection's SSL mode can never silently reuse a pool created under the old mode.
The SSL Mode selector aligns with libpq semantics:
| Mode | Behavior |
|---|---|
disable |
No encryption. |
allow |
Try non-SSL first; fall back to SSL if the server requires it. |
prefer |
Try SSL first; fall back to non-SSL. |
require |
Force encryption, but do not require certificate validation. Use this with self-signed certificates (e.g., default AWS RDS without an explicit CA). |
verify-ca |
Force encryption and validate that the server certificate is signed by a trusted CA (paste the CA bundle into the CA Certificate field). |
verify-full |
Same as verify-ca, plus verify that the server hostname matches the certificate CN or SAN. Strictest mode; recommended for production. |
Startup Script
A connection can carry an optional startup script — SQL that Tabularis runs on every new physical connection in the pool. Because it executes per pooled connection (MySQL/SQLite via after_connect, PostgreSQL via the pool's post_create hook), session-level settings stick across the whole pool regardless of which connection serves a given query.

The motivating case is development against row-level security: a script like
SELECT set_config('app.bypass_rls', 'on', false);
applies to every subsequent query instead of randomly depending on which pooled connection you landed on. Any SET or session-setup statement works; multiple statements can be separated normally, and blank or whitespace-only scripts are skipped. The script is stored with the connection profile as non-secret configuration.
SQLite
For SQLite, provide the absolute path to the .db or .sqlite file using the file picker. There is no host, port, or authentication.
Testing before saving
Click Test before saving. Tabularis makes a real connection attempt and returns the exact database error if it fails (e.g., FATAL: password authentication failed for user "admin"). The test goes through the SSH tunnel if one is configured.
SSH Tunnel System

Tabularis has a full SSH tunneling implementation in Rust with two backends, selected automatically based on your auth method.
Two backends
russh (Native Rust SSH)
Used when a password is provided for the SSH connection. The tunnel is established entirely within the Rust process — no external ssh binary is involved. Host keys are checked against your ~/.ssh/known_hosts (trust-on-first-use for unknown hosts; key-changed errors are surfaced as a hard failure).
System SSH
Used when no password is provided (key-only authentication). Tabularis spawns your system's ssh binary and parses your ~/.ssh/config, which means ProxyJump chains, IdentityFile directives, and all other ~/.ssh/config features work automatically.
Dynamic port assignment
When a tunneled connection opens, Tabularis asks the OS for a free ephemeral port on 127.0.0.1, establishes the SSH tunnel to that port, then points the database driver at 127.0.0.1:<ephemeral_port>. You never need to pick a local port manually.
SSH profiles
SSH connections are stored as separate reusable profiles (ssh_connections.json). A single SSH profile (e.g., your production bastion) can be reused across multiple database connections. Manage SSH profiles via Settings → SSH Connections or the SshConnectionsModal.
| SSH field | Description |
|---|---|
| Host | Bastion hostname or IP |
| Port | Default 22 |
| User | Your user on the bastion host |
| Auth type | password or ssh_key — determines which fields are shown in the UI |
| Password | SSH password (uses Russh backend when set) |
| Key file | Path to private key (for ssh_key auth; uses System SSH backend when no password) |
| Key passphrase | Stored in OS keychain if "Save in keychain" is checked |
ProxyJump / multi-hop example
Define the chain in ~/.ssh/config and use the System SSH backend:
Host bastion
HostName bastion.example.com
User ec2-user
IdentityFile ~/.ssh/prod.pem
Host db-host
HostName 10.0.1.50
User ubuntu
ProxyJump bastion
Set the SSH profile host to db-host, auth type to ssh_key, and leave the password field empty. With no password provided, Tabularis uses the System SSH backend, which delegates to ssh and resolves the chain automatically.
Kubernetes Tunnels
For databases running inside a Kubernetes cluster, the connection modal's Kubernetes tab runs a managed kubectl port-forward as the transport — pick a context, namespace, resource, and container port via cascading dropdowns discovered from your kubeconfig. Saved K8s profiles live in k8s_connections.json and are reusable across connections, mirroring the SSH profile pattern. Connections with a tunnel show a blue K8s badge in the sidebar and on the Connections page.
Full reference: Kubernetes Tunneling.
Connection Actions
Right-click any connection — in the sidebar or on the Connections page — for:
- Edit — modify any field, including switching the SSH profile
- Duplicate — clone the profile with a new name and ID
- Delete — removes the profile from
connections.jsonand the associated keychain entry - Disconnect — closes the active connection pool and SSH tunnel without deleting the profile
- Open in New Window — opens the connection in its own standalone window (see below)
Open in New Window
Open in New Window spins a connection out into its own OS window — useful for keeping one database on a second monitor while you work in the main window. Tabularis test-connects first and only creates the window on success, so a failing connection surfaces its error where you triggered it rather than in a freshly-opened empty window.
A connection opened this way is owned by its window and detaches from the originating sidebar rail (its underlying pool stays warm and is reused). Open state is shared across every window — a connection open anywhere shows as open on every window's Connections page. Disconnecting closes the dedicated window; the main window is never auto-closed. Closing a dedicated window tears its connection down so nothing leaks.
Per-Connection Appearance
Every saved connection can override its driver's default icon and accent color. Open the New Connection modal (or edit an existing one) and expand the Appearance section in the General tab.
- Accent color — pick from a 12-swatch curated palette or paste a custom hex. The accent applies to the connection card on the Connections page, the sidebar entry once the connection is open, the Visual Explain modal's connection chip, and the editor tab bar of the active connection — the active-tab indicator, body gradient, loading bar, rename input, and split-pane panel headers all follow the connection color (falling back to the default blue when no connection is active). Falls back to the driver manifest color when no override is set.
- Icon — four mutually-exclusive tabs:
- Default — keeps the driver's manifest icon.
- Pack — a curated 30-icon subset of lucide-react covering the common shapes (cubes, clouds, layers, shields, branches…).
- Emoji — a single emoji grapheme of your choice.
- Image — upload a PNG, JPG, WebP, or SVG (max 512 KB). MIME type is validated against the file's magic bytes; SVGs are rejected if they contain
<script>,javascript:URLs, oron*=event handlers. Custom images are stored under<app_data>/connection-icons/and cascade-deleted when the connection is removed.
The override is persisted alongside the rest of the connection profile in connections.json and round-trips through Export / Import like every other field. The classic use case is differentiating two same-driver connections that would otherwise look identical in the sidebar — for example, a MySQL local in green next to a MySQL prod in red, each with its own icon.
Connection Groups
Connections can be organized into collapsible folder groups in the sidebar. Right-click on the connection list background and select New Group. Drag connections between groups by grabbing them in the sidebar.
Export / Import
The toolbar on the Connections page exposes Export and Import buttons (the Import button also appears on the empty-state view of a fresh install). Both operate on a single JSON payload that round-trips your full connection set between machines.
Export walks every connection group, saved database connection, and SSH profile, resolves the password stored in the OS keychain for each one (database password, SSH password, SSH key passphrase), and writes the lot into a JSON file. The payload contains plaintext credentials — treat it like a .env and store it accordingly. If you only need to move connection shape and not secrets, strip the password fields before importing.
Import takes that payload, merges it with the existing config (existing connection IDs are kept; new ones are appended), writes any embedded passwords back into the OS keychain under the same service-name conventions described in Keychain Details, and persists connections.json and ssh_connections.json. Empty password fields leave the matching keychain entry untouched, so partial payloads are safe.
A confirmation dialog is shown before import; the dialog uses a non-destructive variant to signal that nothing is being overwritten in place.
Multi-Database Support (MySQL / MariaDB)
MySQL and MariaDB allow a single connection to read and write across multiple databases on the same server. Tabularis exposes this natively: when creating or editing a MySQL connection, open the Databases tab and click Load Databases to fetch every database visible to your user. Check the ones you want and save.
Each selected database appears as its own collapsible node in the Explorer sidebar. Expand a node to see its tables and views. Double-click a table to open it in the editor.
Cross-database references use fully qualified names (database_name.table_name) automatically, so MySQL resolves them correctly regardless of which database the connection was initially opened against.
The connection format accepts either a plain string ("mydb") or an array (["db1", "db2", "db3"]). Existing single-database connections continue to work without any changes.
This feature applies only to drivers that support cross-database access from a single connection. SQLite (file-based) and PostgreSQL (schema-based) are unaffected.
Cleartext Password Plugin (MySQL bastions)
Some MySQL proxies — notably Warpgate — require the mysql_clear_password auth plugin and do not implement the prepared-statement protocol, so ordinary prepared queries fail with server error 1047. Enable Cleartext password plugin in the MySQL connection's advanced options to authenticate through them; when it's on, the driver routes every statement through the text protocol instead of preparing it.
Because the plugin sends the password in cleartext, the toggle is only available when an enforced TLS mode is selected (require, verify-ca, or verify-full) — prefer and disable are rejected, since they can silently fall back to an unencrypted link.
Multi-Schema Support (PostgreSQL)
When connected to PostgreSQL, Tabularis loads all schemas by default. To control which schemas appear in the sidebar for a given connection, use the schema selector in the sidebar header. Your selection is persisted per connection in config.json under selectedSchemas.
The schema preference (which schema is "active" for DDL operations like CREATE TABLE) is also persisted per connection under schemaPreferences.
Connection Health Check
Tabularis continuously monitors every active connection with a lightweight ping loop. If the backend detects that a connection is no longer reachable, it automatically disconnects it and notifies you with a toast alert.
How it works
- Every N seconds (default: 30), Tabularis sends a ping to each open connection.
- Built-in drivers (PostgreSQL, MySQL, SQLite) use a pool-level
ping— no extra query is executed. - Plugin drivers receive a
pingJSON-RPC call. If the plugin has not implementedping, Tabularis falls back totest_connectionautomatically. - After 2 consecutive failures, the connection pool is closed, the connection is removed from the active set, and a
connection-health-failedevent is emitted to the UI.
Configuring the interval
Open Settings → General → Connection Health Check and adjust the Ping Interval slider (0–120 seconds). Setting it to 0 disables health checks entirely.
The setting maps to the pingInterval key in config.json (see Configuration).
What happens on failure
When a health check failure triggers a disconnection:
- The connection pool is closed and resources are freed.
- Any SSH tunnel associated with the connection is torn down.
- A toast notification appears with the error message and a button to navigate back to the Connections page.
- You can reconnect at any time by clicking the connection again.
Read-Only Mode
Toggle Read-Only on a connection to block DML and DDL statements at the application layer. Tabularis parses the SQL AST before execution and refuses to run INSERT, UPDATE, DELETE, DROP, TRUNCATE, CREATE, or ALTER statements. This is a client-side guard — not a substitute for proper database-level permissions.
Keychain Details
The keychain service names used by Tabularis follow these patterns:
| Secret type | Keychain service key |
|---|---|
| DB password | tabularis-connection-<uuid> |
| SSH password | tabularis-ssh-<uuid> |
| SSH key passphrase | tabularis-ssh-passphrase-<uuid> |
| AI API key | tabularis-ai-<provider> |
On macOS you can inspect an entry manually:
security find-generic-password -s "tabularis-connection-<uuid>" -w
On Linux with secret-tool:
secret-tool lookup service tabularis-connection-<uuid>
