A modular database workbench for any JDBC driver. Built for the servers that are still running the business — the DB2 that predates the tooling, the SQL Server nobody is allowed to upgrade — without giving up anything on the modern ones.
Download
Each package carries its own Java runtime, so there is no JDK to install first and no version to get wrong. Copy the folder to a desktop, a share or a memory stick — it runs from wherever it sits.
First start asks for an email address and issues a licence that lasts a year. It is free. After that the application works without a network connection until the licence expires — which is the point, because the databases it is built for often sit on networks that have none.
On macOS, the launcher clears the quarantine flag the system puts on
anything downloaded from the internet, so the first run needs nothing extra from
you. On Windows, if double-clicking appears to do nothing, run
Ananke (cu consola).bat — it keeps the window open and shows why.
Your connections, logs and exports are written to ~/.ananke, never
into the folder itself, so a newer package can replace an older one without
losing anything.
What makes it different
Every database tool lists the same features. These are the decisions that are actually ours — each one there because the alternative failed against a real server.
Modern tools drop old databases because supporting them is unglamorous work.
Ananke is verified against DB2 9.5 and
SQL Server 2014 through their original drivers.
Pre-JDBC-4 jars declare no driver class, so the loader scans them and picks the one
that accepts the URL. Metadata reads survive AbstractMethodError, because
a driver that predates a JDBC method raises it rather than answering false.
When a connection fails, the failure is diagnosed rather than repeated back at you: undersized Diffie-Hellman keys, TLS versions the JDK has retired, a SID given where a service name was wanted, a port with nothing behind it. Each one comes with the next step.
A connection can carry its own driver jars, loaded in their own child-first class loader. The 2008-era Oracle thin driver for the legacy database and the current one for everything else, connected at the same time, in the same application. Most tools have one driver per database type and expect you to pick.
A dialog is forgotten the moment it closes. A statement is saved with the script and runs again next month, on the next environment, from the same file you reviewed last time.
-- structure, data, or both — written where the script says EXPORT DDL > * FROM dbo.tbl_Users EXPORT INSERT > * FROM dbo.tbl_Users WHERE active = 1 ORDER BY id EXPORT EXCEL > * FROM dbo.orders EXPORT CSV > id, name FROM dbo.orders -- follows the foreign keys and takes what the row depends on EXPORT CASCADE INSERT * FROM dbo.orders WHERE id = 42
Rows are streamed and written as they arrive, so the size of the table is not the size of the memory it needs.
Everything that changed something is recorded — one file per connection per day, with the
user, the catalog, the outcome and the elapsed time. Not a log format somebody has to parse:
results and errors are comments, failed statements are commented out, and a USE
marks each change of catalog. The day's work replays against the next environment as it stands.
USE dbNORTHSTAR; -- 2026-08-08 20:14:27.387 user=reporting OK 1 row(s) affected 12 ms UPDATE dbo.tbl_Users SET status = 'A' WHERE id = 5; -- 2026-08-08 20:14:27.390 user=reporting FAILED conflicted with FK_lines_orders -- DELETE FROM dbo.orders WHERE id = 1
Reads are not recorded. A SELECT changes nothing, and logging every one buries
what matters.
"Are you sure?" is not a safety feature — nobody reads it twice. Set an undo limit and the rows are read before anything is written: that answers how many will change, and the same read produces the statements that would put them back. Over the limit, nothing is written until you say so.
Environments carry this as policy. Production defaults to manual commit and to confirmation before any data modification, and tints the connection in the navigator so you can see which one you are typing into.
Statements that changed nothing. An UPDATE whose
WHERE matched no row is how a migration silently does half its job — no error,
no effect, and a line that reads exactly like a success. They are counted and listed, with line
numbers, so you find them before the next environment gets the same file.
Comparing two databases writes a script and never runs it. Aligning databases can drop rows, and the only defensible design for that is a script somebody reads first. Missing tables, new columns, widened columns, indexes and foreign keys are written. Narrowing a column, changing its type and dropping anything are reported and never written — each of those can lose data.
Features
Everything below is built and tested. What is not built yet is listed further down — we would rather you find that here than after installing.
Highlighting, bracket matching, bookmarks, multiple cursors, and a splitter that knows a semicolon inside a literal or a comment is not a separator.
SELECT u. inside FROM tbl_Users u offers that table's columns.
Metadata is read once, in the background, so the popup never blocks the keyboard.
Millions of rows at constant memory. Sort, filter, hide, move and resize columns; copy with headers; export the selection.
Insert, update and delete with the generated DML shown before it is applied. A table without a primary key is read-only, and says why.
Which tables have a customer_id? — the question asked before a migration, and the one a tree cannot answer. Several column names at once, partial names allowed.
Procedures, functions, triggers and views open as editable, searchable text — read from each product's own catalogue, because JDBC cannot be asked for source.
Paste rows, write the statement once with {0} and {1}, get one per row.
Quotes are doubled, so O'Brien does not end the statement early.
Every .sql in alphabetical order — the order migrations are named to run in — under
one progress bar, optionally as a single transaction.
Open query windows are saved on exit and restored on start: text, connection, database, delimiter and row limit — whether or not the connection is up.
Every driver carries its Maven coordinates. One click downloads the jar and registers it. Nothing is ever fetched unless you ask.
Each plugin jar loads in its own class loader, starts in dependency order, and a failure in one cannot take down the others.
~/.ananke — JSON configuration with atomic writes and corrupt-file quarantine.
Passwords are AES-GCM ciphertext, never clear text.
Databases
Legacy variants sit beside the current ones, because "SQL Server" in 2014 and "SQL Server" today are not the same connection. Only H2 and SQLite are bundled — the rest have licences that make redistribution awkward, so they are downloaded on request.
Engineering
Nine modules with one-way dependencies. Nothing below the user interface knows the toolkit exists, so the entire data path is tested without a display — which is why it can be tested at all.
The suite needs no server and no network. A test that cannot run is not a test.
Java 21 and JavaFX, nothing else underneath. It starts when you double-click it.
Exports write as rows arrive. Data comparison walks both sides in key order — one page of memory per side, whatever the table size.
No server, no agent, no account, no telemetry. It talks to your databases and to nothing else.
Status
Ananke is version 0.1.0 and under active development. A product page that hides that
would be the first thing we got wrong, so here is the honest picture.
Connections and driver management, the metadata browser, the SQL editor, execution and the result grid, in-grid editing, export, database comparison, script running, the safety policies and the audit log. Verified against real servers: DB2 9.5 on Windows and SQL Server 2014, both through legacy drivers.