plugins/lisa-expo-copilot/skills/eas-update-insights/SKILL.md
Check the health of published EAS Updates: crash rates, install/launch counts, unique users, payload size, and the split between embedded and OTA users per channel. Use when the user asks how an update is performing, whether a rollout is healthy, how many users are on the embedded build vs OTA, or wants to gate CI on update health.
npx skillsauth add codyswanngt/lisa eas-update-insightsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Query the health of published EAS Updates directly from the CLI: launches, failed launches, crash rates, unique users, payload size, the embedded-vs-OTA user split per channel, and the most popular updates per runtime version. The data is the same data that powers the update and channel detail pages on expo.dev; these commands expose it in the terminal in human and JSON form.
Use this when the user wants to assess the health or adoption of a published EAS Update: crash rates, install counts, unique users, bundle size, or the split between embedded and OTA users on a channel.
Example prompts:
Also fits: post-publish rollout monitoring and regression detection.
Don't use when the user needs per-user crash detail or device-level reporting; this skill only exposes aggregate EAS metrics.
eas-cli installed (npm install -g eas-cli).eas login.channel:insights: run from an Expo project directory (the command resolves the project ID from app.json). update:insights only needs a login.| Command | Purpose |
|---|---|
| eas update:list | Discover recent update groups, their group IDs, and branch names |
| eas update:insights <groupId> | Per-platform launches, failed launches, crash rate, unique users, payload size, daily breakdown |
| eas update:view <groupId> --insights | Update group details + the same metrics appended |
| eas channel:insights --channel <name> --runtime-version <version> | Embedded/OTA user counts, most popular updates, cumulative metrics for a channel + runtime |
All of these support --json --non-interactive for programmatic parsing.
Before querying insights for an update group, you need its group ID. Use eas update:list with either --branch <name> (updates on that branch) or --all (updates across all branches). Always pass --json --non-interactive when running non-interactively; without a branch/--all flag the command will otherwise prompt for a branch selection:
# Latest group id across all branches
eas update:list --all --json --non-interactive | jq -r '.currentPage[0].group'
# Latest group id on a specific branch
eas update:list --branch production --json --non-interactive | jq -r '.currentPage[0].group'
The JSON response has a currentPage array with one entry per update group (both platforms of the same publish are collapsed into one entry):
{
"currentPage": [
{
"branch": "production",
"message": "\"Fix checkout crash\" (1 week ago by someone)",
"runtimeVersion": "1.0.6",
"group": "03d5dfcf-736c-475a-8730-af039c3f4d06",
"platforms": "android, ios",
"isRollBackToEmbedded": false
}
]
}
Entries also carry codeSigningKey and rolloutPercentage, but only when those features are in use for the group (undefined values are omitted from the JSON output).
When called with --branch <name>, the response also includes name (the branch name) and id (the branch ID) at the top level.
eas update:insights <groupId>Shows launches, failed launches, crash rate, unique users, launch asset count, and average payload size for a single update group, broken down per platform (iOS, Android), plus a daily breakdown of launches and failures.
eas update:insights 03d5dfcf-736c-475a-8730-af039c3f4d06
| Flag | Description |
|---|---|
| --days <N> | Look back N days. Default: 7. Mutually exclusive with --start/--end. |
| --start <iso-date> / --end <iso-date> | Explicit time range, e.g. --start 2026-04-01 --end 2026-04-15. |
| --platform <ios\|android> | Filter to a single platform. Omit to see all platforms in the group. |
| --json | Machine-readable output. Implies --non-interactive. |
| --non-interactive | Required when scripting. |
Top level: groupId, timespan (start, end, daysBack), and platforms[] with one entry per platform the group was published to. Each platform entry has updateId, totals (uniqueUsers, installs, failedInstalls, crashRatePercent), payload (launchAssetCount, averageUpdatePayloadBytes), and a daily[] time series of { date, installs, failedInstalls }.
For the complete schema and field reference, see references/update-insights-schema.md.
Fields that matter for health assessment:
platforms[].totals.crashRatePercent, computed as failedInstalls / (installs + failedInstalls) * 100. Zero when there are no installs.platforms[].totals.installs and uniqueUsers give the adoption signal.platforms[].daily is a time series, useful for spotting a sudden spike in failures.Could not find any updates with group ID: "<id>" — group doesn't exist or you lack access.Update group "<id>" has no ios update (available platforms: android) — --platform ios was used but the group wasn't published for iOS.EAS Update insights is not supported by this version of eas-cli. Please upgrade ... — the server deprecated a field the CLI relies on. Run npm install -g eas-cli@latest.eas update:view <groupId> --insightsExtends the standard update:view output with the same per-platform insights, inline.
# Human-readable
eas update:view 03d5dfcf-... --insights
eas update:view 03d5dfcf-... --insights --days 30
# JSON: wrapped as { updates: [...], insights: {...} }
eas update:view 03d5dfcf-... --json --insights
Without --insights, update:view behaves exactly as before — no JSON shape change for existing consumers. The --days / --start / --end flags only apply when --insights is set; passing them alone errors.
eas channel:insights --channel <name> --runtime-version <version>Shows, per channel, how many users are on the embedded build vs over-the-air updates and which updates are pulling the most traffic. Must be run from an Expo project directory.
eas channel:insights --channel production --runtime-version 1.0.6
| Flag | Description |
|---|---|
| --channel <name> | Required. The channel name (e.g. production, staging). |
| --runtime-version <version> | Required. Match exactly what was published. Check runtimeVersion values in update:list. |
| --days <N> | Look back N days. Default: 7. |
| --start / --end | Explicit time range, like update:insights. |
| --json / --non-interactive | Machine-readable output. |
Top level: channel, runtimeVersion, timespan, embeddedUpdateTotalUniqueUsers, otaTotalUniqueUsers, mostPopularUpdates[] (each with rank, groupId, message, platform, totalUniqueUsers), cumulativeMetricsAtLastTimestamp[], plus chart-shaped uniqueUsersOverTime and cumulativeMetricsOverTime objects with labels and datasets.
For the complete schema and field reference, see references/channel-insights-schema.md.
Fields that matter:
embeddedUpdateTotalUniqueUsers is the count of users running the embedded (binary-bundled) build.mostPopularUpdates[] is updates ranked by totalUniqueUsers. Caveat: this is the top-N the server returns; otaTotalUniqueUsers is a sum of that list and may undercount total OTA reach if more than top-N updates are active.uniqueUsersOverTime and cumulativeMetricsOverTime are daily data series for charting.Could not find channel with the name <name> — typo or wrong account.mostPopularUpdates in JSON — no OTA update has been launched for that channel + runtime yet. Usually means the channel is still serving the embedded build only.# 1. Grab the latest publish on production
GROUP_ID=$(eas update:list --branch production --json --non-interactive \
| jq -r '.currentPage[0].group')
# 2. Give it some adoption time (minutes to hours), then check crash rate
eas update:insights "$GROUP_ID" --json --non-interactive \
| jq '.platforms[] | {platform, installs: .totals.installs, crashRate: .totals.crashRatePercent}'
Compare the crashRate across platforms and against previous releases; sudden spikes or asymmetric behaviour (iOS spiking while Android is flat, or vice versa) is the signal to investigate.
for channel in production staging; do
echo "--- $channel ---"
eas channel:insights --channel "$channel" --runtime-version 1.0.6 --json --non-interactive \
| jq '{
channel,
embedded: .embeddedUpdateTotalUniqueUsers,
ota: .otaTotalUniqueUsers,
topUpdate: .mostPopularUpdates[0]
}'
done
eas update:insights "$GROUP_ID" --days 1 --json --non-interactive \
| jq '.platforms[] | select(.totals.crashRatePercent > 1)'
eas update:view "$GROUP_ID" --insights --days 30
Human-readable group details plus 30 days of launches/failures per platform — suitable for pasting into a changelog or incident review.
jq; payloads are structured for easy filtering.--json implies --non-interactive, but passing both is explicit and scripting-friendly.daily[].date are UTC ISO timestamps; the human-readable table renders them as YYYY-MM-DD (UTC).installs / failedInstalls. Same field, different display name.otaTotalUniqueUsers in channel insights, which is a sum over mostPopularUpdates.installs / "Launches" field counts users who downloaded the manifest and launch asset. A confirmed run only registers on the user's next update check (typically up to 24h later, depending on the app's update policy). So metrics lag the real-world state slightly.failedInstalls / "Crashes" counts updates that errored during install/launch and were reported on the next update check. Crashes that don't trigger an update request (e.g. process kill before recovery) won't appear.documentation
Onboard a user to the project via its LLM Wiki. Interviews the user about themselves in relation to the project, captures that to project-scoped memory only, then gives a guided tour of what the project is and sample questions they can ask. Use when someone is new to the project or asks to be onboarded. Read-mostly — it does not open PRs or write PII into the wiki.
documentation
Migrate an existing, hand-rolled wiki implementation onto the lisa-wiki kernel — phased and compatibility-first, with a strict no-loss guarantee. Use when adopting lisa-wiki in a repo that already has its own wiki/, ingest skills, docs, or roles. Renaming things into the canonical shape is fine; losing functionality or data is not. Ends by running /doctor.
development
Health-check the LLM Wiki. Reports orphan pages, contradictions, stale claims, broken internal links, missing index/log coverage, structure-manifest violations, and secret/tenant leaks. Use periodically or before hardening a wiki. Read-only — it reports findings, it does not fix them.
testing
Ingest source material into the LLM Wiki. With an argument (URL, file path, or prompt) it ingests that one source; with no argument it runs a full ingest across every enabled non-external-write source. Routes to the right connector, then runs the ordered pipeline (source note → synthesis → index → log → verify → state → commit/PR). Use whenever new knowledge should enter the wiki.