Skip to content

JSON Contract

Rocky’s CLI output is the interface contract with orchestrators like Dagster. The schema is versioned using semantic versioning.

Current version: 0.1.0

Every JSON output includes a version field:

{
"version": "0.1.0",
"command": "discover",
...
}
  • Patch versions (0.1.x): Bug fixes, no schema changes
  • Minor versions (0.x.0): New fields may be added (backward compatible). Existing fields are never removed or renamed.
  • Major versions (x.0.0): Breaking changes to field names, types, or structure

The asset_key field in materializations and check results follows a fixed format:

[source_type, ...component_values, table_name]

Example: ["fivetran", "acme", "us_west", "shopify", "orders"]

Multi-valued components (like regions) are joined with __:

["fivetran", "acme", "us_west__us_central", "shopify", "orders"]

This format is consumed by dagster-rocky to build Dagster AssetKey objects.

Use the parse_rocky_output() function in dagster-rocky to auto-detect the command type:

from dagster_rocky import parse_rocky_output
result = parse_rocky_output(json_str)
# Returns: DiscoverResult | RunResult | PlanResult | StateResult

The command is detected from the "command" field in the JSON.

Rocky’s JSON output schemas are autogenerated from typed Rust structs. Every CLI command that emits --output json is backed by a struct in engine/crates/rocky-cli/src/output.rs that derives JsonSchema. The full pipeline:

  1. Edit the relevant *Output struct in output.rs
  2. Run just codegen from the monorepo root
  3. This exports JSON schemas to schemas/, regenerates Pydantic v2 models in integrations/dagster/, and TypeScript interfaces in editors/vscode/
  4. Commit the schema and regenerated bindings together

The codegen-drift CI workflow fails any PR where committed bindings don’t match just codegen output.

As of the latest release, there are 28 typed output schemas covering every JSON-emitting command. See the JSON Output reference for the full list.

When adding fields to Rocky’s JSON output:

  1. Add the field as optional (nullable) in Rocky’s Rust output structs
  2. Run just codegen to regenerate Pydantic models and TypeScript interfaces
  3. Bump the minor version
  4. Document the new field in the JSON Output reference