Packata command-line interface

Install the .NET tool with dotnet tool install --global Packata-cli. Run packata --help or packata --version to discover commands and the installed version. The existing packata infer command remains available.

Command index

Command Reference
contract validate Validate
contract inspect Inspect
contract diff Factual differences
contract compare Consumer compatibility
contract satisfies Producer/consumer satisfaction
schema export JSON Schema
schema infer, alias infer Schema inference
data preview Read data
data serve Serve assets over HTTP
data validate Structural validation
quality run Quality execution and OORS reports
lineage export OpenLineage
dialect export CSV dialect
dialect infer Infer CSV parsing settings
connector list, connector show, connector install Connectors
config list, config get, config set, config unset Configuration

Use --help, -h or -? for help. Root version switches are --version and -v. Branch-only invocations show help. Quote arguments with spaces for your shell.

Exit-code families

Commands Codes
data validate 0 structural checks pass; 1 completed violations or invalid contract; 2 invocation error; 3 read/execution error; 4 incomplete/unsupported checks; 130 cancellation
data serve 0 graceful shutdown; 2 startup/selection/invocation error; framework cancellation can return 130
validate, inspect, diff, schema export, dialect export, lineage export, data preview 0 success; 1 invalid/unsupported document or operation; 2 invocation error; 3 I/O failure; 130 cancellation
contract satisfies 0 gate passes; 1 Unsatisfied or default Unknown; 2 input/invocation/I/O/cancellation/analysis error or Unknown under error policy
quality run 0 pass or warning; 1 quality failure without errors; 2 command/contract/execution/report error, cancellation, no matches, or all skipped
contract compare Same base codes, plus 4 for a completed report failing the selected gate and 5 for incomplete analysis; see details
schema infer/infer 0 success; 1 operation failure; 2 caught cancellation or invocation error; framework cancellation can return 130
dialect infer 0 report or save succeeded; 1 operation or I/O failure; 2 invocation error or caught cancellation; framework cancellation can return 130
config and connector discovery 0 success; 1 operation/file failure; 2 invocation error
connector install 0 success; 1 operation failure; 2 caught cancellation/invocation error; framework cancellation can return 130

Shared options

The CLI uses Spectre.Console.Cli. Commands are grouped under contract, schema, data, quality, dialect, lineage, connector, and config. infer remains a compatibility entry point for schema infer. Schema export and generation require their explicit grouped commands.

Option Meaning
--input-format auto\|odcs\|datapackage Interpret the source contract; supported by every contract-reading command
--output-format Select the generated representation; allowed values depend on the command
--output <PATH>, -o <PATH> Destination file, never a representation name
--asset <ID> Exact Data Package resource name or ODCS schema object name

Most reporting commands can save their result with --output. This includes validation, inspection, both kinds of comparison, preview, configuration list/get and connector list/show. The command finishes rendering before it writes the file, refuses to replace an existing file, and omits ANSI styling from saved output. Diagnostics still go to stderr and remain included in JSON results where documented.

Inference handles output differently. With schema infer --output, the saved file is an enriched contract in the source standard, while the interactive report still goes to stdout. There is no separate output-format option. To update the source itself, choose --write; it cannot be combined with --output.

Use the option names shown in this reference. The current parser can ignore unrecognized tokens, so a successful exit alone does not prove that an unsupported flag took effect. In particular, --output always names a destination file. Use --output-format to select a representation; export also accepts its short alias, -f.

For diff and compare, --input-format selects the source standard for both documents. Set --baseline-format or --candidate-format when one input needs a different choice. An explicit auto on either input restores automatic detection for that document.

packata contract inspect contract.yaml --input-format odcs --output-format json -o inspection.json
packata schema export contract.yaml --asset customers --output-format json-schema -o customers.schema.json
packata data preview datapackage.json --asset customers --output-format csv -o customers.csv

Export declared lineage

packata lineage export <SOURCE> --asset <ID> [OPTIONS] emits an OpenLineage JobEvent for the selected asset in an ODCS contract. It reads the contract to find the declared dependencies. When the contract identifies a source dataset but Packata cannot resolve its columns, the event can still include the dataset dependency.

Option Meaning
--input-format <FORMAT> Detect the source format by default. Set odcs to select it explicitly.
--asset <ID> Exact identifier of the output asset in the contract. Required.
--job-namespace <NAMESPACE> OpenLineage namespace of the producing job. Required.
--job-name <NAME> OpenLineage name of the producing job. Required.
--dataset-namespace <NAMESPACE> OpenLineage namespace shared by the input and output datasets. Required.
--output-dataset <NAME> OpenLineage name of the output dataset. Required.
--source-dataset <MAPPING> Map a declared source to a dataset name as REFERENCE=NAME. Supply at least one mapping and use each reference once.
--output <PATH>, -o <PATH> Write to a new file. The default is JSON on stdout.

Use the same job and dataset identifiers as your OpenLineage runtime integration. The command writes diagnostics to stderr and protects existing output files.

packata lineage export orders.odcs.yaml --asset prices --job-namespace commerce-prod --job-name build_prices --dataset-namespace postgres://warehouse.example.com:5432 --output-dataset commerce.analytics.prices --source-dataset order_lines=commerce.raw.order_lines

Export a CSV dialect

packata dialect export <SOURCE> --endpoint <ID> [OPTIONS]

Option / alias Values / default Meaning
--input-format <FORMAT> auto, odcs, datapackage; auto Source standard; locations remain command-specific
--endpoint <ID> Required Exact CSV endpoint identifier
--output-format <FORMAT> json only; json Standalone Table Dialect JSON
--output <PATH>, -o <PATH> Stdout when omitted New destination file; existing files are protected
--overwrite Off Requires --output; permits replacing output but never the source

All shown positional arguments are required. Use --help for command help.

packata dialect export datapackage.json --endpoint customers-endpoint
packata dialect export contract.yaml --endpoint local --output-format json --output customers.dialect.json

This command writes the parsing settings of one CSV endpoint as a standalone Data Package v2 Table Dialect descriptor. Use contract inspection to find the endpoint’s exact ID, then pass that ID with --endpoint. Export reads contract metadata without opening the CSV data.

By default, the JSON goes to stdout and diagnostics go to stderr. Use --output to save it to a file. Replacing an existing output requires --overwrite; the source contract is always protected. The CSV dialect guide explains the library API, supported settings, defaults and diagnostics, with a two-endpoint example.

Infer CSV parsing settings

packata dialect infer <SOURCE> --asset <ID> [OPTIONS]

Read a local ODCS YAML or Data Package JSON/YAML descriptor and sample its selected CSV, TSV or PSV resource. The default prints candidates, warnings, confidence where available and sample limits without changing either file. --output saves an enriched contract, retaining its standard; --write atomically replaces the source. Field definitions, constraints, resource locations and unrelated metadata are preserved.

Option / alias Values / default Meaning
--input-format <FORMAT> auto, odcs, datapackage; auto Input standard
--asset <ID> Required Exact asset with exactly one endpoint binding and one CSV-family path
-o, --output <PATH> Unset Save to a new local file; existing destinations, including the source, are protected
--write Off Replace the local source atomically; mutually exclusive with --output
--maximum-records <COUNT> Positive; 1000 Records to profile, including the header; candidate scoring uses at most 100
--maximum-bytes <COUNT> Positive; 1048576 Source bytes sampled; also bounds the bytes examined for dialect detection
--header <MODE> auto, present, absent; auto Auto honors declared header hints, otherwise detects; explicit modes override hints
--accept-ambiguous Off Explicitly permit saving ambiguous candidates after reviewing the report
--allow-shared-endpoint Off Acknowledge changing parsing settings for every asset bound to the endpoint

Declared delimiter and quote settings seed the detector’s candidates; they can be corrected by detection. Line endings are detected from the sampled text. Escape and null-token rules and spacing hints help parse the sample but are not independently inferred or overwritten. Only delimiter, quote character, line terminator, header presence and header rows can change. Encoding, compression, double-quote rules, null tokens, comments and all other settings are retained. Header rows use the detector’s first-record convention ([1] or []). Advanced multirow headers and comments are not discovered by this operation.

Confidence is a detector heuristic, not a probability of correctness. Quote candidates often tie when no quoted values are present. Ambiguous reports succeed, but saving requires --accept-ambiguous; use --header present or --header absent to resolve header uncertainty. Empty samples fail; fewer than two records, a byte-truncated sample, unresolved detection or inconsistent record widths cannot be saved even with acknowledgement. Increase limits or correct the input before retrying. A sample reaching its record limit may miss later variations. For compressed CSVs the byte limit applies to compressed bytes, and a truncated compressed stream may fail decoding; raise the limit to include a complete compressed resource.

Missing/duplicate assets, multiple or unresolved bindings, unsupported formats, unavailable resources and refused writes return 1. Invalid options return 2. Cancellation returns 2 when caught by the command, or 130 through the framework. Success returns 0. Failed writes leave the original descriptor intact. External dialect references must be inlined before updating. Shared endpoint reports list affected asset IDs; saving requires --allow-shared-endpoint for both output copies and in-place updates.

Descriptors must be ordinary local files: remote descriptors and archive containers are rejected. Resources use existing local or HTTP/HTTPS CSV access, resolved relative to the descriptor; no native cloud backend is added. Saving retains relative resource paths exactly, so put an output copy beside the source or ensure the same relative paths work at its new location. Reserialization warns before writing: comments, formatting and quoting may change. YAML anchors, aliases, explicit tags and merge keys are rejected for updates to protect unrelated values; expand them in a copy first. Duplicate JSON keys are also rejected on save. Review an output copy before adoption.

Use dialect export to export declared settings without sampling data, and schema infer to discover fields and dialect together. See the dialect guide for the dialect-only workflow.

Validate a contract

packata contract validate <SOURCE> [OPTIONS]

Option / alias Values / default Meaning
--input-format <FORMAT> auto, odcs, datapackage; auto Source standard; locations remain command-specific
--schema Selected with --semantic by default Official source-descriptor JSON Schema validation
--semantic Selected with --schema by default Declaration consistency and Packata binding checks
--output-format <FORMAT> text, json; text Result representation
--output <PATH>, -o <PATH> Stdout when omitted New destination file; existing files are protected

All shown positional arguments are required. Use --help for command help.

packata contract validate contract.yaml
packata contract validate datapackage.json --output-format json
packata contract validate descriptor --input-format odcs

Use this command to check an ODCS 3.2.0 contract written in YAML or a Data Package v2 descriptor written in JSON or YAML. Packata identifies the standard from the document’s contents. If you want to select the standard yourself, use the --input-format option shown in the table above.

You can read the descriptor from a local file or an HTTP(S) address, either directly or inside a ZIP, TAR, TAR.GZ or TAR.BR archive. Validation checks the contract document only; it does not open the datasets referenced by that contract.

For any supported archive, include exactly one descriptor with one of the following filenames. The descriptor can be in a subdirectory.

datapackage.json
datapackage.yaml
datapackage.yml
contract.yaml
contract.yml

Archive suffixes are matched case-insensitively from the URL path; query strings and fragments do not affect detection. All four formats have the same command coverage: validation, inspection, diff, compatibility comparison, JSON Schema export and dialect export. Preview also reads bundled CSV-family, Excel and Parquet resources from all four formats. Schema inference accepts these same descriptor transports and reads local, HTTP/HTTPS or archive-relative CSV-family, Excel and Parquet resources. See inference limits and output restrictions. TAR archives use the storage layer’s default materialization limits described in the storage guide.

packata contract validate package.tar.gz --output-format json
packata contract inspect https://example.test/package.tar.br --output-format json
packata contract diff baseline.zip candidate.tar --output-format json

With no layer flags, Packata runs the official source-descriptor schema first, then semantic declaration checks. Supplying either flag selects exactly the requested layers; both flags are additive and their order does not matter. Schema failure explicitly skips semantic validation. Semantic-only prerequisite failures cannot return success. Both JSON and YAML are supported for ODCS 3.2.0 and Data Package v2. See descriptor validation for the semantic checklist, pinned schemas, version policy and limitations.

--output-format text is the default. Text diagnostics go to stderr. --output-format json writes a single object to stdout with schemaVersion: 1, source, valid, layers, and diagnostics. Selected layers report state, executed and an optional skip reason. Each diagnostic has layer, code, severity, sourcePath, and message. Success requires every selected layer to pass. Diagnostics do not include raw parser snippets or stack traces; connection secrets are redacted. Redirected output has no ANSI styling.

Exit codes for these new commands: 0 success, 1 invalid document or operation, 2 invocation error, 3 I/O failure, and 130 cancellation. These do not change the existing infer command’s exit-code contract.

Inspect the canonical contract

packata contract inspect <SOURCE> [OPTIONS]

Option / alias Values / default Meaning
--input-format <FORMAT> auto, odcs, datapackage; auto Source standard; locations remain command-specific
--output-format <FORMAT> text, json; text Result representation
--output <PATH>, -o <PATH> Stdout when omitted New destination file; existing files are protected
--asset <ID> All assets Optional exact asset identifier

All shown positional arguments are required. Use --help for command help.

packata contract inspect contract.yaml
packata contract inspect datapackage.json --asset customers --output-format json

Use inspection to explore the canonical model produced from a contract. It accepts the same sources and input-format choices as validation. Text output shows identity, metadata, assets, schema fields and constraints, endpoint bindings, locations, formats and governance as a tree. Mapping warnings appear on stderr.

By default, you see every asset. To focus on one, pass its exact identifier with --asset. The result then includes only that asset and its referenced endpoints. An unknown or ambiguous identifier fails instead of selecting an asset for you.

Use JSON output when another program needs the result. It returns one object containing the source identifier, mapped contract and diagnostics. The schemaVersion: 1 value identifies the response format.

Within the contract, identity, metadata and governance accompany the assets, endpoints and extensions. Each asset contains its schema fields, constraints and endpoint bindings.

Property names use camelCase, and enum values are strings. Diagnostics use the same four fields as validation. Credentials and connection URLs are redacted throughout the result, including nested extension metadata.

Compare two contract versions

packata contract diff <BASELINE> <CANDIDATE> [OPTIONS]

Option / alias Values / default Meaning
--input-format <FORMAT> auto, odcs, datapackage; auto Source standard; locations remain command-specific
--baseline-format <FORMAT> Inherits --input-format Per-baseline override; explicit auto restores detection
--candidate-format <FORMAT> Inherits --input-format Per-candidate override; explicit auto restores detection
--output-format <FORMAT> text, json; text Result representation
--output <PATH>, -o <PATH> Stdout when omitted New destination file; existing files are protected
--quiet Off Suppress results and file creation; retain stderr diagnostics

All shown positional arguments are required. Use --help for command help.

packata contract diff sales-v1.odcs.yaml sales-v2.odcs.yaml
packata contract diff old/datapackage.json new/datapackage.json --output-format json
packata contract diff old/descriptor new/descriptor --baseline-format odcs --candidate-format datapackage
packata contract diff old.zip https://example.test/new.zip --quiet

The baseline is previous and the candidate is current. An addition is present only in the candidate, a removal only in the baseline, and a modification retains baseline-to-candidate values. Differences are factual data; this command does not apply a compatibility policy or decide whether a change is breaking.

The command loads, detects, validates and maps each input independently. You can supply local files, HTTP(S) addresses, or local and remote ZIP, TAR, TAR.GZ and TAR.BR archives, using the same descriptor loader as inspection.

Comparison reads the descriptors only. It does not open referenced datasets, connect to databases, acquire or configure connectors, or write either input.

Both same-standard and cross-standard diffs use the shared DataContract.Diff API. They compare the canonical model, including preserved extension metadata, without adding CLI-specific matching or normalization. Anything outside that mapping is outside the diff.

For ODCS, the mapper populates SLA and lifecycle commitments and typed value domains. It does not turn native quality rules into canonical executable rules. Use contract compare when you need the separate compatibility analysis and its source-coverage checks.

Unsupported source formats, values that cannot be snapshotted, duplicate semantic identifiers and unknown library change kinds fail explicitly. They do not produce an empty, successful diff. For example, a custom object stored in extension metadata may not be a supported snapshot value.

Text output begins with both source names and the baseline-to-candidate direction. It then shows each change’s operation, asset, semantic path, concrete kind and values. If there are no changes, it prints No differences detected.

The CLI preserves the library’s ordering. Text diagnostics go to stderr, and redirected text and JSON contain no ANSI styling.

JSON stdout contains exactly one object, with this versioned shape:

{
  "schemaVersion": 1,
  "baseline": "sales-v1.odcs.yaml",
  "candidate": "sales-v2.odcs.yaml",
  "hasChanges": true,
  "changes": [
    {
      "kind": "PropertyTypeChanged",
      "operation": "modified",
      "asset": "property",
      "path": "schema.orders.properties.amount.type",
      "datasetId": "orders",
      "propertyId": "amount",
      "previous": "integer",
      "current": "number"
    }
  ],
  "diagnostics": []
}

Each change identifies its kind, operation, asset and semantic path. The operation is added, removed or modified. The table below lists the extra fields emitted for each kind; fields belonging to other kinds are absent.

Applicable values preserve explicit JSON nulls. A present "previous": null therefore means something different from an absent previous field.

Kind Asset Additional fields
ServerAdded, ServerRemoved server server: canonical endpoint
ServerModified server previous, current: canonical endpoints
SlaAdded, SlaRemoved sla sla: canonical service level
SlaModified sla previous, current: canonical service levels
DatasetAdded, DatasetRemoved dataset dataset: canonical asset including its subtree
DatasetModified dataset previous, current: canonical assets
PropertyAdded, PropertyRemoved property datasetId, propertyId, property: canonical field
PropertyModified property datasetId, propertyId, previous, current: canonical fields
PropertyTypeChanged property datasetId, propertyId, previous, current: logical-type strings or null
RelationshipAdded, RelationshipRemoved relationship relationship: canonical relationship
RelationshipModified relationship previous, current: canonical relationships
QualityRuleAdded, QualityRuleRemoved qualityRule qualityRule: canonical quality rule
QualityRuleModified qualityRule previous, current: canonical quality rules
ContractMetadataChanged contractMetadata previous, current: identity, metadata, governance, or extensions, according to path

Payload records use camelCase property names and string enum values. Extensions remain objects keyed by namespace, with each namespace’s key/value map preserved. Dictionary keys retain their original casing, and no CLR type or assembly metadata is added.

Changes follow the library’s ordering: ordinal path first, then concrete change kind. The README’s comparison section explains identifier matching, escaped paths, complete subtrees and immutable snapshots.

A diagnostic identifies which input caused it: baseline, candidate or comparison. It also carries source, code, severity, sourcePath and message. Successful JSON includes warnings in its diagnostics array; in quiet mode, those warnings go to stderr instead.

Sources, diagnostic text, paths, descriptions and nested payloads are checked for credentials and connection strings, which are redacted in both output representations. On failure, diagnostics go to stderr and the command emits no successful or partial diff object.

A completed diff returns 0 even when it finds changes. Use hasChanges and changes to decide what your automation should do with that result.

An invalid or unsupported contract or comparison returns 1. Invalid invocation or option values return 2, an I/O failure returns 3, and cancellation returns 130. This command does not apply compatibility gates, filters or rename heuristics, or generate patches.

Assess consumer compatibility

packata contract compare <BASELINE> <CANDIDATE> [OPTIONS]

Option / alias Values / default Meaning
--input-format <FORMAT> auto, odcs, datapackage; auto Source standard; locations remain command-specific
--baseline-format <FORMAT> Inherits --input-format Per-baseline override; explicit auto restores detection
--candidate-format <FORMAT> Inherits --input-format Per-candidate override; explicit auto restores detection
--output-format <FORMAT> text, json; text Result representation
--output <PATH>, -o <PATH> Stdout when omitted New destination file; existing files are protected
--quiet Off Suppress results and file creation; retain stderr diagnostics
--policy <POLICY> baseline-consumers-v1 only Directional baseline-consumer policy
--fail-on <CLASSIFICATIONS> breaking,potentially-breaking,unknown Comma-separated gate classes or none; does not reclassify results

All shown positional arguments are required. Use --help for command help.

packata contract compare sales-v1.odcs.yaml sales-v2.odcs.yaml
packata contract compare old/datapackage.json new/datapackage.json --output-format json
packata contract compare previous current --baseline-format odcs --candidate-format odcs --policy baseline-consumers-v1
packata contract compare previous.yaml current.yaml --fail-on breaking,unknown --output-format json
packata contract compare previous.yaml current.yaml --fail-on none

Give the previous contract as the baseline and the current contract as the candidate, just as you would for contract diff. The analysis asks whether consumers built against the baseline can safely consume candidate data.

Only same-standard ODCS 3.2.0 or Data Package v2 comparisons are supported. The loader accepts local and HTTP(S) descriptors, including ZIP, TAR, TAR.GZ and TAR.BR packages, but does not open referenced data, databases or connectors. It detects each input’s standard independently unless you select a shared input format or override one input’s format.

Use --output-format json -o compatibility.json to save a report. The command protects existing files, including the source descriptors. Quiet mode suppresses file creation as well as stdout.

A completed report is saved even when its findings fail the selected gate. Invalid documents and failed analyses use the structured failure envelopes described below.

The policy and backend API document directional rules, matching, source semantics, and unsupported constructs. Integer → number is breaking for integer consumers; number → integer strengthens the guarantee. Additional fields are safe under the open-record assumption. contract diff continues to report factual differences only.

Text output shows both sources, direction, policy, completion/outcome, findings with classifications/paths/explanations, and classification totals. For example:

Baseline (previous): previous.yaml
Candidate (current): current.yaml
Direction: baseline -> candidate; policy: baseline-consumers-v1
Analysis: breaking; completed: True; exit code: 4
breaking schema.orders.properties.amount.type: The candidate type permits logical values outside the baseline type.
Totals: {"breaking":1,"potentiallyBreaking":0,"nonBreaking":0,"unknown":0}

JSON uses schemaVersion: 1; the JSON schema defines this envelope:

Field Meaning
baseline, candidate Source identifiers; null on invocation parsing failures
direction, policy baseline-to-candidate and baseline-consumers-v1
completed Analysis finished, independently of unknown findings
outcome compatible, breaking, potentiallyBreaking, unknown, failed
isCompatible True only for established, completed compatibility
hasChanges Observed canonical differences; null for incomplete analysis
failOn, gatePassed, exitCode CLI gate and outcome; gatePassed is null on failure
totals Finding counts for all four classifications, not factual-change counts
findings path, classification, rule, explanation, typed change, sourceLocation
diagnostics input, source, code, severity, sourcePath, message, sourceLocation

When a finding has a typed change, its payload uses the same kind, operation, asset, path and values documented for contract diff. Several findings can refer to the same change. Coverage findings, and model details not represented by the differ, use change: null. An unsupported change in the raw source may therefore be absent from hasChanges.

The backend currently has no line/column mapping, so sourceLocation is explicitly null. Coverage diagnostic paths point into the source descriptor, while typed change paths identify canonical assets. Sources, diagnostics and nested typed values are redacted.

An unchanged supported contract produces:

{
  "schemaVersion": 1,
  "baseline": "previous.yaml",
  "candidate": "current.yaml",
  "direction": "baseline-to-candidate",
  "policy": "baseline-consumers-v1",
  "completed": true,
  "outcome": "compatible",
  "isCompatible": true,
  "hasChanges": false,
  "failOn": "breaking,potentially-breaking,unknown",
  "gatePassed": true,
  "exitCode": 0,
  "totals": {"breaking": 0, "potentiallyBreaking": 0, "nonBreaking": 0, "unknown": 0},
  "findings": [],
  "diagnostics": []
}

If input is invalid, loading fails, analysis fails or the command is cancelled, JSON uses the same envelope with completed: false, outcome: failed and isCompatible: false. Both hasChanges and gatePassed are null. Diagnostics explain the failure, and findings may be partial.

An invalid invocation can also return a JSON failure envelope when JSON output was requested for stdout. The sources are then null, and the usage error also goes to stderr. The accepted spellings are --output-format json, --output-format=json and --output-format:json. Destination options accept the same space, equals and colon forms with --output or -o.

Invocation errors never create output files. Options after -- do not select presentation, and an invalid output-format value cannot itself request JSON. Quiet mode, including an explicit true value, suppresses every envelope; --quiet=false retains normal reporting. Otherwise, JSON diagnostics stay inside the envelope and ordinary logs do not mix with stdout.

Exit code Meaning
0 Completed analysis passes the selected gate
1 Invalid/malformed contract or descriptor package
2 Invalid invocation/options
3 Source or output I/O/access failure
4 Completed analysis contains a classification selected by –fail-on
5 Analysis/mapping cannot complete, including unsupported cross-standard comparisons
130 Cancellation

By default, the gate fails on breaking, potentially breaking or unknown findings. Choose --fail-on none when you want a report without classification-based gating. This changes the exit-code gate, not the classifications, and never turns unknown coverage into compatibility.

Disabling the gate does not waive invocation, invalid-input, I/O, analysis or cancellation failures. JSON already supplies the classifications and explanations needed by #572; GitHub annotations, validation line/column mapping and MCP registration remain separate work.

Export a dataset schema

packata schema export <SOURCE> --asset <ID> --output-format json-schema [OPTIONS]

Option / alias Values / default Meaning
--input-format <FORMAT> auto, odcs, datapackage; auto Source standard; locations remain command-specific
--asset <ID> Optional for exactly one eligible asset Exact Data Package resource or ODCS schema object name
--output-format <FORMAT>, -f <FORMAT> Required; json-schema, avro, avro-idl, spark-json, arrow-ipc Target representation
--output <PATH>, -o <PATH> Stdout when omitted New destination file; existing files are protected
--profile <PROFILE> Omit for generic output Compatibility profiles are accepted only when advertised; none are currently available
--schema-name <NAME> Asset name Avro record name
--schema-namespace <NAMESPACE> packata.generated Avro namespace

Generate schema code or DDL

packata schema generate <SOURCE> --target <TARGET> --language <LANGUAGE> [OPTIONS]

Use --input-format auto|odcs|datapackage to select the descriptor standard. SQL uses --target ddl --dialect <ID>; --language sql is optional. Omit --asset for all eligible assets. --constraints accepts all, none, or comma-separated PrimaryKey,Required,Unique,Checks,ForeignKeys. --no-descriptions omits SQL comments. No connection URL is required. See the schema generation reference for dialect IDs and selection policies.

Code generation uses schema generate --target <TARGET> --language <LANGUAGE> or schema generate --template <PATH> instead of schema export --output-format. Bundled targets include record, datatable, polars (C#), class (C# or Python), dataclass and pydantic (Python), and arrow (C# or Python). For generation, --asset may be omitted when one eligible asset exists. --engine <ENGINE> overrides a custom template’s engine; recognized suffixes such as .scriban and .hbs otherwise select Didot’s engine, with Scriban as the fallback for bar.template.cs. Relative templates resolve from the descriptor directory. --type-mapping <PROFILE> optionally prepares csharp-record, csharp-datatable, or csharp-polars, csharp-arrow, python-arrow, csharp-class, python-class, python-dataclass, or python-pydantic expressions for a custom template. Built-ins fix their engine/profile. --namespace <NAMESPACE> and --type-name <NAME> customize generated names. Repeat --define <KEY=VALUE> for user variables; duplicate keys are errors. Values parse as null, boolean, integer, decimal, then string, and appear only under model.variables. --mapping-fallback <POLICY> defaults to reject; explicit object, string, and logical-type fallbacks retain visible diagnostics. These options conflict with plain JSON Schema export.

packata schema generate sales.odcs.yaml --asset orders --target record --language csharp --namespace Sales > Orders.cs
packata schema generate sales.odcs.yaml --asset orders --target datatable --language csharp --output OrdersTable.cs
packata schema generate sales.odcs.yaml --asset orders --target polars --language csharp > OrdersPolars.cs
packata schema generate sales.odcs.yaml --target arrow --language csharp -o Orders.cs
packata schema generate sales.odcs.yaml --target arrow --language python -o orders_arrow_schema.py
packata schema generate sales.odcs.yaml --template bar.template.cs --define author=Sales
packata schema generate sales.odcs.yaml --template bar.hbs --engine scriban --type-mapping csharp-record

Only complete generated text goes to stdout; diagnostics go to stderr. No partial output is published after mapping/render errors. Exit codes remain 0 success, 1 descriptor/asset/ mapping/template failure, 2 invalid selectors/options, 3 template/output I/O failure, and 130 cancellation. See schema generation for the context, target limits and runnable templates.

All shown positional arguments are required. Use --help for command help.

packata schema export sales.odcs.yaml --output-format json-schema --asset orders
packata schema export sales.odcs.yaml -f json-schema --asset orders -o orders.schema.json

Export one asset from an ODCS or Data Package v2 descriptor. You can use the same local, HTTP(S) and ZIP, TAR, TAR.GZ and TAR.BR sources as inspection. Select the asset by its exact canonical identifier; a missing or ambiguous identifier fails.

Select the required document format with --output-format or -f: json-schema, avro, avro-idl, spark-json, or arrow-ipc. Avro JSON and Avro IDL accept --schema-name and --schema-namespace; see the schema reference for representation policies and limitations. Compatibility profiles are not yet available; omit --profile for generic output.

The result is a JSON Schema Draft 2020-12 object describing one dataset record. By default, only the generated JSON goes to stdout, while diagnostics go to stderr. To save it instead, choose a new UTF-8 file with --output or -o. Existing files, including the source contract, cannot be replaced.

Export reads only the descriptor. It does not access referenced data or install connectors, and it uses the validation command’s exit codes.

The converter supports strings, booleans, integers, numbers and decimals, dates, timestamps and datetimes, times, arrays and objects. It uses JSON Schema formats for temporal values and recursively converts nested objects and array items.

Representable constraints are retained. These include string lengths and patterns, numeric bounds, enums, array size and uniqueness, and object size and required properties.

Requiredness and nullability are independent. A required field is added to its parent’s required list. A nullable field allows null alongside its normal type. When nullability is omitted, it defaults to false. The schema’s additional-property permission is exported as additionalProperties; native DPv2 partial overlap becomes an anyOf presence requirement. Tabular column ordering is outside this JSON object record representation.

Conversion fails for unknown types, including maps and vectors, invalid constraints, temporal range constraints, and dataset-wide uniqueness or primary-key constraints. A schema for one record cannot enforce uniqueness across records.

The export does not emit custom extension keywords. Physical storage details, relationships, quality rules and governance metadata are outside this record-schema representation.

The same converter is available in Packata.Core.Contracts:

var schema = asset.ToJsonSchema();
schema.Serialize(stream);

Preview bound data

packata data preview <SOURCE> --asset <ID> [OPTIONS]

Option / alias Values / default Meaning
--input-format <FORMAT> auto, odcs, datapackage; auto Source standard; locations remain command-specific
--asset <ID> Required Exact Data Package resource or ODCS schema object name
--limit <COUNT> Positive 32-bit integer; 20 Maximum data rows, excluding headers
--staging-maximum-bytes <COUNT> Positive integer; 268435456 (256 MiB) Maximum bytes copied for each non-seekable Excel/Parquet resource; ignored for CSV/inline/database reads
--columns <NAMES> All fields Unique exact names, comma-separated, in output order
--decode-categories Disabled Replace inline category/enum and local Category Tables recipe codes with labels; PocketCsvReader delimited engine (CSV/TSV/PSV) only
--decode-categories-language <LANGUAGE> Unset Enable decoding and select table labels by language, such as fr or fr-BE
--decode-categories-label <FIELD> Unset Enable decoding and select an exact declared logical table-label field, such as label_de or short_label
--output-format <FORMAT> table, json, csv; table Result representation
--output <PATH>, -o <PATH> Stdout when omitted New destination file; existing files are protected
--connector <SCHEME=ID> Repeatable; persisted preference otherwise Invocation connector preference
--connection-env <ENDPOINT=VARIABLE> Repeatable; omitted by default Runtime database URL from environment; never persisted

All shown positional arguments are required. Use --help for command help.

packata data preview contract.yaml --asset customers --limit 20
packata data preview datapackage.json --asset customers --limit 5 --columns id,name
packata data preview contract.yaml --asset customers --output-format json > customers.json

Preview reads an asset from an ODCS YAML or Data Package v2 JSON/YAML descriptor, or a local/HTTP(S) ZIP, TAR, TAR.GZ or TAR.BR containing exactly one supported descriptor. CSV-family, Excel and Parquet resources are read from the archive container without requiring manual extraction. Their paths resolve relative to the descriptor inside the archive, including when that descriptor is in a subdirectory:

packata data preview dataset.zip --asset customers
packata data preview dataset.tar --asset customers
packata data preview dataset.tar.gz --asset customers --limit 5 --output-format json
packata data preview https://example.test/dataset.tar.br --asset customers --columns name,id

For example, datapackage.json can reference data/customers.csv in the same archive. Select the asset explicitly with --asset. Its canonical binding supplies the file paths, physical table names, schema and format or dialect settings. Missing or ambiguous assets and bindings fail rather than being selected automatically. Row limits, column selection and all output formats apply equally to ZIP and TAR previews. TAR containers materialize entries under the default storage limits and retain them until preview finishes; streams and temporary storage are released after success, failure or cancellation.

HTTP and archive streams that cannot seek are staged to disk for Excel/Parquet using the same adapter as schema inference. --staging-maximum-bytes bounds each staged data file; CSV remains streaming. CLI132 identifies a staging-limit failure and no output file is committed. See staging limits, ownership and temporary storage.

Relative file paths and database files resolve against the descriptor’s directory, so the working directory does not change which data is read. Preview registers readers for delimited and inline data, Excel, Parquet and databases. Database reads use the shared connector service and can download a missing connector when the configured policy permits it.

Preview returns at most 20 data rows by default, excluding headers. Set --limit to any positive 32-bit integer to change that bound. Reading stops at the limit or the end of the data.

To select or reorder columns, pass their exact names as a comma-separated --columns value. Omit it to return all columns. Invalid, duplicate or ambiguous names fail.

Pass --decode-categories to display optional labels from ODCS enums or DPv2 inline categories. For example, S with label South displays as South; integer 1 with label Low displays as Low. Entries without labels and unmatched codes retain their original text; nulls stay null. An explicitly empty label displays as an empty string. Decoding is disabled by default. Excel, Parquet, database, inline and other reader engines reject decoding with an explicit diagnostic. Local category-table references resolve their mapped lookup columns when decoding is enabled. ODCS can declare lookup references using Packata custom properties; see the complete ODCS descriptor, bindings and raw/decoded output.

For tables with alternate labels, use --decode-categories-language fr to select by field language, or --decode-categories-label short_label to select an exact declared logical label field. Either option enables decoding, and the two selectors are mutually exclusive. Language selection falls back from the exact tag to the primary language, default label and original code. Explicit column selection requires that label in every involved table and never chooses another column. See category-table metadata, missing translations and examples.

packata data preview datapackage.json --asset directions --output-format json
packata data preview datapackage.json --asset directions --output-format json --decode-categories
packata data preview contract.yaml --asset directions --output-format json --decode-categories

The complete two-format examples show the descriptors and output. Packata uses PocketCsvReader’s native sequence mapping, which matches exact, case-sensitive, unquoted CSV text. Integer 1 matches, while quoted "1" and alternate spelling 01 remain unchanged. Write cells to decode as unquoted, unescaped CSV text. Native sequence replacement skips fields marked as quoted or escaped by PocketCsvReader, even when the parsed code matches. Codes requiring CSV quoting or escaping cannot be decoded. Descriptor strings still follow normal JSON/YAML quoting rules. Columns with labels return strings, including fallback codes, so JSON contains "2" rather than 2 in such an integer column. The .NET reader reports typeof(string) through GetFieldType and string through GetDataTypeName. PocketCsvReader does not implement GetSchemaTable(). Columns without labels keep their original type. This is a presentation option: it does not edit the descriptor, persist labels into the CSV, or replace the allowed codes used by validation.

Preview displays a table by default. Use --output-format to choose JSON or CSV, and --output or -o to save the result to a new file instead of stdout.

Diagnostics go to stderr. JSON and CSV stdout contain only the requested data representation, and redirected output has no ANSI styling.

JSON uses the stable shape {"schemaVersion":1,"columns":["id","name"],"rows":[[1,"Alice"]]}. Each row is an array whose positions match the column list. This preserves JSON nulls and avoids object-key collisions. Empty results still include column names when the reader or declared schema supplies them.

CSV includes a header and quotes delimiters, quotation marks and line breaks. Nulls become empty fields. Values use invariant culture, dates use round-trip format and binary values are base64.

The table view displays null as (null) and flattens line breaks. Wide previews split into column groups sized to the terminal, with row numbers repeated in each group. Cells stay on one line and show an ellipsis when they exceed the available width (at most 40 terminal cells). Use --columns to focus on specific fields. JSON and CSV values are not truncated.

Preview does not write the contract or change source data. Its output buffer contains at most the requested rows. Staging can transfer the entire resource before parsing, and Parquet preview currently materializes all row groups before returning. --limit bounds displayed rows; it does not bound transfer cost or provider memory use. Parquet schema inference continues to parse only metadata after acquisition.

Cancellation is passed to opening and asynchronous reads, and checked between synchronous reads. A synchronous driver call cannot always be interrupted while it is running. Readers and the resources they own are disposed after completion, failure, cancellation or early stopping.

Evaluate producer and consumer contracts

packata contract satisfies <PRODUCER> --consumer <SOURCE> [OPTIONS]

Both sources are ordinary, complete ODCS documents or Data Package v2 descriptors. Supported serializations are YAML and JSON. Same-standard pairs only; their IDs and versions may differ. Sources use the shared loader: local files, HTTP(S) descriptors, and supported ZIP/TAR archives. The operation reads declarations, never referenced datasets, connectors, or observed SLA metrics.

Option / alias Values / default Meaning
--consumer <SOURCE> Required Complete consumer document in the producer’s native standard
--input-format <FORMAT> auto, odcs, datapackage; auto Standard for both documents
--output-format <FORMAT> text, json; text Human-readable report or versioned structured report
--format <FORMAT> text, json Alias for output representation
--output <PATH>, -o <PATH> Stdout when omitted New destination file; existing files are protected
--unknown <POLICY> unsatisfied, ignore, error; unsatisfied Gate unresolved findings without changing them
--quiet Off Suppress results and diagnostics; preserve exit code
packata contract satisfies producer.odcs.yaml --consumer consumer.odcs.yaml
packata contract satisfies producer.datapackage.json --consumer consumer.datapackage.json --format json
packata contract satisfies producer.odcs.yaml --consumer consumer.odcs.yaml --unknown ignore
packata contract satisfies producer.odcs.yaml --consumer consumer.odcs.yaml --unknown error --quiet

For example, these are two native ODCS documents. Save the first as producer.odcs.yaml:

apiVersion: v3.2.0
kind: DataContract
id: sales-producer
version: 2.0.0
status: active
schema:
  - name: orders
    properties:
      - name: order_id
        logicalType: string
        required: true
        nullable: false
        logicalTypeOptions:
          maxLength: 30

Save the consumer as consumer.odcs.yaml:

apiVersion: v3.2.0
kind: DataContract
id: sales-report
version: 1.0.0
status: active
schema:
  - name: orders
    properties:
      - name: order_id
        logicalType: string
        required: true
        nullable: false
        logicalTypeOptions:
          maxLength: 50

The producer’s maximum of 30 fits the consumer’s maximum of 50. Reversing the roles fails. Removing the producer maximum also fails: the producer’s permitted domain is unbounded. Removing the consumer maximum accepts any supported producer length.

ODCS required expresses field presence independently of nullable (default false). Data Package constraints.required controls missing/null values (default false); native fieldsMatch separately determines field presence, closed sets, and ordering. The default exact requires the same ordered fields. equal compares a closed set by name; subset is open by name; superset permits an optional subset; partial remains Unknown. Absent optional consumer fields are reported as accepted absence; required missing fields fail, and dependent checks remain Unknown. Names match ordinally using canonical dataset identifiers and field names; no physical-name matching or rename inference occurs. Extra producer elements are informational under the default open-record policy unless native closed-schema semantics reject them. The .NET strict policy can reject extras.

Fixed-decimal containment requires producer scale <= consumer scale and producer (precision - scale) <= consumer (precision - scale). ODCS number/decimal logicalTypeOptions.precision and scale map to canonical constraints. Incomplete decimal parameters, custom types, unsupported constraints, quality rules, storage-type capacities, format-specific semantics, and SLA/lifecycle semantics remain explicit Unknown findings. Ownership, descriptions, identities, versions, and connection locations are informational. Native unknown members and mapping warnings stay visible even when documents are identical.

JSON has schemaVersion: 1, producer/consumer identities and sources, policy, completion state, status, proven satisfaction, gating result, deterministic findings with codes and both semantic paths, offered/accepted values, explanations, and diagnostics. Failures retain completed: false and diagnostics; they never resemble an empty successful comparison. JSON stdout contains only the redacted JSON payload. --output uses the shared atomic, no-overwrite output mechanism.

Findings after completed analysis unsatisfied ignore error
All applicable expectations proven 0 0 0
Unknown only 1 0 2
Unsatisfied only 1 1 1
Unknown and Unsatisfied 1 1 2

Invalid invocation/documents, mixed standards, I/O failure, cancellation, and incomplete analysis always return 2. Ignoring Unknown changes only the gate: isSatisfied remains false and the Unknown findings remain in the report. A valid empty consumer schema is vacuous structurally; metadata, source coverage, and unsupported semantics are still reported.


Table of contents