The practical itch behind SQLly, and the kind of workbench it grew into.
I am a .NET developer who spent years working mostly in SQL Server, with useful
detours through MySQL, PostgreSQL, Oracle, and MariaDB. My everyday editor was
SQL Server Management Studio, until my work moved to the Mac.
The tool I missed was SSMS. It did not do everything, but it was fast
and stable, which counts for a great deal when it is open all day.
Azure Data Studio offered more on paper, but it is now deprecated and never filled
that particular gap.
The Mac editors I tried were perfectly serviceable, but they lacked the thoughtful,
advanced touches I had grown used to in tools such as
LINQPad.
I kept working around the gap for a while and assumed building a real alternative
would cost more energy than it was worth.
That calculation changed. Modern LLMs, better documentation, and a decade of
sample tooling turned a native, genuinely quick SQL workbench from an impossible
side project into a plausible one. So I started building the tool I wanted to use.
That's SQLly.
What I cared about
Fast and stable: a GPU-rendered native app, not a browser wearing a desktop costume.
Private by default: no telemetry, opt-in cloud features, and identity checks that remain on your machine.
✓ functional works in the app today◐ in progress partially built○ planned designed, not built yet◇ in-tab demo runs in your browser
Features
Features
A guided tour of SQLly, arranged around the work you are here to do.
SQLly is built around one simple idea: the tool should know enough about your
database to be genuinely helpful. These guides follow the shape of real work -
writing a query, understanding its result, and keeping a collection of connections
straight.
A place to write SQL with a little less busywork and a lot more context.
The query editor is where most of the day happens, so it is more than a place to
hold text. IntelliSense works from a live model of your schema and
data, while SQLly directives use ordinary SQL comments to remember
how you want the result to look.
Completions that pay attention to your query, schema, and, when useful, the data itself.
Good completion should feel like a quiet assist, not a slot machine. SQLly builds
suggestions from one SQL model engine: a shared view of your schema
and data, rather than a pile of disconnected regexes. It can therefore see where
the cursor is in the statement and offer the things that belong there.
Scope-aware
SQLly can tell whether you are in a FROM, WHERE, JOIN ... ON, or EXEC parameter list, and adjusts accordingly.
Schema-qualified
Two-part and schema-qualified names complete cleanly, including the system catalogs SQLly discovers.
Procedure-aware
EXEC parameters and stored-procedure filtering use the same model, with value metadata when it is available.
Careful auto-triggering
Suggestions appear when they help and stay quiet when they do not; the trigger matcher is checked against regressions.
SQLly
IntelliSense completing a column inside a live query.
The two ideas below - schema awareness and data awareness - are what let completion work from the database in front of you rather than a generic SQL dictionary.
Suggestions grounded in the tables, columns, routines, and relationships you actually have.
Schema awareness starts with the actual shape of your database:
its tables, columns, procedures, and especially its keys. SQLly keeps that picture
as a snapshot so suggestions can stay quick and consistent, then refreshes it as
the catalog changes.
Tables and views, with their columns and types
Stored procedures and their parameters
Declared foreign keys, pulled in bulk for fast join reasoning
Name-inferred relationships where no formal key exists
The pages below cover the parts you notice most while writing a query.
Start a JOIN and SQLly can offer the ON clause, favoring real foreign keys and clearly labeling its best guesses.
Start typing JOIN OtherTable and SQLly can offer the
ON clause. It follows a deterministic join path through
the model, preferring declared foreign keys and using name-based relationships only
when needed. Each suggestion includes a confidence signal, so a fact
and an educated guess never look the same.
How it decides
Declared foreign keys. When a foreign key connects the tables, SQLly uses that exact column mapping first.
Name-inferred relationships. With no FK, SQLly can match conventions such as CustomerId to Customer.Id and labels the suggestion as inferred.
In-scope joins. It only offers tables already present in the current FROM/JOIN set, so its ON clause resolves in the query you have.
SQLly
Screenshot neededintellisense-auto-join
SQLly proposing an ON clause from a declared foreign key, with a confidence indicator.
Confidence matters. A declared-FK join has an exact mapping. An inferred join is often useful too, but it is worth a quick glance before it meets production data.
Keep joins readable with table-name aliases that stay consistent from the first column to the last.
When a table joins a FROM or JOIN clause, SQLly can offer
a short, readable alias based on its name. It then uses that alias
consistently when it qualifies columns, so the query stays easy to follow.
Why it helps
Stable. The same table receives the same alias throughout a session, which keeps queries familiar.
Readable. Aliases come from the table name, not a parade of t1/t2 labels.
Part of completion. Once an alias exists, column completion uses it automatically, so c. offers Customer's columns.
SQLly
Screenshot neededintellisense-auto-alias
SQLly suggesting a table alias as a table is added to the query, then reusing it for column completion.
Press F2 when completion misses the mark; your report can become the test that keeps the fix in place.
Completion gets better when it meets real work. If a suggestion is wrong, missing,
or noisy, press F2 to capture what happened. A useful report becomes a
regression test, giving the fix a much better chance of staying fixed.
The feedback dialog
SQLly
Screenshot neededintellisense-feedback-dialog
The F2 feedback dialog: what you typed, what was suggested, and what you expected - ready to submit.
What happens to a report
Capture (F2). SQLly saves the statement, cursor context, and the scoped catalog slice needed to reproduce the case.
Redact. SQL literals are removed and the catalog snapshot stays scoped before anything leaves your machine. See Privacy.
Sign and send. The report uploads in the background with retries, so a flaky connection does not lose your feedback.
Triage. Submissions arrive in an admin queue for review.
Lock it in. Accepted reports become cases in a dedicated verification suite: a real test that keeps failing until completion is right.
Privacy first. Feedback carries only what's needed to reproduce the completion, with literals redacted and the catalog snapshot scoped to the tables in play.
When a column's values matter, SQLly can use them to make the next suggestion more useful.
The schema tells SQLly what a column is; data awareness helps it learn
what the column contains. With carefully bounded value introspection,
completion can help on the right side of a WHERE clause and, over
time, let you work with a readable name instead of an opaque id.
Bring real, distinct values into completion so a WHERE clause is less of a guessing game.
When you are completing a value such as WHERE Status = , SQLly can
look into the table and offer the distinct values the column really
holds. It saves you from guessing or opening a scratch query just to check a label.
How it works
SQLly recognizes that the cursor is in a value position for a specific column.
It samples distinct values for that column and adds them as value-completion metadata to the model.
Those values appear in the completion list, ranked and ready to insert.
SQLly
Screenshot neededintellisense-table-values
Value completion offering the real distinct values of a column inside a WHERE clause.
Bounded and cached. Introspection is sampled and LRU-bounded, so it stays quick on wide tables instead of becoming the thing that slows down typing.
Look up a familiar name instead of memorizing an id; SQLly follows the relationship for you.
Databases are fond of ids; people are usually fond of names. With column
introspection configured, SQLly will let you search by name and insert the
id, following the foreign key when you complete
WHERE CustomerId = .
Configuring interchangeability
Point an id column at the display column on its referenced table, such as Customer.Name.
SQLly follows the foreign key when completion is requested for that id column.
Type the readable name and SQLly inserts the matching id.
SQLly
Screenshot neededintellisense-fk-name
Typing a customer name to complete a CustomerId value - SQLly resolves it across the foreign key.
Run the statement you mean to run, then stop it cleanly when the plan changes.
Run the whole document or only the selected statement,
then cancel a runaway query for real instead of merely looking away from it. Multiple
result sets arrive as separate grids, with errors, PRINT output, and
timing in the messages pane.
Run all executes every batch in order.
Run selection executes only the highlighted text, useful in a scratch file full of statements.
Cancel asks the server to stop the query on all four engines, rather than only stopping the local view.
GO-aware. Batch separators are respected and diagnostics from one batch stay with that batch.
Small SQL comments that remember how you want results shaped, formatted, and charted.
A directive is an ordinary SQL comment that SQLly understands.
The database still sees only the query you wrote, while SQLly uses the comment to
shape or format its result. Because directives live in the query text, they travel
with the file and apply again every time you run it.
Every directive shares the same namespace - the word sqlly after the comment marker:
Preconfigure the Chart tab from a comment - type, label, series, and aggregation.
A safety net while you type. If a comment uses the sqlly namespace but is misspelled, placed where it cannot apply, or given an unknown value, SQLly flags it in the editor rather than silently ignoring it.
Turn a familiar result set into a cross-tab with a short, portable comment.
The pivot directive turns a flat result set into a cross-tab without a wizard or
separate tool. Use a view directive to open pivot mode and a
pivot directive to describe the rows, columns, and values.
Fields are separated by ; and written as key:value; their order does not matter. These three are required:
Field
Meaning
row:
One or more column names (comma-separated) that form the pivot's rows.
column:
One or more column names that become the pivot's columns.
value:col:agg
The column to aggregate and the aggregate to apply.
Choose count, sum, avg, min, max, or first as the aggregate. Column names are flexible: [Region], `Region`, and "Region" all resolve to the same column.
Two optional fields format the numbers. valueformat: styles all value cells; format:col: styles one field. Both take either the word default or a comma-separated list of options:
Option
Values
decimals=
A non-negative integer - fixed decimal places.
thousands=
true / false - thousands separators.
red=
true / false - show negatives in red.
parens=
true / false - wrap negatives in parentheses.
align=
left / center / right.
SQLly
Screenshot neededdirectives-pivot
A pivot directive comment above a query, and the cross-tab it produces in the result grid.
Use standalone comment lines. A view: hint belongs on the first non-empty line of the query; pivot: can appear on any comment line of its own. When several valid pivot hints exist, the last one wins.
The same cross-tab is available interactively without touching the query - see Results › Pivot, which builds the directive for you as you drag fields.
Give each column the presentation it deserves, automatically whenever the query runs.
Formatting directives describe how one column should look - numbers, dates,
booleans, text, and more - and apply every time the query runs. Right-click a
column header and choose Set Formatting Override… to have SQLly write
the comment for you, or type one by hand when you prefer.
Spelling is strict here. Unlike the other directives, formatting needs the exact prefix -- sqlly format:: a space after -- and a colon immediately after format. --sqlly format: will not apply, and the editor will let you know.
The first segment is always column=<name>. The second is the format rule:
Rule
Effect
Example
number=N
Fixed-point with N decimals (honors thousands=, style=).
number=2
date=P
Render a date/time with strftime pattern P.
date=%Y-%m-%d
boolean=T/F
Text for true / false values.
boolean=Yes/No
binary=
Render binary values as hex or base64.
binary=hex
text=
Casing: upper, lower, title, none.
text=upper
mask=P/S
Mask the middle, keeping P leading and S trailing characters.
mask=0/4
epoch=
Epoch integer to date: auto, s, or ms.
epoch=s
json=P
Extract a JSON path from the cell.
json=$.customer.name
template=T
Templated cell with pipe helpers.
template={value|upper}
Trailing options: thousands=true|false and style=fixed|percent|bytes refine a number= rule.
Tell the Chart tab what story to draw before the result even arrives.
The chart directive prepares the result's Chart tab from a
comment. It is the same chart you can configure interactively, but the setup travels
with the query and comes back on every run. Use a view directive to
open the Chart tab and a chart directive for the type, labels,
series, and aggregation.
Fields are separated by ; and written as key:value; order does not matter. Only kind: is required, and the rest use the chart's defaults when omitted. Column names are flexible, so [Region], `Region`, and "Region" all resolve to the same column.
Field
Meaning
kind:
The chart type: bar, line, area, scatter, histogram, pie, or donut (required).
label:col
Column whose values label the categories. Defaults to the first text column.
values:col[,col…]
Numeric column(s) to plot as series. Defaults to auto-detecting the numeric columns.
aggregate:agg
Collapse rows per category: none, sum, average, minimum, maximum, or count. (avg/min/max also accepted.)
order:order
Category order: source, category (A–Z), or value (high–low).
top:n
Keep at most n categories after ordering.
navigate:true|false
Clicking a mark selects its source rows on the Grid tab (default true).
Each kind: value draws a different mark. The gallery below names what to expect; its screenshot placeholders are waiting for their real captures.
SQLly
Screenshot neededchart-kind-bar
kind:bar - grouped bars around a zero baseline, one bar per series per category.
SQLly
Screenshot neededchart-kind-line
kind:line - one polyline per series, with gaps at NULLs.
SQLly
Screenshot neededchart-kind-area
kind:area - filled polylines on a zero-floored axis.
SQLly
Screenshot neededchart-kind-scatter
kind:scatter - per-category point markers, good for spread.
SQLly
Screenshot neededchart-kind-histogram
kind:histogram - nice-edged bins of a single numeric column.
SQLly
Screenshot neededchart-kind-pie
kind:pie - radial shares of a single non-negative series.
SQLly
Screenshot neededchart-kind-donut
kind:donut - a pie with the center hollowed out.
Use standalone comment lines. Put view: chart on the first non-empty line of the query; chart: can live on any comment line of its own. When several valid chart hints exist, the last one wins.
The same chart is available interactively without touching the query - right-click the grid and choose Chart…, or click the Chart tab. Saving from the Chart sidebar writes the directive back into your query for you. See also Results › Pivot, the other in-grid view of your rows.
Tidy up a query without changing what it means. The formatter is careful on purpose.
The formatter is configurable, but it is deliberately cautious. SQLly
re-lexes and compares its output token by token with the input; any
mismatch leaves your SQL untouched. It can reindent, recase keywords, and align
clauses without taking chances with comments or literals.
Mark a region to leave exactly as written when the formatter should keep its distance:
-- formatter:offSELECT weird , hand_aligned
, columns -- left exactly as typed-- formatter:on
Cannot hurt the SQL. The token check turns a formatting bug into a no-op, not corrupted SQL.
One fuzzy-search stop for commands, connections, settings, and places you need to get to.
Commands, connections, preferences, and navigation are all one fuzzy search away.
Open the palette with ⌘⇧P or Ctrl+Shift+P, start typing, and it
narrows the list to what you mean. Each row shows its category and, when there is
one, its shortcut.
Two modes, one key.⌘P or Ctrl+P opens Go to Object, a fuzzy jump across the live schema. Type > there to switch into command mode, or open the command palette directly with ⌘⇧P.
File
New Query
New Notebook
Open Notebook
Save Notebook
New Window
Close Tab
Rename Tab…
Reopen Closed Tab
Open SQL File…
Run SQL File…
Open Project File…
Open Folder…
Open SQLLY Export…
Save SQL…
Save to Library…
Save Results…
Save Workspace As
Open Workspace
Manage Workspaces
Add Connection
Connect…
Disconnect
Switch to Connection 1-9
Export Connections…
Import Connections…
Import From Other Tools…
Edit
Find in Editor
Replace in Editor
Toggle Vim Keybindings
Query
Execute Query
Execute into New Result Tab
Execute Without Rollback Wrap
Run Statements…
Run on Multiple Connections…
Cancel Query
Run Notebook Cell
Run All Notebook Cells
Validate SQL
Format SQL
Query History
Explain Query (Actual, executes)
Explain Query (Estimated, no execution)
Explain with Profile (SELECT only)
Open Plan…
Paste Plan from Clipboard
Transaction: Toggle Manual Commit Mode
Transaction: Commit
Transaction: Rollback
Unlock Production Writes for 1 / 5 / 15 Minutes
Lock Production Writes Now
Unlock Read-only Connection for 1 / 5 / 15 Minutes
Lock Read-only Connection Now
Results: Auto-refresh Off / 5s / 10s / 30s / 60s
Generate SQL (AI)…
Ask Schema (AI)…
Send Selection to AI…
Explain Last Error (AI)
Explain Execution Plan (AI)
Analyze Last Run with AI
Build AI Cache and Embeddings
Clear AI Catalog Data
View
Toggle Sidebar
Toggle Results Pane
Maximize / Restore Results
Detach Results to Window
Re-attach Results
Toggle Cell Details Panel
Toggle Version History Panel
Toggle Log Console
Toggle AI Panel
Toggle AI Panel Visibility
Toggle Agent Mode
Toggle IntelliSense Debug Panel
Split Editor Vertically / Horizontally
Split Same Buffer Vertically / Horizontally
Close Split Editor
Search Schema
Show SQL Library
Zoom In
Zoom Out
Actual Size
Theme: System / Light / Dark / High Contrast
Tools
Command Palette
Go to Object…
Preferences…
Open Keyboard Shortcuts…
Tenant Scoping
Relationship Graph
Query Builder
Connection Health
Result Snapshots
Server Dashboard…
Activity Monitor…
SQL Agent…
Security…
Designers…
Edit Structure…
Object Browser…
Index Analyzer…
Query Insights…
Disk Usage…
Extended Events…
Schema Compare…
Data Compare…
Data Transfer…
Import / Export…
Import from Clipboard…
Backup / Restore…
Test Data Generator…
Search Database for Value…
Export Database as SQL…
Document Schema (Markdown)…
Results: Filter Rows…
Results: Transpose
Results: Find in Grid
Results: Go to Column…
Results: Stage New Row
Results: Mark Row for Deletion
Results: Refresh Query
Results: Undo / Redo Staged Edit
Results: Save / Discard Staged Changes
Results: Preview Staged SQL
Refresh IntelliSense Catalog
Refresh Object Explorer
Object Properties…
MCP Server Settings
Manage Tunnel Profiles…
Connection Management…
Template Explorer…
Open in External Editor
Azure SQL Connection…
Add My IP to Server Firewall…
Window, Help & Quick Actions
Next / Previous Editor Tab
Back / Forward through Tab History
SQLLY Help…
Formatting Directives…
Check for Updates…
Quick action 1-9 (your saved snippets)
Two categories are generated from your setup: Switch to Connection 1-9 and Quick actions, which surface the snippet quick-actions you've assigned. Detach / re-attach results are desktop-only and don't appear in the in-browser preview.
Keep the shortcuts your hands already know, or make a new set that fits your workflow.
Your shortcuts should fit your hands, not the other way around. Rebind editor and
app commands to match the muscle memory you already have; bindings live as plain,
version-controllable configuration alongside the rest of your settings.
Everything is a file. The keymap is just another file on disk: back it up, diff it, or keep it in a repository.
Reading the tables:⌘/Ctrl means ⌘ on macOS and Ctrl on Windows/Linux - the same physical role. A few chords use the realCtrl on both platforms; those are written out in full. Chords joined by “or” are alternates for the same action. Everything below ships as the default - all of it rebindable in Preferences ▸ Keybindings unless noted.
Running queries
Action
macOS
Windows / Linux
Execute query
⌘Return or F5
Ctrl+Enter or F5
Execute into new result tab
⌘\
Ctrl+\
Run statements…
⌘⇧Return
Ctrl+Shift+Enter
Run all notebook cells
⌘⇧Return
Ctrl+Shift+Enter
Cancel query
⌘Esc
Shift+Esc
Validate SQL
⌘⇧V
Ctrl+Shift+V
Format SQL
⌥⇧F
Alt+Shift+F
Execution plan viewer
⌘L
Ctrl+L
Go to next error
F8
F8
Transaction: commit
⌘⌥Return
Ctrl+Alt+Enter
Transaction: rollback
⌘⌥Backspace
Ctrl+Alt+Backspace
Transaction: toggle manual commit
⌘⌥T
Ctrl+Alt+T
Send selection to AI…
⌘⇧A
Ctrl+Shift+A
IntelliSense & editing help
Action
macOS
Windows / Linux
Trigger completions
Ctrl+Space
Ctrl+Space
Trigger value lookup
Ctrl+Shift+Space
Ctrl+Shift+Space
Trigger AI inline suggestion
⌥\
Alt+\
Improve IntelliSense (capture feedback)
F2
F2
Qualify identifier
⌘⌥Q
Ctrl+Alt+Q
Paste as IN list
⌥⇧I
Alt+Shift+I
Convert delimited list…
⌥⇧L
Alt+Shift+L
Comments & folding
Action
macOS
Windows / Linux
Toggle line comment
⌘/
Ctrl+/
Add line comment
⌘K ⌘C
Ctrl+K Ctrl+C
Remove line comment
⌘K ⌘U
Ctrl+K Ctrl+U
Fold region
⌘⌥[
Ctrl+Shift+[
Unfold region
⌘⌥]
Ctrl+Shift+]
Fold all regions
⌘⌥⇧[
Ctrl+Alt+Shift+[
Unfold all regions
⌘⌥⇧]
Ctrl+Alt+Shift+]
Find & replace
Action
macOS
Windows / Linux
Find
⌘F
Ctrl+F
Replace
⌘H
Ctrl+H
Find next
⌘G or F3
F3
Find previous
⌘⇧G or Shift+F3
Shift+F3
Selection & multiple cursors
Action
macOS
Windows / Linux
Add cursor for next occurrence
⌘D
Ctrl+D
Select all occurrences
⌘⇧L
Ctrl+Shift+L
Add cursor above
⌘⌥↑
Ctrl+Alt+Up
Add cursor below
⌘⌥↓
Ctrl+Alt+Down
Column select up / down
⌥⇧↑ / ⌥⇧↓
Alt+Shift+Up / Alt+Shift+Down
Select all
⌘A
Ctrl+A
Line operations & clipboard
Action
macOS
Windows / Linux
Move line up / down
⌥↑ / ⌥↓
Alt+Up / Alt+Down
Duplicate line
⌘⇧D
Ctrl+Shift+D
Join lines
Ctrl+J
Ctrl+J
Go to line
Ctrl+G
Ctrl+G
Copy
⌘C
Ctrl+C or Ctrl+Insert
Cut
⌘X
Ctrl+X or Shift+Delete
Paste
⌘V
Ctrl+V or Shift+Insert
Undo
⌘Z
Ctrl+Z
Redo
⌘⇧Z
Ctrl+Y or Ctrl+Shift+Z
Cursor movement
Action
macOS
Windows / Linux
Word left / right
⌥← / ⌥→
Ctrl+Left / Ctrl+Right
Select word left / right
⌥⇧← / ⌥⇧→
Ctrl+Shift+Left / Ctrl+Shift+Right
Delete word backward / forward
⌥Backspace / ⌥Delete
Ctrl+Backspace / Ctrl+Delete
CamelCase left / right
Ctrl+⌥← / Ctrl+⌥→
Alt+Left / Alt+Right
Line start / end
Home, ⌘←, Ctrl+A / End, ⌘→, Ctrl+E
Home / End
Document start / end
⌘↑, ⌘Home / ⌘↓, ⌘End
Ctrl+Home / Ctrl+End
Delete to line start / end
⌘Backspace / ⌘Delete, Ctrl+K
Ctrl+Shift+Backspace / Ctrl+Shift+Delete
Open context menu
Shift+F10 or Menu
Shift+F10 or Menu
Panels & view
Action
macOS
Windows / Linux
Toggle sidebar
⌘B
Ctrl+B
Toggle results pane
⌘J or ⌘⇧R
Ctrl+J or Ctrl+Shift+R
Maximize / restore results
⌘⇧J
Ctrl+Shift+J
Detach results to window
⌘⌥J
Ctrl+Alt+J
Toggle version history panel
⌘⌥H
Ctrl+Alt+H
Toggle AI panel
⌘⇧I
Ctrl+Shift+I
Toggle log console
⌘⇧L
Ctrl+Shift+L
Focus explorer / filter
⌘⇧B / ⌘⇧F
Ctrl+Shift+F (filter)
Zoom in / out
⌘= / ⌘-
Ctrl+= / Ctrl+-
Actual size
⌘0
Ctrl+0
Output tabs
Tab
macOS
Windows / Linux
Results
⌘1
Ctrl+1
Messages
⌘2
Ctrl+2
Plan
⌘3
Ctrl+3
History
⌘4
Ctrl+4
DDL
⌘5
Ctrl+5
Diff
⌘6
Ctrl+6
Results grid
Action
macOS
Windows / Linux
Find in grid
⌘F
Ctrl+F
Go to column…
⌘G
Ctrl+G
Stage new row
⌘N
Ctrl+N
Mark row for deletion
Delete or Backspace
Delete or Backspace
Undo / redo staged edit
⌘Z / ⌘⇧Z
Ctrl+Z / Ctrl+Shift+Z
Refresh query
⌘R
Ctrl+R
Tabs, windows & app
Action
macOS
Windows / Linux
Command palette
⌘⇧P
Ctrl+Shift+P
Go to object…
⌘P
Ctrl+P
New query
⌘N
Ctrl+N
New window
⌘⇧N
Ctrl+Shift+N
Close tab
⌘W
Ctrl+W
Reopen closed tab
⌘⇧T
Ctrl+Shift+T
Next / previous editor tab
Ctrl+Tab / Ctrl+Shift+Tab
Ctrl+Tab / Ctrl+Shift+Tab
Back / forward through tab history
Ctrl+⌥← / Ctrl+⌥→
Ctrl+Alt+Left / Ctrl+Alt+Right
Switch to connection 1–9
Ctrl+Shift+1…9
Ctrl+Shift+1…9
Save SQL
⌘S
Ctrl+S
Open (project / SQL file)
⌘O
Ctrl+O
Open in external editor
⌘⇧E
Ctrl+Shift+E
Open keyboard shortcuts
⌘K ⌘S
Ctrl+K Ctrl+S
Preferences
⌘,
Ctrl+,
Minimize window
⌘M
-
Quit
⌘Q
Ctrl+Q
A few defaults differ by profile: the SSMS keybinding profile maps Execute Query to F5 only. A handful of app chords (zoom, quit, preferences, output-tab selection) are fixed rather than rebindable; everything in the editor and query tables above can be remapped.
Move between open queries with Ctrl+Tab and a preview that helps you pick the right one.
Once a few query tabs are open, titles alone stop being much help. Hold
Ctrl and press Tab for a most-recently-used list with a live
preview of the highlighted query. Keep tapping Tab to move through the
list, then release Ctrl to land where you need to be. Your last two
queries are always one flick apart.
What each entry shows
The switcher has two panes: a compact list of open queries on the left and a preview of the highlighted query on the right.
The list (left)
Each row carries the query's engine glyph, its name (with a dot when it has unsaved edits), and its connection trail - client, project, environment, server, database - so two tabs on different targets never look alike. Rows are ordered most-recently-used.
The preview (right)
A fuller look at the highlighted query, top to bottom: title, AI summary, the query body, and a run line.
The preview, top to bottom
Title. The engine glyph and the query's name.
AI summary. A one-line, plain-language description of what the query does - so you recognise it by intent, not just by filename.
Query body. The SQL itself, rendered as text in the editor font, so you can confirm you've got the right query at a glance. Long queries are clipped with a “… N more lines” marker.
Run line. How long ago the query last ran and how much it returned - e.g. “Ran 3m ago · 1,240 rows · 2 result sets” - or “Not run yet” for a query you haven't executed.
SQLly
Screenshot neededquery-tab-switcher
The Ctrl+Tab switcher: an MRU list of open queries on the left, and a preview on the right showing the title, AI summary, query body, and last-run line.
Recognise queries the way you remember them. Between the AI summary (what it does) and the query body (how it does it), you rarely need to read a tab title to know which query you're switching to.
Turn an execution plan into useful findings, a navigable tree, or a diagram you can follow.
A query plan is the database explaining how it intends to answer your query:
which indexes it uses, how it joins, and where the cost goes. SQLly turns that
explanation into plain-language findings, an operator
tree, and a node-and-edge diagram. One shared model
keeps a PostgreSQL plan and a SQL Server plan readable in the same way.
Capturing a plan
Capture
What it does
Runs the query?
Actual (⌘L / the Explain button)
Runs the query and captures the plan with real row counts.
Yes
Estimated (menu / command palette)
Asks the engine for its plan without executing - estimates only.
No
Profile
An actual capture with extra detail (buffers, verbose). SELECT-only.
Yes
Open / Paste
Load a saved .sqlplan/.json/.xml plan, or one from the clipboard - nothing runs.
No
Actual vs estimated. An actual plan ran, so its row counts show what happened and can reveal where estimates were off. An estimated plan avoids execution, which makes it the safer starting point for a heavy or destructive statement. SQLly warns whenever a capture will execute the query.
Findings - the plan in human terms
The default view isn't a wall of operators - it's a ranked list of
findings, worst first. Each one is written in plain language
with a summary, a why, and a suggested
action - often with ready-to-run SQL you can copy or open in
a new tab, plus the technical detail one expand away.
Table scan - “Scans every row in dbo.Orders to find matches.”
Missing index - with a generated CREATE NONCLUSTERED INDEX statement.
Estimate vs actual divergence - “Estimated 10 rows but read 48.2K → update statistics” (actual plans only).
Implicit conversion, key lookup, spill to tempdb, missing statistics, cross product (no join predicate), row goals, and spools - each with its own explanation and fix.
Below the findings, an Operators list shows every operator most-expensive-first - “Index Seek — 4 rows estimated, 91% of cost, read 7” - with full per-operator detail (node id, physical/logical operator, CPU/IO cost, actual rows, warnings, output columns) on expand.
Tree & diagram
Tree view is the operator hierarchy as an indented,
collapsible tree - each row showing the operator, its share of cost,
estimated rows, the → actual count (highlighted when it diverges),
and a ⚠ warning tally - with keyboard navigation.
Diagram view draws the plan as a top-down
node-and-edge canvas. Each node is a box with the operator
name, a cost% · estimated rows → actual line, and a
cost bar whose length tracks the operator's cost share and
turns amber when it carries a warning. Edges are drawn parent-to-child with
arrowheads; you can pan the canvas and click any node to select it and see
its full detail below - the same selection the tree shares.
SQLly
Screenshot neededquery-plan-diagram
The graphical plan diagram: operator nodes with cost bars connected by arrowed edges, with a selected node's detail below.
Batches, clean plans, and comparison
Multi-statement batches get a per-statement tab strip - findings stay grouped by statement rather than mixed together.
Clean plans say so plainly: “This plan looks good. No issues detected.” The Operators list is still there when you want it.
Comparison mode keeps recent captures and diffs a baseline against a later run - highlighting operators that regressed, improved, or were added/removed - so you can prove a tuning change actually helped.
An AI explain action hands a bounded digest of the plan to the assistant for a natural-language walkthrough.
Engine support
Engine
Actual
Estimated
SQL Server
SET STATISTICS XML
SET SHOWPLAN_XML
PostgreSQL
EXPLAIN (ANALYZE, FORMAT JSON)
EXPLAIN (FORMAT JSON)
MySQL 8
EXPLAIN ANALYZE
EXPLAIN FORMAT=JSON
MariaDB
ANALYZE FORMAT=JSON
EXPLAIN FORMAT=JSON
SQLite
EXPLAIN QUERY PLAN (estimated only - never executes)
Every dialect is parsed into the same plan model, so findings - table scans, cost shares, estimate-vs-actual - read consistently no matter which engine produced the plan.
Open an object's definition right from the query instead of going on a tree-hunting expedition.
Reading a query and need to see what an object really looks like? Cmd-click
on macOS or Ctrl-click on Windows/Linux to open its definition
directly. No tree hunting and no emergency sp_help required. Hold the
modifier first and resolvable names underline, so you know what will open.
What you can click
Tables, views, stored procedures, functions, and user-defined types. You can also open the same view from the data-model rows in the open dialog.
SQLly
Screenshot neededddl-source-navigation
Cmd/Ctrl-clicking a table name in the editor opens its read-only, syntax-highlighted definition.
What it shows
A read-only, syntax-highlighted definition, with a header naming the object, where the source came from, the database, and the connection:
Views, procedures, and functions - the server's own stored definition.
Tables - a CREATE TABLE with columns (type, nullability, identity, collation, defaults) and the primary key, then appended Indexes, Foreign Keys, and Triggers sections. It's labelled “Generated from catalog metadata” when SQLly builds it from the catalog rather than a stored definition.
Each section is best-effort: if one can't be read it appends a -- … unavailable comment instead of failing the whole view. A toolbar gives you Copy and Open as Query - the generated DDL is never dropped into an editable tab unless you ask.
How to configure it
Under Settings › DDL navigation you can enable or disable it, choose the activation modifier, and pick where it opens - a new tab (the default), a side panel on the current tab, or a popup window.
Supported on SQL Server (the fullest - generated tables with index/FK/trigger sections, plus routines, views, and types), PostgreSQL, MySQL/MariaDB, and SQLite.
Find SQL files and database definitions with fuzzy search and a preview before you commit.
Opening SQL should not mean playing hide-and-seek in a stock file panel. SQLly's
Open dialog searches your project with the same fuzzy logic as the editor, previews
a file before you open it, and can jump straight to a database object's definition.
Two ways to browse
Folder - walk one directory at a time, with a parent (..) row and an Up button. Choose Root… points it at a new project folder.
Project SQL - recursively finds every .sql file under the project root at once, each row tagged with the schema and object it defines and whether it was indexed or scanned.
SQLly
Screenshot neededopen-dialog
The Open dialog: mode toggle, searchable file list with schema/object chips, and a syntax-highlighted preview pane.
Search that thinks like IntelliSense
The search box uses the same fuzzy matching as code completion,
so you type initials and it finds the name: PuOr matches
PurchaseOrder, SOH matches
SalesOrderHeader, and case never matters. Every
whitespace-separated term has to match, so you can narrow quickly.
Prefix a term to scope it to one kind of object:
Prefix
Scopes to
t: / table:
Tables
v: / view:
Views
p: / proc: / sproc:
Stored procedures
f: / function:
Functions
tr: / trigger:
Triggers
i: / index:
Indexes
ty: / type:
Types
sch: / schema:
A schema name
"…"
Quote to search literally, prefixes and all
Preview, reveal, and open
Syntax-highlighted preview - select a .sql file and its contents render, line-numbered and colorized, before you commit to opening it. Big files preview a slice with a Load Full File button.
Data-model rows - flip on the DDL toggle and the list also offers your live tables and views; choosing one opens its definition directly.
Reveal in the OS file browser and Copy Path from the preview pane; toggle Show Hidden to include dotfiles.
New SQL File… creates an empty query file to start from.
Keyboard throughout: ↑/↓ move, Enter opens the file (or descends into a folder, or opens an object's DDL), and Escape clears the search before it closes the dialog.
Read the answer, shape it for the task, and take it with you when you are done.
A query returning rows is usually the beginning of the work, not the end. The
result grid is where you read, reshape, compare, and share the answer. These are
the main ways SQLly helps with each result set.
Try the real result grid in your browser, no installation ceremony required.
This is not a mock-up. It is the real SQLly result grid, running
in your browser against bundled sample data. Give it a proper poke: sort, resize,
scroll, and move between the Grid, Pivot, and
Chart tabs just as you would in the desktop app.
sqlly-datatable - web sample
Loading the live sample… the WebAssembly build downloads on first view.
Runs entirely in your browser via WebAssembly + WebGPU - it needs a recent Chrome/Edge, Safari, or Firefox with WebGPU enabled, and it never talks to a server. The build loads only when you open this page and unloads automatically the moment you navigate away, so it never sits idle in the background.
This is the grid you'll read every result in - see Formatting, Pivot, and Export for what it can do with real data.
Make numbers, dates, ids, and text easier to scan without changing the data beneath them.
Formatting helps a result set read like an answer instead of a raw data dump. SQLly
starts from the column type, then lets you set defaults or make a deliberate
per-column exception. Both paths feed the same formatting model:
Type defaults. Open Settings › Results to choose how each type appears across SQLly.
Per-column override. Right-click a header and choose Set Formatting Override…. SQLly writes a -- sqlly format: directive into the query, so the choice travels with the file.
Numeric and temporal types also share an alignment option (left, center, or right), so it does not need repeating on every page below.
Tame casing, truncation, and whitespace so text columns stay useful at a glance.
Text arrives as stored, with no one-size-fits-all defaults pane. When a column
needs help, right-click its header and choose Set Formatting Override….
The picker keeps its options in three focused tabs.
Template
Use a {value} placeholder with pipe helpers for casing, truncation, padding, and the other small adjustments that make text easier to read:
Extract a useful leaf from a JSON text column, such as $.customer.name or $.items[0], and provide a fallback when the path is missing.
Number
Apply numeric styling to any column: fixed, percent (×100 with a % suffix), or bytes (B / KiB / MiB / GiB / TiB), with your chosen decimals and separators.
SQLly
Screenshot neededresults-format-config-string
The per-column formatter picker showing the Template, JSON path, and Number tabs.
Related: sensitive text can be redacted with a mask= override, which can also gate exports.
Build a cross-tab by moving fields around, then keep the setup as a reusable directive if you like.
Every result grid has a Pivot tab alongside Grid and Chart. Open it
to turn a flat result into a cross-tab by moving fields around; the query itself
stays untouched.
Building a pivot
The sidebar lists the available columns and four drop zones. Drag a field into the place where it should do its work:
Rows and Columns - the axes of the cross-tab.
Values - the measure to aggregate. The value chip carries a dropdown to pick the aggregate; it reads e.g. “Sum of Amount”.
Filters - restrict which rows feed the pivot, with a per-field value picker.
Choose from Count, Sum, Avg, Min, Max, and First. Layout options add subtotals, grand totals, and flat rows; per-field formatting handles decimals, separators, negative values, and alignment.
SQLly
Screenshot neededresults-pivot
The interactive pivot: source fields and the Rows / Columns / Values / Filters drop zones, with the cross-tab rendered alongside.
Drill down
Double-click a pivot cell to return to the Grid tab filtered to the rows behind it. SQLly labels the view “Filtered from pivot” and provides a one-click Clear filter.
Wait for the full result. Pivot stays locked while a result set is streaming so it never cross-tabs a partial answer. Once the rows finish arriving, the tab unlocks. Use Save configuration for a setup you will reuse.
Prefer to keep it in the query? The pivot directive expresses the same cross-tab as a comment - and dragging fields here can write that directive for you.
Edit, insert, duplicate, and delete rows through a form that understands the table you are in.
Right-click a result row and choose Edit Row… to get a form
built from the table's metadata, including data types, defaults, nullability, and
constraints. It gives you a clear way to inspect and change data without hand-writing
every UPDATE.
SQLly
Screenshot neededresults-row-editor
The row editor: a per-column form generated from the table's schema, with foreign-key dropdowns and validation.
What you can do
Edit, insert, duplicate, and delete rows; every write is guarded and parameterized, never string-concatenated.
Foreign-key fields become searchable dropdowns of real referenced values, so you can choose a customer by name rather than guess an id.
CHECK constraints are checked in the form before a save leaves the app.
Related rows are one click away in their own tab.
Commit now, or stage your changes
Save one edit immediately, or stage edits, inserts, and deletes to
commit together in one transaction with a generated rollback script alongside.
Staged saves use the same safety gates as normal queries: a read-only or production
connection blocks the write until you unlock it, and an AI-reviewed connection asks
for that review before committing.
Protected by the same policy. The row editor honors the connection's SELECT-only rule, production locks, confirmation dialogs, and identity checks. Convenience should not be a route around guardrails. Provenance-guarded editing is available for SQL Server today.
Row edits reuse the connection's live authentication, so a token-authenticated (Entra) connection edits with the same freshly-minted token it queries with.
Send results onward in the format the next person or tool will actually appreciate.
One Export… command, from the grid menu or toolbar, opens a
single dialog for any result set. Pick a format, choose Copy to clipboard
or Save to file…, and you are done. Standard data formats and
programming-language generators live together, and unused formats can be hidden in
Settings › Results › Export.
SQLly
Screenshot neededresults-export
The consolidated Export dialog: format list grouped into Standard and Programming, with clipboard/file destinations.
Shared export options, also under Settings › Results › Export, apply across formats: how NULL is written, how cell line breaks are handled, whether to include headers, optional gzip, and the batch filename pattern {schema}_{table}_{date}.{format}.
Every example below exports this small two-row result set:
SELECT id, customer, amount, created FROM orders;
-- id | customer | amount | created-- 1 | Acme | 1250.00 | 2026-09-01-- 2 | Globex | 890.50 | 2026-09-02
Standard formats
CSV .csv
Comma-separated, RFC-style quoting. An Excel-compatible variant adds a UTF-8 BOM.
A real .xlsx workbook - a formatted Excel table with banded rows and an auto-filter header. Because it's binary, this format saves to a file (clipboard is disabled for it).
SQLLY Export .sqllyexport
SQLly's own envelope format - carries the rows plus their column types and metadata for lossless round-tripping back into SQLly.
Programming formats
These generators emit ready-to-paste source code that embeds the result rows as data - handy for fixtures, seed data, and quick scripts. One example per language:
C# .cs
var rows = new[]
{
new { Id = 1, Customer = "Acme", Amount = 1250.00m, Created = "2026-09-01" },
new { Id = 2, Customer = "Globex", Amount = 890.50m, Created = "2026-09-02" },
};
The exact field names, types, and value quoting follow the result's columns and your connection's dialect - the samples above are representative. Any format you don't use can be hidden under Settings › Results › Export.
Put two result sets side by side and see what changed without doing row-by-row detective work.
When the question is "what changed?", put two result sets together and let SQLly
answer it plainly. Rows are marked added, removed,
or unchanged, and schema mismatches are called out rather than
quietly producing a misleading comparison.
Capture a query before and after a change, then compare the two runs to prove what moved. No spreadsheet export, no side-by-side squinting.
Open JSON or XML cells as tidy, explorable structures instead of a wall of punctuation.
JSON and XML deserve better than being squeezed into a grid cell. Open either in
a structured, pretty-printed viewer, then expand only the branches you need until
the field you came looking for is right in front of you.
Describe a transformation once, then let SQLly apply it across the columns that need it.
Repeating the same transformation across thirty columns is a fine way to lose an
afternoon. This planned templating language will let you describe the change once
and apply it consistently, keeping result shaping readable and repeatable.
Planned. The design is settled; this one isn't built yet. Today, per-column formatting and the directives cover most of the same ground.
Give multiple result sets the layout that makes the comparison or review easy.
A query can return several result sets at once, and the useful layout depends on
what you are comparing. Choose one from the grid's Layout submenu;
the toolbar toggle moves quickly between Tabbed and Stacked.
A free-form grid you place result sets into with comments.
Detaching is separate.Detach results to window opens the whole results panel in its own OS window, regardless of the current layout, so a second monitor can earn its keep.
Keep the workspace calm by looking at one result set at a time.
Tabbed is the default for a reason: each result set gets a tab and
only the active one is visible. It is the calmest choice when you are focused on
one answer at a time.
Switch to it from the grid's Layout submenu, or flip between Tabbed and Stacked with the layout toggle in the toolbar and results chrome. Your choice is remembered per editor tab when session resume is on.
SQLly
Screenshot neededresults-layout-tabbed
Several result sets shown as a tab strip, one grid visible at a time.Features/Results/Layouts/Stacked
Stacked
✓ functional
Keep every result in view on one scroll when the whole batch matters.
Stacked keeps every result in one scroll as a resizable,
collapsible card. It is useful when several sets need to stay in
view together: collapse the finished ones and keep moving.
Each card has its own collapse control and an inline clear affordance; drag a card's edge to resize it. Reach it from the Layout submenu or the toolbar toggle.
SQLly
Screenshot neededresults-layout-stacked
Multiple result sets as stacked, collapsible cards in one scrolling column.Features/Results/Layouts/Canvas
Canvas
✓ functional
Arrange result panes freely when the answer is easier to understand side by side.
Canvas lays result sets onto a grid you define with comments. It is
for dashboard-style queries where a summary belongs in one place and detail sets
belong somewhere else.
Placing result sets
Declare the grid size, then give each result set a cell:
-- sqlly 4x2-- sqlly result: row:1 col:1SELECT ...; -- lands in the top-left cell-- sqlly result: row:1 col:2SELECT ...; -- next cell across
SQLly builds the board from the result sets and directives, and flags placement problems, such as two sets claiming the same cell, directly in the editor.
SQLly
Screenshot neededresults-layout-canvas
A canvas layout: result sets arranged into a grid of cells defined by SQL comments.Features/Results/Query history
Query history
◐ in progress
Revisit recent results without rerunning a query just to see what happened last time.
Run a query, run another, and the first answer is still nearby. SQLly keeps a
cache of recent runs, including the result rows and exact SQL, so
you can revisit a previous result without executing it again.
The run history strip
After more than one run, a strip of chips appears above the results. Current
holds the live run; retained runs appear newest first with time, row count, and
elapsed time, such as “14:32 · 1,240 rows · 84 ms”.
Select a chip to view that run read-only, return with Current, and
pin or close each retained run as needed.
SQLly
Screenshot neededresults-run-history
The run history strip: a Current chip and retained-run chips with time, row count, and elapsed, plus pin and close buttons.
What's cached per run
The SQL text that produced the run.
The result set(s) - columns and the actual rows.
Row counts, rows-affected, elapsed time, and completion time.
Bounded on purpose. For a spill-backed or incomplete run, or one whose rows exceed the history memory budget, SQLly keeps the counts and SQL but not the rows and explains why. History lives only in session memory; it is not written to disk or carried across restarts.
How many, and what's kept
How many runs - default 5, adjustable from 0 to 20 in Settings › Results, with a master on/off switch.
What counts as a new run - a capture mode controls whether a run is retained when the query changed, when the results changed, on either (the default), or only on both.
Eviction - the oldest un-pinned run drops off once you exceed the limit or the memory budget.
Pinning - a pinned run is protected from eviction. Pin the run you want to keep comparing against. If every retained run is pinned and the strip is full, SQLly hints to unpin one so history can stay bounded.
Scope - history is per editor tab; each query tab keeps its own runs.
Not to be confused with the query-history log. This run cache holds real results in memory for the current session. Separately, SQLly keeps a persistent local log of the SQL you've executed (statement text, target, outcome, and timing - no result rows) in its own database, which feeds the searchable History pane. One lets you re-view results; the other lets you find a statement you ran last week.
Related: Layouts for arranging the sets a run returns, and Export to get any run's rows out.
See which engines SQLly can connect to today and how it keeps their differences from getting in your way.
SQLly understands 30 database engines. Twenty connect
today through native Rust drivers, grouped around the four wire
protocols those engines actually speak. The remaining ten are fully profiled:
SQLly knows their capabilities, quoting, row limits, and type storage, with live
connectors still to come.
Every engine has a capability profile. Whether it connects today or not, each engine describes its supported operations and keywords, identifier quoting, row limits, upserts, and type mappings. That is how one action can produce the right dialect for each engine.
Connect today - native drivers
Wire-compatible engines share a driver: PostgreSQL-protocol engines use the
PostgreSQL connector, and the MySQL family shares MySQL's. Compatibility stays
explicit, so a hosted or distributed engine says which first-party wire it uses.
TDS - SQL Server family
Engine
SQL dialect
Notes
Microsoft SQL Server
T-SQL
First-party. Default schema dbo, [bracket] quoting, SELECT TOP n.
Azure SQL Database
T-SQL
Managed SQL Server; Entra ID sign-in and Azure discovery supported.
First-party. `backtick` quoting, LIMIT, ON DUPLICATE KEY upsert.
MariaDB
MySQL
Adds sequences and RETURNING.
Amazon Aurora MySQL
MySQL
AWS-managed MySQL-compatible edition.
Amazon RDS for MySQL
MySQL
AWS-managed MySQL.
Azure Database for MySQL
MySQL
Flexible server. TLS required.
Google Cloud SQL for MySQL
MySQL
GCP-managed MySQL.
PlanetScale
MySQL
Vitess-based. TLS required.
TiDB
MySQL
Distributed SQL; no stored procedures.
In-process file
Engine
SQL dialect
Notes
SQLite
SQLite
File or in-memory database, opened directly. Dates and UUIDs are text-encoded; no stored procedures.
Modeled - drivers on the way
These engines are fully described in the capability model, so SQLly can generate
their SQL, quoting, and type mappings. They do not yet have native connectors,
which means a live connection from the app is not available today.
Engine
Connects via
SQL dialect
Oracle Database
Oracle Net
Oracle (FETCH FIRST, MERGE)
IBM Db2
DRDA
Oracle-family
IBM Informix
DRDA
Oracle-family (SELECT FIRST n)
Microsoft Access
ODBC / ACE
SQL Server-family (reduced surface)
Snowflake
HTTP API
PostgreSQL-family (QUALIFY, MERGE)
Databricks SQL
HTTP API
PostgreSQL-family (Spark SQL)
Google Cloud Spanner
HTTP API
PostgreSQL-family (GoogleSQL, INSERT OR UPDATE)
DuckDB
In-process file
PostgreSQL-family
Teradata
Proprietary
Oracle-family (SELECT TOP n, QUALIFY)
SAP HANA
Proprietary
Oracle-family
One intent, per-engine SQL
Because engine rules live in the model, one UI action can render the right dialect
wherever you run it. Row limiting is a familiar example: “view top 1000 rows”
becomes:
Pattern
Rendered SQL
Engines
TOP
SELECT TOP 1000 …
SQL Server, Azure SQL, Access, Teradata
LIMIT
… LIMIT 1000
PostgreSQL & MySQL lineages, SQLite, DuckDB, Snowflake
FETCH FIRST
… FETCH FIRST 1000 ROWS ONLY
Oracle, Db2
FIRST
SELECT FIRST 1000 …
Informix
The same per-engine handling covers identifier quoting, string, boolean, and binary literals, upserts (ON CONFLICT, ON DUPLICATE KEY, or MERGE), and how all 15 logical types map to native storage.
Tools that help SQLly explain your database in plain language without pretending it knows more than it does.
A schema can tell you what a column is called; it cannot always tell you what the
column means. SQLly's intelligence work is about closing that gap carefully. The
live value-aware completion features are under IntelliSense › Data awareness; this section covers the next layers taking shape.
Get a plain-language preview of a query from a model you control, before you have to parse every clause yourself.
Before you run a query, it helps to know what it is about to do in ordinary human
language. SQLly's summary bar is built for that quick confidence check; the UI,
per-query preferences, and saved metadata are ready while generation backends are
still being connected.
Use a local model through Ollama or the MLX sidecar
on Apple Silicon, or deliberately opt into a cloud provider such as OpenRouter,
OpenAI, or Claude. No cloud, no API key, and no data leaving your laptop unless
you choose it.
Private by design. On-device is the default; cloud is strictly opt-in, per query.
Trace an unexplained value through DDL and leave behind a useful note for the next person, possibly future you.
Found a mystery code in a result set? When SQLly can follow it through
DDL introspection, it can leave an inline note explaining where
the value came from, so the query answers a little more of its own trivia.
SELECT status /* ← enum: orders.status_id → status_codes.code */
Search across your schema and data by intent, not only by the exact SQL words you happen to remember.
You should be able to search for the idea in your head, not only the exact table
name you happen to remember. Planned grep-ai-style semantic search
will help you find the relevant table, column, or row from a simple fuzzy query.
Bring live databases, local DDL, work in progress, and Git context into one useful picture.
A live database is the truth today, but it is rarely the whole story. Start there,
then layer in local files, work in progress, and Git history to explore the schema
as it is heading, with the uncertainty kept visible.
Layer local files over the live database so the model can include the changes you are actively shaping.
Keep the live database as the baseline, then bring your checked-in DDL along for
the ride. Where the engine exposes modification times, SQLly compares them with
local files and uses the newer file for that table, view, procedure, function, or
query in the overlay.
A real-time local file overlay for Git-based schema management.
Work against checked-in DDL before it is deployed.
The query can still fail against the live database until the schema catches up. That distinction stays explicit; the overlay is helpful, not make-believe.
Get help from rough DDL before it is valid enough to deploy; SQLly keeps that uncertainty visible.
A DDL sketch does not need to be deployment-ready before it can be useful. SQLly
can read a clearly unfinished definition and overlay its best interpretation on
the real schema, without presenting that interpretation as fact.
That means help with column names, keys, indexes, and data types before the model
is valid. SQLly tracks the material as an incomplete region with
its own provenance and confidence, so you always know what is solid and what is
still a well-informed draft.
Help foreign keys show the human-friendly value behind the id, not just another opaque number.
Foreign keys are useful to the database but not always kind to human eyes. SQLly
uses DDL introspection to identify the likely human-friendly display
value for each relationship. The row editor
already offers searchable referenced values; bringing those names into the grid is
the remaining work.
Adjustable when needed. Override the guessed display column for any relationship where SQLly does not pick the right one.
Bring Git timing and authorship into the overlay when the history is part of the answer.
Filesystem timestamps are not always the best historians. The overlay will also
use Git modification times, so it can pick the right version even
when a file's mtime tells a less useful story.
It will also offer live database DDL git blame with notes: hover an object to see who changed it, when, and why.
Type the name you know; SQLly can add the join and make sure the comparison still means what you intended.
Looking for a value hidden behind a foreign key? Type the name you know.
SQLly will add the relationship it needs and compare against the readable value,
saving you a round of manual JOIN gymnastics.
Put a thoughtful pause in front of risky work while keeping ordinary reads pleasantly boring.
Good safeguards should catch the expensive mistake without making every ordinary
read feel like paperwork. Set a policy on a client, project, environment,
server, or database, and it flows down the connection tree until you
deliberately change a branch.
These policies combine with environment defaults - Production, for instance, forces read-only and rollback-wrap on automatically.
Make a connection genuinely read-only when browsing is all it should ever do.
Make a connection truly read-only: SQLly blocks everything except SELECT.
It is a good fit for a replica, an analyst-facing environment, or any server that
should never be at the mercy of a stray script.
Put non-read work inside a transaction you can inspect and roll back before it becomes permanent.
With auto-wrap on, anything beyond a plain read runs inside an outer
transaction. You get a chance to inspect the result and roll it back
before a change becomes permanent.
Review, then commit. The transaction stays open so you can see what changed before making that change permanent.
Ask for an unmistakable "yes, really" before a non-SELECT statement gets to run.
Ask for an explicit “yes, really” before a non-SELECT statement runs. It takes
a half-second and can save the moment when a production query was meant for staging.
Catch, warn about, or block broad UPDATE and DELETE statements before a tiny omission becomes a very long afternoon.
Before a batch runs, SQLly checks for UPDATE and DELETE
statements without a WHERE clause. It masks strings and comments first,
so a keyword inside a literal does not create a false alarm. Connection policy can
warn about these statements or block them outright.
Give production the visual warning it deserves so your peripheral vision can save the day.
Give clients, projects, environments, and servers their own colors and icons. The
point is simple: your peripheral vision should notice production before your hands
get a chance to make it exciting.
Colors are set on connection organization entities and surface as badges in the explorer and status bar.
Ask for a plain-language read on a query's side effects before it runs in a protected place.
In a protected context, require a plain-language review of a query's side effects
before it runs. SQLly already detects and gates the work, and the review dialog
makes the stakes unmissable with its
WE WILL MAKE UPDATE AND DELETE CHANGES. warning. The on-device model
that writes the explanation is still being connected.
Use your operating system's identity check where a mistake would be expensive, and leave routine work alone.
Use the identity check your operating system already knows how to do -
Touch ID on macOS and Windows Hello on Windows -
only where an extra pause is worthwhile. The underlying safety
policy is already in place; the native identity prompts are still on their way.
Require an OS-native identity check before SQLly opens a connection that deserves extra care.
Require an OS-native identity check before SQLly will even open a
connection. Apply it to one sensitive server or an entire client's
production environment; the hierarchy does the repetitive part for you.
# inherits down the tree, override anywhereclient: Acme Corp identity=connectenv: prod identity=connectserver: db-01.prod identity=inherit
Keep reads frictionless; ask for verification before an action with real teeth.
Reads stay easy. When a statement is not a plain SELECT - an
INSERT, UPDATE, DELETE, DROP,
TRUNCATE, or other DDL - SQLly will ask you to verify first. Statement
classification already knows which operations need that pause; the native prompt is
the remaining piece.
SELECT * FROM orders ✓ runsUPDATE orders SET … ☝ identity check required
Set identity rules at the level that makes sense and let them follow the connection hierarchy.
Identity rules use the same multi-dimensional hierarchy as the rest
of connection policy. Set one on a client and its projects, environments, and
servers inherit it until you deliberately change a branch.
Lock down production with one switch, then make a deliberate exception for a read replica if you need one. No copy-pasting the same rule across fifty connections.
Decide whether verification happens for every statement, every session, or somewhere comfortably in between.
Choose how long a verification remains valid. Ask for it on every
statement for the most sensitive targets, or once per session /
N minutes for friendlier ones. It is your production environment;
you get to set the comfort level.
Keep a local, tamper-evident record of who verified a gated action, where, and when.
Every gated action records who verified, which statement, which target, and
when. The result is a local, tamper-evident audit trail for
the inevitable question: “who ran that against production?”
Stays on device. The log never leaves your machine unless you export it.
Use the device passcode or OS sign-in when biometric hardware is unavailable or simply not your thing.
No biometric hardware, or a sensor having a bad day? SQLly can fall back to your
device passcode or OS account sign-in. A gate should be a deliberate
pause, not a lockout, and SQLly explains why it appeared before you approve it.
Keep connections and their schema close at hand, organized for the way you think about your work.
Server Explorer is the tree on the left: connections at the top and a live view of
schemas, tables, views, procedures, and more beneath each database. You decide how
to group connections and arrange objects, while a local
cache keeps the whole thing quick to open.
An ER diagram of a database's foreign keys, laid out, filtered, and exportable.
The header's overflow menu holds the grouping choices plus Manage Connections, Collapse All, and Refresh. Most of the tree's organization is configured in Settings › Data Model › Server Explorer.
See connections flat or grouped by client, project, environment, or server when a longer list needs a little order.
The explorer starts as a flat list. Use the header's overflow menu to switch the
grouping view and arrange connections around the dimension that is
useful right now.
The connection's environment (Local and unset land in “Unassigned”).
Server
The connection's name, falling back to its host.
Group folders are alphabetical with “Unassigned” pinned last. Each carries the matching entity color and icon, so a client's group looks familiar wherever it appears.
SQLly
Screenshot neededexplorer-grouping
The explorer grouped by client, with colored group headers, and the overflow menu showing the grouping choices.Features/Server Explorer/Schema tree
Schema tree
✓ functional
Learn how databases, schemas, and objects settle into a tree that stays easy to navigate.
Expand a connected database to explore its objects as a tree. Its shape is yours
to choose in Settings › Data Model › Server Explorer.
Schema display
Mode
Shape
Group by schema
Each schema gets its own folder; objects show just their name - server ▸ database ▸ schema ▸ Tables ▸ Orders.
All schemas together (default)
Schemas are mixed under shared folders; each object shows its schema as a prefix - Tables ▸ dbo.Orders.
Object-type folders
Objects settle into Tables, Views, and Programmability, which contains Types, Procedures, and Functions. Engines may also show Materialized Views, Sequences, Synonyms, Extensions, Events, and database-level Triggers. Expand a table for its Indexes, Statistics, Foreign Keys, Triggers, and Constraints.
Empty schemas & aligned metadata
General schemas - show them all, hide the empty ones, or show non-empty ones inline and collect the empties into an “Empty Schemas” folder.
Line up object metadata - align each item's name, data type, and nullability into columns (toggle per surface: tables, views, procedure and function parameters), with per-column left/right alignment and an optional fixed width.
SQLly
Screenshot neededexplorer-schema-tree
A database expanded into schema and object-type folders, with column-aligned metadata.
Pinning
Right-click any object - a table, view, procedure, function, database, and
more - and choose Pin to keep it close. A pinned object
floats to the top of the section it organically lives in:
a pinned table leads its own Tables folder, a pinned procedure leads
Programmability, a pinned database leads the server's database list. It
stays under its natural folder - it isn't lifted into a separate group at
the top of the server - so the tree keeps its shape while your
most-used objects sit first. Unpin from the same menu.
Choose whether each engine's built-in objects are folded away, shown inline, or kept out of sight.
Every engine ships useful-but-rarely-visited places such as master,
tempdb, sys, INFORMATION_SCHEMA, and
PostgreSQL's pg_catalog. SQLly tucks them away by default, while
Settings › Data Model › Server Explorer lets you choose how
visible they should be.
What
Choices
Default
System databases master, tempdb, model, msdb; PostgreSQL template0/template1/postgres
Group into a System Databases folder / show inline with user databases / hidden
Keep the schema tree quick with a local cache that checks itself whenever you reconnect.
SQLly keeps a local cache of each connection's schema, including
databases, tables, columns, keys, and routines. That is why Server Explorer and
IntelliSense can respond right away: the tree hydrates from the cache
instead of waiting for a fresh round of catalog queries.
Kept fresh
Revalidated on connect. Each connection refreshes the cached schema in the background, so a stale tree can correct itself without interrupting you.
Manual refresh any time. Choose Refresh from the explorer header's overflow menu to re-read the schema after a migration or a change made elsewhere.
The same cache powers IntelliSense. Completions read from this model of your schema and data, so a manual refresh brings both the tree and your autocomplete up to date together.
Give every connection enough context that the right database is easy to spot before you touch it.
A connection can carry three independent pieces of context - Client,
Project, and Environment - as well as its
Server. Each is a first-class entity with its own
color, icon, and safety policy, so
the explorer can group connections around the question you are asking.
Dev, staging, and prod variants of the same target.
What you can assign to each
Manage clients, projects, and environments in one place: the Manage Clients,
Projects & Environments dialog. They share the same properties, from their
basic identity to a set of query protections.
Property
What it is
Name
The label. The only required field - everything else is optional.
Color
An optional #rrggbb color, typed as hex or picked from a color wheel, with a live preview swatch. It tints the entity's badges and group headers in the explorer and status bar. (There's no fixed preset palette - any color is fair game.)
Icon
An optional custom image - browse to or type the path of a png, jpg/jpeg, gif, svg, ico, bmp, or webp file. It's your own artwork; there's no built-in icon set to choose from.
Query protections
The same nine safety toggles are available for every client, project, and environment. Most tighten safety; two deliberately relax a guard.
Toggle
What it does
Production environment
Marks this as production: connections are read-only until you unlock writes for a timed window, and every data change asks for confirmation showing the exact SQL. (Seeded on for the built-in Production environment.)
Wrap execution in transaction + rollback
Wraps each batch in a transaction that rolls back automatically - a safety net that makes writes reviewable before they commit for real.
Block all but SELECT
Blocks INSERT, UPDATE, DELETE, and every other non-SELECT statement.
Require confirmation dialog before running
Asks for confirmation before running data-changing statements.
Require AI review for data changes
Requires an AI-generated review before any data-changing statement runs.
Allow unconstrained UPDATE relaxes
Permits an UPDATE with no WHERE without the extra confirmation that would otherwise fire.
Allow unconstrained DELETE relaxes
Permits a DELETE with no WHERE without the extra confirmation.
Require Touch ID to connect
Prompts for Touch ID before establishing the connection.
Require Touch ID for non-SELECT
Prompts for Touch ID before any non-SELECT statement runs.
SQLly
Screenshot neededconn-org-entity-dialog
The Manage Clients, Projects & Environments dialog: name, color (with picker and swatch), icon, and the Query Protections checkboxes.
Safety inherits down the tree. A policy on a client, project, or environment applies to every tagged connection. These tiers can only tighten safety, never loosen it; the two “Allow unconstrained” choices remain per-connection. That makes “SELECT-only for production” one switch, with no quiet opt-out on an individual connection.
Switch how the explorer groups everything from the sidebar header (All / Client / Project / Environment / Server).
Use clients as the top-level home for the connections that belong to the same customer or owner.
A Client is the top-level owner for a connection: a customer, team,
or organization. It is more than a label, carrying its own color, icon, and query
protections wherever it appears.
Creating and assigning
In the connection editor, type a client name - the field autocompletes against clients you already have.
A name that doesn't exist yet is registered as a client automatically when you save, so you can immediately give it a color or a safety rule.
Refine it in the Manage Clients, Projects & Environments dialog: name, color (hex + picker), icon (browse or drag-drop an image), and a Query Protections section.
Client matching is by name and case-insensitive, so every connection tagged with a client inherits that client's color and safety policy.
SQLly
Screenshot neededconn-org-clients
A client in the connection organizer, with its color, icon, and the connections grouped under it.
A connection can also carry a Project and an Environment - the three are independent.
Group related databases by the work they support, rather than hoping the server name tells the whole story.
A Project gathers the databases behind one piece of work, whether
that is a product, migration, or analysis. It is the structural twin of a
Client, with the same name,
color, icon, and safety fields.
Client and Project are independent: a connection can have both, either, or neither. A client answers whose database it is; a project answers what work it supports. Like clients, a typed project name autocompletes and is registered on save so it can carry a color or safety rule.
SQLly
Screenshot neededconn-org-projects
A project grouping several related databases in the organizer.
Group the explorer by project from the sidebar header to see work-by-work instead of owner-by-owner.
Make development, staging, and production unmistakable variants of the same target.
An Environment marks which version of a target a connection uses:
Local, Dev, Test,
Staging, or Production. It gives the important
question - “is this production?” - a clear answer before you run anything.
Assigning an environment
Use the connection editor's PROD / STAGE / TEST / DEV / LOCAL control to set the environment; select it again to clear it. Dev, Test, Staging, and Production come ready with their own colors and icons, which appear as badges in the explorer and status bar.
Safety that rides the environment
Production forces SELECT-only and rollback-wrap on, marks the connection production, and shows a PRODUCTION chip in the status bar - keeping writes locked until you deliberately unlock them for a timed window.
Staging forces rollback-wrap on.
Lower environments add no restrictions - and these defaults only ever turn safety on.
Need an exception? A per-connection production override (Inherit / Production / Not production) has the final say on the production flag.
SQLly
Screenshot neededconn-org-environments
Environment variants of one target, with the production connection badged in the status bar.
Color prod an angry red. Give each environment its own color and the difference reaches your peripheral vision before it reaches your fingers.
Environment safety combines with policy from the connection's Client and Project - whichever is strictest wins.
Sign in with Entra, find Azure SQL targets, and get a hand with firewall access when it is needed.
Azure SQL should not require a scavenger hunt for credentials and firewall rules.
Sign in with Entra ID using a device code or browser, discover
the servers and databases you can use, and get help adding a firewall rule when
Azure turns you away at the door.
Interactive Entra sign-in - device-code or browser flow, tokens handled for you.
Server & database discovery across your subscription.
Firewall-rule assist when Azure says no - add your IP without leaving the app.
The engineering behind a responsive workbench, remote reach when you need it, and privacy when you do not.
SQLly is built to stay responsive when the work gets serious, reach your database
when you are not at your desk, and stay quiet when you have not asked it to connect
anywhere.
Let a multithreaded, carefully tested Rust engine handle completion and queries without turning every keystroke into a wait.
Completion and query execution run in a dedicated, multithreaded,
thoroughly tested Rust engine. That separation lets the editor stay with
you while the heavier database work happens alongside it.
Schema refreshes do not need to interrupt you mid-thought.
Caching keeps routine work snappy.
Targeted cache invalidation keeps the model fresh without throwing away useful work.
Stream large results with backpressure and disk spillover so one huge answer does not eat the machine.
A very large result set should not turn into a very large memory problem. Rows
stream through a back-pressured channel and spill to disk, letting
the grid page from its on-disk store whether a query returns 50 rows or 50 million.
That is why the result grid stays smooth on six-figure result sets: it renders only the slice currently on screen.
Reach a database through an end-to-end encrypted relay that can route the traffic but cannot read it.
Reach your database from where you are, without the usual VPN scavenger hunt or
jump-box ritual. An end-to-end encrypted tunnel passes through a
relay that can route the traffic but cannot read it.
No app telemetry today, full stop. SQLly stays quiet unless you explicitly ask it to connect somewhere.
SQLly does not phone home: there is no telemetry in the app today.
If opt-in check-ins ever arrive, the privacy policy changes
first, the feature ships off by default, and its purpose is stated
plainly. Your data and your habits remain yours.
The same native SQLly workbench on the desktops where real database work happens.
SQLly brings the same native workbench to macOS, Windows, and Linux. There is also
a clearly labeled browser preview for a quick look before you download anything.
One GPU-rendered workbench across macOS, Windows, and Linux, using the native graphics path on each rather than a webview in a trench coat.
SQLly is one Rust codebase with a GPU-accelerated native interface on
macOS, Windows, and Linux. You get the same editor, object explorer,
and result grid everywhere; only the small platform layer that talks to the window
system, GPU, and text stack changes underneath. The desktop app renders directly on
the GPU, with no browser runtime along for the ride.
How it talks to each OS
Each platform uses the native rendering and windowing path that fits it best rather
than settling for a shared lowest common denominator:
Layer
macOS
Windows
Linux
GPU rendering
Metal
Direct3D 11 (DirectX)
Vulkan (via Blade)
Windowing
Cocoa / AppKit
Win32 + DirectComposition
Wayland, with X11 fallback
Text & fonts
Core Text
DirectWrite
Fontconfig + Cosmic Text
Target
Apple Silicon (M-series)
x64 and arm64, Windows 10/11
x64 and arm64 desktop
Same engine, same features, same pig. These differences are simply how SQLly feels
at home on each operating system.
macOS
On the Mac, SQLly uses Metal on Apple Silicon,
Core Text for layout, and Cocoa / AppKit for its
windows. The goal is straightforward: it should feel like a good Mac app, not a
compromise that happened to compile there.
Intuitive file navigation - a custom open & save dialog designed for how you actually browse files on macOS; the project file picker already searches with prefixes like v:, p:, f:, and schema:.
Keyboard-first flow - a command palette, a keyboard tab switcher, and fuzzy matching baked into search and navigation throughout.
Native to the platform - real Metal drawing on Apple Silicon, system font rendering via Core Text, and standard macOS window and menu behavior.
SQLly on macOS - Metal-rendered UI on Apple Silicon, with the native open dialog and command palette.
Windows
On Windows, the same UI uses Direct3D 11 (DirectX) and
DirectComposition for smooth presentation, with
DirectWrite handling text. The Win32 window layer keeps snapping,
virtual desktops, and high-DPI scaling behaving as Windows users expect.
DirectX-native rendering - every frame on the GPU via Direct3D 11, no software fallback and no embedded browser.
Crisp text at any scale - DirectWrite handles font shaping and per-monitor DPI, so the editor stays sharp on mixed-DPI setups.
The whole workbench - identical editor, explorer, and result grid; the same keyboard-first flow and command palette.
x64 & ARM64 - native builds for both Intel/AMD and ARM Windows machines, on Windows 10 and 11.
SQLly
Screenshot neededplatform-windows
SQLly on Windows - the same workbench rendered with Direct3D 11 and DirectWrite.
Linux
On Linux, SQLly renders through Vulkan via GPUI's Blade layer and
prefers Wayland, with an X11 path when Wayland is
unavailable. Fontconfig and Cosmic Text pick up the
fonts already on your machine.
Vulkan-accelerated - GPU rendering through Blade on a modern Vulkan driver, not a CPU rasterizer.
Wayland-first - native Wayland windowing with fractional scaling, and an X11 path for older sessions.
System-native fonts - Fontconfig + Cosmic Text pull in the fonts already installed on your machine.
x64 & ARM64 - native builds for both Intel/AMD and ARM64 (aarch64) Linux desktops.
SQLly
Screenshot neededplatform-linux
SQLly on Linux - Vulkan rendering under Wayland, using your system fonts.Features/Platforms/Browser preview (in-tab demo)
Browser preview (in-tab demo)
◇ in-tab demo
Take the workbench for a spin in your browser against sample data; it is a demo, not a cloud detour.
This is a hands-on preview of the workbench compiled to
WebAssembly, running against sample data in your tab. It is the
real editor, object explorer, and result grid, not a screenshot.
Read this first: a great deal here is broken. This preview is
illustrative, not representative. Getting a native, GPU-rendered
SQL workbench to run inside a browser sandbox is genuinely difficult, and
many, many features simply do not work in the WebAssembly build -
some are missing, some are stubbed out, and some will misbehave outright. Treat
anything that breaks here as a limitation of the browser port, not as how SQLly
behaves on your own machine. To judge the real thing, run the desktop app.
It is also not a hosted cloud app: it cannot reach your servers, relay, or
production SQL Server. Local files, Azure sign-in, credential storage, and Cloud
AI stay in the desktop app, and anything that depends on the operating system -
the file system, the keychain, native dialogs, background processes - is either
absent or faked.
SQLly - browser preview
Loading the full app… the WebAssembly build downloads on first view.
Runs entirely in your browser via WebAssembly + WebGPU - it needs a recent Chrome/Edge, Safari, or Firefox with WebGPU enabled, and it never talks to your databases. The build loads only when you open this page and unloads automatically the moment you navigate away, so it never sits idle in the background.
Prefer just the grid? The interactive sample embeds the result grid on its own.
Demo only - not a Cloud SKU. It's a preview of the UI, running
locally in your browser. Longer term there is likely to be a proper hosted
product built on this, with the enterprise security controls that would demand -
tenancy isolation, managed identity, audited access. None of that exists yet.
For now this is simply here so you can have a quick play online without
installing anything.
Connections, history, snippets, cards, and rules live as plain files you can back up, inspect, and keep.
Connections, query history, snippets, entity cards, and identity rules all live as
plain files on disk. There is no opaque database to escape later:
back them up, diff them, or keep them in Git if that suits your workflow.
When you opt in, let iCloud carry your SQLly setup between Macs without routing it through us.
Turn it on and your SQLly setup can follow you to each Mac you use:
credentials, configuration, and
customization travel through Apple's sync, not ours. Sit down at
another Mac and your workspace is ready the way you left it; we never see the data.
// Preferences › iCloudSync via iCloud Drive[ off ]↳ stores everything locally only
Off means off. Flip it off and the files never leave the machine - there's no half-on state.
Tools
Tools
The admin tools SQLly opens from the Object Explorer's right-click Tools menu - some for a whole server, some scoped to a single database.
The admin tools SQLly opens from the Object Explorer's right-click Tools menu - some for a whole server, some scoped to a single database.
Start here
Choose the part that matches what you are trying to get done:
Server tools — Right-click a server, open Tools, and act on the whole instance.
Database tools — Right-click a database, open Tools, and work within that database.
Live health tiles for a connection - sessions, throughput, health, and resources - refreshed on a ticker.
The Server Dashboard is a live, read-only health view for a single connection. It
reads catalog and dynamic-management snapshots on a short ticker and lays them out
as tiles, so the state of the instance is legible at a glance rather than buried in
a dozen queries you have to remember.
Sessions
Connections, running requests, blocked count, longest-running query, and oldest open transaction.
Throughput
Transactions and queries per second, with a small sparkline so a trend is obvious.
Health
Deadlocks and lock waits per second - the numbers that tell you something is fighting.
Resources
Cache hit ratio, page life expectancy, memory in use, storage, and uptime.
It is non-modal and there is one dashboard per connection, so you can
open several and watch multiple servers side by side; the most recently raised one sits
on top. Refresh and pause act only on their own pane.
SQLly
Screenshot neededtools-server-dashboard
The Server Dashboard for a connection: Sessions, Throughput, Health, and Resources tiles over a live catalog snapshot.
Tiles adapt to the engine - PostgreSQL adds idle-in-transaction, MySQL adds slow queries, and SQLite shows only the resource band it can fill.
Browse jobs, history, schedules, operators, and alerts from msdb, with script-first job control.
The SQL Agent browser surfaces the instance's automation from msdb in real
grids: Jobs, History, Schedules, Operators, and Alerts, each on its own tab. It is a
place to read what the Agent is doing without leaving SQLly.
Script-first job control. Start, Stop, Enable, and Delete never run from the dialog. They open the reviewed SQL in a query tab so you decide, in context, whether to run it - the same contract every write path in SQLly follows.
SQLly
Screenshot neededtools-server-sql-agent
SQL Agent: the Jobs tab with a job grid, and script-first Start / Stop / Enable / Delete actions in the footer.
SQL Server only - the Agent and msdb are a SQL Server concept.
Server logins, role membership, and permissions in one place.
Server-level security in one dialog: logins, their role membership, and the
server permissions that decide what each principal can do. It is the counterpart to
SSMS's Login Properties pages, kept in the same paged shape as SQLly's other property
editors.
SQLly
Screenshot neededtools-server-security
Server Security: logins and server-role membership, with the permissions each principal holds.
Security also appears on a database node, where it manages that database's users, roles, and grants instead.
Every saved connection's observed health - badge, ages, last error, and a measured test latency.
Connection Health puts every saved connection in one overlay so you can
see, at a glance, which ones are reachable. Each row shows a status badge, how long ago
it last connected and was last tested, a redacted summary of its last error, and a
client-measured test latency.
Per-row Test - re-check a single connection on demand.
Test All - sweep every connection in one pass and watch the badges settle.
Redacted errors - enough of the last failure to act on, without leaking secrets into the row.
SQLly
Screenshot neededtools-server-connection-health
Connection Health: a row per saved connection with status badge, last-connected and last-tested ages, last error, and measured latency.Tools/Server tools/Disk Usage
Disk Usage
✓ functional
Size every database on the instance, plus the current database's file layout.
Opened from a server, Disk Usage gives you the whole instance: a
Databases tab that sizes every database - data and log - so the space
hogs are easy to spot, plus a Files tab for the current database's
file layout.
Scope-aware. This is the server-wide view. Open Disk Usage from a single database instead and it drops the all-databases tab and shows only that database's files. See Disk Usage (database).
SQLly
Screenshot neededtools-server-disk-usage
Server Disk Usage: the Databases tab sizing every database on the instance.
Read-only - this pane only observes sizes and growth settings; it never changes them.
Users, roles, membership, and access for the selected database.
Database-level security for the selected database: its users, their role membership,
and the object and schema permissions that shape what each one can touch. Same paged
editor as the server version, scoped to one database.
SQLly
Screenshot neededtools-db-security
Database Security: users, roles, and the permissions granted within one database.Tools/Database tools/Backup / Restore
Backup / Restore
✓ functional
Back up and restore the database, with destructive steps scripted first for review.
Back up and restore the database. This was the first real Tools-menu admin dialog and
set the template the rest follow: a focused form on the shared dialog chrome, with any
destructive step scripted first for review rather than run on click.
SQLly
Screenshot neededtools-db-backup-restore
Backup / Restore: choose a backup or restore operation for the database; the resulting statement opens for review.Tools/Database tools/Activity Monitor
Activity Monitor
✓ functional
Live sessions, blocking chains, expensive queries, and wait stats over the connection's DMVs.
A live admin pane over the connection's dynamic management views. Four tabs, each a real
grid: Sessions, blocking chains,
expensive queries, and wait statistics - the wait tab
sampling the change since the previous refresh rather than raw totals.
Scope-aware. Opened from a database, the Sessions view lists only connections on that database. Opened from the server, it shows every session on the instance.
SQLly
Screenshot neededtools-db-activity-monitor
Activity Monitor: the Sessions grid over sys.dm_exec_sessions, with tabs for blocking, expensive queries, and waits.
Auto-refreshes on a ticker you can pause; the age readout stays live even while paused.
Visual object designers for building and altering database objects without hand-writing DDL.
Visual designers for building and altering database objects, so routine structure work
does not mean hand-writing DDL and hoping you got every clause right.
SQLly
Screenshot neededtools-db-designers
Designers: a visual editor for a database object's structure.Tools/Database tools/Import / Export
Import / Export
✓ functional
Load a CSV, JSON, Excel, or SQLly Export file into a table - or export out - through a script-first wizard.
A guided wizard for moving tabular data in and out of a table. Import from a
CSV, JSON, Excel workbook
(.xlsx/.xls), or a .sqllyexport file - or export a
table out. Like every write path, it is script-first: the load is prepared for you to
review before it runs.
SQLly
Screenshot neededtools-db-import-export
Import / Export: pick a source file and target table; the import is prepared as reviewable SQL.Tools/Database tools/Schema Compare
Schema Compare
✓ functional
Compare schema across two connections and generate a review-only migration script.
Compare schema across two connections. Source and target routes are
captured independently, metadata is normalized only where the engines expose comparable
facts, and the generated migration text is review-only - SQLly shows
you the difference and the script, and leaves running it to you.
SQLly
Screenshot neededtools-db-schema-compare
Schema Compare: a source and target connection side by side, with per-object differences and a review-only migration script.
Cross-connection. Pick any two connections as source and target - they do not have to be the same server or even the same engine, within what the engines can meaningfully compare.
Compare table data across connections and generate a review-only sync script.
Compare the data in tables across connections and generate a
review-only sync script for the rows that differ - added, removed, or
changed - so you can reconcile two databases deliberately.
SQLly
Screenshot neededtools-db-data-compare
Data Compare: matched tables across two connections, showing added, removed, and changed rows with a review-only sync script.Tools/Database tools/Data Transfer
Data Transfer
✓ functional
Copy table data to another connection, database, and schema with live progress.
A wizard for copying table data to another connection. Pick the source tables, the
target connection, database, and schema, the write mode and identifier casing, then run
it with live progress.
SQLly
Screenshot neededtools-db-data-transfer
Data Transfer: choose source tables and a target connection/database/schema, then run with a progress readout.Tools/Database tools/Query Insights
Query Insights
✓ functional
Bounded top-query statistics from Query Store, pg_stat_statements, or Performance Schema.
Bounded top-query statistics for the database, sourced from whatever store the engine
keeps: SQL Server Query Store, PostgreSQLpg_stat_statements, or MySQL / MariaDB Performance Schema.
Rank by average duration and open any row's SQL for a closer look.
Needs the store enabled. Query Insights reads the engine's own statement store, so it can only show what that store has collected - if the collector is off, it says so rather than inventing numbers.
SQLly
Screenshot neededtools-db-query-insights
Query Insights: the top queries by average duration, with execution count and logical reads, and Open Selected Query to edit one.Tools/Database tools/Disk Usage
Disk Usage
✓ functional
The selected database's file layout - logical files, size, max, and growth.
Opened from a database, Disk Usage shows just that database's file layout:
each logical file, its type, path, current size, maximum size (or unlimited), and growth
setting.
Scope-aware. This is the single-database view. Open Disk Usage from the server node instead for the all-databases overview. See Disk Usage (server).
SQLly
Screenshot neededtools-db-disk-usage
Database Disk Usage: the Files tab listing one database's data and log files with their sizes and growth.Tools/Database tools/Index Analyzer
Index Analyzer
✓ functional
Real index usage counters, least-read first, with a script-first DROP INDEX for the ones you choose.
Real usage counters for every index in the database, sorted least-read
first, so the indexes nobody is using rise to the top. Removing one is
script-first: SQLly prepares a reviewed DROP INDEX for the ones you decide
to drop.
SQLly
Screenshot neededtools-db-index-analyzer
Index Analyzer: every index with its read/write counters, least-read first, and a script-first DROP INDEX action.Tools/Database tools/Test Data Generator
Test Data Generator
✓ functional
Deterministic, dialect-correct INSERT scripts built from a table's real column metadata.
Generate deterministic, dialect-correct INSERT scripts for a table, built
from its real column metadata - types, nullability, and keys - so the sample data
actually fits the schema you have.
SQLly
Screenshot neededtools-db-test-data-generator
Test Data Generator: choose a table and row count; SQLly emits INSERT statements matching the column types.Tools/Database tools/Relationship Graph
Relationship Graph
✓ functional
An interactive ER diagram of the database's tables and foreign keys.
An interactive ER diagram for the database. Tables and their foreign-key relationships
are laid out on a pannable canvas, so the shape of the schema - and how things connect -
is something you can see rather than infer.
SQLly
Screenshot neededtools-db-relationship-graph
Relationship Graph: tables as nodes and foreign keys as edges on a pannable canvas.Tools/Database tools/Query Builder
Query Builder
✓ functional
A visual query builder - tables as cards, foreign-key join lines, and live SQL.
A visual query builder: tables arrive as cards, foreign keys draw as
join lines on a canvas, clauses live in a side panel, and the SQL
updates live as you go - a way to assemble a query by arranging it.
SQLly
Screenshot neededtools-db-query-builder
Query Builder: table cards with foreign-key join lines, a clause side panel, and the generated SQL updating live.Tools/Database tools/Document Schema
Document Schema
✓ functional
Generate Markdown documentation of the database's schema, ready for a repo or wiki.
Generate Markdown documentation of the database's schema - tables,
columns, and structure - in a form you can drop straight into a repository README or a
team wiki.
SQLly
Screenshot neededtools-db-document-schema
Document Schema: the database's structure rendered as Markdown documentation ready to save.Tools/Database tools/Tenant Scoping
Tenant Scoping
✓ functional
Configure the multi-tenant missing-filter guard: whether it runs, the tenant column, and the tenants table.
Configure SQLly's multi-tenant missing-filter guard for the database:
whether the guard runs at all, which column marks a table as tenant-scoped, and,
optionally, which table holds the tenants themselves. It is how you teach SQLly what
"forgot the tenant filter" means for your schema.
SQLly
Screenshot neededtools-db-tenant-scoping
Tenant Scoping: enable the guard for a database and name the tenant column and tenants table.Tools/Database tools/Query History
Query History
✓ functional
Search the local execution log, keep pinned snippets, and send any statement back to the editor.
A browser over the local execution log. Search across the SQL text, server, and database
at once; keep a pinned section of snippets worth holding onto; and send
any past statement straight back to the editor.
SQLly
Screenshot neededtools-db-query-history
Query History: live search over the local execution log with a pinned section and script-to-editor.
The history lives in a local file, like the rest of your SQLly setup - it is yours to keep, search, and back up.
List Extended Events sessions with running state and per-session detail; start and stop are script-first.
List Extended Events sessions with their running state, and drill into any session's
events and targets. Starting and stopping a session is script-first:
the ALTER EVENT SESSION statement opens in a tab for review rather than
firing from the dialog.
Scope-aware. Opened from a database, it lists that database's own database_event_sessions. Opened from the server, it lists the instance's server-scoped sessions - and on Azure SQL Database, which only has database-scoped sessions, it falls back automatically.
SQLly
Screenshot neededtools-db-extended-events
Extended Events: the session list with running state, per-session event/target detail, and script-first start/stop.
SQL Server family - Extended Events is a SQL Server feature.
// welcome
SQLly documentation
This is the practical tour: what each part of SQLly is for, how it behaves, and where to go next. Every topic has its own link, so you can bookmark the useful bit and skip the rest.
Not sure where to begin? Start with IntelliSense, then follow the trail into results, safety, and the parts that make your daily SQL work less fiddly.