Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>QueryMoatNew to Visual Studio Code? Get it now.
QueryMoat

QueryMoat

QueryMoat

|
1 install
| (0) | Free
Give your AI agent safe access to your database. Zero-config, read-only by default MCP server plus a fast database client for SQLite, PostgreSQL, MySQL, MariaDB and SQL Server.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

QueryMoat for VS Code

Give your AI agent safe access to your database.
QueryMoat connects Claude Code, Cursor, Windsurf and Copilot to your project database through a local MCP server that is read-only by default and never writes to production. It also puts a fast database client right inside VS Code. It finds your databases without setup.

Formerly QueryDock. Same extension, new name. Your .querydockrc files and AI client configs keep working; see Moving from QueryDock.


Why QueryMoat?

AI coding agents write better code when they can see your real schema and data, but letting an agent run SQL against your database is risky. QueryMoat gives the agent what it needs and nothing more:

  • 🛡️ Read-only by default: The MCP server only runs SELECT-style statements. The guard can't be fooled by keywords hidden in strings or comments, or by a write chained after a read.
  • 🔒 Production stays locked: Any connection to a non-local host is read-only for you and for the agent, whatever it is called, until you allow writes on it yourself. Connections tagged or named production, prod or live are always read-only.
  • 🧪 Sandboxed stored procedures: Let the agent call read-only procedures inside a transaction that is always rolled back.
  • 🏠 100% local: The MCP server binds to 127.0.0.1. Nothing goes through a cloud proxy, and QueryMoat collects no telemetry.
  • ⚡ Zero config: QueryMoat finds databases in .env, docker-compose.yml, Laravel, Rails, Django, Supabase, Prisma and Drizzle projects, so your agent is connected in seconds.

"Readonly MCP is the adult version." — @0xTobiasDev

And for you, a complete database client inside the editor:

  • 🚀 Zero-Config Discovery: Automatically detects databases configured in .env, docker-compose.yml, Laravel, Rails, Django, Supabase, Prisma, and Drizzle projects.
  • ⚡ High-Performance Data Grid: Virtualized records, sorting, column filters, and server-side pagination (25–500 rows).
  • ✏️ Safe Inline Editing: Double-click cell values to modify strings, numbers, booleans, dates, or complex JSON with batch change tracking and Cmd+S commit.
  • 🛡️ Environment Safety: Production and protected environments are locked to Read-Only by default with prominent visual warnings.
  • 🔍 Table & Schema Inspector: Inspect column nullability, types, defaults, primary keys, foreign key links, and indexes in a slide-over drawer.
  • 💻 SQL Query Editor: Write and run queries with Cmd+Enter, inspect EXPLAIN query plans, and search query history.

Free and Pro

QueryMoat is free to use, including at work, and everything that keeps your data safe stays free. Pro adds control over what agents do and a record of what they did: a lifetime licence for $14.99 once per developer, or $4.99 for the first 500 buyers. Get Pro on querymoat.com, then run QueryMoat: Enter Pro Licence Key.

Feature Free Pro
Browse, edit, and export data ✅ ✅
SQL query editor, EXPLAIN, query history ✅ ✅
SQLite, PostgreSQL, MySQL, MariaDB, SQL Server ✅ ✅
Zero-config discovery and .querymoatrc ✅ ✅
Read-only guard; remote and production databases locked ✅ ✅
MCP schema and data tools, including run-query ✅ ✅
Multi-project MCP routing for agents ✅ ✅
CI check (querymoat-check) ✅ ✅
Audit log of agent queries, tamper-evident — ✅
Sandboxed stored-procedure execution (SQL Server) — ✅
Write approval: agents propose changes, you approve them — ✅
Your own rules hiding tables or columns from agents ✅ ✅
Automatic masking of personal data and secrets for agents — ✅
SSH tunnels; AWS RDS IAM and Azure Entra ID sign-in — ✅
Audit log viewer with search, filters and CSV export — ✅

Supported Databases

Engine Driver Architecture Capabilities
SQLite sql.js (WebAssembly) Pure cross-platform (macOS/Win/Linux), file-based & in-memory, schema & indexes, mutations, EXPLAIN QUERY PLAN
PostgreSQL pg (Pure JS) Schemas, views, UUID/JSONB/arrays, foreign keys, SSL, EXPLAIN (FORMAT JSON)
MySQL mysql2/promise Schemas, auto-increment, unsigned types, indexes, SSL, EXPLAIN FORMAT=JSON
MariaDB mysql2/promise Full MariaDB support via MySQL wire protocol
Microsoft SQL Server tedious (Pure JS) SQL Server 2017+, Azure SQL, AWS RDS; schemas, keys, indexes, multiple result sets, sandboxed EXEC on read-only connections

Future releases will expand support to MongoDB, DuckDB, and ClickHouse.


Requirements

  • VS Code 1.90 or newer (also works in Cursor, Windsurf, and other VS Code–based editors).
  • No native binaries, database CLIs, or Docker required — every driver is pure JavaScript/WebAssembly.

Platform Support

Runs anywhere VS Code runs: macOS (Intel & Apple Silicon), Windows (x64 & ARM64), Linux (x64, ARM64, ARMhf, Alpine), and remote/WSL/Dev Container workspaces.


Quick Start

  1. Install the QueryMoat extension (.vsix or from Marketplace).
  2. Open any workspace folder containing a SQLite file, .env, or docker-compose.yml.
  3. Click the QueryMoat icon in the Activity Bar.
  4. Your discovered databases will appear under Detected Databases — click Connect to browse immediately!
  5. Double-click any table to open the Data Grid.

Moving from QueryDock

QueryMoat is the new name of QueryDock. Install QueryMoat, then uninstall QueryDock: running both makes them overwrite each other's MCP server file.

Nothing else is required. QueryMoat still:

  • reads .querydockrc, .querydockrc.json and .querydock/config.json;
  • keeps ~/.querydock/mcp-server.js up to date if it exists, so AI client configs that point there keep working;
  • honours QUERYDOCK_PROJECT / QUERYDOCK_PORT for the stdio server;
  • applies protected tags from querydock.readOnlyEnvironments.

When convenient:

  • rename .querydockrc to .querymoatrc;
  • move other settings from querydock.* to querymoat.* (only readOnlyEnvironments carries over automatically; everything else starts at its safe default);
  • re-copy your AI client config (Copy MCP configuration) so it uses ~/.querymoat/mcp-server.js and the server name querymoat;
  • in CI, switch to npx querymoat-check / uses: heysidhant/querymoat@v0.3.0.

Permissions you granted in QueryDock (Allow Writes on a remote database, and allowing agent writes) do not carry over; grant them again if you still need them.


Zero-Config Discovery

QueryMoat automatically discovers your project databases safely without executing arbitrary application code.

Supported discovery targets:

  • .env, .env.local, .env.development, .env.dev, .env.staging, .env.test (.env.production is never read)
    • DATABASE_URL, POSTGRES_URL, MYSQL_URL, SQLITE_DATABASE, DB_CONNECTION, DB_HOST, DB_PORT, DB_DATABASE
  • docker-compose.yml, compose.yml (detects exposed database ports and container service configurations)
  • Frameworks:
    • Laravel: .env, database/database.sqlite
    • Ruby on Rails: config/database.yml
    • Django: manage.py, db.sqlite3
    • Supabase: supabase/config.toml (detects local Postgres instance)
    • Node.js / Prisma: prisma/schema.prisma (detects local SQLite or Postgres connection)
    • Drizzle: drizzle.config.ts (or .js, .mjs, .json): PostgreSQL, MySQL, SQLite and local Turso files. A URL read from process.env.ANY_NAME is looked up in the .env files above. The config is read as text, never run.

Passwords are never displayed in plain text or written to logs — all previews show masked credentials (••••••).


Manual Configuration (.querymoatrc)

You can also explicitly configure database connections for your team using .querymoatrc or .querymoatrc.json in your workspace root:

[
  {
    "name": "Development Postgres",
    "type": "postgres",
    "host": "127.0.0.1",
    "port": 5432,
    "database": "myapp_dev",
    "username": "postgres",
    "password": "${env:DB_PASSWORD}",
    "environment": "development"
  },
  {
    "name": "Local SQLite",
    "type": "sqlite",
    "path": "./database/database.sqlite",
    "environment": "local"
  },
  {
    "name": "Production Replica",
    "type": "postgres",
    "host": "replica.internal",
    "port": 5432,
    "database": "myapp_prod",
    "username": "readonly_user",
    "credentialKey": "prod-replica-pass",
    "environment": "production",
    "isReadOnly": true
  },
  {
    "name": "Payments (dev, read-only)",
    "type": "mssql",
    "host": "db.internal",
    "port": 1433,
    "database": "PAYMENTS",
    "username": "readonly_user",
    "password": "${env:PAYMENTS_DB_PASSWORD}",
    "environment": "development",
    "isReadOnly": true,
    "execPolicy": "sandbox",
    "execAllowlist": ["EM3_*", "dbo.UTIL_*_GET_*"]
  }
]

QueryMoat reads only its own files (.querymoatrc, .querymoatrc.json, .querymoat/config.json); it does not pick up other tools' connection files. Add .querymoatrc to .gitignore when it holds credentials, or use ${env:VAR} / credentialKey.

Read-only connections and stored procedures

A read-only connection runs SELECT-shaped statements only. Stored-procedure calls follow the connection's execPolicy:

execPolicy Behaviour
deny (default) EXEC / CALL are rejected like any other write.
sandbox The call runs inside a transaction that is always rolled back. Every result set is returned; any INSERT/UPDATE the procedure performs is undone. Restrict which procedures qualify with execAllowlist (case-insensitive globs, optional schema. prefix). Dynamic SQL (EXEC (...), sp_executesql, xp_*) is never sandboxed.

Sandbox mode currently supports SQL Server. Side effects that escape a transaction (mail, linked servers, consumed identity values) are not undone — keep the allowlist to read-only procedures.

Secret References

  • Use ${env:VAR_NAME} to reference environment variables without committing passwords.
  • Use "credentialKey": "key-name" to retrieve stored credentials from VS Code's encrypted SecretStorage.

Data Grid & Editing

  • Double Click any cell to edit value inline.
  • Supports strings, numbers, booleans, dates, and JSON objects.
  • Changed cells are highlighted in amber.
  • Press Cmd+S or click Save Changes to commit updates.
  • Press Escape or click Discard to revert unsaved edits.
  • Right-click any cell to Set NULL.
  • Click the trash icon to Delete Row with primary key confirmation.
  • Click Export to export loaded records to CSV, TSV, JSON, or SQL INSERT statements.

Built-in SQL Query Editor

Open via Command Palette (QueryMoat: Open Query Editor) or title bar icon:

  • Syntax highlighting and auto-formatting.
  • Press Cmd+Enter (macOS) or Ctrl+Enter (Windows/Linux) to run.
  • Click Explain to view detailed visual execution plan.
  • Query History Drawer: Review recent executions, durations, and status; click to reload query.
  • Export query results directly to CSV or JSON.

Model Context Protocol (MCP) Server for AI

QueryMoat embeds a local MCP server bound strictly to 127.0.0.1 so AI coding tools (Claude, Cursor, Antigravity) can inspect and query your project database:

Exposed Tools

  • get-database-info: Returns server engine, version, and connection status.
  • get-tables: Lists all tables and views in the schema.
  • get-table-schema: Full column list, data types, nullability, primary & foreign keys.
  • get-indexes: Lists table indexes.
  • get-foreign-keys: Lists relationship mappings between tables.
  • get-table-rows: Paginated table rows with optional filtering.
  • search-table: Text search within table columns.
  • run-query: Executes SQL. Batches and procedures return every result set in resultSets; on read-only connections procedure calls run only under execPolicy: "sandbox" (rolled back).
  • propose-write (Pro): Proposes one change for you to approve; QueryMoat test-runs it first. See Write Approval.
  • get-proposal (Pro): Tells the agent whether you approved, rejected, or let a proposal expire, and the result.

Connecting an AI Agent

Click the plug icon in the QueryMoat dashboard header → Copy MCP configuration and pick your client. The snippet is copied to your clipboard.

QueryMoat installs its MCP server at ~/.querymoat/mcp-server.js and keeps it up to date, so your AI client's config keeps working when the extension updates.

Claude Code (one command):

claude mcp add --transport stdio querymoat node ~/.querymoat/mcp-server.js

Cursor / VS Code (.cursor/mcp.json or .mcp.json) and Windsurf (mcp_config.json). JSON configs need the full path, which the copied snippet fills in for you:

{
  "mcpServers": {
    "querymoat": {
      "command": "node",
      "args": ["/Users/<you>/.querymoat/mcp-server.js"]
    }
  }
}

HTTP (any client that supports Streamable HTTP, while VS Code is open):

{ "mcpServers": { "querymoat": { "type": "http", "url": "http://127.0.0.1:42100/mcp",
  "headers": { "Authorization": "Bearer <token from ~/.querymoat/mcp-token>" } } } }

The copied snippet fills in the token. Keep it out of files you commit.

How it works: the stdio server is a thin proxy. The extension writes ~/.querymoat/mcp.json (workspace path → port) when it starts; the proxy looks up the project from its working directory (--project <path> or QUERYMOAT_PROJECT override it) and forwards tool calls to the extension's HTTP server. VS Code with QueryMoat must be open for the project. projectId is injected automatically, so agents never have to supply it.

Security Controls

  • Read-Only Mode: Controlled by querymoat.mcp.readOnly (default true). Only SELECT/WITH/EXPLAIN/SHOW/PRAGMA/DESCRIBE statements run; keywords inside string literals and comments are ignored by the guard. Procedure calls need the connection's execPolicy: "sandbox" and run inside a rolled-back transaction.
  • Query Limits: An agent's query returns at most querymoat.mcp.maxRows rows (default 500; the agent is told to narrow its query) and is stopped by the database after querymoat.mcp.queryTimeoutSeconds (default 30; PostgreSQL, MySQL, MariaDB, SQL Server). Workspace settings can lower these but not raise them.
  • Prompt-Injection Defence: Rows can contain text written by anyone. Query results reach the agent wrapped in tags with a random boundary the data can't forge, with an instruction to treat everything inside as data, and a warning naming any values that read like instructions to an AI ("ignore previous instructions…").
  • Agents Can't Unlock Themselves: Workspace settings can't turn read-only off. Turning it off in your user settings still needs your click in a confirmation dialog, so an agent that edits settings files can't grant itself write access.
  • Project Isolation: MCP requests must target known workspace project IDs.
  • Localhost Only: Binds strictly to 127.0.0.1, and refuses requests from web browsers (any Origin header) and DNS-rebinding attempts (any Host other than 127.0.0.1/localhost), so a website you visit cannot query your database through QueryMoat.
  • Access Token: Every request needs the token in ~/.querymoat/mcp-token, a file only you can read. The stdio server sends it for you; the copied HTTP configuration includes it. This shuts out callers that can reach 127.0.0.1 but not your files: other users on the machine, containers sharing its network, and local apps tricked into making requests. A program running as you can still read the file. QueryMoat: Reset MCP Access Token replaces it; querymoat.mcp.requireToken turns it off, from user settings only.

Hiding Personal Data

Agents read real rows, and whatever they read ends up in prompts sent to the AI provider. QueryMoat filters everything its MCP tools return. The data grid and SQL editor still show you the real values.

Automatic masking (Pro). Personal data and secrets are detected by column name (email, phone, password_hash, api_key, card_number, ssn, date_of_birth, names, addresses) and by value (email addresses, card numbers that pass the Luhn check, JWTs, AWS/Stripe/GitHub/Slack keys, private keys), which also catches renamed columns such as SELECT email AS contact. The agent sees j***@example.com, **** 4242 or [hidden], plus a note naming the masked columns. Searching a masked column is refused, since it would reveal values one guess at a time. On by default; only user settings can turn querymoat.privacy.maskPersonalData off.

Your own rules (free). Hide or mask specific tables and columns, for every connection in settings or per connection in .querymoatrc:

{ "name": "App DB", "type": "postgres", "host": "localhost", "database": "app",
  "hide": ["users.password_hash", "audit_*", "*.ssn"],
  "mask": ["orders.notes"] }

Hidden tables disappear from get-tables; hidden columns disappear from rows, schemas, indexes and foreign keys; and any query or proposal that names a hidden table or column (quoted, bracketed or aliased) is refused before it runs. Rules from every settings level are combined, so a project can add rules but never remove yours.

What masking can't stop: an agent can still infer things through query shape, for example WHERE email = '...' or COUNT(*), and string functions such as substr(email, 1, 3) can reveal part of a value under a new name. Hide a column when the agent must not touch it at all.

SSH Tunnels and Cloud Sign-in (Pro)

Reach a database behind a bastion host, and sign in with your cloud identity instead of a stored password:

{ "name": "Orders (staging)", "type": "postgres",
  "host": "orders.abc123.eu-north-1.rds.amazonaws.com", "port": 5432,
  "database": "orders", "username": "app_reader", "environment": "staging",
  "cloudAuth": "aws-rds-iam",
  "ssh": { "host": "bastion.example.com", "username": "ec2-user", "privateKeyPath": "~/.ssh/id_ed25519" } }
  • SSH: keys come from privateKeyPath, your SSH agent, or ~/.ssh/id_*; passwords and passphrases go in ${env:VAR}. The first time, QueryMoat shows the server's host key fingerprint for you to confirm, then refuses to connect if it ever changes (set hostKeyFingerprint to pin it up front; Forget SSH Host Keys resets). The tunnel listens on 127.0.0.1 only.
  • aws-rds-iam: uses your AWS CLI credentials (profiles, SSO, environment); set awsProfile to choose one. The region is read from the host name, or set awsRegion.
  • azure-ad: uses az login (or any Azure credential DefaultAzureCredential finds) for Azure SQL, Azure Database for PostgreSQL and MySQL.
  • Remote-host protection still applies: a database reached through a tunnel is read-only until you allow writes on it.

Write Approval (Pro)

When an agent needs to change data, it proposes the change instead of running it:

  1. The agent calls propose-write with one SQL statement and the reason for it.
  2. QueryMoat test-runs it inside a transaction that is always rolled back and shows you how many rows would change, with a sample of them (PostgreSQL and SQLite show the rows themselves).
  3. You review it in the QueryMoat panel and click Approve & run (then confirm) or Reject. The agent has no tool that can approve.
  4. The agent calls get-proposal to learn the outcome.

Guarantees:

  • Exactly what you reviewed, once. Approval is bound to the statement's hash, runs it a single time, and proposals expire after 15 minutes.
  • Never on protected databases. Read-only and production connections refuse proposals outright. Approval only runs a change where you could make it yourself in the editor.
  • Nothing that could escape the test run. One statement per proposal; no BEGIN/COMMIT/ROLLBACK, stored procedures, or dynamic SQL. MySQL and MariaDB schema changes (ALTER, DROP, ...) commit immediately, so they are shown as not test-run for you to judge from the SQL alone.
  • Proposals, approvals and rejections are recorded in the audit log.

Audit Log (Pro)

Every tool call an AI agent makes through QueryMoat is written to ~/.querymoat/audit/ as one JSON line: when it happened, which agent made it, the tool and SQL, whether it was allowed, blocked or sandboxed, the rule that decided it (for example environment is "production"), and where that rule is set (built-in default, user settings, workspace settings, or the connection's .querymoatrc).

{"ts":"2026-10-02T09:14:03.118Z","client":"claude-code 2.1.0","tool":"run-query","verdict":"blocked","rule":"environment is \"production\"","ruleSource":"built-in default","reason":"Query rejected: ... (contains UPDATE).","connectionName":"orders (prod)","connectionOrigin":".querymoatrc","sql":"UPDATE orders SET status = 'shipped' WHERE id = 1187","durationMs":2}
  • Tamper-evident: each line carries a hash of the previous one. QueryMoat: Verify Audit Log reports any line that was changed or removed.
  • Local only: files are readable only by you (0600) and never leave your machine. Query results are not logged.
  • Agents can't switch it off: querymoat.audit.enabled can only be turned off in user settings. Old files are removed after querymoat.audit.retentionDays (default 90).
  • QueryMoat: Open Audit Log opens a viewer across all windows and days: filter by time, result, agent and database, search SQL and rules, open any entry for its details, and export what you see to CSV. Entries from a file that was edited are marked modified.

CI Check

querymoat-check lints your QueryMoat config in CI and fails the build when it finds a problem. --warn-only is opt-in, because warnings that never fail tend to be ignored.

GitHub Actions:

- uses: actions/checkout@v4
- uses: heysidhant/querymoat@v0.3.0

Any CI: npx querymoat-check [dir] [--warn-only] [--format text|github]. It exits 1 on errors, 0 when clean or with --warn-only, and 2 on bad usage.

Rule Level Catches
plaintext-password error A password written into the file instead of ${env:VAR} or credentialKey
remote-missing-environment error A connection to a non-local host (or a ${env:...} host) with no environment tag
remote-writable error "isReadOnly": false on a remote host; allow writes per machine from the UI instead
production-writable error "isReadOnly": false on a connection tagged or named as production
invalid-json error A config file QueryMoat would silently ignore
unknown-environment warning A tag like prd that gets no protection
sandbox-without-allowlist warning execPolicy: "sandbox" with no execAllowlist
workspace-disables-readonly warning querymoat.mcp.readOnly: false in .vscode/settings.json (ignored by QueryMoat)

Keybindings

Command macOS Windows / Linux
Go to Table (QuickPick) Cmd + K, Cmd + G Ctrl + K, Ctrl + G
Run SQL Query Cmd + Enter Ctrl + Enter
Save Database Edits Cmd + S Ctrl + S
Discard Cell Edit Escape Escape

Extension Settings

Setting Default Description
querymoat.debug false Enable verbose debug logging to output channel.
querymoat.defaultPageSize 100 Default row count per page (25, 50, 100, 250, 500).
querymoat.enableAutoDiscovery true Auto-detect databases from workspace files.
querymoat.enableCodeLens true Display CodeLens actions above models and table definitions.
querymoat.enableMcp true Start local MCP server on 127.0.0.1.
querymoat.mcp.readOnly true Enforce strict read-only mode for MCP queries.
querymoat.readOnlyEnvironments ["production", "prod", "live"] Environment tags that enforce read-only protection.
querymoat.queryHistoryLimit 100 Max recent queries stored in history.

Security & Privacy Guarantee

  • No Remote Telemetry: QueryMoat does not collect or transmit telemetry, user analytics, or usage statistics.
  • Zero Cloud Proxies: Database traffic never leaves your local machine or local network.
  • Credential Masking: Passwords and secrets are masked before ever reaching logs or UI previews.
  • Content Security Policy: Webview enforces strict CSP forbidding inline scripts and remote network calls.

Support & Contributing

  • 🐛 Found a bug or have a feature request? Open an issue.
  • 📖 Configuration and MCP docs: github.com/heysidhant/querymoat.
  • ⭐ If QueryMoat saves you time, please leave a review and star the GitHub repo.

License

QueryMoat is free to use under the QueryMoat End User License Agreement. Open-source components it includes are listed in THIRD-PARTY-NOTICES.txt.

© 2026 Sidhant Sinha

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft