.claude/skills/add-warehouse-adapter/SKILL.md
# Add a Warehouse Adapter Step-by-step checklist for adding a new warehouse connection to Lightdash. Follow the Athena adapter as the canonical example (PRs #19751/#19752). The MotherDuck/DuckDB adapter is the most recent implementation. ## Layer 1: Common Types (`packages/common/`) - [ ] Add entry to `WarehouseTypes` enum in `src/types/projects.ts` - [ ] Define `CreateXxxCredentials` type with `type: WarehouseTypes.XXX` discriminant - Sensitive fields (tokens, passwords, keys) should be op
npx skillsauth add lightdash/lightdash .claude/skills/add-warehouse-adapterInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Step-by-step checklist for adding a new warehouse connection to Lightdash. Follow the Athena adapter as the canonical example (PRs #19751/#19752). The MotherDuck/DuckDB adapter is the most recent implementation.
packages/common/)WarehouseTypes enum in src/types/projects.tsCreateXxxCredentials type with type: WarehouseTypes.XXX discriminant
token?: string) — not required with empty-string sentinelXxxCredentials = Omit<CreateXxxCredentials, SensitiveCredentialsFieldNames>sensitiveCredentialsFieldNames array if not already present (tokens, passwords, keys)CreateXxxCredentials to CreateWarehouseCredentials unionXxxCredentials to WarehouseCredentials unionUserWarehouseCredentials union in src/types/userWarehouseCredentials.tsUserWarehouseCredentialsWithSecrets uniongetFieldQuoteChar() in src/utils/warehouse.tsgetAggregatedField() in src/utils/warehouse.ts handles the new adapter (may fall into existing case)src/utils/timeFrames.ts adapter config map has the new adaptersrc/compiler/translator.ts convertTimezone() has the new adapterpnpm -F common typecheck && pnpm -F common lintpackages/backend/)pnpm -F backend create-migration add_xxx_warehouse_typeup: Insert { warehouse_type: 'xxx' } into warehouse_typesdown: Delete xxx credentials and type'xxx' to warehouseTypes array in src/database/entities/warehouseCredentials.tscredentialsTarget() in src/dbt/profiles.ts (before default)
envVarReference()/envVar() pattern (not raw env var names or inline values)password: envVarReference('password') in target, [envVar('password')]: credentials.password in environmentquoteChars in src/dbt/DbtMetadataApiClient.ts has the adaptersrc/services/ProjectService/ProjectService.ts - clearSecretsFromCredentials()
token: undefined) instead of destructuring + unsafe as cast{ ...credentials, password: '' })src/services/ProjectService/ProjectService.ts - warehouse client creation switchsrc/services/ProjectService/ProjectService.ts - user credentials creation switchsrc/services/ProjectService/ProjectService.ts - getDatabaseFromWarehouseCredentials()src/models/UserWarehouseCredentials/UserWarehouseCredentialsModel.tspnpm -F backend typecheck && pnpm -F backend lintpackages/warehouses/)src/warehouseClients/XxxWarehouseClient.ts
WarehouseBaseClient<CreateXxxCredentials>XxxSqlBuilder extends WarehouseBaseSqlBuilderstreamQuery(), getCatalog(), getAllTables(), getFields() (inherited test(), runQuery(), executeAsyncQuery() work via base class — don't add no-op overrides)process.envoverrides param for alternate construction (e.g. pre-aggregate) instead of AnyType casts on readonly fieldssrc/warehouseClientFromCredentials.ts factorysrc/ssh/sshTunnel.ts (typically a no-op break for cloud warehouses)src/index.tssrc/warehouseClients/XxxWarehouseClient.test.tspnpm -F @lightdash/warehouses typecheck && pnpm -F @lightdash/warehouses testpackages/frontend/)src/components/ProjectConnection/WarehouseForms/XxxForm.tsx
AthenaForm.tsx pattern with Mantine v8 componentsXxxSchemaInput for DbtSettingsFormsrc/components/ProjectConnection/ProjectConnectFlow/Assets/WarehouseForms/defaultValues.ts (XxxDefaultValues + add to warehouseDefaultValues)WarehouseForms/validators.tsWarehouseSettingsForm.tsx (labels + forms maps)DbtSettingsForm.tsx (schema input switch)ProjectConnectFlow/utils.tsx (WarehouseTypeLabels array)UserSettings/MyWarehouseConnectionsPanel/CreateCredentialsModal.tsx (defaultCredentials)UserSettings/MyWarehouseConnectionsPanel/EditCredentialsModal.tsx (getCredentialsWithPlaceholders)UserSettings/MyWarehouseConnectionsPanel/WarehouseFormInputs.tsxpnpm -F frontend typecheck && pnpm -F frontend lintpackages/cli/)src/dbt/targets/xxx.ts
XxxTarget type matching dbt profile structurexxxSchema: JSONSchemaType<XxxTarget> for ajv validationconvertXxxSchema() functioncase 'xxx': in src/dbt/profile.ts warehouseCredentialsFromDbtTarget()src/handlers/dbt/getWarehouseClient.ts getMockCredentials()Dockerfile)dbt-xxx) to dbt venvs 1.8+ in the Dockerfile
dbt-xxx (e.g., dbt-duckdb, dbt-athena)"dbt-xxx" if the adapter has its own version scheme, or "dbt-xxx~=X.Y.0" if it tracks dbt-core versionsdbt-athena was added from 1.9+, dbt-duckdb from 1.8+examples/full-jaffle-shop-demo/)dbt/data/seeds.yml column types for the new adapter (DuckDB doesn't support jsonb, TIME, etc.)dbt/macros/ that have warehouse-specific branches (e.g. quarter_end_date.sql, casts.sql)profiles/profiles.yml for testingdbt seed --target xxx && dbt run --target xxxpnpm generate-api (regenerates routes.ts and swagger.json)pnpm generate:chart-as-code-schemapnpm check:chart-as-code-schemapnpm -F common typecheck && pnpm -F backend typecheck && pnpm -F frontend typecheck| Layer | Key File | Purpose |
|-------|----------|---------|
| Common | packages/common/src/types/projects.ts | Types, sensitive fields, unions |
| Backend | packages/backend/src/dbt/profiles.ts | dbt profile generation |
| Backend | packages/backend/src/database/entities/warehouseCredentials.ts | DB entity |
| Warehouse | packages/warehouses/src/warehouseClientFromCredentials.ts | Factory |
| Frontend | packages/frontend/src/components/ProjectConnection/WarehouseSettingsForm.tsx | Form registration |
| CLI | packages/cli/src/dbt/profile.ts | CLI target conversion |
| Docker | Dockerfile | dbt adapter pip packages per version |
02-23-feat_add_duckdb_warehouse_client_with_s3_supporttesting
Create, edit, improve, or audit AgentSkills. Use when creating a new skill from scratch or when asked to improve, review, audit, tidy up, or clean up an existing skill or SKILL.md file. Also use when editing or restructuring a skill directory (moving files to references/ or scripts/, removing stale content, validating against the AgentSkills spec). Triggers on phrases like "create a skill", "author a skill", "tidy up a skill", "improve this skill", "review the skill", "clean up the skill", "audit the skill".
testing
Host security hardening and risk-tolerance configuration for OpenClaw deployments. Use when a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure review, OpenClaw cron scheduling for periodic checks, or version status checks on a machine running OpenClaw (laptop, workstation, Pi, VPS).
testing
Create, edit, improve, or audit AgentSkills. Use when creating a new skill from scratch or when asked to improve, review, audit, tidy up, or clean up an existing skill or SKILL.md file. Also use when editing or restructuring a skill directory (moving files to references/ or scripts/, removing stale content, validating against the AgentSkills spec). Triggers on phrases like "create a skill", "author a skill", "tidy up a skill", "improve this skill", "review the skill", "clean up the skill", "audit the skill".
testing
Host security hardening and risk-tolerance configuration for OpenClaw deployments. Use when a user asks for security audits, firewall/SSH/update hardening, risk posture, exposure review, OpenClaw cron scheduling for periodic checks, or version status checks on a machine running OpenClaw (laptop, workstation, Pi, VPS).