Getting started
Install the CLI, scaffold a config, and check your schema and queries in under a minute. SurrealGuard needs no running database — it analyzes your .surql files statically.
Install
Run the surrealguard CLI with npx — it's published on npm, so there's no toolchain to set up. It needs no running database either; it analyzes your .surql files statically.
# zero install via npm npx surrealguard check # or install from source (Rust) cargo install --git https://github.com/DrewRidley/surrealguard surrealguard
npx surrealguard. A Rust install from source (cargo install --git https://github.com/DrewRidley/surrealguard surrealguard) works too; the crates.io publish is gated on the tree-sitter SurrealQL grammar being published upstream. The @surrealguard/* TypeScript packages are already on npm.
Scaffold a config
surrealguard init writes a starter surrealguard.toml in the current directory (it won't overwrite an existing one).
$ surrealguard init
Created surrealguard.toml
Configure your sources
The config classifies which .surql files are schema, which are queries, and which directories to skip. Point [sources] at your schema and query directories with glob patterns:
# surrealguard.toml [sources] schema = ["schema/**/*.surql", "migrations/**/*.surql"] queries = ["queries/**/*.surql"] ignore = ["target/**", "node_modules/**", ".git/**"] [analysis] strict = false surrealdb_version = "2" [diagnostics] warnings_as_errors = false require_suppression_reasons = false [lints] select_star = "warn" # named lint: allow | warn | deny dynamic_query = "warn" permission_gated_field = "warn" "7xxx" = "warn" # whole-family wildcard ("7*" also works) E1002 = "allow" # specific code — overrides a family that also covers it
Every key is optional; unset keys fall back to defaults. With no config at all, SurrealGuard analyzes every .surql/.surrealql file under the project root, skipping target/, node_modules/, and .git/.
| Section | Key | Default | Meaning |
|---|---|---|---|
| [sources] | schema | **/*.surql | Globs whose DEFINE/REMOVE statements build the schema catalog. |
| [sources] | queries | **/*.surql | Globs analyzed as queries against that schema. |
| [sources] | ignore | target/**, node_modules/**, .git/** | Directories excluded from discovery. |
| [analysis] | strict | false | Tighten otherwise-advisory checks. |
| [analysis] | surrealdb_version | "2" | Target version for version-gated behavior. |
| [diagnostics] | warnings_as_errors | false | Promote every warning to an error (affects exit code). |
| [diagnostics] | require_suppression_reasons | false | Require a written reason on every inline suppression. |
| [lints] | named lint, specific code, or family wildcard | built-in | Level override (allow, warn, or deny) keyed by a named lint (select_star, dynamic_query, permission_gated_field), a specific code (E1002 or bare 7002), or a whole-family wildcard ("7xxx"/"7*"). A specific code overrides a family that also covers it. |
SurrealGuard finds the workspace by walking up from the current directory to the nearest surrealguard.toml. Sources are analyzed in sorted path order, so schema definitions are visible to the queries that follow them.
Write some SurrealQL
-- schema/user.surql DEFINE TABLE user SCHEMAFULL; DEFINE FIELD name ON user TYPE string; DEFINE FIELD age ON user TYPE int; -- queries/users.surql SELECT name, age FROM user WHERE team = $team; -- ^^^^ E1002 unknown field `team` on table `user`
Check
Run surrealguard check from anywhere inside the project. It prints rustc-style diagnostic blocks and a summary; the exit code is non-zero when any error-severity finding survives policy.
$ surrealguard check Checking SurrealQL sources... Checked 2 source(s), found 0 diagnostic(s) All checks passed!
Machine-readable output
Add --json for structured findings — code, severity, source, byte range, message, help, and related spans. This is the shape agents and CI consume.
$ surrealguard check --json { "summary": { "sources_checked": 2, "diagnostics": 1, "errors": 1 }, "diagnostics": [ { "code": "E1002", "severity": "error", "source": "queries/users.surql", "range": { "start": 41, "end": 45 }, "message": "unknown field `team` on table `user`", "help": [], "related": [] } ] }
See the CLI reference for the full command surface and exit codes, and Diagnostics for the code families.