add-data-source
Guide the user to add a data source, connection, or API connector to a Canvas App via Power Apps Studio, then verify and…
Use when the user wants to estimate the download size + sync frequency cost of an offline profile BEFORE pushing to users. Read-only. Wraps verify-offline-profile.js with per-table row-count estimates.
Claude Code
$ npx -y skills add microsoft/power-platform-skills --skill preview-offline-scope --agent claude-code
Codex
$ npx skills add microsoft/power-platform-skills --skill preview-offline-scope -a codex -y
Cursor
$ npx skills add microsoft/power-platform-skills --skill preview-offline-scope -a cursor -y
Gemini CLI
$ npx skills add microsoft/power-platform-skills --skill preview-offline-scope -a gemini-cli -y
GitHub Copilot
$ npx skills add microsoft/power-platform-skills --skill preview-offline-scope -a github-copilot -y
OpenCode
$ npx skills add microsoft/power-platform-skills --skill preview-offline-scope -a opencode -y
Windsurf
$ npx skills add microsoft/power-platform-skills --skill preview-offline-scope -a windsurf -y
name: preview-offline-scope description: Use when the user wants to estimate the download size + sync frequency cost of an offline profile BEFORE pushing to users. Read-only. Wraps verify-offline-profile.js with per-table row-count estimates. user-invocable: false allowed-tools: Read, Bash, AskUserQuestion model: sonnet
**Shared instructions: [shared-instructions.md](${PLUGIN_ROOT}/shared/shared-instructions.md)** — read first.
Read-only diagnostic. Tells you "if you pushed this profile to users right now, here's what their devices would download and how often it would re-sync." No mutations.
Useful before:
Before any project read or command, apply [app-working-directory.md](${PLUGIN_ROOT}/shared/references/app-working-directory.md). Resolve one absolute `working_dir` for this direct invocation, or require the owner's root for a child. Keep all shell calls, file reads, and retries on that root and the same resolved environment/tenant. Read `<working_dir>/offline-profile.json`; a supplied profile ID must match the snapshot before verification. Missing or conflicting context is `NEEDS_CONTEXT`.
1. Verify project + locate profile → 2. Run verify (drift check) → 3. Per-table row counts → 4. Cache-size estimate → 5. Report
---
Same as `/edit-offline-profile` Step 1. Read profileId from `offline-profile.json` or `$ARGUMENTS --profile-id`. Do not read profile metadata from `power.config.json`; it is owned by `pa app init`.
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
environment_id=$(node -p "require('./power.config.json').environmentId || ''") || {
echo "BLOCKED: unreadable power.config.json" >&2; exit 1;
}
if [ -z "$environment_id" ]; then
echo "NEEDS_CONTEXT: selected app has no environmentId" >&2; exit 1;
fi
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$environment_id" --no-cache --require-tenantCapture `<envUrl>` and `<tenantId>` and require them to match any owner identity. Pass that tenant explicitly on verification, row counts, identity reads, and retries.
**Telemetry checkpoint: `verify_offline_profile_snapshot`**
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/verify-offline-profile.js" <envUrl> \
--project-root '<working_dir>' --tenant-id "<tenantId>"If `status: drift`, surface the drift list verbatim. The estimate that follows is still meaningful but flag that the live profile diverges from `offline-profile.json` — recommend re-running `/setup-offline-profile` or `/edit-offline-profile` to reconcile.
**Telemetry checkpoint: `count_offline_profile_rows`**
For each table in the profile, run a `count` query that applies the same filter the runtime would use:
| `recorddistributioncriteria` | `recordsownedby*` flag | Effective filter | |---|---|---| | 1 (All records) | n/a | `?$count=true&$top=0` (whole table) | | 2 + me | recordsownedbyme=true | `?$count=true&$top=0&$filter=_ownerid_value eq <current-user-id>` | | 2 + team | recordsownedbymyteam=true | Approx: `_ownerid_value` in (current user's team-owned IDs); for estimate, use team count from `teamroles_association` | | 2 + bu | recordsownedbymybusinessunit=true | `?$count=true&$top=0&$filter=_owningbusinessunit_value eq <current-bu-id>` | | 0 (Related only) | n/a | Can't estimate independently — depends on parents. Report `~depends on parent counts`. |
For current-user/current-BU filters, resolve identity only inside this skill by calling Dataverse `WhoAmI` through `scripts/dataverse-request.js` against the resolved `<envUrl>` with `--tenant-id "<tenantId>"` from the same guarded root. If that call fails, report the affected scope as `unknown — current user/BU unavailable` instead of blocking the whole preview. Do not expect `scripts/resolve-environment.js` or `auth.config.json.environment` to provide `UserId` / `BusinessUnitId`.
For each table:
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
"<entitysetname>?\$count=true&\$top=0&<scope-filter>" --tenant-id "<tenantId>"Cap at 5000 (Dataverse non-aggregate count cap). When the result is exactly 5000, prefix with `≥` in the report.
**Telemetry checkpoint: `estimate_offline_cache_size`**
Rough byte-per-row heuristics (configurable; replace with measured values once we have a real sync benchmark):
| Column type | Bytes | |---|---| | Uniqueidentifier | 40 | | String (avg 80 chars) | 100 | | Integer / Decimal | 12 | | DateTime | 28 | | Boolean / State / Status | 4 | | Picklist (option value only) | 8 | | Memo (avg 500 chars) | 600 | | Lookup (FK only) | 40 | | Image (URL + thumbnail metadata only — see note below for full-image bytes) | 200 | | File (URL + name metadata) | 200 |
For each table, compute: `estimatedBytesPerRow = sum(bytesForEach column in selectedcolumns)`. Then `tableTotalBytes = rows × estimatedBytesPerRow`.
Per-table sync overhead: each `syncintervalinminutes` interval triggers a delta query → assume ~20% of total rows touched on a typical day. `dailyTransferBytes = (totalBytes × 0.20 × intervalsPerDay)`.
═════════════════════════════════════════════════════════════ Offline Scope Preview — <profileName> ═════════════════════════════════════════════════════════════ Drift status: ok | drift (see verify output) Per-table breakdown: | Table | Scope | Rows | Cols | Est. bytes | Sync (min) | |--------------------|----------------|----------|------
Plugins from Microsoft that teach AI assistants, such as GitHub Copilot and Claude Code, to build on Power Platform.
Guide the user to add a data source, connection, or API connector to a Canvas App via Power Apps Studio, then verify and…
Creates or edits a Power Apps Canvas App through the Canvas Authoring MCP coauthoring session. Handles staged experience design,…
Configure the Canvas Authoring MCP server for the current coauthoring session. Use before starting to edit a canvas app with the…
Use this skill when the user wants to "report a bug", "file an issue", "report an issue", "submit a bug report", or report any…
Adds Azure DevOps connector to a Power Apps code app. Use when querying work items, creating bugs, managing pipelines, or making…
Adds any Power Platform connector to a Power Apps code app. Generic fallback for connectors not covered by a specific skill.
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.