setup-offline-profile
Use when the user wants to enable offline mode for a Power Apps mobile app and create a Mobile Offline Profile in Dataverse — designs per-table row scope, relationships, columns, and sync frequency through a 3-gate approval flow.
git clone --depth 1 https://github.com/microsoft/power-platform-skills /tmp/setup-offline-profile && cp -r /tmp/setup-offline-profile/plugins/mobile-apps/skills/setup-offline-profile ~/.claude/skills/setup-offline-profileSKILL.md
**Shared instructions: [shared-instructions.md](${PLUGIN_ROOT}/shared/shared-instructions.md)** — read first.
**References:**
- [offline-profile-schema.md](${PLUGIN_ROOT}/shared/references/offline-profile-schema.md) — Dataverse entity field map
- [dataverse-offline-api.md](${PLUGIN_ROOT}/shared/references/dataverse-offline-api.md) — Web API recipes for profile / item / association POSTs
- [offline-profile-reconciliation.md](${PLUGIN_ROOT}/shared/references/offline-profile-reconciliation.md) — the `schemaColumns` baseline this skill writes + the lifecycle delta check that consumes it
# Setup Offline Profile
End-to-end wizard for creating a Dataverse Mobile Offline Profile that the app (and any other compatible Power Apps client) can use to download data for offline access.
**Scope of v0**: authoring only. This skill creates the Dataverse entities (`mobileofflineprofile`, `mobileofflineprofileitem`, `mobileofflineprofileitemassociation`) and writes the full app-level offline config — profile metadata, per-table scope, and the temporary SDK-workaround fields — to `offline-profile.json`. **This skill does NOT modify `power.config.json`** (that file is owned by `npx power-apps init` and its schema is controlled upstream). It also does NOT scaffold an offline runtime (SQLite store, sync engine, write queue) in the generated app — that's gated on upstream `@microsoft/power-apps-native-host` runtime support.
**Out of scope for v0**:
- Custom filter mode (`recorddistributioncriteria=3`, savedquery picker) — defer to v0.5
- User/team membership assignment — split into `/assign-offline-profile`
- Row-count download estimation — split into `/preview-offline-scope`
## Workflow
1. Verify project & auth → 2. Resolve mode (create vs extend) → 3. Spawn architect agent → **Gate 1** (table prerequisites) → 4. Run the internal `enable-tables-offline` workflow if needed → 5. POST profile shell → **Gate 2** (per-table row scope) → 6. POST profile items → **Gate 3** (relationships + columns + sync) → 7. POST associations → 8. Validate + publish → 9. Persist artifacts → 10. Summary
---
### Step 1 — Verify project & auth
```bash
test -f power.config.json && test -f app.config.js
# Manifest lives at either root (legacy) or docs/plan-artifacts/ (newer scaffolds)
MANIFEST=$(test -f .datamodel-manifest.json && echo ".datamodel-manifest.json" || \
(test -f docs/plan-artifacts/.datamodel-manifest.json && echo "docs/plan-artifacts/.datamodel-manifest.json"))
test -n "$MANIFEST" && echo "✓ manifest at $MANIFEST"
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$(node -e \"console.log(require('./power.config.json').environmentId)\")"
```
Capture **Environment URL** for `<envUrl>` and **manifest path** for the architect spawn (Step 3) and the artifacts write (Step 9).
**Web-only target detection** — Mobile Offline Profiles only apply to native targets (iOS/Android). If the project is web-only, the profile will be created in Dataverse but **the generated app will never use it**:
```bash
# Inspect platforms declared in app.config.js
node -e "
const c = require('$(pwd)/app.config.js');
const platforms = c?.expo?.platforms ?? [];
const hasNative = platforms.includes('ios') || platforms.includes('android');
console.log(JSON.stringify({ platforms, hasNative }));
" 2>/dev/null
```
| `hasNative` | Action |
|---|---|
| `true` (has `ios` and/or `android`) | Continue normally |
| `false` (web-only or no platforms) | Print: `⚠ This project only targets web — Mobile Offline Profiles don't apply (they require iOS/Android). Continuing will create the profile in Dataverse but no app will use it.` Ask via `AskUserQuestion`: "Continue anyway?" Default No. |
| Parse error / app.config.js missing key | Warn, but assume native (don't block on a parser quirk) |
STOP conditions:
- No `power.config.json` → "Run `/create-mobile-app` first."
- Neither `.datamodel-manifest.json` nor `docs/plan-artifacts/.datamodel-manifest.json` → "Run `/add-dataverse` first — offline profiles require a data model."
- Environment resolution failure → standard auth recovery (`az login --tenant <env-tenant>` or provide environment URL directly; see [shared-instructions.md](${PLUGIN_ROOT}/shared/shared-instructions.md)).
- Web-only + user declines override → STOP. Print: `Offline profile creation skipped — no native target.`
#### Step 1a — Environment consistency check
Same as `/add-dataverse` Step 3a — verify `power.config.json` resolves and `az` can token for the target tenant. STOP if it cannot; user must re-auth with `az login --tenant <env-tenant>`.
#### Step 1b — Resume check
Read `memory-bank.md` `## Offline profile` block. Decide based on `status`:
| `status` value | Action |
|---|---|
| (section absent) OR `status: none` | First-time run. Continue to Step 2. |
| `status: not-applicable` | User previously opted out via `/create-mobile-app` Step 6.85 ("doesn't need offline support"). Re-confirm: "Memory-bank says this app doesn't need offline. Override and proceed? (y/N)". Default N stops here. |
| `status: done` AND a profile matching `profileId` still exists in env | Already complete. Print summary from the memory-bank block; ask user if they want to `/edit-offline-profile` (v0.2) or just exit. |
| `status: done` BUT `GET /mobileofflineprofiles(<profileId>)` returns 404 | Profile was deleted externally (maker portal or another env). Treat as `none`; clear the section; continue to Step 2. |
| `status: in-progress` AND profile exists in env | **Resume flow** — see below. |
| `status: in-progress` BUT profile doesn't exist in env | Memory-bank stale. Auto-clean: clear the section, log `recovered from stale in-progress state`, continue to Step 2 as a fresh run. |
**Resume flow** — when memory-bank has `status: in-progress` AND the profile still exists:
1. `GET /mobileofflineprofiles(<profileId>)?$expand=MobileOfflineProfile_MobileOfflineProfileItem` to compute what's actually been committed:
- 0 items → profile shell exi>-
>-
Adds Azure DevOps connector to a Power Apps code app. Use when querying work items, creating bugs, managing pipelines, or making ADO API calls.
Internal implementation skill invoked by /add-native for camera, image picker, barcode scanner, QR scanner, and camera/gallery Dataverse artifact workflows.
>-
Use when adding a Power Platform connector to an Expo/React Native Power Apps mobile app and no dedicated mobile connector skill exists.
Guide the user to add a data source, connection, or API connector to a Canvas App via Power Apps Studio, then verify and continue. USE WHEN the user asks to add a data source, add a connection, add an API, add a connector, connect to SharePoint / Dataverse / SQL / Excel / OneDrive / Teams / Office 365, or any similar request to make new data available to the app. DO NOT USE WHEN the user is asking to list or describe existing data sources — call list_data_sources or list_apis directly instead.
Use when adding an unspecified data source to an Expo/React Native Power Apps mobile app; routes to Dataverse, SharePoint, or another connector.