enable-tables-offline
This skill modifies Dataverse table metadata to enable offline capability for mobile apps by setting IsAvailableOffline and ChangeTrackingEnabled flags, then…
Identity proven by GitHub's verified organisation badge (microsoft)
- Agents
- Claude Code
- License
- MIT (permissive)
- Pin
- ca144d2pinned Oct 9, 2026
- Context cost
- about 3,000 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 /setup-offline-profile to enable Dataverse table prerequisites for a Mobile Offline Profile.”
Generated summary from the skill's own text
This skill modifies Dataverse table metadata to enable offline capability for mobile apps by setting IsAvailableOffline and ChangeTrackingEnabled flags, then publishes the changes. It is an internal helper invoked only by the setup-offline-profile workflow and requires explicit approval before making any modifications.
When to use it
- Preparing Dataverse tables for inclusion in a Mobile Offline Profile
- Enabling offline-first mobile app configurations that need change tracking
- Completing metadata prerequisites for mobile app offline setup workflows
When not to
- Directly by users or external skills outside the setup-offline-profile orchestrator
- For system-managed or uncustomizable tables that cannot be modified
- When the user lacks Customize System privilege on the Dataverse environment
Install
These commands install from the publisher's repository and need no account.
skills CLI
npx skills add microsoft/power-platform-skills --skill enable-tables-offlineInstalls 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 enable-tables-offline@ca144d29c1665a329ab4b8e14946b2105e7622faInstalls the commit we checked (ca144d2).
Copy by hand
Download the folder at ca144d2 and put it in .claude/skills/enable-tables-offline for Claude Code and in .agents/skills/enable-tables-offline 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 "enable-tables-offline" by Microsoft. Source, pinned to commit ca144d29c1665a329ab4b8e14946b2105e7622fa: https://github.com/microsoft/power-platform-skills/tree/ca144d29c1665a329ab4b8e14946b2105e7622fa/plugins/mobile-apps/skills/enable-tables-offline 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/enable-tables-offline/ for Claude Code and .agents/skills/enable-tables-offline/ 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/enable-tables-offline
SKILL.md at the pin
---
name: enable-tables-offline
description: Internal mobile-app workflow read and executed only by /setup-offline-profile to enable Dataverse table prerequisites for a Mobile Offline Profile.
user-invocable: false
disable-model-invocation: true
allowed-tools: Read, Edit, Write, Grep, Glob, Bash, AskUserQuestion, EnterPlanMode, ExitPlanMode
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) — entity field map (`IsAvailableOffline`, `ChangeTrackingEnabled`)
# Enable Tables Offline
Flip `IsAvailableOffline=true` AND `ChangeTrackingEnabled=true` on the `EntityMetadata` of one or more Dataverse tables, then publish customizations. This is the prerequisite shown in Image 4 of the maker portal ("Can be taken offline" + "Track changes") — without both, a table CANNOT be added to a Mobile Offline Profile.
Sequential (Dataverse metadata lock) and idempotent: re-running on an already-enabled table is a no-op.
## 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: setup-offline-profile`,
`working_dir`, `phase`, `approved_scope`, and supplied answers. Preserve the
selected environment ID/URL/tenant and exact table/prerequisite/publication
allowlist. The marker is not approval. Reuse only matching current offline
approval; a missing or changed scope returns `NEEDS_CONTEXT` to the owner.
For `--plan-only` or a planning-phase handoff, return the proposed prerequisite
changes after permitted read-only inspection, before PUT, publication, or
artifact writes. A gate response cannot lift proposal-only mode.
Apply the canonical root contract to **every shell call and file tool**.
Re-supply the absolute `PLUGIN_ROOT` and invocation context on each call; no
prior `cd`, export, or shell variable persists. Missing values return
`NEEDS_CONTEXT`; never execute an unresolved placeholder.
All linked recovery commands, re-GET verification, and retries use the same
root, environment, and explicit tenant. Read only absolute app-local paths,
including `<working_dir>/power.config.json`, `<working_dir>/memory-bank.md`,
and the manifest locations below.
## Workflow
1. Verify project & auth → 2. Resolve table list → 3. Inspect current state → Gate → 4. PUT EntityMetadata per table → 5. Publish → 6. Verify → 7. Summary
---
### Step 1 — Verify project & auth
```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
```
Require the app's `environmentId` to match the owner's selected environment
before any discovery or mutation. Use this non-persisting lookup from the same 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
```
Capture the **Environment URL** and **Tenant ID** from the resolver for
`<envUrl>` and `<tenantId>`. Pass this tenant explicitly on every helper call
and retry below; missing or conflicting tenant context is `NEEDS_CONTEXT`.
Require the ID, URL, and tenant to match the owner; never switch accounts or
environments to recover. STOP if not authenticated.
### Step 2 — Resolve table list
Use only the exact table allowlist in the owner's `approved_scope`. The comma-
or space-separated table list in `$ARGUMENTS` must match it; `--working-dir` is
root context, not a table name. Missing or conflicting table selection returns
`NEEDS_CONTEXT`; an explicitly empty approved list is a verified no-op.
Inspect `<working_dir>/.datamodel-manifest.json`, or
`<working_dir>/docs/plan-artifacts/.datamodel-manifest.json` for newer apps, only
to verify those selected tables. The manifest is not permission to enable every
row. Do not discover another app's manifest or expand the allowlist silently.
### Step 3 — Inspect current state
**Print before starting:**
> "→ Querying current IsAvailableOffline + ChangeTrackingEnabled for <N> table(s)…"
For each table, in sequence:
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" GET \
"EntityDefinitions(LogicalName='<table>')?\$select=LogicalName,DisplayName,IsAvailableOffline,ChangeTrackingEnabled,IsCustomizable" \
--tenant-id "<tenantId>"
```
Build a status table:
```text
| Table | IsAvailableOffline | ChangeTrackingEnabled | IsCustomizable | Needs change? |
|--------------------|--------------------|-----------------------|----------------|---------------|
| cr123_note | false | false | true | YES (both) |
| cr123_visit | true | false | true | YES (track) |
| contact | true | true | true | NO |
```
**Hard rule:** if `IsCustomizable.Value=false` on any table, that table CANNOT be modified. Drop it from the change set and flag in `DONE_WITH_CONCERNS` — system-managed tables (most OOB) require an admin solution patch path the skill does not handle.
### Gate — Approval before mutation
Compare the status table from Step 3 with the owner's approved prerequisite and
publication delta. Matching current Gate 1 approval is reused without a duplicate
prompt. Otherwise return the status table and `NEEDS_CONTEXT: offline prerequisite
approval` to `/setup-offline-profile`, which owns the approval gate. Do not widen
scope or override proposal-only mode.
Plan body:
```text
The following EntityMetadata changes will be PUT in sequence:
cr123_note → set IsAvailableOffline=true, ChangeTrackingEnabled=true
cr123_visit → set ChangeTrackingEnabled=true (IsAvailableOffline already true)
After all updates, targeted PublishXml will publish only the changed tables.
Tables already in the desired state are skipped (no API call).
```
If the user rejects, STOP. Proceed only with the exact approved delta.
### Step 4 — PUT EntityMetadata per table
**Print before starting:**
> "→ Updating EntityMetadata for <N> table(s) sequentially (Dataverse serializes metadata writes)…"
> **⚠️ Concurrency rule — do not violate.** Metadata writes hold an exclusive lock per org. Issue one PUT, wait for 2xx, then the next. No batching, no parallel calls. Same rule as `/add-dataverse` Step 5.
For each table needing change (skip ones already in target state):
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/update-entity-offline-flags.js" "<envUrl>" \
--table "<table>" \
--offline true \
--tracking true \
--tenant-id "<tenantId>"
```
The helper:
- Re-reads `EntityMetadata` to pick up the current `MetadataId` + `SchemaName` (both required in the PUT body — Dataverse rejects PUT without them).
- Sends `MSCRM.MergeLabels: true` so display labels are preserved (the alternative wipes labels — never use `false`).
- Returns `{ "status": 200, "noop": true, ... }` if the table is already in the target state (skip silently).
- Returns `{ "status": 200, "skipped": "uncustomizable", ... }` for tables whose `IsCustomizable.Value=false` (system-managed; you must surface as `DONE_WITH_CONCERNS`).
- Returns `{ "status": 204, ... }` on successful update.
- Handles 401 token refresh and 429 back-off automatically.
**If the helper returns status 403 `PrivilegeCheckFailed`:** the user lacks "Customize System" privilege. Print the table name and which privilege is missing, then STOP.
**If status 400 with `ChangeTrackingEnabled cannot be disabled`:** ignore — that path only triggers when going from true to false, which we never do.
Print `✓ <table>` after each 204; print `↷ <table> (already enabled)` for no-ops; print `⚠ <table> (uncustomizable)` for skips.
### Step 5 — Publish customizations (targeted PublishXml, with PublishAllXml fallback)
**Print before starting:**
> "→ Publishing customizations (targeted PublishXml on the entities just edited)…"
**Use targeted `PublishXml`** scoped to the entities that were actually modified — avoids the org-wide rate-limit storms (`0x80071151` "concurrent PublishAll already running") observed on shared envs. Empirical 2026-05-25.
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
# Build the <entities> XML body from the list of tables modified in Step 4
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" POST \
"PublishXml" --tenant-id "<tenantId>" --body '{
"ParameterXml": "<importexportxml><entities><entity><table></entity></entities></importexportxml>"
}'
```
Substitute `<entity>...</entity>` lines for every table the helper PUT'd flags on in Step 4. Tables that were no-ops or uncustomizable are omitted.
**On 204**: success — continue to Step 6.
**On 429 / 0x80071151 ("concurrent publish already running")**: back off automatically via `dataverse-request.js`'s retry logic. If still failing after 4 retries, return `DONE_WITH_CONCERNS: publish bottlenecked on shared env; metadata changes are committed but maker portal will not refresh until next publish`. The downstream skill (`/setup-offline-profile`) can proceed — metadata-level writes are durable.
**Fallback to `PublishAllXml`** only when the targeted call returns a non-rate-limit
error such as `0x80048d19` and the owner separately approves the broader publication.
Table-only approval does not authorize publishing unrelated changes.
```bash
cd -- '<working_dir>' || { echo "BLOCKED: cannot enter working_dir" >&2; exit 1; }
node "${PLUGIN_ROOT}/scripts/dataverse-request.js" "<envUrl>" POST \
"PublishAllXml" --tenant-id "<tenantId>" --body '{}'
```
Same timeout-but-success handling as `/setup-offline-profile` Step 8: if the client times out but a follow-up GET on the table's EntityMetadata shows the flags are set, treat as success.
### Step 6 — Verify
**Print before starting:**
> "→ Re-querying EntityMetadata to confirm flags are set…"
Re-run the Step 3 query for each modified table. Assert `IsAvailableOffline=true` and `ChangeTrackingEnabled=true` on every changed row. If any disagree, BLOCKED — something rejected the PUT silently (extremely unlikely; usually an indication of a managed-solution layer that's masking the unmanaged change).
### Step 7 — Summary
Print:
```text
✓ Offline prerequisites enabled on <N> table(s):
- cr123_note (IsAvailableOffline + ChangeTrackingEnabled set)
- cr123_visit (ChangeTrackingEnabled set; IsAvailableOffline already on)
Skipped (already enabled): contact
Next: return to the current /setup-offline-profile workflow.
```
Update `<working_dir>/memory-bank.md` under `## Offline profile` with the timestamp
and verified table list. Return the results to the current owner; do not launch
another offline setup workflow.
## Status code
The literal first line of the skill's response is one of:
- `DONE` — all requested tables now have both flags set
- `DONE_WITH_CONCERNS: <list>` — some tables skipped (uncustomizable, publish warning, etc.)
- `NEEDS_CONTEXT: <missing>` — couldn't resolve table list and user didn't provide
- `BLOCKED: <reason>` — auth failure, privilege check failed, or post-PUT verification disagreed
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.md12 KB · e5bfa70bc056
1 file, 12 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