Unleak
Use unleak for database questions only when the current project has an unleak/ folder. Unleak reduces leakage risk; it is not a sandbox.
Rules
- Never read or edit
unleak/local/db-conf.json. - Never read ADC source files.
- Never edit
unleak/scripts/**,unleak/local/schema/**, orunleak/local/active-policies/**. - Never run
activate-policy.mjs; only suggest the manual command with!node. - Never use raw database CLIs when
unleakis configured. - Do not query until schema and an active policy exist.
- When schema and an active policy already exist, answer normal data-inspection requests by querying approved data only. Do not propose, validate, activate, or re-create policy unless the user explicitly asks to set up or update policy.
- Prefer inline SQL with
query.mjs --sqlfor normal queries. Do not create project-visible query files like./query.sqlfor routine analysis. - Create a SQL file only when the query is very complex. Put those files under
unleak/local/queries/in the skill local state, not in the user's project surface. - Treat Claude permissions as guardrails, not a complete sandbox.
- Keep the user's current project directory as the working directory. Relative paths must continue to work for the user.
Workflow
Run scripts from the user's current project directory, replacing .claude/skills/unleak with the actual unleak/ folder path.
Important cwd rule:
- Do not leave the shell inside the Unleak skill root after installing dependencies.
- Prefer
npm install --prefix .claude/skills/unleakso the working directory stays at the project root. - If you must change directories to install dependencies, immediately return to the original project directory before retrying scripts or giving the user any relative-path commands.
- Check readiness:
node .claude/skills/unleak/scripts/check-readiness.mjsIf the output reportsDEPENDENCIES_NOT_INSTALLEDor suggestsnpm install, run:npm install --prefix .claude/skills/unleakThen retry the same readiness command from the original project directory and continue. - List safe connections:
node .claude/skills/unleak/scripts/list-connections.mjsIf the user asked to inspect, analyze, query, or find patterns in data and the requested connection already has schema and an active policy, skip setup and policy work. Write focused SELECT queries and run:node .claude/skills/unleak/scripts/query.mjs --connection <name> --sql "SELECT ..."Continue iterating with more SELECT queries until the user's data question is answered. If a query is too complex for inline SQL, create it under.claude/skills/unleak/local/queries/<short-name>.sqland run:node .claude/skills/unleak/scripts/query.mjs --connection <name> --file .claude/skills/unleak/local/queries/<short-name>.sqlOnly continue to setup steps 3-12 when config, schema, or active policy is missing, or when the user explicitly asks to set up, propose, validate, activate, or update policy. - If config is missing, do not read or create
unleak/local/db-conf.json. Ask the user to run:node .claude/skills/unleak/scripts/init-config.mjs - Ask the user to edit
unleak/local/db-conf.jsonmanually:- Set a random
hmacSecret. - Keep and configure only the connections they need.
- For SQLite, set the database file path.
- For Postgres, set host, port, dbname, username, and password.
- For BigQuery, users may run
gcloud auth application-default login, then manually paste ADC JSON intocredentials.adcand setcredentials.projectId. Service account JSON is supported for advanced or CI use.
- Set a random
- When the user says the config is saved, rerun:
node .claude/skills/unleak/scripts/list-connections.mjs - Install deny rules if needed:
node .claude/skills/unleak/scripts/install-claude-settings.mjs - Dump schema:
node .claude/skills/unleak/scripts/dump-schema.mjs - Propose policy:
node .claude/skills/unleak/scripts/propose-policy.mjs - Read schema and proposed policy files. Briefly explain policy recommendations.
- Edit only files under
./unleak-policy-review/*.policy.proposed.json. - Validate:
node .claude/skills/unleak/scripts/validate-policy.mjs - Ask the user to activate manually:
!node .claude/skills/unleak/scripts/activate-policy.mjs ./unleak-policy-review/<connection>.policy.proposed.json - Query approved data:
node .claude/skills/unleak/scripts/query.mjs --connection <name> --sql "SELECT ..."For BigQuery, include dataset schema:node .claude/skills/unleak/scripts/query.mjs --connection <name> --schema <dataset> --sql "SELECT ..."
Initialized Query Playbook
When a schema and active policy exist for the requested connection, optimize for valid queries:
- Read the schema file and active policy for that connection before writing analysis SQL:
.claude/skills/unleak/local/schema/<connection>.schema.json.claude/skills/unleak/local/active-policies/<connection>.json
- Make a quick allowed-field map:
- objects with
objectPolicy: "enabled" - columns with policy
visible,masked,hashed, orjoinable - columns with policy
visibleonly
- objects with
- Build queries from this map, not from guessed database knowledge.
- For first-pass exploration, prefer simple one-table summaries:
COUNT(*), visible categorical counts, visible numericMIN/MAX/AVG/SUM, and visible date buckets. - Avoid
UNIONfor table overviews. Run simple count queries separately instead. - Avoid parallel or chained query batches until each query shape has passed once. One failed query can cancel useful follow-up work.
- For non-trivial queries, run
--dry-runfirst, then run the same SQL without--dry-runafter it validates. - For BigQuery, always use local table names only, such as
FROM ordersorJOIN customers c. Do not use fully qualified names, dataset-qualified names, wildcard tables, decorators, or system-time queries. BigQuery dry-run cost checks run automatically.
Policy-aware SQL rules:
WHERE,HAVING,ORDER BY, scalar expressions, and aggregate expressions may reference only columns with the matching capability. Without explicitcapabilities, this keeps the legacy rule: onlyvisiblecolumns are allowed.GROUP BYmay reference any column policy by default. Grouped protected values are still transformed or hidden according to their output policy.- Direct
SELECTmay include non-hidden columns, but protected columns (masked,hashed,joinable) should not be used in filters, sorts, calculations, or aggregate expressions. - Join conditions may use equality between
visibleorjoinablecolumns only. - Every derived expression must have an explicit alias, e.g.
COUNT(*) AS cnt. ORDER BYmay use output aliases or direct sortable columns. Do not use ordinals or raw expressions.- Prefer qualified column names in joins, e.g.
t.company_id = lc.company_id. - If validation fails, read the error code and adjust the SQL to use visible columns or simpler direct selections. Do not respond by proposing a new policy unless the user asked to update policy.
Column policy handling:
visible: Safe for normal analysis. May be selected, filtered, grouped, sorted, joined, and used in expressions or aggregates.masked: May be selected directly when useful for display or grouped counts, but the output is transformed. Do not use it for filters, sorting, joins, expressions, or aggregates.hashed: May be selected directly for pseudonymous display, local comparison, or grouped counts, but the output is transformed. Do not use it for filters, sorting, joins, expressions, or aggregates.joinable: Intended for equality joins, direct pseudonymous selection, and grouped counts. May be used inON a.col = b.colwhen both sides arevisibleorjoinable. Do not filter, sort, aggregate, or calculate with it.hidden: May be used only inGROUP BYwhen needed for counts. Never select it or reference it elsewhere.disabledobject: Never query it.
Capability overrides:
- Policies may add
capabilitiesper column to allow analysis use without changing output transformation. - Valid capabilities:
select,filter,group,sort,join,aggregate,expression. - Example: a hashed
account_idcan use["select", "join", "group"]for pseudonymous investigation, or addfilter/sortonly when policy owners explicitly allow that workflow. - Hidden columns may only declare
group.
Policy Updates
Treat an active policy as initialized state. For prompts like "inspect data", "find patterns", "analyze this connection", or "run a SELECT", use the active policy and focus on queries. Do not refresh schema, propose a replacement policy, edit proposed policies, validate proposals, or ask for activation just because the user requested analysis.
Policy can be updated only when the user explicitly asks to update, revise, expand, tighten, regenerate, or re-activate policy. In that case, run the relevant setup/policy steps above and keep edits limited to ./unleak-policy-review/*.policy.proposed.json.