Skip to content

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
qualytics checks create \
    --datastore-id 42 \
    --file ./checks/orders/notnull_customer_id.yaml

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
qualytics checks create \
    --datastore-id 42 \
    --file ./checks/orders/all.yaml

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.

qualytics checks create --datastore-id 1 --file checks.yaml
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:

- rule_type: isNotNull
  container: orders
  fields: [order_id]
  status: Active
- rule_type: isUnique
  container: orders
  fields: [order_id]
  status: Active

Get a check

qualytics checks get --id 100
qualytics checks get --id 100 --format json
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

qualytics checks list --datastore-id 1 --status Active --format json \
  | jq -r '.[] | "\(.id)\t\(.rule_type)\t\(.container.name)"'

Update a check

Replace a check's definition from a YAML or JSON file.

qualytics checks update --id 100 --file updated_check.yaml
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 to Archived status. It stops running, but you can restore it with activate.
  • 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:

qualytics checks export --datastore-id 1 --output ./backup-$(date +%F)

Activate Draft or Archived checks

qualytics checks activate --id 100
qualytics checks activate --ids "100,101,102"
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

checks/
  orders/
    isNotNull_customer_id.yaml
    satisfiesExpression_total_positive.yaml
  customers/
    isUnique_email.yaml
    matchesPattern_phone.yaml
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:

qualytics operations sync --datastore-id 99
qualytics checks import --datastore-id 99 --input ./checks

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.

qualytics checks import-templates --input ./templates.yaml
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