Our company’s Snowflake data warehouse combines data from over 20 different domain websites and various apps. Most of it I have very limited knowledge about — what tables exist, what columns they have, how they join together. But recently I was tasked with getting some user subscription data out of Snowflake.
I started with the Snowflake web UI, which works fine — but it requires me clicking around, checking column names, copy-pasting queries, which is a fading pattern in this AI era. The right pattern should be me talking to Claude Code (CC) and CC does everything (or most of it). Since Claude Code is very good at using CLI tools, and Snowflake does have a CLI tool, the thought came naturally:
How to let Claude Code use Snowflake CLI?
🎯 What I Built #
By the end of this setup, I was able to just type questions in plain English and Claude would write the SQL, run it, and return the answer:
You: How many active O+ subscribers do we have right now?
Claude: [writes the SQL, runs it, returns the answer: 113,477]No switching between apps. No looking up column names. Claude Code understands the database schema, writes correct Snowflake SQL, executes the queries via CLI, and gives me the results — all without leaving the terminal.
The goal of this post is to walk you through how to set up the same thing for your own Snowflake database.
📋 Prerequisites #
- Claude Code installed (claude.com/claude-code)
- Homebrew installed (brew.sh)
- A Snowflake account with credentials (username, password, account identifier)
Part 1: Installing Snowflake CLI #
First, add the Snowflake tap to Homebrew. A “tap” is a third-party repository of Homebrew packages — this tells Homebrew where to find Snowflake’s CLI formula:
brew tap snowflakedb/snowflake-cliThen install the CLI:
brew install snowflake-cliVerify the installation:
snow --versionYou should see something like Snowflake CLI version: 3.x.x.
Part 2: Connecting to Your Snowflake Warehouse #
Step 1: Add Your Connection #
Run this command, replacing the values with your own Snowflake account details. You can get the connection details from Snowflake UI (as shown in the video).
snow connection add \
--connection-name my_connection \
--account "YOUR_ACCOUNT_ID" \
--user "YOUR_USERNAME" \
--authenticator "username_password_mfa" \
--role "YOUR_ROLE" \
--warehouse "YOUR_WAREHOUSE" \
--default \
--no-interactiveThis saves the connection to ~/.snowflake/config.toml.
⚠️ Choosing the right authenticator — this is where I spent the most time debugging. Pick the one that matches your org’s setup:
username_password_mfa— password + MFA (Duo, Okta Verify, etc.)externalbrowser— SAML SSO (Okta, Azure AD, etc.)snowflake— username/password only (no MFA)If you’re not sure, check with your Snowflake admin. Using the wrong authenticator will give you confusing errors that don’t obviously point to auth as the problem.
Step 2: Set Your Password #
The password should be provided via environment variable — don’t add it to the config file.
Per session (most secure):
export SNOWFLAKE_PASSWORD='your_password_here'Persistent (add to ~/.zshrc):
Open ~/.zshrc in your editor and add:
export SNOWFLAKE_PASSWORD='your_password_here'Then reload: source ~/.zshrc
💡 Tip: Don’t use
echoto append the password — the!character in passwords triggers zsh history expansion and will cause errors. Edit the file directly.
Step 3: Test the Connection #
snow connection testIf you’re using MFA, approve the push notification on your phone. You should see a success message.
Step 4: Fix the MFA Problem ⚡ #
This is a big one. If your account uses MFA, you’ll get a Duo/Okta push for every single query by default. This makes the CLI nearly unusable — imagine approving a push notification every time Claude wants to run a query.
The fix: ask your Snowflake admin to enable MFA token caching:
-- Admin runs this (requires ACCOUNTADMIN role):
ALTER ACCOUNT SET ALLOW_CLIENT_MFA_CACHING = TRUE;With this enabled, you approve MFA once and then get 4 hours of push-free queries. This is the single most important step for a good CLI experience.
How to check if it’s already enabled:
snow sql -q "SHOW PARAMETERS LIKE 'ALLOW_CLIENT_MFA_CACHING' IN ACCOUNT" --format jsonPart 3: Using Snowflake CLI with Claude Code #
Now that you can run snow sql from your terminal, let’s connect it to Claude Code.
Step 1: Create a Project Directory #
mkdir -p ~/Projects/snowflake
cd ~/Projects/snowflakeStep 2: Create the CLAUDE.md File #
CLAUDE.md is a file that Claude Code reads automatically when you start a session in the directory. It tells Claude about your database schema, connection details, and how to run queries.
Create a file called CLAUDE.md in your project directory with your connection info:
# Snowflake Project
## Connection
- **Connection name:** `my_connection`
- **Warehouse:** `MY_WAREHOUSE`
- **Role:** `MY_ROLE`
### Running Queries
Run queries using the Snowflake CLI with sandbox disabled
(`dangerouslyDisableSandbox: true` on the Bash tool), since the
sandbox cannot access the Snowflake config file or password:
snow sql -c my_connection -q "SELECT ..." --format json💡 Why
dangerouslyDisableSandbox? Claude Code runs commands in a sandboxed environment by default. This sandbox can’t access your Snowflake config file (~/.snowflake/config.toml) or theSNOWFLAKE_PASSWORDenvironment variable, sosnow sqlcommands will fail inside it. When Claude runs a query with the sandbox disabled, it will prompt you for permission the first time. Approve it, and subsequent queries in the same session run automatically.If you prefer more control, skip this instruction and run queries yourself using the
!prefix:! snow sql -c my_connection -q "SELECT ..." --format json
Step 3: Let Claude Explore Your Schema #
Here’s the key insight: you don’t need to manually document every table. Instead, identify a few tables you know you’ll be querying, and ask Claude to explore them for you.
Start Claude Code in your project directory:
cd ~/Projects/snowflake
claudeThen tell Claude about the tables you care about:
You: Here are some tables I use regularly:
- prd_datamart.core.subscription_metrics (subscription data)
- prd_rivt.ods_public.user_profile (user profiles)
Can you explore the schema of these tables and document them
in CLAUDE.md?Claude will run queries like DESCRIBE TABLE ... and SELECT * FROM ... LIMIT 5 to understand the column names, types, and relationships. It documents everything in your CLAUDE.md — table schemas, join keys, data types, and common patterns.
You invest a few minutes upfront, and every query after that benefits from the context.
💡 Tip: The more context you give Claude during this exploration phase, the better. Mention things like:
- “USER_ID in events is actually a UUID that joins to USER_PROFILE.UUID”
- “EVENT_PROPERTIES is a JSON column — use
:notation to extract fields”- “We have two event schemas — always UNION both”
These nuances get documented and used correctly in future queries.
What It Looks Like in Practice #
You ask questions in plain English, and Claude writes the SQL, runs it via the Snowflake CLI, and returns the results:
Simple counts:
You: How many active subscribers do we have right now?
Claude: [runs the query → 113,477]Breakdowns:
You: Break that down by payment processor.
Claude: [runs GROUP BY query → stripe: 60k, apple: 12k, google: 5k, ...]Cross-table joins:
You: Show me the 5 most recent subscribers with their email and signup source.
Claude: [joins 3 tables with correct keys → returns results]Follow-ups:
You: Can you visualize that as a chart?
Claude: [writes a Python script, generates the chart]Because Claude Code maintains conversation context, you can build on previous queries naturally — “now filter that to just US users” or “what’s the month-over-month trend?”
The CLAUDE.md schema documentation is what makes this work well. Claude knows the table names, column types, JSON extraction syntax, and join relationships — so you don’t have to remember any of it.
🛠 Tips #
-
CLAUDE.md. Ask Claude Code to explore the schema and save relevant details as JSON files, with an updated memory to remind Claude Code to refer to that schema when needed.
-
Disable the sandbox for
snowcommands. Claude Code runs in a sandbox by default, which can’t access~/.snowflake/config.tomlor yourSNOWFLAKE_PASSWORDenv var. AdddangerouslyDisableSandbox: trueinstructions in your CLAUDE.md so Claude can runsnow sqldirectly. It will still prompt you for permission the first time. -
Save large results to files. For big result sets, pipe output to JSON files that Claude can then analyze:
snow sql -c my_connection -q "SELECT ..." --format json > results.json
🔧 Troubleshooting #
“Connection not configured” error
The Snowflake CLI looks for config at ~/.snowflake/config.toml. If yours is elsewhere (e.g., ~/Library/Application Support/snowflake/config.toml), move it or specify the path: snow sql --config-file "/path/to/config.toml" ...
MFA push on every query Your admin needs to enable MFA token caching (see Part 2, Step 4 above). Without this, the server doesn’t return a cacheable token regardless of client settings.
Password not found / empty password error
Make sure SNOWFLAKE_PASSWORD is exported in the shell session where you run the query. The env var must be set in your shell profile (~/.zshrc).