VisuaLeaf v1.0.2350 Release Notes
Release Date: September 14 2026
Headline: Quality-of-Life Release — Favourite Views, Cell Previews, Follow Any Foreign Key, and a Shell That Opens Instantly
This one is full of the small things you hit every day. **Results open in the view you actually
want — set it once, or let VisuaLeaf notice and offer. Hover any grid cell and read the whole
value, instead of right-clicking a clipped ellipsis into a panel. Follow a foreign key from
anywhere you see one**, in the tree as well as the grid, into a tab beside the one you came from
instead of a screen sliced in half. And the Visual Shell opens straight away on TLS connections
rather than sitting on "Starting shell session…" for a minute.
Alongside those: schema diagrams gained a text side — paste DBML or JSON Schema and watch the
diagram build itself, edit the diagram and watch the text follow. Verify Schema works, in both
directions and with counts you can trust. **Every import and export now reports what actually
happened**, so a run against a server that is down fails in seconds instead of finishing green an hour
later. And a computer that is never allowed online can now be activated, by carrying a short code
to any device that has internet and a token back.
Also shipping: bring-your-own AI endpoint, a cleaned-up MongoDB index manager, saved SQL queries that
reopen with their builder intact, and a long list of SQL fixes across PostgreSQL, MySQL, Oracle,
SQLite and DuckDB.
Offline Activation
Some computers are not allowed to reach the internet — a workstation on a regulated network, a machine
in an isolated lab, a laptop behind a proxy that swallows everything. Until now those computers could
not be activated at all. You can now activate any computer without it ever connecting.
What you can see
- A third tab in the Activate window: Offline. It shows this computer's activation request code —
- A place to paste the licence token you get back, or open it from the file you were emailed.
- **Settings → Licensing shows an Offline licence line** with the date it is valid until and how many
- **In your licence-server account, Licenses → Device Activations has Activate a machine offline.**
a short block of text that describes the computer and can only be read by the licence server — with
Copy and Save as file… next to it.
Before you activate, one line tells you exactly what will happen: the plan, the date it is valid
until, and that it is for this computer. If the token is for another machine, or is a server licence
pasted by mistake, it says so in words and the Activate button stays off.
days are left, and offers Re-activate offline when the time comes.
It reads the code you paste, shows the machine it came from, tells you how many of your machine
activations are in use, and hands you the token — on screen, as a download, and by email with a.vlic attachment. Offline machines are marked in the list with the date their token runs out.
What you can do
- On the offline computer, open Activate → Offline and copy the request code, or save it to a
- On that device, sign in to your licence-server account, open the licence, and choose **Activate a
- Back on the offline computer, paste the token or open the file, check the one-line summary, and
file. Carry it to any device that is online.
machine offline**. Paste the code, confirm, and copy or download the token. It is also emailed to you.
click Activate. That's it — the computer never needs to connect, not now and not later.
A few things worth knowing:
- An offline computer never contacts the licence server again. No check-ins, no telemetry, no
- An offline token lasts up to a year (or until your licence ends, if that is sooner). About a
- When a token runs out, VisuaLeaf keeps working as Community Edition until you re-activate.
- To move the activation to another computer, release the machine on the Device Activations page.
- Offline activation is for the desktop app. Server installs already have their own licence file.
waiting on a connection that is not there — not even on startup.
month before it runs out VisuaLeaf reminds you, and the licence server emails you too. Renewing is
the same three steps and does not use up another machine activation.
Nothing is deleted.
The original computer keeps working until its token runs out.
Community Edition Actually Works Offline
There used to be four situations where VisuaLeaf told you it was "running as Community Edition" and
then locked everything, including the Connection Manager: a fresh install behind a firewall that had
never reached the licence server, a licence that had lapsed, an offline token that had run out, and a
build newer than your update window. All four now give you a real free tier — connections, shell,
queries, aggregation, table and tree views, saved queries and scripts, inline editing and the rest of
the Free plan — instead of an empty app with a banner on it.
Starting a trial got shorter too: **click the link in the verification email and the trial unlocks by
itself**, a few seconds later, without coming back to the app to press a button. You can close the
"check your inbox" screen and it still works.
Schema Diagrams: Type It or Draw It
The schema designer gained a text panel beside the canvas, and the two stay in step with each other.
What you can see
- A live text view of the whole diagram, in DBML or JSON Schema. Edit a card, drag a
- A "what Apply would do" summary before anything happens: green chips for what gets added, red for
- A Relations panel listing every relation in the diagram, searchable, with a count. Rows are
relation, rename a field — the text updates as you go.
what gets removed, blue for what changes. Syntax errors are pointed at the line, and the message
waits for you to stop typing rather than flickering on every keystroke.
flagged when a relation points at a card that isn't on the canvas any more, or at a card you've
hidden. Click a row and the canvas frames that relation.
What you can do
- Paste a DBML or JSON Schema document and get a diagram — tables, columns, types and the
- Export the diagram back out as DBML or JSON Schema, to share, to check into a repo, or to feed to
- Edit either side. Fix a column in the text, apply, and the cards move; move the cards, and the
relationships between them, laid out for you.
another tool.
text says the same thing.
Relations drawn between cards are also more accurate now, and the relationship detector no longer
proposes matches it can't back up.
Verify Schema
Checking a collection against its JSON Schema now works — and gives you an answer you can trust.
- Both questions, one toggle. Switch the result set between the documents your schema rejects
- "Verify Schema" used to fail outright on the matching side. Asking which documents match the
- "Not matching" used to list the entire collection. In a collection of ~9,000 documents where 259
- **You can see why a document was rejected.** Offending fields are flagged in the tree view where
and the ones it accepts, without touching the query. Each side is asked of the whole collection
rather than the page you are looking at, so the counts and paging are real.
schema returned an error instead of results. Fixed — both directions run.
genuinely failed the schema, the not-matching list quietly returned all of them. The worst kind of
bug: the query succeeded and returned rows, so nothing looked wrong. Fixed.
you are reading them, and a field the schema requires but the document doesn't have is marked on the
document itself — previously a document rejected for a missing field looked perfectly fine.
Imports and Exports That Tell You the Truth
A mongodump task whose server was down used to run for a full minute and finish **Completed, with a
green badge and an 80% success rate**. That whole family of dishonest outcomes is gone.
What you can see
- **A new outcome: Completed with errors.** A run that finished but skipped collections along the way
- A run that could not reach its source or target fails immediately, in seconds, naming the
- The history charts count it honestly. A run that finished with errors has its own colour on the
- A run that had nothing to do says so, in the history, with the reason ("no tables matched", "no
- Tasks that reference a connection you deleted are called out before the run, rather than failing
- One unreadable job no longer takes the whole export area down with it. A job saved by a newer
no longer wears the same badge as one that didn't. The failed pieces are listed by name.
connection and the host — instead of grinding through the whole job first. This now covers MongoDB,
every SQL engine, and S3-compatible storage.
timeline and lowers the success rate rather than disappearing into the green.
.sql files in this folder", "this cluster has no user databases") and a hint on how to fix it.
Empty upstreams are legitimate in a chained pipeline, so the run still counts as finished — it just
isn't silent about it any more.
halfway.
build could name a source or target this build doesn't know, and that single row made every export
screen fail to load — and keep retrying every few seconds. Now it costs that one job, which shows an
unknown target you can re-pick, and everything else loads.
What you can do
- Trust the file on disk. An export writes to a temporary file and only replaces the previous one
- Resume a restore and have it actually resume. Collections that already landed are skipped instead
- Cancel a run and see it as cancelled, not quietly relabelled Completed.
- Pick schemas, not just databases, for SQL jobs. Export jobs, data-source variables and the mock
once it has finished. A failure halfway through no longer overwrites last night's good export with
tonight's truncated one — that goes for CSV, JSON, SQL scripts, SQL dumps and Mongo→SQL exports.
of being dropped and re-imported.
data generator all take a schema now, and the picker remembers what it already loaded instead of
re-fetching every time you open it.
Bring Your Own AI Endpoint
(GitHub issue #32) Settings → AI now takes a provider you point at yourself: **base URL, model id and
API key**. There is one entry per wire format rather than one per vendor —
- OpenAI-compatible — anything speaking the chat-completions API: a local Ollama, OpenRouter,
- Anthropic-compatible
- Gemini-compatible
a third-party gateway, or an enterprise install.
Paste the URL in whichever form your provider publishes it — with or without the trailing /v1, both
work. (This also fixes Grok, which was hitting a doubled path and failing.) Where a gateway renames the
models it serves, two dropdowns let you override how requests are shaped instead of leaving VisuaLeaf
to guess from the model name. Ollama takes an optional API key for setups behind an authenticating
proxy, and existing AI settings keep working untouched.
A provider with no API key is no longer reported as unconfigured. The AI Assistant toggle read
"AI Assistant (Not configured)" with a greyed-out icon while the assistant beside it was happily
answering from a local model. Ollama has no key and a self-hosted endpoint needn't have one; both now
show as configured.
SQL
Foreign keys
- "Go to referenced table" now appears in the tree view as well as the grid. It used to exist only
- Following a key opens a normal tab beside the one you came from, instead of splitting the screen
- Each hop gets its own tab, named after the key you followed —
fk_customers (id=3)— so you can - Foreign keys are editable in the table designer. Change
ON DELETE/ON UPDATEon an existing
in the table grid — and the tree is the default view — so on a fresh install right-clicking a column
badged FK offered nothing at all. (SOZO-1505)
in half for what is a lookup. (SOZO-1455)
hold two rows of the same table side by side. Following the same key twice focuses the tab you
already have rather than piling up duplicates.
key, add or remove column pairs on a new one, and see modified fields ringed before you save.
What the tree offers you can actually open
- MySQL: a database you have no privilege on is no longer listed, expanded, and then failed with a
- Oracle: the tree used to offer 19 schemas and only ever fill 9 — the two halves of the tree
raw driver error. If an operation does hit a permissions wall, you get a sentence you can act on
instead of Access denied for user 'x'@'%' to database 'y'.
disagreed about which system schemas to hide. They now use one rule, so every schema listed is one
that opens.
Values that come back as themselves
jsonbin the SQL editor renders as a document you can expand, not as a three-field wrapper with- Fixes for SQLite and DuckDB value handling, and for Neon specifically.
- Browsing a DuckDB file no longer poisons every later connection to it. Once you had opened a
your JSON trapped inside as an escaped string. The editor, the table browser and row comparison now
read values the same way, so the same column no longer shows two different answers in two places.
This covers PostgreSQL and every Postgres-family engine — Neon, Supabase, Timescale, Citus,
CockroachDB, YugabyteDB, Redshift, CrateDB, QuestDB and the rest. (SOZO-1495)
DuckDB file in the tree, export pre-flight, the export run itself and Test Connection all failed
against that same file with "Can't open a connection to same database file with a different
configuration" — for the rest of the session.
Saved queries reopen as you left them
- A saved query remembers which engine it belongs to. A DuckDB, Oracle or MySQL query used to
- It remembers the schema too, so the table it addresses is the one you saved it against rather
- The visual builder comes back with it. Joins, filters and canvas layout are restored instead of
reopen labelled Postgres and generate Postgres-dialect SQL.
than a same-named table in the connection's default schema — or nothing at all.
the tab opening on bare SELECT text with an empty builder. Queries saved before this release open
exactly as they did.
Users and roles
- The SQL user management page's create-user and role dialogs are now proper modals — they stack,
- User & Roles Management no longer appears for SQLite and DuckDB. Those engines have no users to
close on Escape, and lock the page behind them like every other dialog in the app.
manage, so the page opened on zeroes and every button on it failed.
The table designer
Every control across the columns, foreign keys, indexes, partitions, triggers and constraints tabs —
and the create-table form — now sits on one size, one type scale and one surface. A single row used to
mix a 22px pill, a 28px button, a 29px input and a 30px select. The forms also follow the UI font you
picked in Settings → Appearance, which they previously ignored.
Visual Shell
- Opening a shell on a TLS connection is fast again. (GitHub issue #31) It used to sit on
- A brand-new shell no longer says "Not Connected" with Run greyed out. It was connected the whole
- Turning a shell session off works properly.
find()filters keep their BSON types. A filter matching on a date, anObjectIdor a
"Starting shell session…" for up to a minute on a connection the dashboard opened instantly; the
shell now opens with the same settings as the rest of the app — your custom CA, self-signed
certificate or client certificate included — and stops making two round trips it never used. On an
unreachable host, use <db> went from six seconds to a few milliseconds.
time; the tab just had no way to say so.
Decimal128 inside an object value used to lose the type on its way to the server and silently match
nothing.
Favourite Views
Everyone has a view they always end up in. VisuaLeaf now lets you say so — or works it out and offers.
- Settings → Appearance → Default result view — pick Tree, Table or JSON, and every result opens
- VisuaLeaf offers to remember your favourite. Keep landing on the same view and it asks, once,
- It only asks when you've actually shown a preference. The count is of unbroken runs, so
there: collections, SQL tables, queries, aggregation previews and shell results, in the main window,
in a popout, in Electron. One setting, every entry point.
whether to make that your default.
flipping between Tree and Table all day never triggers it — one switch somewhere else resets the
run. Say no and it waits much longer before asking again; say no twice and it stops asking for good.
Say yes and it never holds that against you: the next suggestion starts fresh.
MongoDB Index Manager
(GitHub issue #33) The Create Index screen no longer lets you get stuck, and no longer accepts input
it then silently ignores.
- A disabled Create button always says why. One line next to it names the reason — a row with no
- Field rows that need a name say so. The row is flagged where the problem is, but only once
- The last remaining field row can't be removed, and hovering its X explains why rather than
- TTL takes whole seconds and nothing else. Typing
eused to be accepted and then quietly - TTL echoes back what it will do — "2,592,000 seconds ≈ 30 days" — so a long run of digits is
field name, a duplicate index name, an invalid TTL — instead of leaving you to guess.
you've been in it or once another row is filled in, so an untouched form is never shown as an error.
looking clickable and doing nothing.
produced an index with no TTL at all; scientific notation, decimals and minus signs are now
refused at the keyboard, and pasting "3600 seconds" keeps the 3600. Values over MongoDB's ceiling
(about 68 years) and negative values are rejected with a message.
readable before you commit. A TTL of 0 explains itself too: documents expire at the time held in the
indexed date field.
Everyday Improvements
Grids
- Hovering a cell shows a preview (GitHub issue #30) — a grid cell is one line wide and clipped
with an ellipsis, so a long string or a nested object could only be read by right-clicking into a
panel. The tooltip now carries the full value, the hint that used to live in the browser tooltip
("Double-click to edit"), and a link that opens the value in the viewer. It appears where your
cursor is, after a short pause, and doesn't slow the grid down while you sweep across it.
The data viewer can stay open
- Dock the data viewer as a tab instead of a floating panel. Docked and left unpinned, it absorbs
- Pin it and it holds what it has, sending the next value to a floating panel. That's how you get
- Float it again whenever you like — docking is a preference, not a commitment.
- The tab says which tab it is following, and keeps up when that tab is renamed.
every value you open from the table it was docked from — click down a column and read each one in
place.
two documents side by side.
Saved queries and scripts
- Saving tells you it saved. Every save and save-as — Mongo find, aggregation, SQL, Redis —
- Importing a script accepts your engine's files.
.sqland.redisfiles are read as scripts
confirms, instead of some engines confirming and others going quiet.
rather than being run through a JSON parse, the wording tells you which file types this dropdown
takes, and an imported report.sql is saved as "report" instead of "report.sql".
Connections
- Filter the connection list by database type. Click the count on any section — Project, Connected,
- Edit a connection straight from the sidebar — right-click it in the connections list instead of
and the rest — and pick the engines you want to see. The count becomes "2 of 5" so you always know
you are looking at a filtered list rather than an empty one.
opening the manager first. Works for MongoDB, Redis and SQL, and each opens on its own form.
Connections an administrator has made read-only don't offer it, rather than opening a form that
then refuses to save.
MongoDB sync
- A failed sync job tells you why, in the job list and on the monitor — the phase it failed in and
- Running or not is answered by the server, so a job's state is no longer guessed from progress
- Estimated document counts are marked as estimates — shown as "~4.2M" rather than as a precise
the reason, instead of a red badge and nothing else.
rows that can't tell the difference.
figure — and a total the server genuinely doesn't know is no longer displayed as an empty collection.
Fixes
- The Redis key browser stayed readable in a narrow window. Below a certain width the Value column
- PDF previews in GridFS work again — they failed with a version-mismatch error. The preview now
- The last row of a grid keeps its stripe. Any table with an even number of rows lost the striping
- The What's new dialog's heading showed a line of raw template code instead of the words "What's
collapsed to one character per line and the Value and TTL headers overlapped; the table now scrolls
sideways instead. (SOZO-1487)
always ships the matching viewer, so an upgrade can't break it again. (SOZO-1514)
on its final row.
new". (SOZO-1248, SOZO-1513)
Infrastructure
- Faster startup for shells, and the shell no longer leaks a connection pool per shell you open.
- Cached connection clients are properly released when you edit or delete a connection.
- One shared licence key ring with pinned signing keys and revocation lists, so a key can be rotated
- New test coverage across offline activation, licence entitlements, export outcomes and pre-flight
without a new build.
checks, atomic file writes, restore resume, SQL value conversion, Oracle schema filtering, custom AI
endpoints, DBML and JSON Schema import/export, and end-to-end coverage for licence activation and
foreign-key navigation.
Notes
- The AI endpoint fields moved to generic ones. Existing Ollama settings are read as before; you do
- **Notifications for a run that ends Completed with errors** still report it as Completed. The run
- Foreign-key navigation needs a table or tree view of the results — it lives on the column, so a
not need to re-enter anything.
itself, the history and the task list all show the new outcome correctly.
JSON view offers nothing to right-click.