Using Dinorules to Control AI-Generated Code in dbt™ Projects

Feb 26, 2026

Table of Contents

AI assistants write dbt™ code fast—but without guardrails, "fast" quickly turns into "chaotic." One model uses SELECT in uppercase, another in lowercase. A staging model is named stg_orders in one file and staging_orders in another. A generated query uses SELECT * that silently breaks when a source schema changes.

.dinorules solves this. It is a plain-text configuration file, committed to the root of your dbt™ repository, that tells DinoAI (Paradime's AI platform) exactly how to generate SQL, Jinja, and YAML. Every AI interaction—inline completions, agent-mode generation, prompt-based code creation—reads .dinorules first and constrains output to match your team's declared conventions. No linting after the fact. No post-processing. Standards are enforced at generation time.

This guide walks through what .dinorules is, how to set it up, what rules to start with, and how it compares to alternatives like CLAUDE.md and dbt™ Agent Skills.

Why AI-Generated dbt™ Code Drifts Without Explicit Rules

AI assistants like GitHub Copilot and Claude generate syntactically correct SQL. The code compiles. It runs. But syntactically correct is not the same as stylistically consistent.

Without explicit rules, every prompt is an isolated event. The AI has no memory of what your team decided about comma placement last Tuesday, or that staging models must start with stg_. The result is a codebase that works but is increasingly expensive to maintain—because every pull request becomes a formatting debate and every new team member encounters a different pattern in every file.

Formatting Churn in Pull Requests

Inconsistent formatting creates noisy diffs that slow code reviews and obscure meaningful logic changes:

  • Trailing vs. leading commas: AI may alternate between styles across files, making it impossible to see at a glance which columns were actually added or removed

  • Keyword casing: Uppercase SELECT in one model, lowercase select in another—trivial differences that pollute diffs with irrelevant changes

  • Indentation depth: Two spaces in one model, four in another—making side-by-side comparisons unreadable

These aren't bugs. They're friction. And friction compounds across hundreds of models.

Inconsistent Naming Conventions

AI has no opinion about your naming conventions unless you give it one. Without rules, you might get:

  • stg_orders in one file and staging_orders in another

  • dim_customers alongside customer_dimension

  • fct_revenue next to fact_revenue

This breaks discoverability. Analysts searching for the staging model of orders now need to check two patterns. Downstream models that depend on a consistent naming scheme break silently when a name changes. The dbt™ project evaluator explicitly warns against inconsistent prefixes for this reason.

Risky Patterns Like SELECT * and Implicit Joins

Some AI-generated patterns are not just inconsistent—they are dangerous:

  • SELECT * — Pulls every column from a source. When a source schema changes (a column is added, renamed, or removed), downstream models break without warning.

  • Comma joins (implicit joins)FROM orders, customers WHERE orders.customer_id = customers.id is valid SQL but error-prone. Missing a join condition silently produces a Cartesian product.

  • Missing WHERE clauses on DELETE statements — A DELETE FROM table_name without a WHERE clause wipes the entire table.

These patterns pass linting. They compile. They run. And they cause production incidents.

What Is .dinorules and How Does It Work

.dinorules is a plain-text configuration file that you commit to the root of your dbt™ repository. It contains natural language instructions—written in plain English using bullet points, sections, or numbered lists—that tell DinoAI exactly how to generate code. Think of it as a .cursorrules or .windsurfrules file, but purpose-built for analytics engineering workflows.

No special syntax is required. No YAML schemas to learn. You write rules in plain English, and DinoAI reads them.

Repo-Committed Rules for AI Governance

.dinorules lives alongside dbt_project.yml in the repository root, making standards:

  • Portable — Every team member who clones the repo gets the same rules. No IDE settings to sync, no Slack messages to remember.

  • Auditable — Changes go through pull requests. You can see exactly when a rule was added, who approved it, and why.

  • Version-controlled — Rules evolve with the codebase. When you adopt a new convention, you update .dinorules in the same PR that implements the change.

Unlike IDE-specific settings or team wikis, .dinorules travels with the code itself.

How DinoAI Reads and Applies Rules at Generation Time

When you interact with DinoAI—whether through inline suggestions, agent mode, or prompt-based generation—it automatically loads .dinorules as part of its context window. The mechanism is straightforward:

  1. DinoAI detects .dinorules in the repository root

  2. It parses the rules before generating any SQL, Jinja, or YAML

  3. Generated output is constrained to match declared conventions

  4. Rules apply to every interaction: new models, updates, documentation, and tests

No additional configuration is needed. No plugins to install. The file's presence is sufficient.

DinoAI reads .dinorules before generating any code, ensuring output matches team conventions from the start.

Where to Place .dinorules in Your dbt™ Project

Place .dinorules in the root directory of your repository—at the same level as dbt_project.yml. DinoAI auto-detects the file; no additional configuration is needed.

Tip: While iterating on your rules locally, you can temporarily add .dinorules to .gitignore. Once the team agrees on the rules, remove it from .gitignore, commit, and share.

Starter .dinorules Template for dbt™ Style Guide Enforcement

Here is a copy-paste ready template covering the three pillars—SQL formatting, dbt™ conventions, and safety guardrails. Drop this into your repo root as .dinorules and customize as needed:

Each section maps directly to a category of problems described earlier: SQL style prevents formatting churn, dbt™ conventions prevent naming inconsistencies, and safety guardrails prevent production incidents.

SQL Formatting Rules for Consistent AI Output

SQL formatting rules eliminate the single largest source of pull request noise: style disagreements that have nothing to do with logic.

Lowercase or Uppercase SQL Keywords

The dbt™ Labs SQL style guide recommends lowercase for all keywords, field names, and function names. Most modern dbt™ teams follow this convention. In your .dinorules:

With this rule active, DinoAI will never generate SELECT order_id FROM orders. It will always produce:

Leading Commas vs Trailing Commas

Leading commas produce cleaner diffs when adding or removing columns. When a new column is added, only one line changes—the new line. With trailing commas, adding a column requires modifying the previous line to add a comma.

Before (trailing commas—noisier diffs):

After (leading commas—cleaner diffs):

Note: The dbt™ Labs style guide officially recommends trailing commas. Leading commas are a popular alternative favored by many teams for diff clarity. Choose whichever your team prefers and encode it in .dinorules.

In your .dinorules:

Explicit Join Conditions

Implicit joins use comma-separated tables in the FROM clause:

Explicit joins make the relationship between tables clear:

In your .dinorules:

dbt™ Convention Rules for ref() source() and Staging Patterns

Beyond SQL formatting, .dinorules enforces dbt™-specific conventions that maintain lineage integrity, project structure, and model predictability.

Always Use ref() and source()

Hardcoded table names break dbt™'s lineage graph. If a model references raw.jaffle_shop.orders directly instead of using {{ source('jaffle_shop', 'orders') }}, dbt™ cannot track the dependency. Lineage becomes invisible, and dbt build cannot determine the correct execution order.

In your .dinorules:

With these rules, DinoAI will generate:

Enforce Staging Model Naming

The dbt™ staging best practices guide recommends the pattern stg_[source]__[entity]s—with a double underscore separating the source system from the entity name and a plural entity suffix.

In your .dinorules:

This prevents AI from generating staging_orders, stg_orders, or stg-jaffle-shop-orders. Every staging model follows the same pattern: stg_jaffle_shop__orders, stg_stripe__payments, stg_google_analytics__sessions.

Incremental Model Best Practices

Incremental models are one of the most powerful—and most error-prone—features in dbt™. Without explicit rules, AI might generate an incremental model that lacks a unique_key (causing duplicate rows) or omits the is_incremental() block (causing full-table scans on every run).

In your .dinorules:

With these rules, DinoAI generates incremental models that follow dbt™ best practices:

Safety Guardrails to Prevent Risky AI-Generated Code

Safety rules prevent the patterns that cause production incidents. They act as guardrails that catch problems before code review—because the problems never make it into the generated code.

Block SELECT * in All Models

SELECT * is the single most common source of silent breakage in dbt™ projects. When a source schema changes—a column is added, renamed, or removed—every model using SELECT * inherits the change without warning. Downstream models that expect specific columns fail. Dashboards break. Data contracts are violated.

In your .dinorules:

With this rule, DinoAI will always enumerate columns explicitly, functioning as a schema contract between your model and its dependencies.

Require WHERE Clauses on Deletes

A DELETE FROM table_name without a WHERE clause wipes every row in the table. This is catastrophic in production and trivially easy for AI to generate if not explicitly guarded against.

In your .dinorules:

Disallow Implicit Joins

Implicit joins—comma-separated tables in the FROM clause—are error-prone because a missing WHERE condition silently produces a Cartesian product. The result is a table with exponentially more rows than expected, often discovered only when storage costs spike or dashboards show inflated metrics.

In your .dinorules:

This reinforces the explicit JOIN...ON syntax described earlier, but framed as a safety requirement rather than a style preference.

How DinoAI Applies .dinorules Across Paradime Surfaces

.dinorules is not limited to a single interface. It works everywhere DinoAI operates, ensuring consistent standards regardless of how your team interacts with AI.

Copilot in the Paradime Code IDE

When you use DinoAI Copilot in the Paradime Code IDE, .dinorules applies to:

  • Inline code completions — Autocomplete suggestions follow your declared formatting and naming conventions

  • Chat suggestions — Responses to questions about how to build a model respect your team's patterns

  • Code generation prompts — Full model generation from natural language follows every rule in .dinorules

Bolt AutoPilot for Self-Healing Pipelines

When Bolt AutoPilot detects a pipeline failure, DinoAI reads the failure logs, traces dependencies across repositories, and generates a fix. Because DinoAI loads .dinorules as part of its context, auto-generated fixes match your team's coding standards—the same formatting, the same naming conventions, the same safety patterns.

This means a 2 AM pipeline fix looks indistinguishable from code a team member wrote during business hours.

MCP Server for External AI Clients Like Claude and Cursor

Teams using external AI tools—Claude Desktop, Claude Code, Cursor, ChatGPT, GitHub Copilot—can connect via Paradime's MCP Server. The MCP Server provides DinoAI's full context graph (lineage, catalog, Bolt logs, and more) to any MCP-compatible client. Because .dinorules is part of the repository context, standards travel with the project regardless of which AI client the team uses.

.dinorules flows from the repository through DinoAI to every surface where AI generates code.

Advanced .dinorules for Team Maturity Levels

Not every team needs the same rules on day one. Start simple and add complexity as your team matures.

Maturity Level

Focus Areas

Example Rules

Beginner

Formatting + safety

Keyword case, no SELECT *, explicit joins

Intermediate

Naming + macros

stg_ prefix, required ref(), macro usage patterns

Advanced

Performance

Partitioning, clustering, incremental strategies

Beginner Rules for Formatting and Safety

Start here. These rules have the highest impact-to-effort ratio—they eliminate formatting noise in PRs and prevent the most dangerous AI defaults:

This set of 7 rules is enough to make AI-generated code consistently reviewable. Adoption friction is minimal because the rules align with widely accepted conventions.

Intermediate Rules for Naming Conventions and Macros

Once the team is comfortable with basic rules, add naming enforcement and macro usage patterns:

At this level, you might also add rules for custom macros your team uses frequently—for example, requiring a specific logging macro or a standard audit column pattern.

Advanced Rules for Partitioning and Performance

Advanced rules are warehouse-specific and require more context. They prevent costly query patterns that are easy for AI to generate:

Validate That Your .dinorules Are Working

After committing .dinorules, verify that rules are applied correctly before trusting them across the team.

Before and After Prompt Examples

Use the same prompt with and without .dinorules to see the difference.

Prompt: "Create a staging model for the orders table from the jaffle_shop source"

Without .dinorules (inconsistent output):

With .dinorules (standards-compliant output):

The second output follows your .dinorules: lowercase keywords, leading commas, source() macro, proper naming convention, CTE pattern.

PR Checklist and Code Review Heuristics

For the first few AI-generated pull requests, review closely against this checklist:

  • ✅ Does keyword casing match the rule (all lowercase)?

  • ✅ Are all table references wrapped in ref() or source()?

  • ✅ Are joins explicit (inner join, left join) with ON conditions?

  • ✅ Is SELECT * absent from all models?

  • ✅ Do staging models follow the stg_[source]__[entity]s pattern?

  • ✅ Do incremental models include unique_key and is_incremental()?

  • ✅ Are primary key columns tested with unique and not_null?

  • ✅ Is the comma style consistent (leading or trailing, per your rule)?

If any items fail, refine your .dinorules wording—sometimes a rule needs to be more explicit for the AI to interpret it correctly.

Common .dinorules Pitfalls and How to Avoid Them

Over-Constraining AI Output

Rules that are too strict can make AI struggle to generate useful code. For example, specifying exact CTE names, exact comment formats on every line, and rigid column ordering simultaneously may cause DinoAI to produce stilted, overly verbose output.

Recommendation: Start with 10–15 rules maximum. Don't add rules that linters like SQLFluff can auto-fix—focus .dinorules on patterns that are hard to fix after generation (naming conventions, ref()/source() usage, safety patterns).

Conflicting Rule Definitions

What happens when .dinorules contains contradictory instructions—for example, requiring both uppercase AND lowercase keywords? DinoAI validates rules at parse time and surfaces conflicts in the IDE, allowing teams to resolve contradictions before they affect code generation.

Treat .dinorules as code: review it for logical consistency just as you would review a SQL model for correctness.

Failing to Update Rules as Standards Evolve

.dinorules is not a "set and forget" file. As dbt™ best practices evolve—new materialization strategies, new macro patterns, new warehouse features—your rules should evolve too.

Recommendation: Schedule a quarterly .dinorules review. Audit recent pull requests for recurring review comments that could be codified as rules. Remove rules that are no longer enforced or relevant. Update rules when adopting new dbt™ features.

How .dinorules Compares to CLAUDE.md and dbt™ Agent Skills

Teams evaluating AI governance for dbt™ projects often encounter three options. Here's how they compare:

Feature

.dinorules (Paradime)

CLAUDE.md

dbt™ Agent Skills

Purpose

AI coding standards enforcement for dbt™

General project context for Claude Code

Reusable skill definitions for AI agents working with dbt™

Scope

All DinoAI surfaces + MCP clients

Claude Code only

Any MCP-compatible agent (open-source)

Version control

Native (repo-committed, git-tracked by default)

Manual (repo-committed but not auto-loaded by all tools)

Repo-committed (open-source on GitHub)

dbt™-specific rules

Yes — ref(), source(), staging patterns, incremental configs

Generic — requires manual dbt™ context

Partial — provides dbt™ workflow skills, not formatting rules

Enforcement mechanism

Rules applied at generation time; no post-processing

Context injection; no enforcement guarantee

Skill execution; focuses on capability, not style

Multi-surface support

Paradime IDE, Bolt AutoPilot, MCP Server

Claude Code terminal only

Depends on client implementation

Key distinction: .dinorules is purpose-built for dbt™ workflows. It enforces coding standards—how code should look and what patterns to follow. CLAUDE.md provides context—project descriptions, architecture notes, general instructions. dbt™ Agent Skills provide capabilities—the ability for AI to compile, test, and manage dbt™ projects. These tools serve different purposes and can complement each other.

Ship Consistent Standards-Compliant dbt™ Code with Paradime

.dinorules eliminates the guesswork from AI-generated dbt™ code. Instead of hoping that AI follows your team's conventions, you declare them once, commit the file, and every AI interaction—across every surface—produces standards-compliant output.

The implementation path is straightforward:

  1. Create a .dinorules file in your repo root (start with the template above)

  2. Commit and push

  3. Every DinoAI interaction now follows your declared standards

No plugins to install. No settings to sync. No post-generation linting.

Paradime offers a free tier to try DinoAI and .dinorules immediately. Start for free →

FAQs About .dinorules in dbt™ Projects

Can .dinorules be scoped to specific folders or model types?

Currently, .dinorules applies globally across the entire dbt™ project. Folder-specific or model-type scoping is on the roadmap for teams that need varied conventions across different domains or layers.

Do .dinorules work alongside .dinoprompts for reusable prompts?

Yes. .dinorules enforces coding standards (how code should look), while .dinoprompts stores reusable prompt templates (what code to generate). Both are version-controlled in the same repository and work together for consistent AI behavior.

How should teams version-control and review changes to .dinorules?

Treat .dinorules like any production code—changes should go through pull requests with team review to ensure new rules don't conflict with existing ones or over-constrain AI output. This also creates an audit trail of when and why standards evolved.

What happens when DinoAI encounters conflicting rules in .dinorules?

DinoAI validates rules at parse time and surfaces conflicts in the IDE, so teams can resolve contradictions before they affect code generation. For example, if your file contains both "use uppercase keywords" and "use lowercase keywords," the conflict is flagged immediately.

Does .dinorules enforcement add latency to AI response time?

Rule parsing adds negligible overhead. .dinorules is read once per session and applied during generation, with no noticeable impact on response speed. The file is typically small (under 100 lines), making parsing near-instantaneous.

Interested to Learn More?
Try Out the Free 14-Days Trial

Stop Managing Pipelines. Start Shipping Them.

Join the teams that replaced manual dbt™ workflows with agentic AI. Free to start, no credit card required.

Stop Managing Pipelines. Start Shipping Them.

Join the teams that replaced manual dbt™ workflows with agentic AI. Free to start, no credit card required.

Stop Managing Pipelines. Start Shipping Them.

Join the teams that replaced manual dbt™ workflows with agentic AI. Free to start, no credit card required.

Copyright © 2026 Paradime Labs, Inc. Made with ❤️ in San Francisco ・ London

*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.

Copyright © 2026 Paradime Labs, Inc. Made with ❤️ in San Francisco ・ London

*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.

Copyright © 2026 Paradime Labs, Inc. Made with ❤️ in San Francisco ・ London

*dbt® and dbt Core® are federally registered trademarks of dbt Labs, Inc. in the United States and various jurisdictions around the world. Paradime is not a partner of dbt Labs. All rights therein are reserved to dbt Labs. Paradime is not a product or service of or endorsed by dbt Labs, Inc.