Getting Started with the Playground
The Rocky playground creates a self-contained sample project that runs entirely on DuckDB. It needs no warehouse credentials, no Fivetran account, and no external services. It is the quickest way to try Rocky’s compiler, type system, lineage engine, and AI features.
1. Create the Playground
Section titled “1. Create the Playground”rocky playground my-projectThis creates a directory with everything you need:
my-project/├── rocky.toml # DuckDB pipeline config├── models/│ ├── raw_orders.sql # SQL replication model│ ├── raw_orders.toml # Model config│ ├── customer_orders.rocky # Rocky DSL transformation│ ├── customer_orders.toml # Model config│ ├── revenue_summary.sql # SQL transformation│ └── revenue_summary.toml # Model config├── contracts/│ └── revenue_summary.contract.toml # Data contract└── data/ └── seed.sql # DuckDB seed dataThe default template, quickstart, is the only template. rocky playground loads its seed into playground.duckdb when it creates the project, so rocky run builds every model on the first try.
Enter the project directory:
cd my-project2. Explore the Generated Files
Section titled “2. Explore the Generated Files”rocky.toml
Section titled “rocky.toml”The pipeline config uses a local DuckDB adapter instead of Databricks. No credentials are required:
[adapter]type = "duckdb"path = "playground.duckdb"
[pipeline.playground]type = "transformation"models = "models/**"
# Models land in the database's default schema (`playground.main`), so a model# can reference an upstream by name (`from raw_orders`) and it resolves both# when materialized by `rocky run` and in the in-memory `rocky test` run.[pipeline.playground.target.governance]auto_create_schemas = true
[pipeline.playground.execution]concurrency = 4This is a transformation pipeline. The unnamed [adapter] block auto-wraps as the default adapter, and models = "models/**" builds the model DAG from the models/ directory.
The same playground.duckdb file backs the whole run. rocky test ignores path: it runs models against an in-memory database and loads data/seed.sql on the fly. rocky run materializes models into the file, which rocky playground already seeded when it created the project. So the playground works end to end with no manual seeding step. Re-seed the file at any time with duckdb playground.duckdb < data/seed.sql.
raw_orders.sql + raw_orders.toml
Section titled “raw_orders.sql + raw_orders.toml”The first model selects raw order data from the seeded source table:
raw_orders.sql:
SELECT order_id, customer_id, product_id, amount, status, order_dateFROM raw__orders.ordersThe data/seed.sql file creates the raw__orders.orders table this model reads from.
raw_orders.toml:
[strategy]type = "full_refresh"
[target]catalog = "playground"schema = "main"customer_orders.rocky
Section titled “customer_orders.rocky”This model uses the Rocky DSL, a compact syntax for common aggregation patterns. The playground includes both kinds of model: two are plain SQL, and this one is DSL.
-- Customer orders aggregation (Rocky DSL)from raw_orderswhere status != "cancelled"group customer_id { total_revenue: sum(amount), order_count: count(), first_order: min(order_date)}where total_revenue > 0The Rocky DSL compiles to standard SQL. The compiler type-checks column references, validates aggregation semantics, and resolves the raw_orders dependency automatically.
revenue_summary.sql
Section titled “revenue_summary.sql”A standard SQL transformation that builds on customer_orders:
SELECT customer_id, total_revenue, order_count, total_revenue / order_count AS avg_order_value, first_orderFROM customer_ordersWHERE order_count >= 2revenue_summary.contract.toml
Section titled “revenue_summary.contract.toml”A data contract that enforces the output schema of revenue_summary:
# Loose contract suitable for the playground.# Type checker can't infer non-null from `SELECT col FROM raw__orders.orders`# (the source schema is unknown to the compiler), so columns are declared# nullable here to keep `rocky compile --contracts contracts` clean.
[[columns]]name = "customer_id"type = "Int64"nullable = true
[[columns]]name = "total_revenue"type = "Decimal"nullable = true
[[columns]]name = "order_count"type = "Int64"nullable = true
[rules]required = ["customer_id", "total_revenue", "order_count"]protected = ["customer_id"]The contract declares two rules:
- required: these columns must exist. The compiler checks a declared type only when it can infer the output type.
- protected: these columns cannot be removed by a later change. The compiler fails with error
E013if a protected column disappears from the model’s output.
The columns are marked nullable = true, and the TOML comment above explains why. A strict-contract walkthrough that pins types and nullability lives in the dedicated POCs.
3. Compile the Models
Section titled “3. Compile the Models”Run the compiler to type-check all models, resolve dependencies, and validate contracts. Pass --contracts contracts to check the model output against the contract files. Plain rocky compile skips contract validation.
rocky compile --contracts contractsThe command exits 0, but this template reports I003 information notices.
The compiler cannot infer every type from raw__orders.orders during this
compile. It still checks the required output-column names.
The compiler performs three checks:
- Dependency resolution: it builds a DAG from the model configs.
customer_ordersdepends onraw_orders, andrevenue_summarydepends oncustomer_orders. - Type inference: it carries known types through the model graph. This template leaves some types unknown, so it reports
I003notices. - Contract validation: it checks required and protected output columns. It checks a declared type only when it can infer that type. An
I003notice says when it could not.
The template’s local transformation pipeline does not support rocky plan.
Use rocky emit-sql to inspect the statements before you run them. It does not
create a saved plan or an approval.
Try introducing an error
Section titled “Try introducing an error”Edit revenue_summary.sql and drop a required column. Remove the order_count line from the SELECT:
SELECT customer_id, total_revenue, total_revenue / order_count AS avg_order_value, first_orderFROM customer_ordersWHERE order_count >= 2Run rocky compile --contracts contracts again:
✓ raw_orders (6 columns) ✓ customer_orders (4 columns) ✗ revenue_summary x error[E010]: required column 'order_count' missing from model output help: add `order_count` to the SELECT, or remove it from `[rules] required`
Compiled: 3 models, 1 errors, 0 warningsRestore the line before continuing. Use the compile command as a gate before you run models:
rocky compile --contracts contracts && rocky runThe && runs rocky run only when the contract compile exits 0.
The two commands read the project separately. A model or contract edit between them can change what runs.
For a selected full_refresh model, rocky run --pipeline <NAME> --model <NAME> --contracts contracts checks the contract in the run’s own compile. This template runs the whole model graph here, so it still needs the separate compile gate.
A failed compile leaves tables from a previous run in playground.duckdb.
rocky preview rows shows those stored rows. It does not prove the current
source passed the contract check.
4. Run the Tests
Section titled “4. Run the Tests”Rocky executes models locally on DuckDB, with no warehouse connection:
rocky testExpected output:
Testing 3 models...
All 3 models passed
Result: 3 passed, 0 failedThe test runner does four things:
- Compiles all models.
- Executes each model’s SQL against DuckDB, in dependency order.
- Validates contract assertions against the actual output, when you pass
--contracts contracts. - Reports pass or fail for each model.
Test a single model
Section titled “Test a single model”rocky test --model revenue_summaryRun the Models and Inspect the Rows
Section titled “Run the Models and Inspect the Rows”Materialize the model graph into playground.duckdb after the contract check
passes:
rocky compile --contracts contracts && rocky runInspect the materialized result:
rocky preview rows --model revenue_summaryThe command shows the output columns and up to 100 rows from the local DuckDB file. Run it again after a change to verify the materialized result.
5. View Column Lineage
Section titled “5. View Column Lineage”Rocky traces data flow at the column level. See the full lineage for a model:
rocky lineage revenue_summaryModel: revenue_summaryUpstream: customer_ordersDownstream:
Columns: customer_id <- customer_orders.customer_id (direct) total_revenue <- customer_orders.total_revenue (direct) order_count <- customer_orders.order_count (direct) avg_order_value (no lineage) first_order <- customer_orders.first_order (direct)avg_order_value shows (no lineage) because it is a computed expression, total_revenue / order_count. The column tracer follows only columns that pass through directly or through an aggregation.
Trace a single column through the entire chain
Section titled “Trace a single column through the entire chain”rocky lineage revenue_summary --column total_revenueColumn trace: revenue_summary.total_revenue <- customer_orders.total_revenue (direct) <- raw_orders.amount (aggregation: sum) <- raw__orders.orders.amount (direct)Generate Graphviz output
Section titled “Generate Graphviz output”rocky lineage revenue_summary --format dotdigraph lineage { rankdir=LR; "customer_orders.customer_id" -> "revenue_summary.customer_id"; "customer_orders.total_revenue" -> "revenue_summary.total_revenue"; "customer_orders.order_count" -> "revenue_summary.order_count"; "customer_orders.first_order" -> "revenue_summary.first_order";}Pipe this to Graphviz to generate an SVG: rocky lineage revenue_summary --format dot | dot -Tsvg -o lineage.svg
6. Try AI Features
Section titled “6. Try AI Features”If you have an Anthropic API key, you can generate models from natural language:
export ANTHROPIC_API_KEY="sk-ant-..."Generate a new model
Section titled “Generate a new model”rocky ai "monthly revenue per customer from raw_orders, only completed orders"Rocky sends your intent to Claude, receives generated code, and compiles it against the available project context. Compilation can find supported static problems. It does not prove warehouse behavior or business correctness. Review the SQL and run relevant checks before you use the generated model.
Add intent to existing models
Section titled “Add intent to existing models”rocky ai-explain --all --saveThis reads each model’s SQL, generates a plain-English description, and saves it to the model’s TOML config as an intent field. ai-sync later reads that intent to update models when upstream schemas change.
Generate tests from intent
Section titled “Generate tests from intent”rocky ai-test --all --saveGenerates test assertions based on each model’s SQL logic and intent description, and saves them to the tests/ directory.
See the AI Features guide for a complete walkthrough.
7. Run CI Locally
Section titled “7. Run CI Locally”The ci command runs compilation and local tests in one pass. Pass the
contracts directory when contract checks are part of the job:
rocky ci --contracts contractsRocky CI Pipeline
Compile: PASS (3 models) Test: PASS (3 passed, 0 failed)
Exit code: 0Exit code 0 means the configured supported checks passed. It does not prove
warehouse execution or business correctness. A non-zero exit code fails the CI
job.
8. Explore the POC Catalog
Section titled “8. Explore the POC Catalog”Beyond this walkthrough, the playground ships 101 self-contained POCs across 8 categories. Each one demonstrates a single Rocky capability end to end. Browse them, grouped by category with a link to every one, in the Examples & POC catalog. Or run one directly:
cd examples/playground./pocs/02-performance/01-incremental-watermark/run.shMost run on local DuckDB with no credentials. The exceptions: AI (ANTHROPIC_API_KEY), Governance (a Databricks workspace), and the warehouse-specific adapter POCs.
9. Benchmarks
Section titled “9. Benchmarks”The playground ships a benchmark suite. The bench-rocky target measures Rocky’s compile time and peak memory:
cd examples/playground/benchmarksmake bench-rockySee Benchmarks for the methodology and the numbers.
Next Steps
Section titled “Next Steps”- Connect to a warehouse — point the project at a real warehouse
- The Browser UI — run
rocky serve --uito see the models, the DAG, runs and plans in a browser - IDE Setup — install the VS Code extension for hover types, go-to-definition, and inline lineage
- CI/CD Integration — add Rocky to your GitHub Actions or GitLab CI pipeline
- Migrating from dbt — import an existing dbt project
- AI Features — generate models, sync schema changes, and create tests with AI
- Data Governance — configure contracts, permissions, and quality checks