This file provides guidance to AI coding agents working with code in this repository.
DJ (dbt-json) Framework is a VS Code extension that revolutionizes dbt development through a structured, JSON-first approach. Users define dbt models and sources as validated .model.json and .source.json files that automatically generate corresponding SQL and YAML configurations.
The extension provides a rich visual UI built with React, including interactive model and column lineage graphs, a visual model creation wizard, query result previews, and a data modeling canvas -- all rendered as VS Code webviews.
Key Technologies:
- TypeScript extension backend running in Node.js/VS Code extension host
- React 18 + Vite frontend for webviews (interactive lineage graphs, model wizards, data explorer)
- dbt Core integration with manifest.json parsing
- Trino CLI integration for data catalog browsing and query execution
- Lightdash CLI integration for BI dashboards
# Install dependencies
npm install
# Start all watchers (recommended for active development)
npm run dev
# Watch specific components
npm run watch:esbuild # Extension JS bundle
npm run watch:tsc # Extension TypeScript
npm run watch:web-build # Web assets (Vite build)
npm run watch:web-tsc # Web TypeScript
npm run watch:test # Tests in watch modenpm test # Run all tests
npm run watch:test # Watch mode
npm run fixtures:update # Update test fixturesnpm run compile # Compile extension TypeScript
npm run compile:web # Build web assets (Vite)
npm run vscode:prepublish # Full production build with linting
npm run package # Create .vsix packagenpm run lint # Extension only
npm run lint:web # Web only
npm run lint:all # Both extension and web
npm run lint:fix:all # Fix both
npm run format # Format all files (Prettier)
npm run format:check # Check formattingnpm run schema # Regenerate TypeScript types from JSON schemas
npm run update-test-schemas- Open project in VS Code
- Press
F5to launch Extension Development Host - Open a dbt project in the new window
- Make changes and press
Cmd+Shift+F5to reload
npm run package
code --install-extension dj-framework-*.vsixExtension Backend (src/) — TypeScript running in VS Code extension host:
- Entry point:
src/extension.tsactivates theCoderservice - Core orchestrator:
src/services/coder/index.tswires up all services - Uses ServiceLocator pattern for lazy dependency injection to avoid circular dependencies
Web Frontend (web/) — React app rendered in VS Code webviews:
- Built with Vite, outputs to
dist/web - Pages: ModelCreate, SourceCreate, Home, QueryView, ModelRun, ModelTest, LightdashPreviewManager
- Lineage views: DataExplorer (model lineage), ColumnLineage, ModelLineage
- Message-based RPC communication with extension host
- State management with Zustand stores
Shared Code (src/shared/) — Cross-environment utilities used by both backend and frontend
Services follow a layered architecture:
VS Code Commands & Views (UI Layer)
↓
Api Router (Message Bus) - src/services/api.ts
↓
Domain Services:
• Framework (src/services/framework/index.ts) - JSON↔SQL/YAML sync
• Dbt (src/services/dbt.ts) - manifest parsing, tree views
• Trino (src/services/trino.ts) - query execution, catalog browsing
• DataExplorer (src/services/dataExplorer.ts) - model lineage graph
• ColumnLineage (src/services/columnLineage.ts) - column-level lineage
• ModelLineage (src/services/modelLineage.ts) - model-level lineage
• Lightdash (src/services/lightdash/index.ts) - BI integration
↓
Shared Utilities & Types (src/shared/)
ServiceLocator Pattern (src/services/ServiceLocator.ts):
- Breaks circular dependencies between services
- Lazy instantiation on first access via factory registration
- Type-safe access via
SERVICE_NAMESconstants - Example:
locator.register('dbt', () => new Dbt(locator.get('logger')));
const dbt = locator.get<Dbt>(SERVICE_NAMES.Dbt);Handler Pattern:
- Large services split into specialized handlers
- Framework service uses handlers in
src/services/framework/handlers/: UIHandlers, ModelDataHandlers, ModelCrudHandlers, ColumnLineageHandlers, SourceHandlers, PreferencesHandlers
Flow:
.model.json (user-editable, JSON Schema validated)
↓
Framework.handleJsonSync() triggers after debounce (configurable via dj.syncDebounceMs)
↓
SyncEngine orchestration (src/services/sync/SyncEngine.ts):
1. Discovery - scan all .model.json files
2. Dependency Resolution - build dependency graph (dependencyGraph.ts)
3. Validation - validate against schemas (ValidationService.ts)
4. Processing - ModelProcessor & SourceProcessor in dependency order
5. Execution - generate and write SQL/YAML files (fileOperations.ts)
↓
.sql + .yml files (auto-generated, read-only)
Key Points:
- JSON Schema Validation using Ajv with 93 schemas in
schemas/ - Hash-based caching (
cacheManager.ts) to skip unchanged files - Batch updates to prevent VS Code API overload
- Rename detection (
RenameHandler.ts) tracks old→new file pairs - Manifest management (
ManifestManager.ts) for dbt manifest parsing - Sync queue (
SyncQueue.ts) for ordered processing
Each model has a type field validated by JSON schema:
Staging (3 types):
stg_select_source— Select from Trino source tablesstg_union_sources— Union multiple sourcesstg_select_model— Transform staging data
Intermediate (6 types):
int_select_model— Aggregations and business logicint_join_models— Join multiple modelsint_join_column— Unnest arrays/flatten complex dataint_union_models— Union processed modelsint_lookback_model— Trailing time window analysisint_rollup_model— Roll up to higher time intervals
Mart (2 types):
mart_select_model— Analytics-ready datasetsmart_join_models— Comprehensive 360-degree views
Each type has its own schema file: schemas/model.type.*.schema.json
Dbt Service (src/services/dbt.ts):
- Discovers dbt projects by scanning for
dbt_project.yml - Parses
target/manifest.jsonto build in-memory maps:models: Map<string, DbtModel>— all dbt models with dependenciessources: Map<string, DbtSource>— all dbt sourcesmacros: Map<string, DbtMacro>— all dbt macrosprojects: Map<string, DbtProject>— all dbt projects
- Executes dbt commands via Python virtual environment (configured in
dj.pythonVenvPath) - Provides tree view data for VS Code sidebar
Python Integration:
const env = buildProcessEnv({ venv: '.venv' }); // Uses configured venv
spawn('dbt', ['compile', '--select', model], { env });Trino Service (src/services/trino.ts):
- Executes SQL queries via Trino CLI subprocess
- Browses catalogs/schemas/tables/columns for source creation
- Provides query results to Data Explorer
- Configured via environment variables:
TRINO_HOST,TRINO_PORT,TRINO_USERNAME,TRINO_CATALOG,TRINO_SCHEMA - Falls back to VS Code setting
dj.trinoPath
Message-based RPC between React webviews and extension host:
// Webview sends (web/src/):
api.send({ type: 'framework-model-create', request: { projectName, type, ... } });
// Extension routes (src/services/api.ts):
switch (payload.type) {
case 'framework-model-create': return framework.handleApi(payload);
case 'dbt-run-model': return dbt.handleApi(payload);
// ... routes to appropriate service
}All API message types defined in src/shared/api/types.ts with full TypeScript safety.
ColumnLineageService (src/services/columnLineage.ts):
- Traces column origins and transformations across the DAG
- Analyzes SQL expressions to classify transformations:
- passthrough:
{ expr: "customer_id" } - renamed:
{ expr: "id", name: "customer_id" } - derived:
{ expr: "amount * quantity" } - aggregated:
{ expr: "SUM(revenue)" }
- passthrough:
- Expands bulk selects like
dims_from_model,all_from_model - Builds DAG rendered in webview using React Flow
ModelLineage Service (src/services/modelLineage.ts):
- Model-level dependency visualization
- Shows upstream/downstream traversal
- Uses manifest.json's dependency graph
- Renders with Dagre layout algorithm + @xyflow/react
- Layer visualization by model type (staging/intermediate/mart)
vscode-dbt-json/
├── src/
│ ├── extension.ts # Entry point - activates Coder service
│ ├── admin.ts # Platform utilities (paths, process runners)
│ ├── services/
│ │ ├── coder/ # Main orchestrator (ServiceLocator, commands, views)
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── api.ts # Message router between webviews and services
│ │ ├── ServiceLocator.ts # ServiceLocator for dependency injection
│ │ ├── framework/ # JSON↔SQL/YAML sync engine
│ │ │ ├── index.ts
│ │ │ ├── FrameworkState.ts
│ │ │ ├── handlers/ # UIHandlers, ModelCrudHandlers, etc.
│ │ │ └── utils/ # column-utils, model-utils, source-utils, sql-utils
│ │ ├── sync/ # Sync engine components
│ │ │ ├── SyncEngine.ts
│ │ │ ├── ModelProcessor.ts
│ │ │ ├── SourceProcessor.ts
│ │ │ ├── ManifestManager.ts
│ │ │ ├── ValidationService.ts
│ │ │ ├── dependencyGraph.ts
│ │ │ ├── cacheManager.ts
│ │ │ ├── fileOperations.ts
│ │ │ ├── RenameHandler.ts
│ │ │ └── SyncQueue.ts
│ │ ├── dbt.ts # dbt integration and manifest parsing
│ │ ├── trino.ts # Trino CLI integration
│ │ ├── dataExplorer.ts # Model lineage visualization
│ │ ├── modelLineage.ts # Model lineage graph
│ │ ├── columnLineage.ts # Column-level lineage
│ │ ├── lightdash/ # Lightdash BI integration
│ │ ├── agent/ # AI agent support (prompts, utils, decorators)
│ │ ├── webview/ # Webview providers and utilities
│ │ ├── modelEdit.ts # Model editing service
│ │ ├── config.ts # Configuration service
│ │ ├── djLogger.ts # Logging service
│ │ ├── statemanager.ts # State management
│ │ ├── validationErrors.ts # Custom validation functions
│ │ ├── constants.ts # Command IDs and constants
│ │ └── utils/ # fileNavigation, fileSystem, git, process, sql
│ └── shared/ # Cross-environment utilities
│ ├── api/ # API message types and routing
│ ├── dbt/ # dbt types and utilities
│ ├── framework/ # Framework types
│ ├── trino/ # Trino types and constants
│ ├── lightdash/ # Lightdash types
│ ├── modellineage/ # Model lineage types
│ ├── lineage/ # Lineage shared types
│ ├── dataexplorer/ # Data explorer types
│ ├── schema/types/ # Generated from schemas/ via `npm run schema`
│ ├── state/ # State types and constants
│ ├── types/ # Common types and config
│ ├── sql/ # SQL utilities
│ ├── web/ # Web constants
│ └── webview/ # Webview types
├── web/ # React webview frontend (Vite)
│ ├── src/
│ │ ├── pages/
│ │ │ ├── ModelCreate.tsx
│ │ │ ├── SourceCreate.tsx
│ │ │ ├── Home.tsx
│ │ │ ├── QueryView.tsx
│ │ │ ├── DataExplorer/
│ │ │ ├── ModelLineage/
│ │ │ ├── ModelRun/
│ │ │ ├── ModelTest/
│ │ │ ├── ColumnLineage/
│ │ │ └── LightdashPreviewManager/
│ │ ├── features/ # DataModeling, Lineage, ModelWizard, Tutorial
│ │ ├── context/ # React contexts (Environment, App, Trino)
│ │ ├── elements/ # Reusable React components
│ │ ├── forms/ # Form components
│ │ ├── hooks/ # Custom React hooks
│ │ ├── stores/ # Zustand stores
│ │ ├── utils/ # Utility functions
│ │ └── styles/ # CSS styles
│ └── vite.config.ts # Builds to ../dist/web
├── schemas/ # JSON Schema definitions (93 files)
│ ├── model.schema.json # Root schema (anyOf 11 model types)
│ ├── model.type.*.schema.json # 11 model type schemas
│ ├── source.schema.json # Source definition schema
│ └── column.*.schema.json # Column properties schemas
├── macros/ # dbt macros shipped with extension
├── airflow/ # Airflow DAG templates
│ ├── v2_7/
│ └── v2_10/
├── templates/ # Code templates
├── tests/ # Test files and fixtures
│ ├── fixtures/ # Test data (manifest + model files)
│ ├── update-fixtures.ts
│ └── update-test-schemas.ts
├── docs/ # Documentation
│ ├── models/ # 11 model type docs
│ ├── setup/ # Setup guides (Trino, Lightdash)
│ └── integrations/ # Integration guides
├── .github/ # GitHub workflows and actions
├── dist/ # Build output
│ ├── extension/
│ └── web/
├── CONTRIBUTING.md
├── DEVELOPMENT_SETUP.md
├── CODE_OF_CONDUCT.md
├── CHANGELOG.md
├── ROADMAP.md
└── Makefile
Extension Code (tsconfig.json):
import { log } from 'admin'; // src/admin.ts
import { Dbt } from '@services/dbt'; // src/services/dbt.ts
import { ApiMessage } from '@shared/api/types'; // src/shared/api/types.ts
import { parseModel } from '@shared/framework'; // src/shared/framework/index.tsWeb Code (web/tsconfig.json):
import { useEnvironment } from '@web/context/environment';
import { Button } from '@web/elements/Button';
import { useModelStore } from '@web/stores/useModelStore';- Target: ES2023
- Module: CommonJS for extension, ESNext for web
- Strict mode: enabled
- Paths configured for import aliases (see above)
Jest Configuration (jest.config.js):
- Preset:
ts-jest - Supports same path aliases as tsconfig.json via
moduleNameMapper - Test files:
**/*.test.ts - Ignores:
out/,dist/,.venv/
type(scope): description
Types: feat, fix, docs, style, refactor, test, chore
Scopes: extension, web, macros, schemas, scripts
- Classes:
PascalCase - Methods/variables:
camelCase - Constants:
UPPER_SNAKE_CASE - Types/interfaces:
PascalCase - Command IDs:
dj.command.*viaCOMMAND_IDconstants insrc/services/constants.ts
Important commands:
dj.command.jsonSync— Regenerate SQL/YAML from JSONdj.command.modelCreate— Open model creation wizarddj.command.modelEdit— Edit model (opens draft)dj.command.modelClone— Clone existing modeldj.command.modelCompile— Compile with dbtdj.command.modelRun— Run model with dbtdj.command.modelPreview— Preview model resultsdj.command.modelLineage— Open Data Explorerdj.command.columnLineage— Open Column Lineage paneldj.command.lightdashPreview— Start Lightdash previewdj.command.sourceCreate— Create source from Trino catalogdj.command.refreshProjects— Refresh dbt projectsdj.command.clearSyncCache— Clear JSON sync cachedj.command.testTrinoConnection— Test Trino connection
Cmd+Shift+C— Compile modelCmd+Shift+J— Jump to JSONCmd+Shift+M— Jump to Model SQLCmd+Shift+Y— Jump to YAMLCmd+Shift+L— Open Data ExplorerCmd+Enter— Preview model (when editor focused and DJ active)Cmd+'— Open target compiled SQL (when editor focused and DJ active)
Activity Bar (sidebar):
- Project Navigator — dbt project tree
- Selected Resource — current model/source details
- Query Engine — Trino connection and query history
- Actions — quick actions (create model/source)
- Edit Drafts — in-progress model edits
Panel (bottom):
- Data Explorer — model lineage graph (webview)
- Column Lineage — column-level lineage (webview)
Extension watches for changes to:
.model.json— triggers JSON sync.source.json— triggers JSON syncmanifest.json— triggers manifest reload.sql/.yml— for related updates
- User clicks "Create Model" in Actions view
- Extension opens webview with ModelCreate React component
- User fills form (project, type, group, topic, name)
- Webview sends
framework-model-createAPI message - Framework validates, generates
.model.json - JSON sync triggers and generates
.sqland.yml - Extension opens generated files in editor
- User edits
.model.jsonfile - FileSystemWatcher detects change
- Framework adds to
SyncQueue - Debounce timer (configurable via
dj.syncDebounceMs, default 1500ms) triggers sync - SyncEngine:
- Discovers dependencies from manifest
- Validates JSON against schema
- Generates SQL/YAML via processors
- Writes files in batches
- VS Code refreshes file tree
- User opens
.model.json, clicks "Column Lineage" - Extension opens Column Lineage panel (webview)
- ColumnLineageService:
- Parses model JSON
- Expands bulk selects (
dims_from_model) - Analyzes expressions (passthrough vs derived)
- Recursively traces upstream columns
- Builds DAG
- Webview renders graph with React Flow
- User clicks column to navigate to definition
- Extension logs: View → Output → "DJ"
- Log level: configurable via
dj.logLevelsetting (debug, info, warn, error) - Reload extension:
Cmd+Shift+F5in Extension Development Host - Webview debugging: Developer → Open Webview Developer Tools
- Full reload: Developer → Reload Window
- Services are lazily initialized via ServiceLocator (
src/services/ServiceLocator.ts) - Use
SERVICE_NAMESconstants for type-safe service access - Be careful with circular dependencies — use ServiceLocator to break cycles
- Handler pattern preferred for large services (see Framework service
handlers/directory) - All service API messages must be typed in
src/shared/api/types.ts
To add/modify JSON schemas:
- Edit schema files in
schemas/ - Run
npm run schemato regenerate TypeScript types - Types appear in
src/shared/schema/types/ - Update validators in Framework service if needed
- React code in
web/src/pages/ - Use
api.send()to communicate with extension host - Define message types in
src/shared/api/types.ts - Handle messages in appropriate service (via Api router)
- State management with Zustand stores in
web/src/stores/ - Reusable components in
web/src/elements/
- Extension writes files via VS Code workspace API (atomic updates)
- Batch updates to prevent API overload
- Hash-based caching to skip unchanged files
- Always use absolute paths from
admin.WORKSPACE_ROOT
| Setting | Type | Default | Description |
|---|---|---|---|
dj.pythonVenvPath |
string | — | Python virtual environment path (e.g., .venv) |
dj.trinoPath |
string | trino-cli |
Trino CLI executable path |
dj.dbtProjectNames |
array | [] |
Restrict which dbt projects to recognize |
dj.dbtMacroPath |
string | _ext_ |
Subfolder for extension-provided macros |
dj.airflowGenerateDags |
boolean | false |
Toggle Airflow DAG generation |
dj.airflowTargetVersion |
string | 2.7 |
Target Airflow version (2.7, 2.8, 2.9, 2.10) |
dj.airflowDagsPath |
string | dags/_ext_ |
Folder where extension writes Airflow DAGs |
dj.syncDebounceMs |
number | 1500 |
Debounce delay (ms) before triggering sync |
dj.logLevel |
string | info |
Logging level (debug, info, warn, error) |
dj.codingAgent |
string | — | Coding agent (github-copilot, claude-code, cline) |
dj.aiHintTag |
string | — | Standard tag for resources with AI Hints |
dj.columnLineage.autoRefresh |
boolean | true |
Auto-refresh Column Lineage on file switch |
dj.dataExplorer.autoRefresh |
boolean | false |
Auto-refresh Data Explorer on file switch |
dj.lightdashProjectPath |
string | — | Custom path to dbt project for Lightdash |
dj.lightdashProfilesPath |
string | — | Custom path to dbt profiles for Lightdash |
dj.autoGenerateTests |
object | — | (Experimental) Auto-generate tests on models |
Trino Connection:
TRINO_HOST=your-trino-host
TRINO_PORT=8080 # 443 for Starburst Galaxy
TRINO_USERNAME=your-username
TRINO_CATALOG=your-catalog
TRINO_SCHEMA=your-schemaLightdash (optional):
LIGHTDASH_URL=your-lightdash-url
LIGHTDASH_PREVIEW_NAME=your-preview-name
LIGHTDASH_PROJECT=your-project-uuid
LIGHTDASH_TRINO_HOST=host.docker.internal # Trino host override for DockerThe extension includes built-in support for AI coding agents to help users create DJ-compliant dbt models.
Project-level AGENTS.md generation: When installed in a dbt project, the extension generates an AGENTS.md file in the user's project root. This file contains DJ framework-specific instructions (model types, JSON schema structure, naming conventions, column definitions) that users can reference in their LLM workflows to generate valid .model.json and .source.json files. The generated file is tailored to the project's configuration and available models/sources.
Coding agent setting (dj.codingAgent): Users can configure which coding agent they use (github-copilot, claude-code, cline) to tailor the generated instruction files for their preferred tool.
Agent service (src/services/agent/): Contains decorators (@Prompt, @InputField, @OutputField), prompt signature classes (in prompts/), and utilities for generating agent instruction files. Prompt signatures like CreateModelSignature define structured instructions with typed inputs, which buildPromptFromDecorators() compiles into prompt text that gets written to the user's project.
- README.md — User-facing documentation and setup guide
- DEVELOPMENT_SETUP.md — Detailed development environment setup
- CONTRIBUTING.md — Contribution guidelines and code standards
- CHANGELOG.md — Release history
- ROADMAP.md — Future plans
- docs/ — Complete documentation including tutorials and examples
- docs/models/README.md — Detailed reference for all 11 model types
- docs/SETTINGS.md — Full settings reference