Quality Checks
Manage quality checks from the command line: create them in bulk from YAML, promote them between environments, export them to Git, and lock down a set of golden rules as reusable templates. Every operation supported in the Qualytics web app is available here, and most are faster.
What's a quality check?
A quality check is a rule that runs against a container (table or file) and produces an anomaly when the rule is violated. Checks have a rule_type (for example isNotNull, satisfiesExpression, isUnique), a target container and fields, an expected coverage, and a status (Active, Draft, or Archived). See Data Quality Checks for the full conceptual overview.
Check lifecycle
graph LR
Y[Define in YAML] --> C[qualytics checks create]
C --> Draft
C --> Active
Draft -->|update --status Active or activate| Active
Active -->|delete --archive| Archived
Archived -->|activate| Active
Active -->|delete --no-archive| Gone((Deleted))
Archived -->|delete --no-archive| Gone
A check moves through four states. Draft and Active are open states; Archived is a soft-delete that can be reversed; Deleted is permanent.
| State | Runs in scans? | Reversible? | How to enter |
|---|---|---|---|
Draft |
No | Yes | create with status: Draft, or AI Managed checks generated by Profile with --infer-as-draft |
Active |
Yes | Yes | create with status: Active, activate a Draft or Archived check, or update --status Active |
Archived |
No | Yes (via activate) |
delete --archive (the default) |
Deleted |
No | No | delete --no-archive |
Use cases
The scenarios below are the situations customers run into most often. Each one points to the command sections further down for full flag references.
Use case 1: Define a single check from a YAML file
The simplest scenario: write the rule in YAML, point the CLI at it.
# checks/orders/notnull_customer_id.yaml
rule_type: isNotNull
container: orders
fields:
- customer_id
description: Customer ID must not be null
coverage: 1.0
filter: null
tags:
- production
- orders
properties: {}
status: Active
Use container names, not IDs
The check file references the container by name (container: orders), not by ID. This makes the same file portable across datastores: dev, staging, and prod all have an orders table, even though their internal IDs differ.
Use case 2: Bulk-create a library of checks
When you have dozens of checks to create, put them all in one file as a YAML list:
# checks/orders/all.yaml
- rule_type: isNotNull
container: orders
fields: [order_id]
status: Active
- rule_type: isUnique
container: orders
fields: [order_id]
status: Active
- rule_type: satisfiesExpression
container: orders
fields: [total]
properties:
expression: "total >= 0"
status: Active
The CLI prints i/total progress as it creates each check, with per-check success or failure.
Use case 3: Promote checks from Dev to Prod
Export from Dev, commit to Git, import to Prod. This is the cleanest way to keep environments in sync.
graph LR
Dev[(Dev datastore)] -->|checks export| FS[checks/ folder]
FS -->|git commit| Repo[(Git repo)]
Repo -->|git pull| Pipe[CI pipeline]
Pipe -->|checks import| Prod[(Prod datastore)]
# In Dev
qualytics checks export --datastore-id 1 --output ./checks/
# Review the diff and commit
git add checks/
git commit -m "Update quality checks from dev"
git push
# In Prod (preview first)
qualytics checks import --datastore-id 99 --input ./checks/ --dry-run
qualytics checks import --datastore-id 99 --input ./checks/
For the full CI/CD pipeline pattern (PR validation, tagged release promotion, environment gating), see Promote checks Dev to Prod.
Use case 4: Audit and clean up draft checks
When Profile runs with --infer-as-draft, the AI Managed checks it generates land in Draft status. Periodically review them and either promote or remove:
# List all draft checks for a datastore
qualytics checks list --datastore-id 42 --status Draft
# Approve specific ones by activating them (they go Active immediately)
qualytics checks activate --ids "501,502,503"
# Or archive the rest as a batch
qualytics checks delete --ids "510,511,512" --archive
Run profiling with --infer-as-draft
If you want every AI Managed check to land in Draft status pending human review, run profile with the flag. See Operations and AI Managed Checks.
Use case 5: Lock down golden checks as templates
Templates are reusable check definitions you can apply to many containers. Useful for "every PII column must have isNotNull and matchesPattern" style governance.
# Export your golden checks as templates to a file
qualytics checks export-templates \
--rules "isNotNull,matchesPattern" \
--tags "pii,golden" \
--output ./templates/pii.yaml
# Import them into a new instance
qualytics checks import-templates --input ./templates/pii.yaml
For applying a template to many containers in the web app, see Apply Check Template.
Command reference
Create checks
Create one or more quality checks from a YAML or JSON file.
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--datastore-id |
INTEGER | — | Yes | Target datastore ID |
--file, -f |
TEXT | — | Yes | YAML or JSON file with check definition(s) |
--owner-id |
INTEGER | — | No | Apply this owner user ID to every check (overrides the file) |
--default-anomaly-assignee-id |
INTEGER | — | No | Apply this default anomaly assignee user ID (overrides the file) |
Check YAML schema
rule_type: isNotNull
container: orders
fields:
- customer_id
description: "Customer ID must not be null"
coverage: 1.0
filter: null
tags:
- production
- orders
properties: {}
status: Active
| Field | Required | Description |
|---|---|---|
rule_type |
Yes | Check rule type (e.g., isNotNull, satisfiesExpression, isUnique) |
container |
Yes (or container_id) |
Container name to apply the check to (portable across datastores) |
container_id |
Yes (or container) |
Container ID (less portable; useful when names collide) |
fields |
Yes | List of field names |
description |
No | Human-readable description |
coverage |
No | Expected pass rate (0.0 to 1.0) |
filter |
No | SQL WHERE clause to filter rows |
tags |
No | List of tag names |
properties |
No | Rule-specific properties (varies by rule_type) |
status |
No | Active or Draft |
additional_metadata._qualytics_check_uid |
No | Stable ID for idempotent import (auto-generated on export) |
Bulk file (list of checks)
A single file can contain a list of checks. The CLI processes each in order and reports per-check status:
Get a check
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--id |
INTEGER | — | Yes | Quality check ID |
--format |
TEXT | yaml |
No | Output format: yaml or json |
List checks
qualytics checks list --datastore-id 1
qualytics checks list --datastore-id 1 --containers "10,20" --status Active
qualytics checks list --datastore-id 1 --tags "production" --format json
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--datastore-id |
INTEGER | — | Yes | Datastore ID |
--containers |
TEXT | — | No | Comma-separated container IDs |
--tags |
TEXT | — | No | Comma-separated tag names |
--status |
TEXT | — | No | Filter by status: Active, Draft, or Archived |
--format |
TEXT | yaml |
No | Output format: yaml or json |
Pipe into jq for scripting
Update a check
Replace a check's definition from a YAML or JSON file.
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--id |
INTEGER | — | Yes | Quality check ID to update |
--file, -f |
TEXT | — | Yes | YAML or JSON file with updated check definition |
--owner-id |
INTEGER | — | No | Override owner user ID (set to 0 to clear) |
--default-anomaly-assignee-id |
INTEGER | — | No | Override default anomaly assignee (set to 0 to clear) |
Editing an AI Managed check converts it to Authored
Updating rule properties, coverage, filter clause, or fields on an AI Managed check silently converts it to an Authored Check on save. Future Profile runs no longer touch it. Editing only description, tags, additional metadata, anomaly message field, owner, anomaly assignee, or status does not trigger the conversion. To revert to AI Managed, delete the check and re-run Profile. See AI Managed Checks.
Delete checks
Soft-delete (archive) by default, or hard-delete with --no-archive.
# Soft-delete (archive) a single check (reversible)
qualytics checks delete --id 100
# Bulk soft-delete
qualytics checks delete --ids "100,101,102"
# Hard-delete (permanent, cannot be undone)
qualytics checks delete --id 100 --no-archive
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--id |
INTEGER | — | No | Single check ID to delete |
--ids |
TEXT | — | No | Comma-separated check IDs for bulk delete |
--archive / --no-archive |
FLAG | --archive |
No | Soft-delete (default) or hard-delete |
Archive vs delete
delete --archive(default): the check is moved toArchivedstatus. It stops running, but you can restore it withactivate.delete --no-archive: the check is permanently removed. The associated anomalies stay, but the check definition is gone.
Hard delete is irreversible
Once a check is deleted with --no-archive, the only way to get it back is to recreate it. Always export your checks first if you're cleaning up at scale:
Activate Draft or Archived checks
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--id |
INTEGER | — | No | Single check ID to activate |
--ids |
TEXT | — | No | Comma-separated check IDs for bulk activation |
Export checks
Export checks to a directory structure organized by container. Each check is saved as a separate, git-friendly YAML file.
qualytics checks export --datastore-id 1 --output ./checks
qualytics checks export --datastore-id 1 --containers "10,20" --tags "production"
qualytics checks export --datastore-id 1 --status Draft --output ./drafts
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--datastore-id |
INTEGER | — | Yes | Datastore ID to export from |
--output, -o |
TEXT | ./checks |
No | Output directory |
--containers |
TEXT | — | No | Comma-separated container IDs |
--tags |
TEXT | — | No | Comma-separated tag names |
--status |
TEXT | — | No | Filter by status: Active, Draft, or Archived |
Output directory layout
One file per check, grouped by container. Re-running export over the same folder produces zero git diff if nothing changed, so it's safe to commit.Import checks
Import checks from a directory into one or more datastores. Uses upsert logic: existing checks (matched by _qualytics_check_uid) are updated, new ones are created.
# Single datastore
qualytics checks import --datastore-id 1 --input ./checks
# Preview without applying
qualytics checks import --datastore-id 1 --input ./checks --dry-run
# Multi-datastore in one shot
qualytics checks import \
--datastore-id 1 \
--datastore-id 2 \
--datastore-id 3 \
--input ./checks
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--datastore-id |
INTEGER | — | Yes | Target datastore ID (repeat the flag for multiple) |
--input, -i |
TEXT | ./checks |
No | Input directory containing check files |
--dry-run |
FLAG | false |
No | Preview what would be created or updated |
Idempotent imports
Each exported check carries a stable _qualytics_check_uid in additional_metadata. On import, the CLI matches on that UID against existing checks in the target datastore. Match found → update. No match → create. Re-running the same import is always safe.
Container name resolution
Imports look up containers by name within each target datastore. If a check references a container that doesn't exist in the target, the check fails with a clear error. Sync the target datastore first if the schema is out of date:
Sample dry-run output
Loaded 15 check definitions from ./checks/
[DRY RUN] Importing to datastore 99...
Import Summary
┏━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┓
┃ Datastore ID ┃ Created ┃ Updated ┃ Failed ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━┩
│ 99 │ 10 │ 5 │ 0 │
└──────────────┴─────────┴─────────┴────────┘
Export check templates
Export reusable check templates to either an enrichment datastore or a local file.
# Export to enrichment datastore
qualytics checks export-templates --enrichment_datastore_id 10
# Export to local file
qualytics checks export-templates --output ./templates.yaml
# Filter by rule types and tags
qualytics checks export-templates \
--output ./templates.yaml \
--rules "isNotNull,isUnique" \
--tags "production"
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--enrichment_datastore_id |
INTEGER | — | No | Enrichment datastore ID for export |
--check_templates |
TEXT | — | No | Comma-separated template IDs |
--status |
BOOLEAN | — | No | Template locked status (true for locked, false for unlocked) |
--rules |
TEXT | — | No | Comma-separated rule types |
--tags |
TEXT | — | No | Comma-separated tag names |
--output |
TEXT | ~/.qualytics/data_checks_template.yaml |
No | Output file path |
--format |
TEXT | yaml |
No | Output format: yaml or json |
Import check templates
Import templates from a file. Creates new templates only; existing templates are not updated.
| Option | Type | Default | Required | Description |
|---|---|---|---|---|
--input |
TEXT | ~/.qualytics/data_checks_template.yaml |
No | Input file path |
Templates are create-only on import
Unlike checks import, import-templates does not update existing templates. To update a template, edit it in the web app or delete and re-import.
Tips and gotchas
Always export before any bulk delete or update
The five seconds it takes to run qualytics checks export --datastore-id N --output ./backup-$(date +%F) saves hours when something goes wrong.
Use tags as your filter primitive
Tags work everywhere: list --tags, export --tags, delete (via the IDs you got from a tag-filtered list). Tag your checks meaningfully (pii, golden, experimental) and you can target subsets without ever opening the web app.
status in YAML overrides what's already in the system
If you export a check that's Active, edit the YAML to status: Draft, and re-import, the check goes back to Draft. This is intentional but easy to forget.
Where to look next
- Examples & Use Cases: multi-command workflows that include checks (dev → prod promotion, drift detection, daily triage)
- Operations: how scans run checks and produce anomalies
- Anomalies: triaging the output of your checks
- Config as Code: exporting and importing checks alongside connections, datastores, and computed containers