LibreDB Studio
The database editor that deploys next to your data, not onto your laptop.
English · 简体中文 · 日本語 · Español · اردو
Listed by the PostgreSQL project: News · PostgreSQL Clients · Software Catalogue · Community Guide to GUI Tools
Also listed in official Redis, ClickHouse MariaDB, Trino and Apache Cloudberry docs
Quick Start • Live Demo • Install Options • Deploy Your Own
Quick Start
Run a full Database Editor in one command, no clone, no build:
# Docker (recommended)
docker run -p 3000:3000 ghcr.io/libredb/libredb-studio:latest
or with Node.js 24+ (no Docker)
npx @libredb/studio
Then open http://localhost:3000. On first run, the admin password is printed to the log (zero-config).
Need Helm, Homebrew, Snap, winget, or deb/rpm? See all install options.
Live Test
Try LibreDB Studio instantly without installation!
| Test | URL | Credentials | |------|-----|-------------| | Public Test With OIDC | app.libredb.org | SSO | | Public Test With JWT | trial.libredb.org | [email protected] / Admin!2026 [email protected] / User!2026 |
The test instance comes with a pre-configured PostgreSQL database via Seed Connections. No setup required!
Overview
You create a Postgres on a managed platform. It is ready in forty seconds. Then you want to look inside it — so you open a port to the internet, dig an SSH tunnel, or install a desktop client on every machine that needs one.
LibreDB Studio goes the other way. It deploys next to the data: a container, a Helm chart, an operator, a one-click template on your PaaS, or npm i @libredb/studio inside your own product. Nothing has to face outward.
Sixteen engines share one interface — PostgreSQL, MySQL, Oracle, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, ClickHouse, Druid, Elasticsearch, OpenSearch, Apache Trino and Apache Cassandra — with the same explorer everywhere, and ER diagrams, schema diff and monitoring wherever the engine has something to report. Three of the sixteen are read-only because their own SQL is: Druid, Elasticsearch and OpenSearch have no UPDATE and no CREATE TABLE in the grammar at all, so those controls are reported as unsupported instead of failing when used. Cassandra is the newest, and the one that reports the least on purpose: it publishes no row count and no size that is true, so the object browser shows neither rather than showing a number that is wrong — the estimate it does publish counts partitions from flushed files, and it read 143 for a 500-row table. Trino is the other odd one: it is a query engine rather than a database, so it declares no keys and no indexes and reports the bytes as belonging to the systems behind its connectors.
And nothing is held back. Single sign-on, ER diagrams, the AI features and the NoSQL engines all ship in the MIT build. MIT is not generosity here, it is a requirement of the architecture: you cannot place a per-seat licensed, feature-gated tool into every environment you own.
Why LibreDB Studio?
- Deploys next to the data: container, Helm chart, Rancher, OpenShift operator, one-click PaaS template, or embedded via npm.
- Sixteen engines, one interface: PostgreSQL, MySQL, Oracle, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, Cassandra.
- Runs where you are: browser, phone, Windows, MacOS, Linux desktop.
- A read-only agent, with your own model: state a question, and the run drafts SQL, reads the results, and writes a report whose claims cite them. Gemini, OpenAI, or a local Ollama with open-source models.
- Nothing behind a wall: RBAC, OIDC single sign-on, query audit trail, and ER diagrams all ship under MIT.
Connect to PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Couchbase, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, Cassandra, Redis, SQLite, DuckDB, or libSQL with SSL/TLS and SSH Tunnel support.
Key Features
Professional SQL IDE
- Monaco Engine: Powered by the same core as VS Code.
- Smart Autocomplete: Schema-aware suggestions for tables, columns, and SQL keywords.
- Command Palette: Quick access to tables, connections, saved queries, and actions with
Cmd/Ctrl+K. - Multi-Tab Workspace: Handle parallel tasks with independent execution states.
- Saved Query Backups: Export the complete saved-query library as JSON. Import validates the file, preserves query metadata and merges new entries, reporting duplicate IDs while keeping existing queries intact.
- Duplicate Connections: Open an independent
(copy)of an editable saved connection in the connection editor, adjust its settings and save. Cancelling leaves the saved connections unchanged; administrator-managed connections cannot be duplicated. - Visual EXPLAIN: Graphical execution plans to identify performance bottlenecks.
- Interactive ER Diagrams: Visual schema graph with real foreign key edges, cardinality labels, MiniMap navigation, table search/filter, compact mode, and PNG/SVG export. Automatic hierarchical layout powered by ELK.js.
- Schema Diff & Migration: Compare schema snapshots or cross-connection schemas side-by-side. Color-coded diff view (added/removed/modified) with automatic migration SQL generation for PostgreSQL, MySQL, SQLite, Oracle, and SQL Server, plus ClickHouse column modifications.
- Snapshot Timeline: Visual horizontal timeline of schema snapshots. Click any two points to instantly compare and track schema evolution over time.
Visual schema explorer with interactive ER diagrams powered by ReactFlow.
The Database Agent
Studio's main AI surface is an agent rail beside the editor; the model-backed helpers listed below it are the others. You state an objective: "which department has the most employees?", *"why is this query slow?"*; and press Start. The run drafts SQL against the connected database, reads what comes back, and finishes by composing a report whose every claim cites the result it came from.
- Read-only, enforced by the database rather than by a parser. Every statement the agent runs
executeAuditedOperation, src/lib/db/operations/execution.ts:129)
— under a read-only execution profile: a read-only transaction on PostgreSQL, PRAGMA query_only
re-asserted per statement on SQLite, and a READ_ONLY engine handle on DuckDB paired with an
SQL-level guard, because that flag alone still lets COPY … TO, EXPORT DATABASE and the
local-file table functions through. Writes and DDL are refused before the database is reached,
and EXPLAIN ANALYZE is default-denied because it would run the statement. This pipeline is the
agent's alone: statements you run yourself in the editor call the provider directly
(src/app/api/db/query/route.ts:44) and are neither policy-checked nor audited this way.
- Agent mode reads PostgreSQL, SQLite and DuckDB only. The read-only profile is database-native,
queryReadOnly on postgres.ts:915,
sqlite.ts:537 and duckdb/index.ts:525, and nowhere else. On any other engine, an Agent-mode run ends engine-unsupported
(src/lib/agent/runtime.ts:199). Plan mode opens on every connection — the model there is
toolless, runs no statement of yours, writes nothing, and drafts a statement for you to run
yourself. Its GROUNDING reaches every engine: on PostgreSQL and SQLite the server composes catalog
statements itself, and on every other connection it asks that connection's own provider to describe its
schema — the reading the sidebar already performs — which needs no read-only statement path. So the
two limits are separate: agent mode is those three engines, grounding is all of them, and a run whose
reading fails says so plainly rather than inventing tables.
- Three workflows: Investigate (answer a question), Optimize (compare estimated plans,
- Nothing runs itself. The agent never starts a run for you, never writes to the editor, and
- Evidence or nothing. A claim with no citation cannot be composed, and the run states its own
- Bounded, and the meter is on screen: 20 statements, 60 s of database time, 200 rows per read,
- Your own model. Gemini (the default), OpenAI, Ollama, or any OpenAI-compatible endpoint.
src/lib/agent/capability-gate.ts:74), so a model refused for Agent mode can still
be used in Plan mode, which is what the rail offers you.
- No model configured, no AI. With no
LLM_*settings at all, the rail does not render, and
docs/AGENT_DATA_FLOW.md.
Standalone application only: the embedded @libredb/studio package carries no agent surface.
Guide: docs/AGENT_GUIDE.md · What leaves the machine:
docs/AGENT_DATA_FLOW.md · Behaviour and limits:
docs/AGENT.md · Which local model to run:
docs/llms/
Model-backed helpers
- Universal LLM Support: Defaults to Gemini and serves OpenAI, Ollama, and any OpenAI-compatible endpoint (LM Studio, LiteLLM, vLLM).
- Query Safety Analysis: AI-powered pre-execution risk assessment for destructive queries (DELETE, DROP, TRUNCATE). With no provider configured, the confirmation remains available with a plain query warning. Setting
LLM_PROVIDERwithout its credentials is an unfinished setup, so that error stays visible, as do other configuration and service errors. - AI Query Explainer: EXPLAIN plans translated into plain language with optimization suggestions.
- Schema Awareness: the connected database's schema is sent as context, so an explanation names your own tables and columns.
- Data Profiler summary: the profiler's per-column statistics written up in prose. That context carries each column's
minandmax, which are real values from your data; see Agent Data Flow.
Pro Data Management
- Universal Data Grid: Virtualized rendering (TanStack) for millions of rows.
- Inline Editing: Double-click to update values directly in the grid, on engines whose SQL has a single-table row update (the control is hidden elsewhere).
- Column Filtering: Per-column text filters on query results for instant data exploration.
- Interactive Pivot Table: Client-side pivoting with 5 aggregation functions (COUNT, SUM, AVG, MIN, MAX) and SQL generation.
- Expert Exporter: Instant CSV and JSON exports for reporting. CSV import and result export offer comma (default), semicolon and tab separators.
Advanced Data Visualization
- 8 Chart Types: Bar, Line, Pie, Area, Scatter, Histogram, Stacked Bar, and Stacked Area charts powered by Recharts.
- Data Aggregation: Group-by with SUM, AVG, COUNT, MIN, MAX aggregation functions. Date grouping by hour, day, week, month, or year.
- Chart Persistence: Save chart configurations and reload them instantly. Manage a library of saved charts.
- Chart Dashboard: Grid view of all saved charts for at-a-glance data overview directly in the bottom panel.
Display Masking (Preview)
- Client-Side Display Layer: Masks sensitive values in the browser UI — useful for screen sharing, demos, and reducing accidental on-screen exposure. Not server-enforced; query API responses still contain full values for authenticated users.
- Column-Name Pattern Matching: 10 built-in patterns (email, phone, credit card, SSN, password, IP, date, financial, and more) match result column headers by regex. Works when the output name matches (e.g.,
SELECT salary). Aliases (salary AS x) and aggregates (SUM(salary)) are not masked today. - Configurable Rules: Admin panel to add, edit, enable/disable masking patterns. Email, phone, credit card and SSN presets prefill the Add Pattern form so column patterns can be adapted before saving. Custom patterns support regex. Settings stored per-browser in localStorage.
- RBAC UI Controls: User role cannot toggle or reveal masked cells in the UI. Admin role can toggle masking and temporarily reveal individual cells (10s auto-hide).
- Export & Clipboard: CSV, JSON, and SQL INSERT exports use masked display values when masking is active in the UI. This does not prevent access to raw data via the API, browser DevTools, or admin reveal.
- UI Coverage: Grid, mobile card/table views, row detail sheet, and clipboard copy respect the active display mask.
Analyst & Developer Tools
- AI Data Profiler: One-click table profiling with column statistics (null %, cardinality, min/max, sample values) and AI-powered narrative summaries.
- ORM Code Generator: Generate TypeScript interfaces, Zod schemas, Prisma models, Go structs, Python dataclasses, and Java POJOs from live table schemas.
- Test Data Generator: Schema-aware fake data generation with 30+ semantic column inferences (email, phone, name, address, etc.). Produces INSERT statements or MongoDB insertMany JSON.
- Database Documentation: Auto-generated searchable data dictionary from live schema with AI-powered documentation and Markdown export.
One-click column profiling: null %, cardinality, min/max, and sample values for 300K+ rows.
Generate TypeScript interfaces, Prisma models, Go structs, and more from live schemas.
Authentication & SSO
- Dual Auth Modes: Local email/password login or OpenID Connect (OIDC) Single Sign-On; switchable via environment variable.
- Vendor-Agnostic OIDC: Works with any OIDC-compliant provider — Auth0, Keycloak, Okta, Azure AD, Zitadel, Google, and more.
- PKCE Security: Authorization Code Flow with Proof Key for Code Exchange (S256) for secure authentication.
- Auto Role Mapping: Configurable claim-based role mapping with dot-notation for nested claims (e.g.,
realm_access.roles). - Provider Logout: Logout clears both the local JWT session and identity provider session.
DBA Maintenance Toolkit (Admin Only)
- Live Monitoring Dashboard: 7-tab monitoring with Overview, Performance, Queries, Sessions, Tables, Storage, and Connection Pool views.
- Time-Series Trend Charts: Real-time metric trends (connections, cache hit ratio, buffer pool, deadlocks) with auto-refreshing ring buffer history.
- Configurable Auto-Refresh: Polling intervals from 5s to 60s with play/pause control.
- Threshold Alerting: Color-coded health indicators (healthy/warning/critical) for cache hit ratio, connection usage, deadlocks, and buffer pool utilization.
- Connection Pool Stats: Live total/active/idle/waiting pool metrics with utilization progress bars.
- One-Click Maintenance: Trigger
VACUUM,ANALYZE,REINDEX,UPDATE STATISTICS,DBCC CHECKDB, andALTER INDEX REBUILDper database engine. - Audit Trail: Full history of every query executed across the organization. The admin Audit tab exports loaded operations and query history as CSV or JSON, respecting the current filters.
Supported Databases
| Database | Driver | Features |
| :--- | :--- | :--- |
| PostgreSQL | pg | Full SQL IDE, EXPLAIN plans, transactions, query cancellation (pg_cancel_backend) |
| MySQL | mysql2 | Full SQL IDE, EXPLAIN plans, transactions, query cancellation (KILL QUERY) |
| Oracle | oracledb (Thin mode) | Full SQL IDE, FETCH FIRST N ROWS pagination, V$ monitoring views, ANALYZE TABLE, ALTER INDEX REBUILD, transactions |
| SQL Server | mssql (tedious) | Full SQL IDE, TOP N / OFFSET FETCH pagination, sys.dm_* DMVs, UPDATE STATISTICS, DBCC CHECKDB, transactions, Azure SQL auto-detect |
| SQLite | bun:sqlite / node:sqlite (runtime-selected) | Full SQL IDE, file-based or in-memory databases (server-local file) |
| libSQL | none — HTTP (the Hrana protocol, POST /v2/pipeline, port 8080) | Full SQL IDE against a libSQL server or Turso Cloud — the same SQLite dialect as the row above, reached across a network instead of on disk. EXPLAIN QUERY PLAN, sqlite_master and pragma_* introspection, and real per-table bytes from dbstat, which the file-based driver above cannot read. The credential is an auth token rather than a password. Two maintenance operations only, REINDEX and PRAGMA integrity_check: the server refuses VACUUM, ANALYZE, PRAGMA optimize and PRAGMA wal_checkpoint outright, so no control is offered for them |
| DuckDB | @duckdb/node-api (a native N-API addon, ~68 MB of platform bindings) | Full SQL IDE against a local DuckDB file or :memory:, on the server the app runs on. EXPLAIN (FORMAT JSON) physical plan trees, duckdb_* catalog introspection, real per-table bytes from pragma_storage_info block allocation, and query cancellation through the driver's own interrupt(). Three maintenance operations, VACUUM, ANALYZE and CHECKPOINT: REINDEX is a parser error here and neither PRAGMA integrity_check nor PRAGMA optimize exists, so no control is offered for them. No slow-query log and no session list — DuckDB publishes neither, so those panels say so rather than showing a zero. The file admits exactly ONE operating-system process, refused in read-only mode too, so a second Studio instance cannot open a database this one holds |
| MongoDB | mongodb | JSON query editor, collection operations (find, aggregate, insert, update, delete) |
| Couchbase | none — HTTP (Query + management REST) | Full SQL++ IDE, EXPLAIN plans, bucket/scope/collection explorer, INFER column inference, read-your-writes consistency, UPDATE STATISTICS / BUILD INDEX / request kill |
| ClickHouse | none — HTTP (SQL interface, port 8123) | Full SQL IDE, JSON EXPLAIN plan trees, system-table schema introspection, OPTIMIZE TABLE / table statistics / query kill maintenance |
| Apache Druid | none — HTTP (POST /druid/v2/sql, Router port 8888 or Broker 8082) | Read-only SQL IDE, native-query EXPLAIN plan trees, INFORMATION_SCHEMA datasource introspection, sys.* monitoring (segments, servers, ingestion tasks). Druid SQL has no UPDATE, no DELETE and no CREATE TABLE, and nothing it can do counts as a maintenance operation — a datasource changes through ingestion, not from the editor |
| Elasticsearch | none — HTTP (POST /_sql?format=json, port 9200) | Read-only SQL IDE, mapping-driven index/field explorer, cluster health plus per-index document counts and store sizes. No EXPLAIN, no maintenance operation, no slow-query or session panel: those live in log files and stats APIs the SQL surface does not reach. Elasticsearch SQL also has no OFFSET, so a second page of results cannot be requested — narrow the statement or raise the limit instead |
| OpenSearch | none — HTTP (POST /_plugins/_sql, port 9200) | The same read-only SQL IDE and explorer, from the same provider module. LIMIT n OFFSET m does work here, so paging does |
| Apache Trino | none — HTTP (the client protocol, POST /v1/statement, port 8080) | Full SQL IDE across every configured catalog, EXPLAIN (FORMAT JSON) plan trees, information_schema schema tree for the catalog the connection pins, system.runtime + jmx monitoring, real SHOW STATS row counts, query cancellation and kill_query maintenance. Trino is a query engine and stores nothing, so it declares no primary keys, no foreign keys and no indexes anywhere — the ER diagram draws boxes and no edges, inline row editing is switched off, and the size panels name the catalogs rather than inventing a footprint. A failed statement arrives as HTTP 200, and a password is refused over plain HTTP even on a cluster with authentication disabled |
| Apache Cassandra | cassandra-driver (pure JS, no native module) | CQL IDE over the native protocol (port 9042), keyspace browser marking partition and clustering keys, system_views overview, uptime and running statements. No EXPLAIN (the keyword is not in CQL), no cancellation (the protocol has none), no maintenance (every operation is a nodetool action), and no row counts or sizes: the only figures Cassandra publishes are partition estimates from flushed files and whole mebibytes, so neither is shown rather than shown wrong |
| Redis | ioredis | Command editor, key browser, INFO-based monitoring |
Twenty-six more engines have no driver of their own. The sixteen above are the drivers this build ships. Twenty-six further engines speak one of those wire protocols and connect through an existing driver unchanged, so sixteen drivers reach forty-two named engines in all. They are MariaDB, Percona Server for MySQL, TiDB, Vitess, StarRocks, Apache Doris, OceanBase, SingleStore, Databend, Citus, Percona Distribution for PostgreSQL, ParadeDB, OrioleDB, TimescaleDB, YugabyteDB, AlloyDB Omni, Apache Cloudberry (incubating), CockroachDB, Materialize and RisingWave (as PostgreSQL or MySQL), Valkey, DragonflyDB, KeyDB and Garnet (as Redis), FerretDB (as MongoDB), and ScyllaDB (as Cassandra). Each was measured against a live instance, and how much of the product works differs per engine. MariaDB, both Percona distributions, TiDB, Vitess, AlloyDB Omni, Citus, TimescaleDB, YugabyteDB, ParadeDB, OrioleDB, Valkey, DragonflyDB, KeyDB and FerretDB behave as their driver's own engine, though three of them report statistics you should not trust: a Citus distributed table and a TimescaleDB hypertable report row counts and sizes that are wrong rather than missing, and YugabyteDB reports 0 until you runANALYZE. Vitess is not one of those three, its row counts and sizes being exact to the byte, but a running query cannot be cancelled there: vtgate refusesKILL QUERYand the statement runs to completion. AlloyDB Omni is not one of them either, reporting 2000 rows for 2000 and 270336 bytes for 270336, but two things there surprise:version()names AlloyDB nowhere, so the version panel cannot be told apart from a stock PostgreSQL 17, and eight of AlloyDB's owngoogle_mltables list in the object browser, which any role that can connect at all may also read. StarRocks reports itself as MySQL 5.1 and loses its overview, health and session panels, its monitoring dashboard rendering six panels with the session one carrying the engine's own refusal; Apache Doris - the engine StarRocks is a fork of - loses only the overview and health panels, to one statement form its grammar rejects, and is the more trustworthy of the two where it counts: it reports 2000 rows and 10187 bytes for a table holding exactly that, where StarRocks reports zeros, though a freshly loaded table there reads 0 for about a minute before its background statistics land, no index is ever reported, and a foreign key is accepted, listed bySHOW CONSTRAINTS, invisible to the ER diagram and unenforced; Cloudberry loses the monitoring dashboard and its table and index statistics, all three to one MPP planner restriction, and reads a foreign key back as though it were enforced when it is not, though its row counts are correct; CockroachDB loses the object browser and the size panels; OceanBase answers fourteen of the fifteen surfaces but only twelve of them usefully, health failing outright because its tenant has noperformance_schemadatabase at all and every size reading 0 B, though its row counts are correct onceANALYZE TABLEhas run; SingleStore lost five surfaces to a cause that was ours rather than its own - the provider sent every statement through the prepared-statement protocol, which SingleStore refuses for theSHOWandEXPLAINstatements four panels need - and four of those five are now recovered, its Explain panel being the one that is not, because there the grammar wantsEXPLAIN JSONand the statement fails on either protocol; its numbers are still missing rather than wrong, a 2000-row table reading 0 rows and 0 B with noANALYZEable to change it; ScyllaDB loses five surfaces and Test Connection with them, all six to one absent keyspace - the overview, health, performance-metrics, active-session and monitoring panels read Cassandra'ssystem_viewsvirtual tables and ScyllaDB has nosystem_viewskeyspace at all - those five now degrade to empty rather than throwing, so Test Connection passes and the dialog saves the connection, which it could not do at all until that change - while the editor and the object browser work in full, every one of 18 CQL types reading back byte-identically to the Cassandra 5.0.9 probed in the same pass; ParadeDB and OrioleDB are both full and their costs are opposites: ParadeDB's nine extensions put 41 objects in the object browser for 2 user tables and break agent plan mode on a stock install, while OrioleDB's browser is clean and its own storage is invisible to PostgreSQL's size functions, so every index reads 0 bytes and the cache hit ratio reads N/A. Materialize, RisingWave and Databend are query-editor-only, and Databend is the one of those three whose catalogs answer perfectly well when asked directly - the object browser is empty because our parameterised reads use a prepared protocol it does not implement. Garnet behaves as Redis and is one of three relatives here (with Valkey and DragonflyDB) whose own versionINFOcarries beside the Redis compat level and the overview now labels ahead of it -Garnet 2.1.5 (Redis 7.4.3)- and two of its readings are absences wearing a value, every size showing 0 B because it publishes noused_memoryand the cache hit ratio showing 100% because it publishes no keyspace counters. The per-engine detail, with the exact version probed, is indocs/providers/README.md— we publish a name only after connecting to it, so a name absent there is untested rather than unsupported.
Transport security is cross-cutting, not per engine. The SSH tunnel is opened before the provider connects and the connection is rewritten to the local endpoint, so it is provider-independent: it applies to any connection configured with a host and a port. A connection entered as a connection string instead (an option for MongoDB, Couchbase, ClickHouse and libSQL) carries neither, so it is not tunnelled; SQLite and DuckDB have neither either. The SSL/TLS panel is honoured by every engine that shows it — which is every engine except the three file-based ones, SQLite, DuckDB and the embedded LibreDB, where no transport exists to secure and no panel is offered. On Trino it is load-bearing rather than optional, because the coordinator refuses a password over plain HTTP. Oracle is the one engine whose mapping carries a caveat worth stating up front: its Thin driver always verifies the certificate chain, so require needs the server's CA supplied when that certificate is self-signed, and a connect string pasted whole keeps whatever protocol it names.
All SQL databases share: schema explorer, ER diagrams, schema diff & migration, display masking (preview), monitoring dashboard, and connection string import. Druid, Elasticsearch, OpenSearch and Trino are each the exception twice over: their HTTP SQL APIs have no URI convention this build can parse, so they are configured by host and port only, and a generated migration names the limitation instead of emitting column-modification DDL against an engine whose SQL contains none — as it also does for Couchbase's schemaless collections. An ER diagram over a search cluster draws boxes and no edges: an index declares no foreign keys and the engine's model has none to declare, which the provider states as declaresForeignKeys: false rather than leaving to be guessed from an empty list.
Provider reference docs: each database has an in-depth reference (design, connection, query format, monitoring, limitations) underdocs/providers/. For the provider architecture seedocs/DATABASE_PROVIDERS.md, and to add a new database seedocs/ADDING_A_PROVIDER.md.
Tech Stack
| Component | Technology | Target |
| :--- | :--- | :--- |
| Framework | Next.js 16 (App Router), React 19 | Web, Mobile |
| UI Engine | Tailwind CSS 4, Radix UI, shadcn/ui | Web, Mobile |
| Theming | CSS Variables + @theme inline (Guide) | Web, Mobile |
| Editor | Monaco Editor (VS Code Engine) | Web |
| AI | Multi-Model (Gemini, OpenAI, Ollama, Custom) | Web, Mobile |
| Auth | JWT (jose) + OIDC (openid-client), PKCE, Role Mapping | Web, Mobile |
| Database | PostgreSQL, MySQL, Oracle, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Apache Trino, Apache Cassandra, Redis | Web, Mobile |
| Charts | Recharts (Bar, Line, Pie, Area, Scatter, Histogram, Stacked) | Web, Mobile |
| ERD | React Flow, ELK.js (auto-layout) | Web |
| State/Grid | TanStack Table & Virtual | Web, Mobile |
| Deployment | Docker, Kubernetes | Web |
Getting Started
### Install
| Channel | Command | Notes |
| :--- | :--- | :--- |
| Docker | docker run -p 3000:3000 ghcr.io/libredb/libredb-studio:latest | Zero-config: the admin password is printed to the log on first run |
| Helm (Kubernetes) | helm install libredb oci://ghcr.io/libredb/charts/libredb-studio | Zero-config: first-run admin credentials are printed to the pod log |
| npx | npx @libredb/studio | Linux/macOS/Windows, Node 24+ (24 LTS is the reference runtime); downloads the release server archive |
| Homebrew | brew trust libredb/tap && brew install libredb/tap/libredb-studio | brew trust is required once (Homebrew 6+; run brew update if unknown) |
| deb / rpm | sudo dpkg -i libredb-studio_ | Attached to each GitHub release; systemd service included |
| Snap | sudo snap install libredb-studio | Zero-config: the admin password is printed to sudo snap logs libredb-studio on first run — Snap Store listing |
| winget (Windows) | winget install LibreDB.Studio | Portable zip with a bundled Node.js runtime; run libredb-studio — listed in the winget community repository |
| Chocolatey (Windows) | choco install libredb-studio | Same standalone zip — listed in the Chocolatey community repository; the first push (0.9.59) cleared moderation on 2026-08-24, and every release publishes automatically since (#114) |
| Portable zip (Windows) | .\libredb-studio.exe | Download from GitHub Releases; bundled Node runtime, no package manager needed |
| Desktop app (Linux, AppImage) | chmod +x libredb-studio-desktop- | Native window, no browser tab and no login prompt; the server runs as a local sidecar. For a sandboxed build, use the Flatpak row below (#232) |
| Desktop app (Debian/Ubuntu) | sudo apt install ./libredb-studio-desktop- | Same desktop app, installed into the menu; needs no FUSE and takes WebKitGTK from the distribution. Not the server package — that one is libredb-studio_ |
| Desktop app (Flatpak) | flatpak --user remote-add --if-not-exists flatpark https://dl.flatpark.org/flatpark.flatpakrepoflatpak --user install flatpark org.libredb.Studio | Sandboxed desktop app from the FlatPark remote — no filesystem access at all; databases are reached over TCP. Developer-approved listing (#241) |
> Homebrew, deb/rpm, Snap, the Windows portable zip, winget/Chocolatey, the desktop AppImage and Debian package, and the npx launcher consume standalone artifacts attached to each GitHub release. Full per-channel guide — commands, configuration, systemd usage, and the Docker image tag model — in docs/DISTRIBUTION.md. Channel coverage scorecard (live / pending, by platform and category) — docs/CHANNELS.md.
### Quick Start (Docker)
Run LibreDB Studio with a single command — no clone, no install, no build:
docker run \
--name libredb-studio \
-p 3000:3000 \
-e [email protected] \
-e ADMIN_PASSWORD=LibreDB.2026 \
-e [email protected] \
-e USER_PASSWORD=LibreDB.2026 \
-e JWT_SECRET=change-me-to-a-random-32-char-string \
ghcr.io/libredb/libredb-studio:latest
> Registry: ghcr.io/libredb/libredb-studio is the primary image (no pull rate limits — preferred for Kubernetes/CI). The same image is also mirrored to Docker Hub as libredb/libredb-studio for convenience.
> IPv6: the container picks its own bind address at startup and prefers ::, which serves IPv4 and IPv6 through one socket — so an IPv6-only host needs no flags. It falls back to 0.0.0.0 where the namespace has no usable IPv6, and logs which it chose. Add -e HOSTNAME=0.0.0.0 to pin it to IPv4 — details, and the Kubernetes equivalent, in docs/DISTRIBUTION.md.
Open http://localhost:3000 and login with [email protected] / LibreDB.2026.
> Auth env vars (local provider): ADMIN_PASSWORD and JWT_SECRET are only required when AUTH_BOOTSTRAP=off; otherwise both are generated on first start (see Zero-config first run below). USER_EMAIL / USER_PASSWORD are optional; omit them to run admin-only (no default user password is ever assumed). ADMIN_EMAIL defaults to [email protected]. Using OIDC (NEXT_PUBLIC_AUTH_PROVIDER=oidc)? None of these are needed.
> Tip: Add -e LLM_PROVIDER=gemini -e LLM_API_KEY=your_key -e LLM_MODEL=gemini-2.5-flash to enable AI features.
### Zero-config first run
Starting the server without JWT_SECRET / ADMIN_PASSWORD works out of the box:
the missing values are generated on first start, stored in /auth-bootstrap.json
(file mode 0600), and the admin password is printed once to the server log. Explicitly
set environment variables always take precedence. Set AUTH_BOOTSTRAP=off to require
explicit configuration instead (recommended for production deployments).
A JWT_SECRET you set yourself must be at least 32 characters. A shorter one is a
hard error at startup: the server prints what is wrong and exits with code 1, instead
of booting into a state where the health check reports healthy but every login returns
503. Unset the variable to let the first run generate a strong secret for you.
### Linux packages (.deb / .rpm)
Native packages for Debian/Ubuntu and RHEL/Fedora (amd64 and arm64) are attached to every GitHub release. They bundle the standalone server together with a private Node.js runtime (nothing else to install) and register a systemd service:
# Debian / Ubuntu
sudo dpkg -i libredb-studio_<version>_amd64.deb
RHEL / Fedora / Rocky
sudo rpm -i libredb-studio-<version>.x86_64.rpm
Start the service (first run prints the generated admin password to the journal)
sudo systemctl enable --now libredb-studio
journalctl -u libredb-studio
Configuration lives in /etc/libredb-studio/env (loaded by the unit; see the commented template
installed there), state (SQLite storage and generated credentials) in /var/lib/libredb-studio.
The libredb-studio command can also be run directly without systemd. Full details for this and
every other channel: docs/DISTRIBUTION.md.
### Prerequisites - Bun (Recommended) or Node.js 24+ - A target database to query (PostgreSQL, MySQL, Oracle, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Apache Trino, Apache Cassandra, or Redis)
### Quick Start (Local) 1. Clone & Install
git clone https://github.com/libredb/libredb-studio.git
cd libredb-studio
bun install
2. Configure Environment
Create a .env.local file:
# Authentication (email/password)
[email protected]
ADMIN_PASSWORD=your_admin_password
[email protected]
USER_PASSWORD=your_user_password
JWT_SECRET=your_32_character_random_string
# Optional: OIDC Single Sign-On (Auth0, Keycloak, Okta, Azure AD, etc.)
# NEXT_PUBLIC_AUTH_PROVIDER=oidc
# OIDC_ISSUER=https://your-provider.com
# OIDC_CLIENT_ID=your_client_id
# OIDC_CLIENT_SECRET=your_client_secret
# LLM Configuration
LLM_PROVIDER=gemini # options: gemini, openai, ollama, custom
LLM_API_KEY=your_api_key
LLM_MODEL=gemini-2.5-flash
LLM_API_URL=http://localhost:11434/v1 # optional for local LLMs (Ollama)
- Launch
bun dev
Open http://localhost:3000
### Embedding in your own app (@libredb/studio)
Studio is published as an npm package as well as a server, so the editor can live inside your own product:
npm i @libredb/studio
Adopt Studio's security headers from your own Next.js config. The @libredb/studio/security
subpath publishes the header policy as pure data — securityHeaders() returns a plain
Record, and the module it comes from imports nothing, so it is safe to load from
a next.config.ts where no path alias and no Studio runtime exist yet:
// next.config.ts
import { securityHeaders } from "@libredb/studio/security";
export default {
async headers() {
return [
{
source: "/:path*",
headers: Object.entries(securityHeaders()).map(([key, value]) => ({ key, value })),
},
];
},
};
Options: reportOnly emits Content-Security-Policy-Report-Only instead of the enforcing header;
hsts: false disables HSTS (or an object customises it); allowEval adds 'unsafe-eval', which
React's development build needs; monacoVsPath adds the origin serving Monaco's bundle when it
is not same-origin; and extra merges your own sources per directive. studioCspDirectives() and
HSTS_MAX_AGE_SECONDS are exported too, for a config that needs to compose the policy rather than
send it.
Read the policy before you inherit it: the CSP permits inline scripts, because every document
route is statically prerendered with nonce-less hydration scripts, so what it contains is where an
injected script could send data, not whether one can run. That trade-off, and the two delivery
paths a Next.js app has for these headers, are argued in
docs/SECURITY.md.
Development Databases
Need databases to test with? We provide ready-to-use containers for all supported engines:
# Start every default-profile database (PostgreSQL, MySQL, MongoDB, SQL Server, Oracle, ...)
docker compose -f database-compose.yml up -d
Or start a specific database
docker compose -f database-compose.yml up -d postgres
docker compose -f database-compose.yml up -d mssql
docker compose -f database-compose.yml up -d oracle
Apache Druid: profile-gated, so a bare up -d does NOT start it. Druid is a distributed
system with no single-container mode - five Druid processes plus ZooKeeper plus its own
metadata database is the minimum that can answer a SQL query, so all seven services carry
profiles: [druid] rather than doubling the default stack. Connect to the Router on 8888
(or the Broker on 8082 - the same endpoint, no different configuration).
docker compose -f database-compose.yml --profile druid up -d
Start PostgreSQL with sample e-commerce data
docker compose -f docker/postgres.yml up -d
Stop (keeps data)
docker compose -f database-compose.yml down
Stop and remove all data
docker compose -f database-compose.yml down -v
The Druid containers need the profile flag here too - without it down leaves them running
docker compose -f database-compose.yml --profile druid down -v
Connection Details
| Database | Host | Port | User | Password | Database/Service |
|----------|------|------|------|----------|-----------------|
| PostgreSQL | localhost | 5432 | postgres | postgres | postgres |
| MySQL | localhost | 3306 | root | root | mysql |
| SQL Server | localhost | 1433 | sa | Password123! | master |
| Oracle | localhost | 1521 | system | Password123! | freepdb1 |
| MongoDB | localhost | 27017 | admin | admin | — |
| Apache Druid | localhost | 8888 (Router) or 8082 (Broker) | — | — | — (one catalog, always druid) |
| Apache Trino | localhost | 8080 | — | — | tpch (a catalog; tpcds, memory, system and jmx are configured too) |
PostgreSQL Sample Data
The docker/postgres.yml setup includes a pre-loaded e-commerce schema:
| Feature | Description |
|---------|-------------|
| PostgreSQL 18 | Official image with pg_stat_statements |
| pg_stat_statements | Pre-enabled for query monitoring |
| Sample Schema | E-commerce database (app schema) |
| Sample Data | 25 customers, 30 products, 100 orders |
| Views | Order summary, product sales, customer LTV |
Sample tables: app.customers, app.products, app.orders, app.order_items, app.product_reviews, app.categories, app.coupons, app.audit_log
This setup is ideal for testing the Monitoring Dashboard features with real pg_stat_statements data.
Testing
LibreDB Studio has a comprehensive test suite with 3,000+ unit/integration tests and 32 E2E tests across 6 layers, with 100% line coverage enforced by CI (bun run coverage:check).
Quick Commands
# Run all tests (unit + API + integration + hooks + components)
bun run test
Run by layer
bun run test:unit # Pure function tests (1,600+ cases)
bun run test:api # API route handler tests (270+ cases)
bun run test:integration # Database provider tests (340+ cases)
bun run test:hooks # React hook tests (250+ cases)
bun run test:components # Component tests with mock isolation (570+ cases)
E2E tests (requires build)
bun run test:e2e # Playwright browser tests (32 cases)
Coverage report (lcov)
bun run test:coverage
Test Architecture
| Layer | Directory | Runner | Tests | What it covers |
|-------|-----------|--------|-------|----------------|
| Unit | tests/unit/ | bun:test | ~1,609 | Pure functions: SQL parser, connection strings, data masking, query limiter, schema diff, error classes, DB icons, showcase queries |
| API | tests/api/ | bun:test | ~279 | Route handlers: auth, query, transaction, maintenance, AI endpoints, middleware |
| Integration | tests/integration/ | bun:test | ~346 | Database providers: PG, MySQL, SQLite, MongoDB, Couchbase, Redis, Oracle, MSSQL, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino |
| Hooks | tests/hooks/ | bun:test | ~251 | React hooks: auth, connections, tabs, query execution, transactions, inline editing, monitoring |
| Components | tests/components/ | bun:test + happy-dom | ~570 | UI components: Studio, Sidebar, QueryEditor, ResultsGrid, Admin Dashboard, Charts, ERD |
| E2E | e2e/ | Playwright | ~32 | Full browser flows: login, connections, query execution, tabs, export, admin |
Key Details
- Test runner:
bun:test(built-in, Jest-compatible API) withhappy-domfor DOM environment - Component isolation: Component tests run in 6 isolated groups via
tests/run-components.shto preventmock.module()cross-contamination - E2E: Playwright runs the full suite on Chromium and the
security-headersspec on WebKit (webkit-security), against a production build (bun run build && bun start) - CI: GitHub Actions runs lint + typecheck + build, unit/integration tests with coverage, E2E tests, and SonarCloud analysis
- Coverage:
bun test --coveragegenerates lcov reports for SonarCloud integration
Important: Always usebun run testinstead of barebun test. The test script handles proper isolation between test groups.
One-Click Deploy
Deploy your own instance of LibreDB Studio with a single click on DigitalOcean, Koyeb, Render, Railway, Sealos, CapRover, or Dokploy: