edit-offline-profile
This skill edits a single table's configuration within an existing mobile offline profile, such as changing row scope, sync frequency, or column selection.
Identity proven by GitHub's verified organisation badge (microsoft)
- Agents
- Claude Code
- License
- MIT (permissive)
- Pin
- ca144d2pinned Oct 9, 2026
- Context cost
- about 3,300 tokenswhen the skill loads
- GitHub stars
- 978on microsoft/power-platform-skills
- Scripts
- None found
What it does
“Internal mobile-app workflow read and executed only by mobile orchestrators to change one table's scope, columns, or sync settings in a Mobile Offline Profile.”
Generated summary from the skill's own text
This skill edits a single table's configuration within an existing mobile offline profile, such as changing row scope, sync frequency, or column selection. It reads the profile from the working directory, shows a diff of current versus proposed changes, applies patches to Dataverse, publishes the profile, and updates local artifacts. It operates only as a child of a mobile app orchestrator and requires strict context binding to the working directory and environment.
When to use it
- Modify sync interval, row scope, or columns for one table in an active profile
- Rename or update description of an existing offline profile
- Avoid re-running the full setup wizard for a single-field table edit
- Adjust column selection after schema changes without full profile reset
When not to
- Adding a new table to the profile, use the add-table skill instead
- Deleting an entire profile or changing relationships between tables
- Running outside a mobile app orchestrator context
Install
These commands install from the publisher's repository and need no account.
skills CLI
npx skills add microsoft/power-platform-skills --skill edit-offline-profileInstalls from the repository's default branch, which may have changed since the commit we checked.
GitHub CLI 2.90 or later
gh skill install microsoft/power-platform-skills edit-offline-profile@ca144d29c1665a329ab4b8e14946b2105e7622faInstalls the commit we checked (ca144d2).
Copy by hand
Download the folder at ca144d2 and put it in .claude/skills/edit-offline-profile for Claude Code and in .agents/skills/edit-offline-profile for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.
Claude Code plugin
/plugin install azure-cosmos-db-assistant@claude-plugins-officialThe publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.
Claude Code plugin
/plugin install azure@claude-plugins-officialThe publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.
Claude Code plugin
/plugin install azure-sql-developer@claude-plugins-officialThe publisher's plugin in Claude's official marketplace. It may hold more than this skill, and we have not pinned it.
Copy for your agent
A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.
Prompt
Install the agent skill "edit-offline-profile" by Microsoft. Source, pinned to commit ca144d29c1665a329ab4b8e14946b2105e7622fa: https://github.com/microsoft/power-platform-skills/tree/ca144d29c1665a329ab4b8e14946b2105e7622fa/plugins/mobile-apps/skills/edit-offline-profile 1. Download that folder at exactly this commit. Do not use the default branch. 2. Copy every file unchanged, keeping the folder structure, into .claude/skills/edit-offline-profile/ for Claude Code and .agents/skills/edit-offline-profile/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist. 3. Do not edit the files, and do not run any script in the folder unless I ask you to. 4. When you are done, list the files you copied and where you put them. Listing and checks: https://www.agentnative.dev/skills/microsoft/edit-offline-profile
SKILL.md at the pin
---
name: edit-offline-profile
description: Internal mobile-app workflow read and executed only by mobile orchestrators to change one table's scope, columns, or sync settings in a Mobile Offline Profile.
user-invocable: false
disable-model-invocation: true
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:**
- [dataverse-offline-api.md](${PLUGIN_ROOT}/shared/references/dataverse-offline-api.md) §4 / §7 — POST item + PATCH selectedcolumns
- [offline-profile-reconciliation.md](${PLUGIN_ROOT}/shared/references/offline-profile-reconciliation.md) — refreshing the `schemaColumns` baseline after a column edit
# Edit Offline Profile
Re-run a single piece of an existing profile — change one table's row scope, update the column list, adjust sync frequency, or rename the profile. Avoids the cognitive cost of walking the full /setup-offline-profile wizard for a one-line change.
Scope: existing profile (read from `<working_dir>/offline-profile.json` or
`--profile-id`); edits at the table-item granularity. To ADD a new table return to
the owner for `/add-table-to-offline-profile`; deleting an entire profile is
outside this helper's scope, not an automatic recovery.
## Invocation context and root binding
This internal helper is always a **child invocation**. Before any project read or
command, execute [app-working-directory.md](${PLUGIN_ROOT}/shared/references/app-working-directory.md).
Require the owner's absolute `working_dir`; `--working-dir`, when supplied, must
identify that same native-canonical root. Missing, relative, or conflicting root
context returns `NEEDS_CONTEXT` before project access; an inaccessible directory
is `BLOCKED`. Never use the launch cwd or introduce another root resolver.
Receive `MOBILE_APP_ORCHESTRATING=1`, `orchestrator`, `working_dir`, `phase`,
`approved_scope`, and supplied answers from the owner. Preserve the selected
environment ID/URL/tenant, profile ID, table allowlist, item IDs, and exact
scope/column/sync/name/description changes. Missing or conflicting scope returns
`NEEDS_CONTEXT`, not another environment/profile/table selection. The marker is
not approval: schema approval alone does not authorize profile edits, publication,
deletion, or membership edits. Retain Step 3's single confirm unless supplied
answers already approve that same current offline change.
For `--plan-only` or a planning-phase handoff, return the current/proposed diff
after read-only discovery and STOP before Apply, PATCH, publication, or artifact
writes. A gate response cannot lift proposal-only mode.
Apply the canonical contract to **every shell call and file tool**, including
version/auth checks, manifest/screen reads, commands copied from references,
verification, recovery, and retries. Re-supply the absolute `PLUGIN_ROOT` and
required context on each call; no prior `cd`, export, or shell variable persists.
Use the canonical Bash guard below or its PowerShell equivalent. Replace
placeholders with validated, shell-quoted invocation values; missing values
return `NEEDS_CONTEXT`, never execute an unresolved placeholder.
File tools use absolute `<working_dir>/...` paths; plugin reads/scripts use
`${PLUGIN_ROOT}/...`. Never search another app when a file is absent.
## Workflow
1. Verify project + locate profile → 2. Resolve target (which table / what to change) → 3. Show current vs proposed → Single confirm → 4. PATCH → 5. Publish → 6. Update artifacts → 7. Summary
---
### Step 1 — Verify project + locate profile
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
if [ ! -f power.config.json ] || [ ! -f app.config.js ]; then
echo "BLOCKED: working_dir is not an initialized app" >&2
exit 1
fi
```
Read `<working_dir>/power.config.json` and require a nonempty `environmentId`
matching the owner's selected environment. Reuse matching complete environment
context, or perform this non-persisting lookup from the bound root:
```bash
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" ] || [ "$environment_id" != "<selected-environment-id>" ]; then
echo "NEEDS_CONTEXT: selected environment does not match working_dir" >&2
exit 1
fi
node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "$environment_id" --no-cache --require-tenant
```
Require the returned environment ID, HTTPS URL, and tenant to match the owner;
incomplete or conflicting context returns `NEEDS_CONTEXT`. Never drop
`--no-cache --require-tenant`, change configuration, or switch auth/environment
to recover a failure. Use that exact `<envUrl>` and `<tenantId>` for every request.
Profile ID resolution (same priority as `/assign-offline-profile` Step 1):
| Source | Used when |
|---|---|
| `$ARGUMENTS` `--profile-id <guid>` | Explicit selection matching the owner's profile context |
| `<working_dir>/offline-profile.json` top-level `profileId` | Default for `/setup-offline-profile`-created projects, matching the owner's profile context |
| Otherwise | Return `NEEDS_CONTEXT` to the owner to select the intended profile; never pick another profile silently |
STOP if no profile found: "Run `/setup-offline-profile` first."
Verify the selected live profile belongs to the selected environment. A conflicting
snapshot/argument returns `NEEDS_CONTEXT`; a 404 or permission failure is
`BLOCKED`, not permission to discover a substitute. Resolve each `<itemId>` only
within this profile and verify its table matches the exact requested logical name.
> **`<working_dir>/power.config.json` is intentionally NOT consulted for the profile ID.**
> That file is owned by `pa app init`. The local profile ID lives in
> `<working_dir>/offline-profile.json` only.
### Step 2 — Resolve target (what to edit)
Parse `$ARGUMENTS`:
| Flag pattern | Effect |
|---|---|
| `--rename <new-name>` | Update profile `name` |
| `--describe <text>` | Update profile `description` |
| `--table <logical-name> --scope <0\|1\|2>` | Change one table's `recorddistributioncriteria`. Combine with `--me`, `--team`, `--bu` to set sub-flags when scope=2. |
| `--table <logical-name> --sync <minutes>` | Change one table's `syncintervalinminutes` (range 5–1440) |
| `--table <logical-name> --columns add:col1,col2 remove:col3` | Add or remove logical names from `selectedcolumns`. Comma-separated, both add/remove optional. |
| `--table <logical-name> --columns reset` | Replace selectedcolumns with union of always-include + manifest lookups + screen-grep'd (re-runs the architect's Step 6 union for this table) |
If no flags → interactive picker. `AskUserQuestion` with up-to-4 most likely edits:
- "Rename profile"
- "Change a table's scope" → next message asks which table
- "Change a table's sync frequency" → next message asks which table + value
- "Edit a table's column list" → next message asks which table + add/remove
Restrict the picker and explicit flags to the owner's exact current scope.
`--columns reset` reads the selected table from
`<working_dir>/.datamodel-manifest.json` or
`<working_dir>/docs/plan-artifacts/.datamodel-manifest.json` and greps only
absolute `<working_dir>/app/` and `<working_dir>/src/` paths. Keep the chosen
absolute manifest path for the whole invocation; no other-app fallback.
Changing the table, profile, or operation requires returning `NEEDS_CONTEXT`
to the owner, not expanding an existing approval.
### Step 3 — Show current vs proposed (single gate)
GET the current item state from Dataverse for any tables being edited:
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" GET \
"mobileofflineprofileitems(<itemId>)?\$select=name,recorddistributioncriteria,recordsownedbyme,recordsownedbymyteam,recordsownedbymybusinessunit,syncintervalinminutes,selectedcolumns" \
--tenant-id "<tenantId>"
```
Render a current/proposed diff:
```
Profile : <name> (<id>)
Editing : <table-logical-name> item
Current → Proposed
Scope : Org+me → All records
Sync (min) : 10 → 30
Columns : 14 → 16 (add: chnl_notes, chnl_actual_visit_date)
```
`AskUserQuestion`: "Apply this change? [Apply / Cancel]"
If `Apply` → continue. If `Cancel` → STOP.
### Step 4 — PATCH
Build the PATCH body with only the fields that changed:
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" PATCH \
"mobileofflineprofileitems(<itemId>)" --tenant-id "<tenantId>" \
--body '{
"recorddistributioncriteria": <new>,
"recordsownedbyme": <new-bool>,
"syncintervalinminutes": <new>,
"selectedcolumns": "{\"Columns\":[...]}"
}'
```
For profile-level edits (name / description):
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" PATCH \
"mobileofflineprofiles(<profileId>)" --tenant-id "<tenantId>" \
--body '{"name": "...", "description": "..."}'
```
Check returned HTTP statuses as well as process exit. A
403/`PrivilegeCheckFailed` is `BLOCKED`; do not change identity or profile to
bypass permissions. Preserve every field and table outside the approved delta.
### Step 5 — Publish
Use the **targeted `PublishXml`** recipe from [shared/references/dataverse-offline-api.md §9](${PLUGIN_ROOT}/shared/references/dataverse-offline-api.md):
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" POST \
"PublishXml" --tenant-id "<tenantId>" --body '{
"ParameterXml": "<publish><mobileofflineprofiles><mobileofflineprofile><profileId></mobileofflineprofile></mobileofflineprofiles></publish>"
}'
```
Publishes only this profile, not the entire org's customizations. Avoids the 429 rate-limit storms on shared envs that the legacy `PublishAllXml` triggered.
On `400 / 0x80071141` "circular relationship" — same handling as
`/setup-offline-profile` Step 8 (parse cycle path, prompt user to drop one
association, retry). Fallback to `PublishAllXml` only if `PublishXml` returns an
unexpected error other than the cycle case **and** the owner/user approves that
broader publication; a profile-scoped approval does not cover it.
All linked recovery commands, re-GET verification, and retries must bind the
same root and pass the same environment/tenant/profile/table/item context.
Never retry on a different profile or bypass a permission failure. Confirm
publication before Step 6.
If a linked recipe requires another offline helper, return the proposed change
to the owner for approval first, then read the helper at its absolute
`${PLUGIN_ROOT}/skills/<helper>/SKILL.md` path. Forward:
```text
Arguments: --working-dir '<working_dir>' --profile-id "<profileId>" --table "<table>" <exact-approved-change-flags>
Context: MOBILE_APP_ORCHESTRATING=1, orchestrator, working_dir, phase, approved_scope,
selected environment ID/URL/tenant, profile ID, table allowlist, item ID,
supplied answers, --plan-only (if present)
```
The recipient must enforce the same canonical root contract. Missing context
returns `NEEDS_CONTEXT`; do not fall back to direct invocation or rediscovery.
### Step 6 — Update artifacts
Re-read the changed item(s) in the same profile/environment and rewrite the
matching entry in `<working_dir>/offline-profile.json`. When the edit changed a
table's **columns** (`--columns add:/remove:/reset`), also refresh that entry's
`schemaColumns` to the table's current full column set from the bound absolute
manifest. This re-baselines the schema-reconciliation marker for the next
`${PLUGIN_ROOT}/scripts/offline-profile-delta.js` run; leave `schemaColumns`
untouched for scope/sync/rename-only edits. Any delta check uses
`--project-root '<working_dir>'` in its own guarded call. See
[offline-profile-reconciliation.md](${PLUGIN_ROOT}/shared/references/offline-profile-reconciliation.md).
Append a one-line entry to `<working_dir>/memory-bank.md` `## Offline profile` block:
```yaml
edits:
- { at: 2026-05-19T..., field: 'chnl_storevisit.syncintervalinminutes', from: 5, to: 10 }
```
### Step 7 — Summary
```
✓ Edited profile.
Field : chnl_storevisit.syncintervalinminutes
From : 5 min
To : 10 min
Published: 2026-05-19T...
offline-profile.json + memory-bank.md updated.
```
## Status code (final line)
- `DONE` — change applied and published
- `DONE_WITH_CONCERNS: <list>` — change applied but with caveats (publish timeout-then-success, etc.)
- `NEEDS_CONTEXT: <missing>` — couldn't resolve target table or profile
- `BLOCKED: <reason>` — auth or PATCH failure
## What this skill does NOT do
- Add a NEW table to the profile → use `/add-table-to-offline-profile`
- Add a new association (relationship inclusion) → blocked on v0.2 `selectedrelationshipsschema` work; use maker portal in the meantime
- Delete the whole profile → manual `DELETE /mobileofflineprofiles(<id>)` (cascade-deletes items + associations); see [dataverse-offline-api.md §11](${PLUGIN_ROOT}/shared/references/dataverse-offline-api.md)
- Migrate the profile between environments → use `CloneMobileOfflineProfile` action (v0.5 work)
From microsoft/power-platform-skills at ca144d2, shown as plain text under its license: MIT (permissive). The license text is in LICENSE.
View SKILL.md on GitHub at ca144d2Files
- SKILL.md14 KB · 63b7f786d6ac
1 file, 14 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.
Skill folder on GitHub at ca144d2More from Microsoft
pull-requests
This skill guides the agent in writing high-quality pull request descriptions following the Agent Framework repository template and in systematically handling…
Claude Code, Codex, Cursor +4 · about 1.5K tokens · pinned 6 days ago
appinsights-instrumentation
This skill provides guidance and reference materials for instrumenting webapps with Azure Application Insights across ASP.NET Core, Node.js, Python, and…
Contains scripts
Claude Code, Codex, Cursor +3 · about 840 tokens · pinned 6 days ago
azure-ai
This skill enables agents to use Azure AI services including Search for full-text and vector queries, Speech for transcription and synthesis, OpenAI for…
Claude Code, Codex, Cursor +4 · about 750 tokens · pinned 6 days ago
azure-diagnostics
The skill diagnoses Azure production issues across App Service, Functions, Container Apps, AKS, VMs, and Messaging services using AppLens, Azure Monitor…
Contains scripts
Claude Code, Codex, Cursor +3 · about 1.6K tokens · pinned 6 days ago
add-camera
This skill generates typed TypeScript wrappers for camera capture and image gallery selection in Power Apps mobile apps using Expo libraries.
Claude Code · about 5.2K tokens · pinned 6 days ago
add-connector
This skill adds Power Platform connectors to Expo/React Native mobile apps by discovering the connector, establishing a connection, generating service files…
Claude Code · about 3.8K tokens · pinned 6 days ago
Related in Mobile
expo-app-intents
This skill adds Apple App Intents to Expo apps, enabling Siri voice commands and Shortcuts automation through Swift declarations that dispatch to JavaScript…
by ExpoOfficial publisher
Claude Code, Codex, Cursor +4 · about 3.6K tokens · pinned 6 days ago
eas-app-stores
This skill configures and executes iOS and Android app builds and store submissions using EAS, Expo's app distribution service.
by ExpoOfficial publisher
Claude Code, Codex, Cursor +3 · about 1.7K tokens · pinned 6 days ago
eas-simulator
Runs a user's app on a remote iOS or Android simulator hosted on EAS cloud infrastructure, accessible from machines without local simulator support like Linux…
by ExpoOfficial publisher
Claude Code, Codex, Cursor +3 · about 6.3K tokens · pinned 6 days ago
eas-update
Configures and publishes over-the-air JavaScript and asset updates using EAS Update and the EAS CLI.
by ExpoOfficial publisher
Claude Code, Codex, Cursor +3 · about 2.3K tokens · pinned 6 days ago
expo-animation
This skill guides building animations in React Native and Expo apps using Reanimated, Gesture Handler, and Expo Router.
by ExpoOfficial publisher
Claude Code, Codex, Cursor +3 · about 4.6K tokens · pinned 6 days ago
expo-app-clip
This skill adds an iOS App Clip target to an Expo project, creating a lightweight app experience invoked from URLs on your domain.
by ExpoOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.3K tokens · pinned 6 days ago