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.