From co-dev
Query, list, analyze, or investigate Firebase Crashlytics crash data. Use when the user wants to check crashes, list top crashes, investigate a crash, get stack traces, view crash trends, analyze crash data, or find crash issues. Queries Crashlytics data exported to BigQuery via the bq CLI. Supports Android, iOS, and tvOS.
npx claudepluginhub cloud-officer/claude-code-plugin-dev --plugin co-devThis skill is limited to using the following tools:
Query Firebase Crashlytics crash data exported to BigQuery. List top crashes, investigate specific issues, retrieve stack traces, and help identify fixes. Supports Android, iOS, and tvOS platforms.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Query Firebase Crashlytics crash data exported to BigQuery. List top crashes, investigate specific issues, retrieve stack traces, and help identify fixes. Supports Android, iOS, and tvOS platforms.
Prefer BigQuery MCP tools (mcp__bigquery__*) when available for executing queries. If MCP tools are not available (tool not found errors), fall back to the bq CLI.
| Operation | MCP Tool | CLI Fallback |
|---|---|---|
| Run SQL query | mcp__bigquery__query | bq query --use_legacy_sql=false --format=prettyjson "SQL" |
| List tables | mcp__bigquery__list_tables | bq ls --format=json $BQ_PROJECT:$BQ_CRASHLYTICS_DATASET |
| Get table schema | mcp__bigquery__get_table_schema | bq show --format=json $BQ_PROJECT:$BQ_CRASHLYTICS_DATASET.TABLE |
Note: Both methods require GCP authentication. The MCP server uses Application Default Credentials; the bq CLI uses gcloud auth application-default login.
This skill requires the following environment variables:
BQ_PROJECT — GCP project IDBQ_CRASHLYTICS_DATASET — BigQuery dataset name (e.g., firebase_crashlytics)BQ_CRASHLYTICS_ANDROID_TABLE — Android REALTIME table nameBQ_CRASHLYTICS_IOS_TABLE — iOS REALTIME table nameBQ_CRASHLYTICS_TVOS_TABLE — tvOS REALTIME table nameCheck that required environment variables are set:
echo "BQ_PROJECT=$BQ_PROJECT"
echo "BQ_CRASHLYTICS_DATASET=$BQ_CRASHLYTICS_DATASET"
echo "BQ_CRASHLYTICS_ANDROID_TABLE=$BQ_CRASHLYTICS_ANDROID_TABLE"
echo "BQ_CRASHLYTICS_IOS_TABLE=$BQ_CRASHLYTICS_IOS_TABLE"
echo "BQ_CRASHLYTICS_TVOS_TABLE=$BQ_CRASHLYTICS_TVOS_TABLE"
If any required variable is missing, tell the user which variables need to be set and stop.
bq query --use_legacy_sql=false --project_id="$BQ_PROJECT" "SELECT 1"
If this fails, tell the user to run gcloud auth application-default login and gcloud auth application-default set-quota-project $BQ_PROJECT.
Parse the user's request to determine:
Map platform to table environment variable:
| Platform | Table Variable |
|---|---|
| Android | $BQ_CRASHLYTICS_ANDROID_TABLE |
| iOS | $BQ_CRASHLYTICS_IOS_TABLE |
| tvOS | $BQ_CRASHLYTICS_TVOS_TABLE |
The fully qualified table name is: `$BQ_PROJECT.$BQ_CRASHLYTICS_DATASET.$TABLE_NAME`
NEVER execute a query without showing it to the user first. Display the query in a code block and briefly explain what it does.
Use bq query with --use_legacy_sql=false and --project_id="$BQ_PROJECT".
Always add --max_rows=100 to prevent huge outputs unless the user asks for more.
If the user asks about a specific crash issue, fetch detailed information:
SELECT
issue_id,
issue_title,
issue_subtitle,
blame_frame.file AS blame_file,
blame_frame.line AS blame_line,
blame_frame.symbol AS blame_symbol,
event_timestamp,
application.display_version AS app_version,
application.build_version AS build_version,
device.model AS device_model,
device.os_version AS os_version,
threads
FROM `PROJECT.DATASET.TABLE`
WHERE issue_id = 'ISSUE_ID'
ORDER BY event_timestamp DESC
LIMIT 5
When presenting deep dive results:
If a crash blame frame references a file in the current codebase:
Glob to find the file by nameRead to show the code around the blamed lineSELECT
issue_id,
issue_title,
issue_subtitle,
COUNT(*) AS crash_count,
COUNT(DISTINCT installation_uuid) AS affected_users,
MAX(event_timestamp) AS last_seen,
ANY_VALUE(application.display_version) AS latest_version
FROM `PROJECT.DATASET.TABLE`
WHERE event_timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL N DAY)
GROUP BY issue_id, issue_title, issue_subtitle
ORDER BY crash_count DESC
LIMIT 20
SELECT
DATE(event_timestamp) AS day,
COUNT(*) AS crash_count,
COUNT(DISTINCT installation_uuid) AS affected_users
FROM `PROJECT.DATASET.TABLE`
WHERE issue_id = 'ISSUE_ID'
AND event_timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY day
ORDER BY day DESC
SELECT
application.display_version AS app_version,
COUNT(*) AS crash_count,
COUNT(DISTINCT installation_uuid) AS affected_users
FROM `PROJECT.DATASET.TABLE`
WHERE event_timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY app_version
ORDER BY crash_count DESC
LIMIT 20
SELECT
device.model AS device_model,
device.os_version AS os_version,
COUNT(*) AS crash_count
FROM `PROJECT.DATASET.TABLE`
WHERE event_timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY device_model, os_version
ORDER BY crash_count DESC
LIMIT 20
SELECT
issue_id,
issue_title,
issue_subtitle,
COUNT(*) AS crash_count,
COUNT(DISTINCT installation_uuid) AS affected_users,
MIN(event_timestamp) AS first_seen,
MAX(event_timestamp) AS last_seen
FROM `PROJECT.DATASET.TABLE`
WHERE event_timestamp > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY issue_id, issue_title, issue_subtitle
HAVING first_seen > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
ORDER BY crash_count DESC
LIMIT 20
/create-issue), or attempting a fix if the code is in the current repo.