pi-snowflake-query
Pi extension for read-only Snowflake queries via the team `claude` connection, with a specialized snowflake-analyst agent.
Package details
Install pi-snowflake-query from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-snowflake-query- Package
pi-snowflake-query- Version
0.1.0- Published
- May 20, 2026
- Downloads
- not available
- Author
- pi-porenta
- License
- MIT
- Types
- extension
- Size
- 36.1 KB
- Dependencies
- 0 dependencies · 4 peers
Pi manifest JSON
{
"extensions": [
"./snowflake-query.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
aptive-snowflake-query
Pi extension for read-only Snowflake queries via the team claude
connection plus a dbt tool that wraps the local dbt env
(run, test, build, compile, seed, snapshot, debug,
deps, parse, clean, docs-generate, run-operation, list,
source-freshness). Ships a snowflake-analyst subagent that uses
openai/gpt-5.4-mini.
The extension enforces the safety rules from the dbt repo's CLAUDE.md:
- Every Snowflake query runs through
snow sql -c claude(the connection is hard-defaulted; override only withSNOWFLAKE_CONNECTION). - Only one SQL statement per
snowflake_querycall. No;-chained DDL/DML smuggling. - The first SQL keyword must be one of
SELECT,WITH,SHOW,DESC,DESCRIBE,EXPLAIN,LIST. Anything else is rejected before exec. - A
tool_callgate blocks directbashinvocations ofsnow sqlthat don't use the configured connection or that look destructive. dbt --full-refreshis opt-in and is refused when the selector mentions raw tables (matches the "never full-refresh raw tables" rule — those models permanently delete their S3 source files).- All tool output is truncated; the full payload is written to a temp file when it exceeds the default size/line limits.
Install
Bundled with this repo. To run it as a one-off extension:
pi -e extensions/snowflake-query/snowflake-query.ts
To wire it into the standard team runtime, add the same -e flag to
bin/pi-team.sh or bin/pi-safe.sh.
To install as a package elsewhere:
pi install npm:aptive-snowflake-query
Requirements
- Snowflake CLI (
snow) installed and on$PATH. Verify withsnow --version. - A
claudeconnection configured in~/.snowflake/config.toml(or whatever name you set viaSNOWFLAKE_CONNECTION). The connection should be scoped to a role with read-only privileges. - For the
dbttool: eitherdbton$PATH(with your virtualenv active), or a wrapper script such as./.claude/tools/dbt-run.shthat activates the env. PointDBT_BINat whichever you use.
Configuration
| Env var | Default | Purpose |
|---|---|---|
SNOWFLAKE_CONNECTION |
claude |
Connection name passed to snow sql -c. |
SNOW_CLI_BIN |
snow |
Override the snow CLI binary (e.g. an absolute path). |
SNOWFLAKE_QUERY_TIMEOUT_MS |
120000 |
Per-query timeout in ms. Hard ceiling is 600000 ms (10 min). |
DBT_BIN |
dbt |
Path to the dbt binary or a wrapper script that activates the venv. |
DBT_PROJECT_DIR |
process cwd |
Working directory used for dbt invocations. |
DBT_TIMEOUT_MS |
1800000 |
Per-invocation dbt timeout in ms. Hard ceiling is 3600000 ms (1 hour). |
Tools
snowflake_query— Run a single read-only SQL statement. Parameters:query(string, required): the SQL.database,schema,warehouse(string, optional): passed tosnow sqlto override the connection profile defaults.format(json|csv|table, optional): output format. Defaultjson.timeoutMs(integer, optional): per-call timeout. Capped at 10 min.
snowflake_describe— Convenience wrapper aroundDESC TABLE <name>. Use this before issuing a SELECT to avoid wasted warehouse resumes.dbt— Run a dbt subcommand against the configured project. Parameters:command(enum, required):run,test,build,compile,seed,snapshot,debug,deps,parse,clean,docs-generate,run-operation,list,source-freshness.select,exclude(string, optional): selectors.target(dev|prod, optional): profiles.yml target.fullRefresh(boolean, optional): pass--full-refresh. Refused when the selector mentions raw tables.vars(string, optional): YAML/JSON passed verbatim to--vars.operation,operationArgs(string, optional): required whencommandisrun-operation.timeoutMs(integer, optional): per-invocation timeout. Default 30 min, capped at 1 hour.
Commands
/snowflake <SQL>— Ask Pi to run a read-only query for you viasnowflake_querywithout composing a full prompt./snowflake-conn— Print the currently configured Snowflake + dbt context (connection, binaries, working dir, timeouts)./dbt <args>— Ask Pi to run a dbt command via thedbttool (e.g./dbt run --select tag:Aspyn).
Specialized agent: snowflake-analyst
A read-only persona pairs naturally with these tools. The agent definition is single-sourced at:
.pi/agents/snowflake-analyst.md
That's the canonical path the team's launchers (bin/pi-team.sh,
bin/pi-safe.sh) already pick up. The package itself does not ship a
duplicate copy.
Key frontmatter:
name: snowflake-analyst
tools: read, grep, find, ls, bash, snowflake_query, snowflake_describe, dbt
model: openai/gpt-5.4-mini
systemPromptMode: replace
The persona's job is to inspect Snowflake data, validate dbt model
outputs, run targeted dbt compile/dbt test checks, and debug
transformations — never to full-refresh raw tables or run destructive
SQL.
Model availability: the extension itself doesn't pin a model; the agent frontmatter does. If your Pi install doesn't expose
openai/gpt-5.4-mini, update themodel:line in the agent file to a model your providers actually serve (e.g.openai/gpt-5.5).
Try it
> /snowflake-conn
Snowflake connection: `claude` ... dbt binary: `dbt` ...
> Use snowflake_describe on analytics.dbt.model_aspyn_customers
> Then: SELECT count(*) FROM analytics.dbt.model_aspyn_customers LIMIT 10
> /dbt compile --select model_aspyn_customers
> /dbt test --select model_aspyn_customers --target dev
Security
- The extension executes the local
snowCLI as a child process. It inherits the same credentials and permissions you have configured for theclaudeconnection. - The read-only gate is a defense-in-depth check, not a substitute for a
least-privilege Snowflake role. Always grant the
claudeconnection the minimum role required. - The
tool_callgate only inspectsbashcalls that matchsnow sql. Other shells (e.g. invoking SQL through Python) are not intercepted. - Tool output is truncated to keep the LLM context bounded. The full
payload is written to a temp file under
os.tmpdir(); clean those up periodically.
Development
npm run typecheck --prefix extensions/snowflake-query
npm run test --prefix extensions/snowflake-query
npm run pack:dry-run --prefix extensions/snowflake-query
pi -e extensions/snowflake-query/snowflake-query.ts
The unit tests cover the read-only SQL gate (_shared/sql-gate.ts) and
run via node --test after a tsc step into .tmp-test/, mirroring the
extensions/verifier test harness.