Skip to content
Development
Skill

/preview-offline-scope

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.

From plugin
power-platform-skills
1.1k110 skills25 agents5 MCP

Claude Code

$ npx -y skills add microsoft/power-platform-skills --skill preview-offline-scope --agent claude-code

SKILL.md

preview-offline-scope.SKILL.md
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.

Preview Offline Scope

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:

  • `/setup-offline-profile` for a final sanity check
  • `/assign-offline-profile` (so users don't get surprised by data caps)
  • `/edit-offline-profile` to gauge impact of a column-list change

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`.

Workflow

1. Verify project + locate profile → 2. Run verify (drift check) → 3. Per-table row counts → 4. Cache-size estimate → 5. Report

---

Step 1 — Verify project + locate profile

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-tenant

Capture `<envUrl>` and `<tenantId>` and require them to match any owner identity. Pass that tenant explicitly on verification, row counts, identity reads, and retries.

Step 2 — Run verify

**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.

Step 3 — Per-table row counts (with scope-applied filter)

**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.

Step 4 — Cache-size estimate

**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)`.

Step 5 — Report

═════════════════════════════════════════════════════════════
  Offline Scope Preview — <profileName>
═════════════════════════════════════════════════════════════

Drift status: ok | drift (see verify output)

Per-table breakdown:

| Table              | Scope          | Rows     | Cols | Est. bytes | Sync (min) |
|--------------------|----------------|----------|------
Read more
@microsoft
Ships withpower-platform-skills

Plugins from Microsoft that teach AI assistants, such as GitHub Copilot and Claude Code, to build on Power Platform.

1.1k110 skills25 agents5 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.1k
Star history of microsoft/power-platform-skills on GitHub, a chart by star-history.com

Other skills on power-platform-skills.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills13d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react4d252k
@facebook@facebookInstall Skill

Questions about preview-offline-scope.

Which coding agents can use preview-offline-scope?
preview-offline-scope installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.