'Configure Snowflake local development with testing, mocking, and fast iteration. Use when setting up dev environment, writing tests against Snowflake, or establishing a fast iteration cycle with SnowSQL and dev warehouses. Trigger with phrases like \"snowflake dev setup\", \"snowflake local development\", \"snowflake dev environment\", \"develop with snowflake\", \"snowflake testing\". '
Scanned 9/12/2026
Install to Claude Code
npx -y skills add thedixitjain/the-mega-skill-library --skill snowflake-local-dev-loop --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Snowflake Local Dev Loop?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/thedixitjain-snowflake-local-dev-loop)More formats (shields.io, HTML) on the badges page.
---
name: snowflake-local-dev-loop
description: "'Configure Snowflake local development with testing, mocking, and fast iteration. Use when setting up dev environment, writing tests against Snowflake, or establishing a fast iteration cycle with SnowSQL and dev warehouses. Trigger with phrases like \"snowflake dev setup\", \"snowflake local development\", \"snowflake dev environment\", \"develop with snowflake\", \"snowflake testing\". '"
allowed-tools: "Read, Write, Edit, Bash(npm:*), Bash(pnpm:*), Grep"
category: backend-and-data
source_repo: jeremylongshore/claude-code-plugins-plus-skills
source_path: "plugins/saas-packs/snowflake-pack/skills/snowflake-local-dev-loop/SKILL.md"
source_url: https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/HEAD/plugins/saas-packs/snowflake-pack/skills/snowflake-local-dev-loop/SKILL.md
---
# Snowflake Local Dev Loop
## Overview
Set up a fast, reproducible local development workflow for Snowflake with separate dev warehouses, mocked tests, and SnowSQL for rapid iteration.
## Prerequisites
- Completed `snowflake-install-auth` setup
- Node.js 18+ or Python 3.9+
- A dedicated dev warehouse (e.g., `DEV_WH_XS`) with auto-suspend
## Instructions
### Step 1: Create Dev-Specific Snowflake Objects
```sql
-- Run once to set up isolated dev environment
CREATE WAREHOUSE IF NOT EXISTS DEV_WH_XS
WAREHOUSE_SIZE = 'XSMALL'
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE
INITIALLY_SUSPENDED = TRUE;
CREATE DATABASE IF NOT EXISTS DEV_DB;
CREATE SCHEMA IF NOT EXISTS DEV_DB.SANDBOX;
-- Grant to dev role
GRANT USAGE ON WAREHOUSE DEV_WH_XS TO ROLE DEV_ROLE;
GRANT ALL ON DATABASE DEV_DB TO ROLE DEV_ROLE;
```
### Step 2: Project Structure
```
my-snowflake-project/
├── src/
│ ├── snowflake/
│ │ ├── connection.ts # Connection wrapper with connectAsync
│ │ ├── queries.ts # Typed query functions
│ │ └── types.ts # Row type definitions
│ └── index.ts
├── tests/
│ ├── unit/
│ │ └── queries.test.ts # Mocked — no Snowflake needed
│ └── integration/
│ └── snowflake.test.ts # Requires SNOWFLAKE_* env vars
├── sql/
│ ├── migrations/ # Versioned DDL scripts
│ │ ├── V001__create_users.sql
│ │ └── V002__add_orders.sql
│ └── seeds/
│ └── dev-data.sql # Sample data for dev
├── .env.local # Local secrets (git-ignored)
├── .env.example # Template for team
└── package.json
```
### Step 3: Connection Wrapper with Async/Await
```typescript
// src/snowflake/connection.ts
import snowflake from 'snowflake-sdk';
// Enable promise-based API
snowflake.configure({ logLevel: 'WARN' });
export function createSnowflakeConnection() {
return snowflake.createConnection({
account: process.env.SNOWFLAKE_ACCOUNT!,
username: process.env.SNOWFLAKE_USER!,
password: process.env.SNOWFLAKE_PASSWORD!,
warehouse: process.env.SNOWFLAKE_WAREHOUSE || 'DEV_WH_XS',
database: process.env.SNOWFLAKE_DATABASE || 'DEV_DB',
schema: process.env.SNOWFLAKE_SCHEMA || 'SANDBOX',
role: process.env.SNOWFLAKE_ROLE || 'DEV_ROLE',
});
}
// Promise wrapper for connection.execute
export function executeQuery(
conn: snowflake.Connection,
sqlText: string,
binds?: any[]
): Promise<any[]> {
return new Promise((resolve, reject) => {
conn.execute({
sqlText,
binds,
complete: (err, stmt, rows) => {
if (err) reject(err);
else resolve(rows || []);
},
});
});
}
// Promise wrapper for connect
export function connectAsync(
conn: snowflake.Connection
): Promise<snowflake.Connection> {
return new Promise((resolve, reject) => {
conn.connect((err, conn) => {
if (err) reject(err);
else resolve(conn);
});
});
}
```
### Step 4: Unit Tests with Mocked Snowflake
```typescript
// tests/unit/queries.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
// Mock the snowflake-sdk module
vi.mock('snowflake-sdk', () => ({
default: {
configure: vi.fn(),
createConnection: vi.fn(() => ({
connect: vi.fn((cb) => cb(null, { getId: () => 'mock-id' })),
execute: vi.fn(({ sqlText, complete }) => {
// Return mock data based on query
if (sqlText.includes('CURRENT_WAREHOUSE')) {
complete(null, {}, [{ WAREHOUSE: 'DEV_WH_XS' }]);
} else if (sqlText.includes('SELECT')) {
complete(null, {}, [
{ ID: 1, NAME: 'Alice' },
{ ID: 2, NAME: 'Bob' },
]);
} else {
complete(null, { getNumUpdatedRows: () => 1 }, []);
}
}),
destroy: vi.fn((cb) => cb(null)),
})),
},
}));
import { createSnowflakeConnection, executeQuery, connectAsync } from '../../src/snowflake/connection';
describe('Snowflake Queries', () => {
it('should connect and execute a query', async () => {
const conn = createSnowflakeConnection();
await connectAsync(conn);
const rows = await executeQuery(conn, 'SELECT * FROM USERS');
expect(rows).toHaveLength(2);
expect(rows[0].NAME).toBe('Alice');
});
});
```
### Step 5: Integration Tests (Against Real Snowflake)
```typescript
// tests/integration/snowflake.test.ts
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { createSnowflakeConnection, connectAsync, executeQuery } from '../../src/snowflake/connection';
describe.skipIf(!process.env.SNOWFLAKE_ACCOUNT)('Snowflake Integration', () => {
let conn: any;
beforeAll(async () => {
conn = createSnowflakeConnection();
await connectAsync(conn);
// Create temp table for test isolation
await executeQuery(conn, `
CREATE TEMPORARY TABLE test_users (
id INTEGER AUTOINCREMENT, name VARCHAR(100)
)
`);
});
afterAll(async () => {
conn?.destroy(() => {});
});
it('should insert and query data', async () => {
await executeQuery(conn,
'INSERT INTO test_users (name) VALUES (?)', ['TestUser']
);
const rows = await executeQuery(conn, 'SELECT * FROM test_users');
expect(rows.length).toBeGreaterThan(0);
expect(rows[0].NAME).toBe('TestUser');
});
});
```
### Step 6: SnowSQL for Quick Iteration
```bash
# Install SnowSQL CLI
brew install --cask snowflake-snowsql # macOS
# Configure named connection
cat >> ~/.snowsql/config << 'EOF'
[connections.dev]
accountname = myorg-myaccount
username = my_user
dbname = DEV_DB
schemaname = SANDBOX
warehousename = DEV_WH_XS
rolename = DEV_ROLE
EOF
# Quick queries
snowsql -c dev -q "SELECT COUNT(*) FROM my_table"
# Run migration scripts
snowsql -c dev -f sql/migrations/V001__create_users.sql
```
## Error Handling
| Error | Cause | Solution |
|-------|-------|----------|
| `000606: No active warehouse` | Dev warehouse suspended | Set `AUTO_RESUME = TRUE` on warehouse |
| `Module not found: snowflake-sdk` | Not installed | Run `npm install snowflake-sdk` |
| `Tests timeout` | Warehouse resuming from suspend | Increase test timeout to 30s, or pre-warm |
| `002003: Object does not exist` | Wrong database/schema context | Check `.env.local` DB and SCHEMA values |
## Resources
- [Node.js Driver Options](https://docs.snowflake.com/en/developer-guide/node-js/nodejs-driver-options)
- [Vitest Documentation](https://vitest.dev/)
- [SnowSQL Reference](https://docs.snowflake.com/en/user-guide/snowsql)
## Next Steps
See `snowflake-sdk-patterns` for production-ready code patterns.
---
**Source:** [`jeremylongshore/claude-code-plugins-plus-skills`](https://github.com/jeremylongshore/claude-code-plugins-plus-skills) → `plugins/saas-packs/snowflake-pack/skills/snowflake-local-dev-loop/SKILL.md`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!