Skip to main content
ClaudeChatGPT

V1 Project Layout

Archived: This page describes the v1 flat-file project layout. For the current v2 folder-per-entity format, see Wren Project.

This guide explains the Wren MDL project structure, file formats, and typical workflow for managing your data models as a collection of YAML files. The Wren Project format makes it easy to version control your models, track changes, and separate connection information from model definitions.

A Wren MDL project is a directory of YAML files that makes MDL manifests human-readable and version-control friendly — similar to how dbt organizes models. Instead of managing a single large JSON file, each model lives in its own YAML file, and the project is compiled to a deployable mdl.json when needed.

YAML files use snake_case field names for readability. The compiled target/mdl.json uses camelCase, which is the wire format expected by ibis-server.

Project Structure​

my_project/
├── wren_project.yml # Project metadata (catalog, schema, data_source)
├── models/
│ ├── orders.yml # One file per model
│ ├── customers.yml
│ └── ...
├── relationships.yml # All relationships
└── views.yml # All views

After building, the compiled file is written to:

my_project/
└── target/
└── mdl.json # Deployable MDL JSON (camelCase)

Connection info is managed via the MCP server Web UI (http://localhost:9001) — it is not stored in the project directory.


Project Files​

wren_project.yml​

The root metadata file describing the project:

name: my_project
version: "1.0"
catalog: wren
schema: public
data_source: POSTGRES
FieldDescription
nameProject name
catalogMDL catalog (matches the catalog in your MDL manifest)
schemaMDL schema
data_sourceData source type (e.g. POSTGRES, BIGQUERY, SNOWFLAKE)

models/<model_name>.yml​

One file per model. Example for an orders model:

name: orders
table_reference:
catalog: ""
schema: public
table: orders
columns:
- name: order_id
type: INTEGER
is_calculated: false
not_null: true
is_primary_key: true
properties: {}
- name: customer_id
type: INTEGER
is_calculated: false
not_null: false
properties: {}
- name: total
type: DECIMAL
is_calculated: false
not_null: false
properties: {}
primary_key: order_id
cached: false
properties: {}

relationships.yml​

All relationships between models in a single file:

relationships:
- name: orders_customer
models:
- orders
- customers
join_type: MANY_TO_ONE
condition: orders.customer_id = customers.customer_id

views.yml​

All views in a single file:

views:
- name: recent_orders
statement: SELECT * FROM wren.public.orders WHERE order_date > '2024-01-01'
properties: {}

Field Mapping​

When converting between YAML (snake_case) and JSON (camelCase):

YAML fieldJSON field
data_sourcedataSource
table_referencetableReference
is_calculatedisCalculated
not_nullnotNull
is_primary_keyisPrimaryKey
primary_keyprimaryKey
join_typejoinType

All other fields (name, type, catalog, schema, table, condition, models, columns, cached, properties) are identical in both formats.


Building the Project​

Building compiles the YAML project into target/mdl.json:

# target/mdl.json — assembled MDL manifest (camelCase)

After building, deploy the MDL via the MCP server:

deploy(mdl_file_path="/workspace/target/mdl.json")

Or place it in the workspace before starting the container so it is auto-loaded via MDL_PATH.

Connection info is configured separately via the Web UI (http://localhost:9001) — it is not part of the build output.


Typical Workflow​

1. Configure connection info

Open the Web UI at http://localhost:9001, select the data source type, and fill in connection credentials. Use /wren-connection-info in Claude Code for per-connector field reference.

2. Generate MDL

Run /generate-mdl in Claude Code. The skill uses MCP tools (list_remote_tables, list_remote_constraints) to introspect the database and build the MDL JSON.

3. Save project

Write wren_project.yml, models/*.yml, relationships.yml, and views.yml by converting the MDL JSON (camelCase) to snake_case YAML.

4. Add target/ to .gitignore

target/

5. Commit to version control

Commit the model YAML files — target/ is excluded.

6. Build

Read the YAML files, rename snake_case → camelCase, and write target/mdl.json.

7. Deploy

deploy(mdl_file_path="/workspace/target/mdl.json")

Migrating to v2​

The v2 project layout uses a folder-per-entity structure with richer features (memory, instructions, profiles). To migrate:

Step 1 — Build mdl.json from the v1 project​

If you have a v1 project, build it first to get the compiled JSON:

deploy(mdl_file_path="/workspace/target/mdl.json")

Or copy the target/mdl.json from your existing project. If you only have a raw mdl.json (e.g. from the MCP server), use that directly.

Step 2 — Install the Wren CLI​

pip install "wren-engine[ui,memory]"

Step 3 — Convert JSON to v2 YAML project​

Use --from-mdl to convert the camelCase JSON into a v2 folder-per-entity project:

wren context init --from-mdl /path/to/mdl.json --path my_project_v2

This produces:

my_project_v2/
├── wren_project.yml # schema_version: 2
├── models/
│ ├── orders/
│ │ └── metadata.yml # one directory per model
│ └── customers/
│ └── metadata.yml
├── views/
│ └── recent_orders/
│ └── metadata.yml # one directory per view
├── relationships.yml
└── instructions.md

Step 4 — Set up a profile and verify​

wren profile add my-db --ui # configure connection
wren context validate # check YAML structure
wren context build # compile to target/mdl.json
wren --sql "SELECT 1" # verify connection

Step 5 — Initialize memory​

wren memory index

Your project is now on v2 with the full CLI workflow (profiles, memory, instructions). See Wren Project for the complete v2 reference.


Version Control Benefits​

Storing MDL as a YAML project (rather than a single JSON blob) gives you:

  • Readable diffs — model changes show up as clear line-level diffs in pull requests
  • One file per model — merge conflicts are isolated to the affected model file
  • Separation of secrets — connection info lives in the Web UI, not in the project; target/ is gitignored
  • Reproducible builds — target/mdl.json is always regenerated from source, never committed