Explore Lakehouse
Use bq CLI to explore the BigQuery lakehouse for this project.
Environment
Resolve connection details from env vars before running any command:
echo "Project: $GOOGLE_CLOUD_PROJECT"
echo "Dataset: $REVOS_BQ_DATASET"
$GOOGLE_CLOUD_PROJECT — BQ project ID
$REVOS_BQ_DATASET — default dataset (may be overridden by user)
INFORMATION_SCHEMA queries: omit --location flag — use plain bq query --nouse_legacy_sql
Commands
List tables in the org's dataset:
bq ls $REVOS_BQ_DATASET
List all datasets in the project (only if the user explicitly asks):
bq ls --project_id=$GOOGLE_CLOUD_PROJECT
Inspect a table schema (filter out internal columns):
bq show --schema --format=prettyjson $REVOS_BQ_DATASET.<table> | python3 -c "
import json, sys
cols = json.load(sys.stdin)
names = [c['name'] for c in cols if not c['name'].startswith('_airbyte')]
print('\n'.join(names))
"
Preview sample rows:
bq head -n 5 $REVOS_BQ_DATASET.<table>
Get row counts for a list of tables:
for table in table1 table2 table3; do
echo -n "$table: "
bq query --nouse_legacy_sql --format=csv \
"SELECT COUNT(*) FROM \`$GOOGLE_CLOUD_PROJECT.$REVOS_BQ_DATASET.$table\`" 2>/dev/null | tail -1
done
Check null rates on a set of columns:
bq query --nouse_legacy_sql "
SELECT
COUNTIF(col1 IS NULL) AS col1_null,
COUNTIF(col2 IS NULL) AS col2_null,
COUNT(*) AS total
FROM \`$GOOGLE_CLOUD_PROJECT.$REVOS_BQ_DATASET.<table>\`
"
Workflows
"What's in my database?" / general overview
- List tables in the org's dataset:
bq ls $REVOS_BQ_DATASET
- If the dataset is empty (no tables), tell the user:
- They can add data sources by running
revos sources create to open the RevOS UI
- They can view existing sources with
revos sources list
- Stop here — no further exploration is possible without data
- Infer the data source and domain from table name prefixes (e.g.
salesforce_*, stripe_*, hubspot_*)
- Group tables by source/domain
- Return: sources found, table count per source, table types (TABLE/VIEW), one-line description per group
"What layer is this data?" / bronze–silver–gold assessment
- Check dbt model folders:
find dbt/models -type f | sort
- If folders contain only
.gitkeep → that layer hasn't been built yet
- Assess the tables themselves:
- Bronze indicators: raw source-prefixed names, many flat columns with source-system naming (e.g.
properties_*, fields_*), no aggregations, no joins visible in schema
- Silver indicators: cleaned column names, deduplicated, conformed types,
_id foreign keys
- Gold indicators: aggregated metrics, wide fact tables, business-named columns (
arr, churn_rate, ltv)
- Report which layers exist and which are missing
"Is data complete?" / data quality check
- Get all tables:
bq ls <dataset>
- For each table, fetch its schema to discover actual column names
- Identify the business-critical columns from the schema — look for:
- Identity/key columns: anything named
id, *_id, email, name
- Date columns:
created_at, *_date, *_at
- Relationship columns: foreign keys linking to other objects
- Core metric columns: amounts, statuses, stages, owner assignments
- Run a single
COUNTIF(col IS NULL) query per table covering those columns
- Where a source uses an
archived / is_deleted flag, filter it out: WHERE archived = false OR archived IS NULL
- Present results per table:
| Field |
Nulls |
% Missing |
Status |
| ... |
... |
...% |
✅ / ⚠️ / ❌ |
Status thresholds: ✅ < 5% · ⚠️ 5–50% · ❌ > 50%
- Summarise findings: which tables are well-populated, which have critical gaps, and what that means for downstream use
"What's in a specific table?"
bq show --schema — get full column list (omit _airbyte_* columns)
SELECT COUNT(*) — row count
bq head -n 5 — sample rows
- Identify and highlight the most important business columns from the schema
Output rules
- Never mention Airbyte — it is an internal ETL mechanism invisible to users
- Do not reference
_airbyte_* columns by name or explain their origin; omit them from schema summaries
- Describe data freshness neutrally: "updated daily" not "partitioned on
_airbyte_extracted_at"
- Do not use phrases like "via Airbyte", "Airbyte's flat-column pattern", or "Airbyte artifact"
- Always discover table structure dynamically from the schema — never assume column names from a previous session
- Group output by integration source when listing many tables
- Note small row counts (< 100 rows) as a possible indicator of sandbox or test data
1---2name: explore-lakehouse3description: Inspect the RevOS BigQuery lakehouse: list datasets and tables, introspect table schemas and column types, preview sample rows, assess data layers (bronze/silver/gold), and check data completeness and null rates. Required companion skill for create-dbt-transformations and create-cubes — load before generating dbt models or cube definitions to introspect warehouse columns and types. Use when asked to: explore the lakehouse, list BigQuery tables, inspect a table schema, preview data, check raw source tables, assess data quality, check null rates, understand available data, or perform BigQuery schema introspection.4---56# Explore Lakehouse78Use `bq` CLI to explore the BigQuery lakehouse for this project.910## Environment1112Resolve connection details from env vars before running any command:1314```bash15echo "Project: $GOOGLE_CLOUD_PROJECT"16echo "Dataset: $REVOS_BQ_DATASET"17```1819- `$GOOGLE_CLOUD_PROJECT` — BQ project ID20- `$REVOS_BQ_DATASET` — default dataset (may be overridden by user)21- `INFORMATION_SCHEMA` queries: omit `--location` flag — use plain `bq query --nouse_legacy_sql`2223## Commands2425List tables in the org's dataset:2627```bash28bq ls $REVOS_BQ_DATASET29```3031List all datasets in the project (only if the user explicitly asks):3233```bash34bq ls --project_id=$GOOGLE_CLOUD_PROJECT35```3637Inspect a table schema (filter out internal columns):3839```bash40bq show --schema --format=prettyjson $REVOS_BQ_DATASET.<table> | python3 -c "41import json, sys42cols = json.load(sys.stdin)43names = [c['name'] for c in cols if not c['name'].startswith('_airbyte')]44print('\n'.join(names))45"46```4748Preview sample rows:4950```bash51bq head -n 5 $REVOS_BQ_DATASET.<table>52```5354Get row counts for a list of tables:5556```bash57for table in table1 table2 table3; do58 echo -n "$table: "59 bq query --nouse_legacy_sql --format=csv \60 "SELECT COUNT(*) FROM \`$GOOGLE_CLOUD_PROJECT.$REVOS_BQ_DATASET.$table\`" 2>/dev/null | tail -161done62```6364Check null rates on a set of columns:6566```bash67bq query --nouse_legacy_sql "68SELECT69 COUNTIF(col1 IS NULL) AS col1_null,70 COUNTIF(col2 IS NULL) AS col2_null,71 COUNT(*) AS total72FROM \`$GOOGLE_CLOUD_PROJECT.$REVOS_BQ_DATASET.<table>\`73"74```7576## Workflows7778### "What's in my database?" / general overview79801. List tables in the org's dataset: `bq ls $REVOS_BQ_DATASET`812. If the dataset is empty (no tables), tell the user:82 - They can add data sources by running `revos sources create` to open the RevOS UI83 - They can view existing sources with `revos sources list`84 - Stop here — no further exploration is possible without data853. Infer the data source and domain from table name prefixes (e.g. `salesforce_*`, `stripe_*`, `hubspot_*`)864. Group tables by source/domain875. Return: sources found, table count per source, table types (TABLE/VIEW), one-line description per group8889### "What layer is this data?" / bronze–silver–gold assessment90911. Check dbt model folders: `find dbt/models -type f | sort`922. If folders contain only `.gitkeep` → that layer hasn't been built yet933. Assess the tables themselves:94 - **Bronze indicators:** raw source-prefixed names, many flat columns with source-system naming (e.g. `properties_*`, `fields_*`), no aggregations, no joins visible in schema95 - **Silver indicators:** cleaned column names, deduplicated, conformed types, `_id` foreign keys96 - **Gold indicators:** aggregated metrics, wide fact tables, business-named columns (`arr`, `churn_rate`, `ltv`)974. Report which layers exist and which are missing9899### "Is data complete?" / data quality check1001011. Get all tables: `bq ls <dataset>`1022. For each table, fetch its schema to discover actual column names1033. Identify the business-critical columns from the schema — look for:104 - **Identity/key columns:** anything named `id`, `*_id`, `email`, `name`105 - **Date columns:** `created_at`, `*_date`, `*_at`106 - **Relationship columns:** foreign keys linking to other objects107 - **Core metric columns:** amounts, statuses, stages, owner assignments1084. Run a single `COUNTIF(col IS NULL)` query per table covering those columns1095. Where a source uses an `archived` / `is_deleted` flag, filter it out: `WHERE archived = false OR archived IS NULL`1106. Present results per table:111112| Field | Nulls | % Missing | Status |113| ----- | ----- | --------- | ------------ |114| ... | ... | ...% | ✅ / ⚠️ / ❌ |115116Status thresholds: ✅ < 5% · ⚠️ 5–50% · ❌ > 50%1171187. Summarise findings: which tables are well-populated, which have critical gaps, and what that means for downstream use119120### "What's in a specific table?"1211221. `bq show --schema` — get full column list (omit `_airbyte_*` columns)1232. `SELECT COUNT(*)` — row count1243. `bq head -n 5` — sample rows1254. Identify and highlight the most important business columns from the schema126127## Output rules128129- Never mention Airbyte — it is an internal ETL mechanism invisible to users130- Do not reference `_airbyte_*` columns by name or explain their origin; omit them from schema summaries131- Describe data freshness neutrally: "updated daily" not "partitioned on `_airbyte_extracted_at`"132- Do not use phrases like "via Airbyte", "Airbyte's flat-column pattern", or "Airbyte artifact"133- Always discover table structure dynamically from the schema — never assume column names from a previous session134- Group output by integration source when listing many tables135- Note small row counts (< 100 rows) as a possible indicator of sandbox or test data