Skip to content
Development
Skill

/assign-offline-profile

Use when the user needs to bind users or teams to a Mobile Offline Profile so they actually receive offline sync on their devices. Without this, the profile exists in Dataverse but no one's app uses it.

From plugin
power-platform-skills
86896 skills19 agents4 MCP
Install
$ npx -y skills add microsoft/power-platform-skills --skill assign-offline-profile --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/assign-offline-profile

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when the user needs to bind users or teams to a Mobile Offline Profile so they actually receive offline sync on their devices. Without this, the profile exists in Dataverse but no one's app uses it.

SKILL.md

assign-offline-profile.SKILL.md
name: assign-offline-profile
description: Use when the user needs to bind users or teams to a Mobile Offline Profile so they actually receive offline sync on their devices. Without this, the profile exists in Dataverse but no one's app uses it.
user-invocable: false
allowed-tools: Read, Edit, Write, Grep, Glob, Bash, AskUserQuestion
model: sonnet

**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) — `usermobileofflineprofilemembership` / `teammobileofflineprofilemembership` entity field map
  • [dataverse-offline-api.md](${PLUGIN_ROOT}/shared/references/dataverse-offline-api.md) — Web API recipe (§12 — membership POSTs)

Assign Offline Profile

Bind one or more users and/or teams to an existing Mobile Offline Profile. Without this step, the profile exists in Dataverse but is unbound — no one's app actually uses it for offline sync.

Per the maker portal's UX (the "Assign profile to user" dialog under env settings), this is a separate operation from profile creation. Many users hit "I created the profile but offline still doesn't work" — the missing piece is membership.

Workflow

1. Verify project + locate profile → 2. Pick users/teams → 3. Discover existing memberships → 4. Confirm diff (single gate) → 5. POST memberships → 6. Verify → 7. Summary

---

Step 1 — Verify project + locate profile

test -f power.config.json
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$(node -e \"console.log(require('./power.config.json').environmentId)\")"

Profile ID resolution (in order):

| Source | Used when | |---|---| | `$ARGUMENTS` contains `--profile-id <guid>` | Explicit override | | `$ARGUMENTS` contains `--profile-name <name>` | Resolve via `GET /mobileofflineprofiles?$filter=name eq '<name>'&$select=mobileofflineprofileid` | | `offline-profile.json` in cwd | Read top-level `profileId` field | | Otherwise | `GET /mobileofflineprofiles` and present `AskUserQuestion` with the list (max 4 options) |

STOP if no profile can be resolved. Print: `Run /setup-offline-profile first, or pass --profile-id`.

> **`power.config.json` is intentionally NOT consulted here.** That file is owned by `npx power-apps init`. The profile ID lives in `offline-profile.json` only.

Step 2 — Pick users/teams

`$ARGUMENTS` parsing:

| Flag | Effect | |---|---| | `--user <upn>` (repeatable) | Add specific user(s) by UPN (`user@domain.com`) | | `--team <name>` (repeatable) | Add specific team(s) by name | | `--me` | Add the current Dataverse user from `WhoAmI` / `systemusers(<UserId>)` — useful for solo dev demos | | `--all-app-users` | Add every user with **System User** role in the current env (broad; intended for prod rollout — confirm at gate) | | `--unassign-user <upn>` / `--unassign-team <name>` | Remove an existing membership rather than add |

If no flags passed, present `AskUserQuestion`:

> **Question**: "Who should receive this offline profile?" > > **Options** (max 4): > - `Just me (the current user)` — equivalent to `--me` > - `Pick specific users by UPN` — you reply with comma-separated emails in the next message > - `Pick a team` — list env's teams and pick one > - `All users with System User role` — equivalent to `--all-app-users`; broad scope, confirm at gate

For pick-users flow: after the choice, print:

> "Reply with comma-separated UPNs (e.g. `rm1@contoso.com, rm2@contoso.com`)"

Then read the next user message and parse.

Step 3 — Discover existing memberships

**Telemetry checkpoint: `discover_offline_profile_memberships`**

For idempotency:

# Existing user memberships for this profile
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "usermobileofflineprofilememberships?\$filter=_mobileofflineprofileid_value eq <profileId>&\$select=usermobileofflineprofilemembershipid,_systemuserid_value&\$expand=systemuserid_systemuser(\$select=domainname)"

# Existing team memberships for this profile
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "teammobileofflineprofilememberships?\$filter=_mobileofflineprofileid_value eq <profileId>&\$select=teammobileofflineprofilemembershipid,_teamid_value&\$expand=teamid_team(\$select=name)"

Build the set of `already-bound` UPNs and team names.

For each candidate user/team from Step 2, look up their `systemuserid` / `teamid` (skip if already in `already-bound`):

node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "systemusers?\$filter=domainname eq '<upn>'&\$select=systemuserid,fullname,domainname&\$top=1"

node "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET \
  "teams?\$filter=name eq '<team-name>' and teamtype eq 0&\$select=teamid,name&\$top=1"

(`teamtype eq 0` excludes Access Teams and Owner Teams — only Manage Teams get profile assignments.)

Construct three lists:

  • `to_add` — resolved IDs to POST
  • `to_remove` — resolved IDs to DELETE (from `--unassign-*` flags)
  • `not_found` — UPNs/team-names that didn't resolve (warn)
  • `already_bound` — skipped no-ops

Step 4 — Confirm diff (single gate)

**Telemetry checkpoint: `confirm_offline_profile_assignment_diff`**

`AskUserQuestion`:

> **Question header**: `Confirm membership changes` > > **Question body**: > > ``` > Profile: <name> (<profileId>) > > Will ADD: > - User: rahul@contoso.com (Rahul Bansal) > - User: charanma@... (Charan Mahankali) > - Team: Field Service RMs (12 members) > > Will REMOVE: > (none) > > Already bound (skipping): > - User: admin@... (no-op) > > Could not resolve: > - someone@external.com — not in this env's system users > > Proceed? > ``` > > **Options**: > - `Proceed` > - `Cancel`

Step 5 — POST memberships

**Telemetry checkpoint: `assign_offline_profile_memberships`**

For each in `to_add`, POST sequentially (parallel POSTs occasionally return 429):

**User membership:**

Read more
Ships withpower-platform-skills

Official agent skills/plugins for Power Platform development by Microsoft.

Get the whole plugin

Other skills on power-platform-skills.