File formats¶
.dql — the core format¶
Canonical, git-friendly, version-headered.
// dql-format: 1
block "Revenue by Segment" {
domain = "finance"
type = "custom"
status = "draft"
description = "Revenue by customer segment."
owner = "analytics@company.com"
tags = ["revenue"]
query = """
SELECT segment, SUM(amount) AS revenue
FROM analytics.orders
GROUP BY 1
"""
visualization {
chart = "bar"
x = segment
y = revenue
}
}
- Version header —
// dql-format: Non line 1. Older files without a header are still parsed;zlens fmtadds the header on next save. - Canonical whitespace —
zlens fmtenforces it. CI should runzlens fmt --check . - Forward compatibility — unknown top-level keys are preserved verbatim
- Display hints — block
visualizationis stored in the manifest asdisplayHints; Apps and notebooks can override it without changing the block.
.dqlnb — notebook¶
JSON document holding a sequence of cells (markdown, sql, dql, chart).
Written in a stable key-order so git diffs stay readable.
{
"version": 1,
"metadata": { "name": "Welcome", "createdAt": "2026-04-17T00:00:00Z" },
"cells": [
{ "id": "c1", "type": "markdown", "source": "# Welcome" },
{ "id": "c2", "type": "sql", "source": "select 1" }
]
}
.run.json — run snapshots¶
Sibling file next to a notebook holding the last execution's results:
{
"version": 1,
"notebookPath": "notebooks/overview.dql",
"capturedAt": "2026-04-15T12:34:56Z",
"cells": [
{
"cellId": "abc123",
"status": "success",
"executionCount": 4,
"result": { "columns": [...], "rows": [...], "rowCount": 42 }
}
]
}
- Git-ignored by default — ZLens auto-appends
*.run.jsonto.gitignoreon first write - Used for rehydration — re-opening a notebook loads results without re-running queries
- Save trigger — debounced 600ms after a cell's execution count / row count changes
.dql/local/notebook-research.sqlite — notebook research state¶
Project-local SQLite database for notebook research runs. It stores local review state such as source-cell fingerprints, reviewed SQL, preview metadata, context-pack evidence, parameter review, duplicate/reuse decisions, and DQL draft promotion references.
- Local/private by default — do not commit
.dql/local/** - Source of queue state — powers the notebook Research panel filters, counts, source coverage, and next-action buckets
- Not a certified artifact — create a DQL draft and certify the block when the research becomes shared business logic
.dqld — App dashboard page¶
JSON document for one dashboard page inside an App. It stores grid layout,
block refs, text tiles, filters, page metadata, and per-tile consumer display
metadata. A tile's viz is the current renderer choice. A tile's display
is the governed GenUI contract: why that renderer was chosen, which
visualizations are allowed, and whether the presentation is certified or still
review-required.
{
"version": 1,
"id": "daily-ops",
"metadata": {
"title": "Daily Ops",
"visibility": "shared",
"lifecycle": "review"
},
"layout": {
"kind": "grid",
"cols": 12,
"rowHeight": 80,
"items": [
{
"i": "approval-rate",
"x": 0,
"y": 0,
"w": 4,
"h": 3,
"block": { "blockId": "card_approval_rate" },
"title": "Approval Rate",
"viz": { "type": "kpi", "options": { "valueField": "approval_rate" } },
"display": {
"mode": "block_hint",
"component": "KpiMetric",
"defaultVisualization": "kpi",
"allowedVisualizations": ["kpi", "single_value", "table"],
"fieldHints": { "value": "approval_rate" },
"layoutIntent": "compact",
"rationale": "Executive app uses KPI presentation for the certified approval-rate block.",
"trustState": "certified",
"reviewStatus": "certified"
}
}
]
}
}
Dashboard pages are committed under apps/<app-id>/dashboards/*.dqld.
Private layout overrides and saved views stay local under .dql/local/.
AI pins are local until promoted into draft/certified DQL blocks or reviewed
dashboard tiles.
dql.app.json — App manifest¶
JSON document for a local-first App package.
{
"version": 1,
"id": "cards-ops",
"title": "Cards Operations",
"domain": "cards",
"subdomain": "fraud",
"groups": ["daily-ops"],
"visibility": "shared",
"lifecycle": "draft",
"dashboards": [
{ "id": "daily-ops", "path": "dashboards/daily-ops.dqld", "title": "Daily Ops" }
],
"notebooks": [
{
"path": "notebooks/investigation.dqlnb",
"title": "Investigation Notebook",
"role": "analysis",
"visibility": "shared"
}
]
}
In OSS, visibility, domain, subdomain, groups, audience, and
lifecycle are organization metadata and trust labels. They are not hosted
permissions or RBAC enforcement.
dql.config.json — project config¶
Lives at the project root. Written by zlens init and create-zlens-app.
{
"project": "jaffle-analytics",
"layout": { "version": 2, "mode": "oss-dbt-workspace", "skillsPath": "skills" },
"connections": {
"default": { "driver": "duckdb", "filepath": ":memory:" }
},
"metadataScopes": {
"default": {
"mode": "selected_scopes",
"scopes": [
{ "catalogOrDatabase": "jaffle_shop", "schemas": ["main"] }
]
}
},
"semanticLayer": { "provider": "dql", "path": "semantic-layer" },
"dbt": {
"projectDir": "../dbt",
"manifestPath": "target/manifest.json"
},
"datalex": {
"manifestPath": "../datalex/datalex-manifest.json"
},
"governance": {
"required_fields": ["domain", "owner", "description"]
},
"agent": {
"valueProfile": { "mode": "off" },
"resultReview": { "mode": "off" }
}
}
Fields:
project— human-readable project namelayout— OSS workspace convention. New projects use version2and keep shared agent guidance in visibleskills/; legacy.dql/skills/is read only for migration compatibility.connections— named database connections.defaultis used unless a block overrides itmetadataScopes— optional per-connection warehouse metadata allowlists. The notebook Database panel writes this only after the connection target and bounded metadata synchronization succeed.dbt_relationsindexes exact current manifest relations;selected_scopesindexes only the named databases/catalogs and schemas;dbt_plus_selectedcombines both. Secrets, observed target identity, and generated fingerprints are never stored here.semanticLayer—{ provider, path, projectPath }. Providers:dql(local YAML),dbt,cubejs,snowflakedbt—{ projectDir, manifestPath }for in-place or sibling dbt projects.zlens compileandzlens sync dbtread from heredatalex— optional{ manifestPath }for validatingdatalex_contractreferences. ZLens works without DataLex; this only enables interop checks when a DataLex manifest existsgovernance— required fields every block must declare to passzlens certifyagent.valueProfile—{ mode: "off" | "sampled", exclude: [patterns] }, off by default.sampled: each warehouse-first schema sync also reads a few example values and the range of each column for Ask's SQL drafter; those values reach your AI provider with the drafting prompt. Sensitive columns and values are never read, and never under a hosted server. See value profile.agent.resultReview—{ mode: "off" | "on" }, off by default.on: before an AI-drafted answer is shown, one more AI call checks its result against the question and may revise the SQL once. It sends the question, the SQL and the result's shape (row count, distinct and empty values per column, repeated rows), never a value from the result. Costs about one AI call per AI-drafted answer (median 3.6 s on Claude). See a second look at the result. Both settings are read at every question, so a change applies to the next one.
Environment variables¶
Environment variables that configure ZLens use the ZLENS_ prefix, for example
ZLENS_SERVER_TOKEN and ZLENS_ALLOWED_ORIGINS. The older DQL_ names (for
example DQL_SERVER_TOKEN) are still read as a fallback when the ZLENS_
variable is not set, so existing setups keep working.
ZLENS_ASK_RESULT_REVIEW=1 turns the result review on and =0 turns it off,
whatever agent.resultReview says.
dql-manifest.json — build output¶
Generated by zlens compile. Declares every block/notebook/dashboard in the
project plus their lineage edges. Consumed by OpenLineage export and
third-party lineage tools.