Features

Not a feature list, but one task from start to finish

Create a connection, run a query, edit the result and check the status bar, in eight scenes. All eight are real screens, none of them scaled up or down.

01Connect

Start by creating a connection

Pick a DB type and enter the host, port and user. Two things are already decided here: where the password is stored and whether this is a production server.

The new connection form (General tab). “New Connection” in the Name field, “MySQL / MariaDB” in the DB Type dropdown and next to it the “Mark as a production server (red tab and status bar)” checkbox. Below are Host localhost, Port 3306, User root, an empty Password field with a note under it, and Default Database scratch.
The note under the password field says where it goes: Stored only in the OS keychain (never written to the profile file). The Mark as a production server checkbox above marks this connection as a production server.

Passwords go only into the OS keychain

That means Keychain on macOS and Credential Manager on Windows. Passwords are never stored in plain text. Open the profile file and you won't find one.

Production servers look different

A connection marked as production shows a different tab and status bar, so you don't have to remember which server you're on.

Idle connections stay open

DBerio reads the server's wait_timeout and interactive_timeout and sends a ping at half that interval (between 15 and 60 seconds). It does not reconnect automatically, on purpose. Quietly reviving a dropped connection would silently lose any transaction that was open. If you need an SSH tunnel, set it up in the second tab of the same form.

SSH tunnels are the second tab of the same form

Connections that go through a jump server are set up in the same place, with no extra tool. Like the connection form, the notes on this tab tell you what is stored where rather than just what to enter.

The SSH Tunnel tab of the connection form. The “Open this connection through a jump server” checkbox, SSH Host bastion.example.com, SSH Port 22, SSH User deploy, Authentication “Key file”, a Private Key File picker button, and the Key passphrase and Host Key Fingerprint fields, each with a note.
The key file field says Only absolute paths are stored, and the passphrase field says Stored in the OS keychain as an entry separate from the DB password, so it goes into the keychain as a separate entry from the DB password. For the fingerprint, The fingerprint is checked and stored on the first connect: it is saved the first time you connect and checked on every connection after that. You never type it in.

02capability

Once connected, the screen fits that DB

DBerio doesn't squeeze four kinds of database into one screen. When an adapter connects, it asks what this DB can do, and screen elements turn on or off based on the answer. That's why Redis opens a key browser instead of a query editor. Redis is a key-value store, not SQL.

DB Type Where the screen differs
MySQL · MariaDBSQLReference screen
PostgreSQLSQLDDL can be rolled back inside a transaction
SQLiteSQLChanging a column type rebuilds the table, and there is no users and privileges screen
RedisKVKey browser, TTL and views for each value type. No query editor
DBerio connected to Redis. There is no query editor. On the left are a key pattern field and a folder tree under db0 (bulk, tags, text, user, stream, leaderboard, queue, counter, big, session), with name string and profile hash under user:3. On the right are the “user:3:profile hash · TTL Permanent · Set expiry” header and a field/value table. The status bar at the bottom shows Key ≈10,026 · hash TTL Permanent · Transaction Interactive transactions not supported.
Same app, but no query editor. Keys in the tree carry a badge for their value type (string, hash), and the header shows TTL Permanent with a button to set an expiry. The right side of the status bar is explicit: Transaction: Interactive transactions not supported. The transaction UI isn't just greyed out. The app states that transactions don't apply to this DB.

This is the whole window (1440×892). It isn't cropped so the status bar at the bottom stays visible. The image is shown at 1:1. On a narrow screen, scroll sideways inside the image.

It asks about screen elements, not labels

DBerio doesn't stick a broad label like “SQL or key-value” on a database. The UI only needs to know whether a given screen element makes sense, so capabilities are defined at that level.

capability What it asks
transactional_ddlCan DDL be rolled back inside a transaction?
supports_interactive_transactionDo autocommit, commit and rollback mean anything?
supports_ttlIs there a concept of TTL?
supports_column_modifyCan an existing column's type be changed?
supports_editable_resultsetCan F8 (editable results) be turned on?
supports_multiple_result_setsCan it return multiple result sets?
supports_user_adminDoes a users and privileges screen apply?
supports_schema_syncDoes a schema sync tool apply?
value_typesKey-value types: String, Hash, List, Set, ZSet, Stream

The only screens on this page are MySQL and Redis. There are no real captures of PostgreSQL or SQLite yet, so they aren't shown. Instead of drawing screens that don't exist or labeling other screens with their names, the table above describes them in words.

03Run

Three run keys, each with its own meaning

The point isn't that there are three keys. The point is that you choose what kind of result you get back for the same query. And that promise is written in small print under each button, not in a manual.

The three buttons on the run toolbar. From the left: “Execute — One query at the cursor · read-only”, “Execute (Editable) — Same query · asks for an editable result” and “Execute Selection — Selection only · does nothing without one”.
Each button states what it does right underneath it. You don't have to press it to find out.
  • F9 ExecuteOne query at the cursor · read-only
  • F8 Execute (Editable)Same query · asks for an editable result
  • Ctrl+F9 Execute SelectionSelection only · does nothing without one

The default is the safe option

F9 runs only the statement under the cursor, and the result is read-only. A LIMIT 1000 is added by default, and one extra row is read to tell whether there's more. You won't pull in ten million rows by accident. If you run the wrong thing, you can stop it without dropping the session. Query cancellation is a required part of the contract for every adapter.

With a selection, the third button tells you so

The run toolbar and three lines of the editor with a selection. The third button's note now reads “Selection only · 3 lines right now”, and three lines of SELECT … FROM scratch.orders ORDER BY placed_at DESC are selected in the editor below. On the right are the autocommit ON toggle and the Commit and Rollback buttons.
Drag to select, and the third button's note changes to Selection only · 3 lines right now. You know what will run before you press it, and with no selection it runs nothing at all (does nothing without one). It never quietly runs the whole editor.

The image above is at its original size (1044×112). On a narrow screen, scroll sideways inside the image.

Tabs don't pile up

F9 and F8reuse the same result tab. You don't get a new tab every time you run a query.

04Results

Results tell you their own state

This result came from F9. The header already says Read-only (F9) · F8 to edit. Editing actions are turned off for the same reason. You won't have to click around to figure out why something doesn't work.

A read-only result grid. Column headers id bigint unsigned, customer_id int unsigned, amount decimal(10,2), status varchar and placed_at timestamp, with 12 rows below sorted by placed_at descending.
Column headers show the name and the type together, as in amount decimal(10,2). No need to count whether there are two decimal places or four. You can also see that the rows are sorted by placed_at, not id. The query ran with F9, so the result is read-only.

The image above is at its original size (1030×246). On a narrow screen, scroll sideways inside the image.

Why editing is off is defined as a type

That's why the screen never gives a vague answer. When editing is off, it's for one of the five reasons below, and the reason is shown as is.

Reason What it means
Not requestedRan with F9. An editable result wasn't requested
Not supported by adapterThis DB's adapter doesn't support editable result sets
No source tableOnly expressions or aggregates, so there's nowhere to write back
Multiple tablesIt's a JOIN result, so there's no way to decide which table to update
Same source column twiceIt's a self-join. This prevents the wrong row from being updated without notice

Export re-runs the query instead of saving the rows on screen

This matters. Normal runs have a row limit, so saving the rows on screen would give you only the first part of the data. Export runs the same statement again without the limit.

The “Export Result Set — scratch-mysql” dialog. Target is “Query result (12 rows shown)” with a note below it. Format has CSV, TSV and JSON with CSV selected, Save file can only be set with the file button, Delimiter is a comma, “Write column names on the first line” is checked, and Encoding is UTF-8 with CRLF line endings. At the bottom: “Export is read-only — it does not change the source data.”
The note explains why: Writes the result of re-running the same statement with no row limit, not the rows on screen. The bottom line, Export is read-only — it does not change the source data., confirms that exporting never touches the original data. (This is a result set export, so it has three formats. Table data export also offers SQL and Excel.)

The grid draws only the visible rows (virtualized rendering), and large results are streamed in chunks instead of all at once. For the same reason, you can't type a save path by hand. Only the absolute path returned by the file dialog is used.

05Edit

Press F8 only when you mean to edit

Run the same statement again with F8 and the result mode changes. So does the header.

An editable result grid. The header reads “Done 3 rows · 47ms · First chunk 36ms · Editable — edit a cell and leave the row to save (Esc to discard)”. Row checkboxes are turned on.
The badge in the header changes to Editable — edit a cell and leave the row to save (Esc to discard). It tells you exactly when changes are saved, so there's no guessing.

The image above is at its original size (1030×298). On a narrow screen, scroll sideways inside the image.

This one extra step is the reason the product exists

Since editing needs its own key, there's no default path that changes production data by accident. For people who use a DB client all day, defaults like this matter more than the number of features.

06Status bar

The status bar covers the rest

The result header is about “this run”. The status bar is about “this window right now”. It shows the connection state, the selection, the cursor position and the encoding.

The right side of the status bar. “Connected to scratch-mysql · Selection 3 lines · 98 chars · Cursor Ln 3, Col 27 · UTF-8”.
It shows the connection name, the selection (3 lines · 98 chars), the cursor position and the encoding. The left side shows the server version, load and transaction mode, which you can see in scene 08.

Table options follow the same rule. Values are read from the server, so AUTO_INCREMENT is the real next number and the engine is the table's real engine.

07Shortcuts

Every key used so far comes from one contract file

Key bindings come from a single source, docs/keymap-contract.json (v0.7). Writing shortcuts directly into components is not allowed, and an audit checks the contract against the code automatically. The keys match because they're checked, not because someone lined them up by hand.

For you, that means three things: shortcuts are the same on every OS, all of them can be changed (including JSON export), and they don't change between versions.

Item Value
Actions102 (number of actions)
Key combinationsWindows 114, macOS 126
Scopesglobal 66 · editor 19 · grid 9 · browser 6 · dialog 2
Categorieseditor 18 · schema 18 · result 12 · connection 9 · common 9 · browser 6 · powertool 5 · tools 5 · statement 4 · query 3 · format 3 · panel 3 · user 3 · app 3 · favorites 1

This is everything that changes on macOS

The rule is to keep Ctrl combinations working on macOS too. Where they clash with keys reserved by the OS, the Windows key is kept and an alternative key is added. Of the 102 actions, 13 have different keys on macOS, and 12 of those simply add a Cmd combination while keeping the Windows key. The only Windows key that's gone is Quit. Alt+F4 doesn't exist on macOS, so it became Cmd+Q.

Action Windows macOS Why
Autocomplete Ctrl+SpaceCtrl+Space · Option+EscOn macOS, Ctrl+Space is used to switch input sources
Insert/Update dialog F11F11 · Cmd+F11F11 is the system's “Show Desktop” key
Close tab Alt+LAlt+L · Cmd+WmacOS convention, and it keeps this separate from disconnecting
Copy, paste, save, find, undo Ctrl+…Ctrl+… · Cmd+…Common editing actions also accept the Cmd combination
Quit Alt+F4Cmd+QThe only action where the Windows key was replaced

One thing to know up front. On macOS, F1 to F12 act as media keys by default. To use F9, F8 and F12, turn on “Use F1, F2, etc. keys as standard function keys” in System Settings.

The first-run guide points out this setting, and combinations with Fn also work.

Menus are built from the same contract. macOS uses the native menu bar and Windows uses an in-window menu bar, and there's no place where keys are written into menus by hand.

08One window

Everything so far is part of one window

The result header (04), the grid (05) and the status bar (06) aren't separate screens. Below is the bottom half of the main window, cropped straight from the original, showing how the three fit together.

The bottom half of the main window. On the left is the empty lower part of the Object Browser panel. On the right are the Result 1, Profiler, Messages, Table Data, Info and History tabs, the result header “Done 12 rows · 59ms First chunk 51ms · Read-only (F9) · F8 to edit”, the result grid below it, and the status bar across the bottom of the window.
This is the bottom half of a single window. On the left of the status bar are Load 0.6 q/s · 2 / 151 · 2, the server version and the transaction mode. At the far right is the cursor position you saw in scene 06.

Cropped from the original 1440×892 below y=562. The cut is at the border between the editor and the result panel, so it ends at a panel edge rather than halfway through a row. The image is shown at 1:1. On a narrow screen, scroll sideways inside the image.

One filter box finds everything on the left

Above the cropped area, on the left, is the Object Browser. The filter doesn't search only tables. The same text also finds views, procedures and triggers.

The Object Browser panel. “ord” is typed in the filter box under root@127.0.0.1:33107, and under scratch utf8mb4 it shows Tables (order_items, orders), Views (v_customer_orders), Stored Procedures (sp_count_orders) and Triggers (trg_orders_ai AFTER INSERT · orders, trg_orders_bi BEFORE INSERT · orders).
Three letters, ord, found tables, views, procedures and triggers together. Triggers also show when and where they fire, as in AFTER INSERT · orders. You don't pick an object type first. If you know the name, it shows up.

The rest of the window

Tabs come in three levels: connection tabs, query tabs and result tabs. There are also a connection manager, a table structure editor (columns, indexes, foreign keys, options and SQL preview) and a users and privileges screen.

EndBuild

Even error messages are in your language

The app is available in three languages: Korean, English and Japanese. Switch with Alt+Shift+L inside the app. Each language has the same 1,499 translated strings.

Many tools translate only the interface and show server or engine errors in English. Here, the backend sends a template and its values instead of a finished sentence, so the error message itself is built in your language. Messages from the server itself (MySQL or PostgreSQL error text) are shown as they are. Those aren't ours to translate.

What it's built with

Layer Details
ShellBuilt with Tauri 2, using the OS web view instead of Electron. That's WebView2 on Windows and WKWebView on macOS.
BackendRust (mysql_async, tokio-postgres, russh, keyring)
FrontendReact 19, TypeScript, the Monaco editor, Glide Data Grid and Zustand
IPC typesTypeScript types are generated from the Rust definitions, not kept in sync by hand

The editor is Monaco. It reads the schema for autocomplete, and its built-in keys are synced with the same keymap registry. Export formats depend on where you start the export: table data supports CSV, TSV, JSON, SQL and Excel (xlsx), and result sets support CSV, TSV and JSON. Database connections and license checks run inside the compiled Rust binary. There is no license logic in the frontend JS.

The “Export Table Data — scratch-mysql” dialog. Target is scratch.orders, and the Format row shows five options side by side: CSV, TSV, JSON, SQL and Excel (xlsx).
Table data export puts all five formats on one row: CSV, TSV, JSON, SQL and Excel (xlsx). The formats differ from result set export because the two start from different places, not by mistake.
Two lines in the editor. With “SELECT id, customer_id, amount, status” and then “FROM scratch.or” typed, the autocomplete list is open, and the “or” part of the four suggestions order_items, orders, sp_count_orders and v_customer_orders is in bold. Each suggestion has a different icon for table, procedure or view.
Suggestions come from the schema, so views and procedures appear along with tables, and the icon tells you which is which. The letters you typed, or, are shown in bold wherever they match, even in the middle of a name.

There are no “X times faster” numbers here because we haven't measured anything. We haven't measured memory use, startup time or query speed. All we can say for now is the structural fact that it's a native app using the OS web view.