add-sample-data
The add-sample-data Claude Code skill populates Dataverse tables with sample records via OData API to enable users to test and demonstrate Power Pages sites. Use this skill when you need to quickly load test data into custom Dataverse tables while respecting referential integrity by inserting parent records before child records, tracking progress across six phases, and gracefully handling insertion failures without attempting rollback.
git clone --depth 1 https://github.com/microsoft/power-platform-skills /tmp/add-sample-data && cp -r /tmp/add-sample-data/plugins/power-pages/skills/add-sample-data ~/.claude/skills/add-sample-dataSKILL.md
> **Plugin check**: Run `node "${CLAUDE_PLUGIN_ROOT}/scripts/check-version.js"` — if it outputs a message, show it to the user before proceeding.
# Add Sample Data
Populate Dataverse tables with sample records via OData API so users can test and demo their Power Pages sites.
## Core Principles
- **Respect insertion order**: Always insert parent/referenced tables before child/referencing tables so lookup IDs are available when needed.
- **Use TaskCreate/TaskUpdate**: Track all progress throughout all phases -- create the todo list upfront with all phases before starting any work.
- **Fail gracefully**: On insertion failure, log the error and continue with remaining records -- never attempt automated rollback.
**Initial request:** $ARGUMENTS
---
## Phase 1: Verify Prerequisites
**Goal**: Confirm PAC CLI auth, acquire an Azure CLI token, and verify API access
**Actions**:
1. Create todo list with all 6 phases (see [Progress Tracking](#progress-tracking) table)
2. Follow the prerequisite steps in `${CLAUDE_PLUGIN_ROOT}/references/dataverse-prerequisites.md` to verify PAC CLI auth, acquire an Azure CLI token, and confirm API access. Note the environment URL as `<envUrl>` for subsequent script calls.
**Output**: Authenticated session with valid token and confirmed API access
---
## Phase 2: Discover Tables
**Goal**: Find the custom tables available in the user's Dataverse environment
**Actions**:
### Path A: Read `.datamodel-manifest.json` (Preferred)
Check if `.datamodel-manifest.json` exists in the project root (written by the `setup-datamodel` skill). If it exists, read it -- it already contains table logical names, display names, and column info.
See `${CLAUDE_PLUGIN_ROOT}/references/datamodel-manifest-schema.md` for the full manifest schema.
### Path B: Query OData API (Fallback)
If no manifest exists, discover custom tables via OData:
```
node "${CLAUDE_PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET "EntityDefinitions?\$select=LogicalName,DisplayName,EntitySetName&\$filter=IsCustomEntity eq true"
```
For each discovered table, fetch its custom columns:
```
node "${CLAUDE_PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET "EntityDefinitions(LogicalName='<table>')/Attributes?\$select=LogicalName,DisplayName,AttributeType,RequiredLevel&\$filter=IsCustomAttribute eq true"
```
### 2.1 Present Available Tables
Show the user the list of discovered tables with their columns so they can choose which to populate.
**Output**: List of discovered tables with their columns presented to the user
---
## Phase 3: Select Tables & Configure
**Goal**: Gather user preferences on which tables to populate and how many records to create
**Actions**:
### 3.1 Select Tables
<!-- gate: add-sample-data:3.1.tables | category=plan | cancel-leaves=nothing -->
> 🚦 **Gate (plan · add-sample-data:3.1.tables):** Multi-select over discovered tables — decides which tables get populated with sample data.
>
> **Trigger:** Phase 2 discovery completed.
> **Why we ask:** Auto-selecting all tables can pollute production-shape tables (e.g. `contact`) with throwaway records.
> **Cancel leaves:** Nothing — no record inserts yet.
Use `AskUserQuestion` to ask which tables they want to populate (use `multiSelect: true`). List all discovered tables as options.
### 3.2 Select Record Count
<!-- gate: add-sample-data:3.2.count | category=plan | cancel-leaves=nothing -->
> 🚦 **Gate (plan · add-sample-data:3.2.count):** Pick records-per-table (5 / 10 / 25 / Custom). Custom branch is a follow-up free-text prompt under the same gate.
>
> **Trigger:** Tables selected in 3.1.
> **Why we ask:** Inserting hundreds of records can blow past Dataverse storage / API throttling budgets.
> **Cancel leaves:** Nothing — no record inserts yet.
Use `AskUserQuestion` to ask how many sample records per table:
| Option | Description |
|--------|-------------|
| **5 records** | Quick test -- just enough to verify the setup |
| **10 records** | Light demo data for basic testing |
| **25 records** | Fuller dataset for realistic demos |
| **Custom** | Let the user specify a number |
### 3.3 Determine Insertion Order
Analyze relationships between selected tables. Parent/referenced tables must be inserted first so their IDs are available for child/referencing table lookups.
Build the insertion order:
1. Tables with no lookup dependencies (parent tables) -- insert first
2. Tables that reference already-inserted tables -- insert next
3. Continue until all tables are ordered
**Output**: Confirmed table selection, record count, and insertion order
---
## Phase 4: Generate & Review Sample Data
**Goal**: Generate contextually appropriate sample records and get user approval before inserting
**Actions**:
### 4.1 Generate Contextual Sample Data
For each selected table, generate sample records with contextually appropriate values based on column names and types:
- **String columns**: Generate realistic values matching the column name (e.g., "Email" -> `jane.doe@example.com`, "Phone" -> `(555) 123-4567`, "Name" -> realistic names)
- **Memo columns**: Generate short descriptive text relevant to the column name
- **Integer/Decimal/Currency columns**: Generate reasonable numeric values
- **DateTime columns**: Generate dates within a sensible range (past year to next month)
- **Boolean columns**: Mix of `true` and `false` values
- **Picklist/Choice columns**: Query valid options first (see references/odata-record-patterns.md), then use actual option values
- **Lookup columns**: Reference records from parent tables that will be/were already inserted
### 4.2 Present Sample Data Preview
For each table, show a markdown table previewing the sample records directly in the conversation:
```markdown
### Project (cr123_project) -- 5 records
| Name | Description | Status | Start Date |
|------|-------------|--------|------------|
| Website Redesign | Modernize the corporate website | 100000000 (Active) | 2025-03-15 |
|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.
Creates or edits a Power Apps Canvas App through the Canvas Authoring MCP coauthoring session. Handles new app generation from requirements, simple inline edits, and complex multi-screen changes with parallel screen builders. Triggers on requests to create, build, generate, modify, update, change, or edit a Canvas App or .pa.yaml files.
Configure the Canvas Authoring MCP server for the current coauthoring session. USE WHEN "configure MCP", "set up MCP server", "MCP not working", "connect Canvas Apps MCP", "canvas-authoring not available", "MCP not configured", "set up canvas apps". DO NOT USE WHEN prerequisites are missing — direct the user to install .NET 10 SDK first.
[DEPRECATED — use canvas-app instead] Generate a complete Power Apps canvas app.
>
Adds Azure DevOps connector to a Power Apps code app. Use when querying work items, creating bugs, managing pipelines, or making ADO API calls.
Adds any Power Platform connector to a Power Apps code app. Generic fallback for connectors not covered by a specific skill.
Adds a data source or connector to a Power Apps code app. Asks what the user wants to accomplish and routes to the appropriate specialized skill.