Ch 02 · Chapter 2: Configuring Your AI Dev Team
Part 1 · Chapter 02 ≈ reading…

Chapter 2: Configuring Your AI Dev Team

"The setup chapter is the one everyone skips and then regrets. Don't skip this one. Every hour you invest here saves ten hours later."
In this chapter
  • Licensing requirements and costs for Claude Code and GitHub Copilot
  • Every configuration file Claude Code uses — what each does and how to write it well
  • How to configure all relevant MCP servers for Power Platform development
  • How to manage Claude Code permissions so it can act without constant approval prompts
  • How to set up PAC CLI with multiple environment auth profiles
  • Every GitHub Copilot configuration asset — VS Code settings, project instructions, workspace settings
  • How to install the Power Platform skill packs
  • A complete, copy-paste-ready configuration reference for a new project

The Configuration Landscape

Before touching any file, understand what you're configuring and why.

Diagram 1

Figure 2.1 — The full configuration landscape. Claude Code reads a layered set of files at session start. GitHub Copilot reads project-level files continuously as you edit. PAC CLI stores authenticated environment profiles separately.

Part 1: Claude Code

Installation

Prerequisites: Node.js 18 or later.

bash
npm install -g @anthropic-ai/claude-code
claude --version   # verify

API Key

Get your key from console.anthropic.comAPI Keys → Create Key.

Set it permanently in your shell profile:

powershell
# Windows PowerShell — add to $PROFILE
$env:ANTHROPIC_API_KEY = "sk-ant-api03-..."
bash
# macOS / Linux — add to ~/.zshrc or ~/.bashrc
export ANTHROPIC_API_KEY="sk-ant-api03-..."

Or authenticate interactively (stores token in the Claude Code credential store):

bash
claude auth login

Spend limits: Set a monthly spend limit in the Anthropic console before any heavy use. Claude Code sessions for Power Platform work typically cost $0.10–$2.00. Runaway agentic loops can cost more — a limit prevents surprises.

Licensing

Before configuring anything, understand what you're paying for and what you're not.

Claude Code / Anthropic API

Claude Code itself is free to install. You pay only for the API calls it makes. There is no separate "Claude Code subscription" — it runs on the same Anthropic API account you'd use for any other Anthropic integration.

How you're billed: Per token, per model. Every message you send and every response Claude generates consumes tokens. The Anthropic console shows your usage in real time.

Models and what they cost (approximate, as of 2025):

ModelWhen to useRelative cost
claude-haiku-4-5-20251001Fast answers, simple completions, high-volume tasksLowest
claude-sonnet-4-6The default for Claude Code — best balance of quality and costModerate
claude-opus-4-7Complex architectural decisions, maximum reasoning qualityHighest

(Model IDs as of mid-2025 — check console.anthropic.com for current model IDs, as these change with new releases.)

For day-to-day Power Platform development (generating flows, scaffolding Canvas apps, reviewing Dataverse schema), Sonnet is the right default. Reserve Opus for the moments where quality justifiably matters more than cost — a complex multi-table data model design, a production-critical system prompt.

What a typical Claude Code session costs:

TaskApproximate cost
Generate a Dataverse data model (5 tables)$0.05–$0.15
Scaffold a 3-screen Canvas app$0.10–$0.30
Generate + review a Power Automate flow$0.05–$0.20
Full chapter review and revision cycle$0.20–$0.80
Extended multi-file refactoring session (1–2 hours)$1.00–$3.00

These are estimates. Context size is the biggest cost driver — the more files Claude Code reads in a session, the more tokens are consumed. This is why the skills and CLAUDE.md approach in this chapter matters: well-structured context is also efficient context.

Setting a spend limit:

In the Anthropic consoleSettings → Billing, set a monthly spend limit before any serious use. $20–$50/month is a reasonable starting point for a single developer. At that ceiling, you can run hundreds of generation sessions before hitting the limit — and the limit prevents any runaway loop from generating a surprise bill.

Diagram 2

Figure 2.2 — Claude Code is free. You pay for the API calls it makes, billed to your Anthropic account with a spend limit you control.

Free tier: Anthropic offers limited free API credits for new accounts. For a book walkthrough or initial exploration, this may be sufficient. For ongoing Power Platform development, a paid plan is necessary.


GitHub Copilot

GitHub Copilot is a subscription product with four tiers:

TierPriceBest for
Free$0Students, verified open-source maintainers, GitHub Education participants
Individual$10/month or $100/yearSolo developers
Business$19/user/monthTeams; adds policy controls, audit logs, excludes public code matching
Enterprise$39/user/monthLarge organisations; adds Copilot for pull requests, fine-tuning on private repos, enterprise SSO

For most Power Platform developers working in a corporate environment, the relevant question is Business vs. Enterprise. The practical difference for the use cases in this book:

  • Business gives you everything covered in this book: inline completions, Copilot Chat, @workspace, .github/copilot-instructions.md context, and Copilot in the CLI.
  • Enterprise adds features useful at scale: Copilot for pull request summaries, knowledge bases trained on internal repositories, and enterprise policy enforcement. Worth it if your organisation is rolling Copilot out to 50+ developers.

Free tier eligibility: If you're a student, verified teacher, or a maintainer of a qualifying open-source project, apply at education.github.com or github.com/github-copilot-for-open-source. Eligibility is verified — it is not automatically applied.

Activating in VS Code: After subscribing, install the GitHub Copilot and GitHub Copilot Chat extensions (both are free in the VS Code marketplace; the subscription is what enables them). Sign in with your GitHub account. Copilot becomes active immediately.

Corporate procurement note: Many enterprise Microsoft 365 agreements include GitHub Enterprise, which bundles Copilot Business. Check with your IT procurement team before purchasing individually — you may already have access.


PAC CLI and MCP Servers

Both are free. PAC CLI is an open-source Microsoft tool. The MCP servers covered in this chapter (Dataverse, Canvas Authoring, Power Pages, Microsoft Docs, Context7) are installed via npx at no cost. The Dataverse MCP server uses your existing Dataverse environment — no additional licensing is required beyond the Power Platform license you already hold for development work.

Power Platform licensing note: The development tools covered in this chapter (Claude Code, GitHub Copilot, PAC CLI, MCP servers) have no additional licensing cost beyond what you already pay. However, the solutions you build will carry their own licensing requirements when deployed to users — Premium connectors, Dataverse capacity, Power Pages monthly active users. Budget for production user licensing separately from development tool costs.


~/.claude/settings.json — Global Settings

This is the most important configuration file. It governs everything that should apply across all your projects: MCP servers, permissions, model preferences.

jsonc
// ~/.claude/settings.json
{
  // Default model for all sessions
  "model": "claude-sonnet-4-6",

  // MCP servers — covered in full detail in Part 2 of this chapter
  "mcpServers": { ... },

  // Permissions — commands Claude Code can run without asking
  "permissions": {
    "allow": [
      "Bash(pac:*)",
      "Bash(npm:*)",
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "Bash(git add:*)",
      "Bash(git commit:*)"
    ],
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)"
    ]
  }
}

.claude/settings.json — Project Settings

Stored in your project folder under .claude/. Overrides global settings for this project only. Commit this file to git — it contains project configuration that all team members should share.

jsonc
// .claude/settings.json  (committed to git)
{
  // Override MCP server to use this project's specific environment
  "mcpServers": {
    "dataverse": {
      "command": "dataverse-mcp-server",
      "args": [],
      "env": {
        "DATAVERSE_URL": "https://contosodev.crm.dynamics.com"
        // Credentials come from settings.local.json — not here
      }
    }
  },

  // Project-specific allowed commands
  "permissions": {
    "allow": [
      "Bash(pac solution:*)",
      "Bash(pac canvas:*)",
      "Bash(pac pages:*)",
      "Bash(pac auth:*)"
    ]
  }
}

.claude/settings.local.json — Local Secrets

Same structure as settings.json, but never committed to git (add it to .gitignore). Store credentials, personal API keys, and machine-specific values here.

jsonc
// .claude/settings.local.json  (gitignored)
{
  "mcpServers": {
    "dataverse": {
      "env": {
        "DATAVERSE_URL": "https://contosodev.crm.dynamics.com",
        "DATAVERSE_CLIENT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "DATAVERSE_CLIENT_SECRET": "your-actual-secret-here",
        "DATAVERSE_TENANT_ID": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
      }
    }
  }
}

Layering order: settings.local.json values merge on top of settings.json, which merges on top of ~/.claude/settings.json. This means you can keep secrets out of git while still committing the project-level structure.

The CLAUDE.md Files

CLAUDE.md is plain markdown. Claude Code reads it at the start of every session. It shapes every response, every generated file, and every decision Claude Code makes for the duration of that session. Think of it as a standing brief you hand your developer before they start work.

There are two levels:

~/.claude/CLAUDE.md — Global User Memory

Applies to every Claude Code session, regardless of project. Use this for your personal preferences and cross-project standards.

markdown
# My Development Standards

## General Preferences
- Always explain what you're about to do before doing it
- When generating files, show a summary of what was created
- Prefer small, targeted edits over large rewrites when modifying existing files
- Ask before deleting any file

## Power Platform Standards (apply to all projects)
- All flows use connection references — never direct connection names
- All sensitive configuration values go in environment variables
- Canvas apps: Tablet layout (1920×1080) unless told otherwise
- Dataverse columns: use schema names in all expressions and queries

## Communication Style
- Be concise. Skip preamble.
- If something is ambiguous, ask one clarifying question before proceeding
- When reviewing generated output, lead with what's correct, then flag issues

CLAUDE.md — Project Context

Lives in the project root. This is where project-specific conventions, table names, environment URLs, and team standards live. The more precise this file is, the less correction you'll need.

markdown
# Project: Contoso Field Service App

## Environment
- Dev:  https://contosodev.crm.dynamics.com
- UAT:  https://contosouat.crm.dynamics.com
- Prod: https://contoso.crm.dynamics.com
- Solution name: FieldServiceApp
- Publisher prefix: fs_
- Publisher name: Contoso

## Connection References (use these exact names in all flows)
- Dataverse: shared_commondataservice
- Office 365 Outlook: shared_office365
- Microsoft Teams: shared_teams
- SharePoint: shared_sharepointonline

## Environment Variables (never hardcode these values)
- DispatcherEmail — email address of the duty dispatcher
- ManagerEmail — email address of the operations manager
- ModelDrivenAppUrl — URL to the model-driven app (for deep links in emails)
- ReorderThresholdDays — days before expiry to trigger reorder

## Key Tables and Schema Names
| Display Name      | Schema Name          | Key Columns                            |
|-------------------|----------------------|----------------------------------------|
| Work Order        | fs_workorder         | fs_name, fs_status, fs_priority, fs_scheduleddate |
| Technician        | fs_technician        | fs_name, fs_skilllevel, fs_availabilitystatus |
| Service Location  | fs_servicelocation   | fs_name, fs_addressline1, fs_restrictedaccess |
| Parts Used        | fs_partsused         | fs_quantity, fs_unitcost               |

## Canvas App Standards
- Layout: Tablet 1920×1080
- Naming: scrScreenName, galGalleryName, btnButtonName, txtInputName
- Colors: Primary #1B3A6B, Accent #E87722, Surface #F8F9FA
- Every gallery must have an empty-state message: "No records found"
- Every Patch() must have error handling via IfError()

## Flow Standards
- Name format: "Contoso - [Trigger Table] - [Purpose]"
- All Dataverse columns referenced by schema name, not display name
- Error handling required on: HTTP, email send, approval actions
- Approval flows: 7-day timeout with escalation branch

## Power Pages Standards
- Publisher prefix: fs_
- All FetchXML must include account filter for the authenticated user
- All Web API calls must include CSRF token
- User input must be escaped with | escape filter

## Do Not
- Do not use App.OnStart for data loading in Canvas apps
- Do not create tables without Status and Status Reason columns
- Do not hardcode GUIDs anywhere
- Do not use text fields for fixed-choice data
- Do not commit .claude/settings.local.json

Claude Code Permissions

By default, Claude Code asks for approval before running certain commands. For Power Platform development, many of these commands are routine — asking for approval every time adds friction without adding safety.

Configure the allow list in ~/.claude/settings.json:

jsonc
{
  "permissions": {
    "allow": [
      // PAC CLI — all Power Platform operations
      "Bash(pac solution:*)",
      "Bash(pac canvas:*)",
      "Bash(pac pages:*)",
      "Bash(pac auth:*)",
      "Bash(pac dataverse:*)",
      "Bash(pac flow:*)",
      "Bash(pac pcf:*)",
      "Bash(pac copilot:*)",

      // npm — package management
      "Bash(npm install:*)",
      "Bash(npm run:*)",
      "Bash(npm build:*)",

      // git — read-only and safe write operations
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "Bash(git add:*)",
      "Bash(git commit:*)",
      "Bash(git pull:*)",
      "Bash(git checkout:*)",
      "Bash(git branch:*)"
    ],
    "deny": [
      // Never allow without explicit confirmation
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)",
      "Bash(git reset --hard:*)",
      "Bash(pac solution delete:*)"
    ]
  }
}

The deny list matters. Even if a command would otherwise be allowed, an explicit deny blocks it. Protect the operations that are hard to reverse.

The Skills Directory

Skills are markdown files that encode reusable procedures. Two locations:

code
~/.claude/skills/           # Global — available in every project
.claude/skills/             # Project — available only in this project, 
                            # overrides global if same name

Installing the Power Platform Skill Packs

The official Power Platform plugins are published by Microsoft at github.com/microsoft/power-platform-skills. Install them individually via /plugin install commands inside a Claude Code session — no git clone required.

These are the official Microsoft plugins. The enterprise skills you write yourself (Chapter 9) layer on top of these, encoding your environment's conventions and project-specific patterns. They complement the official plugins, not replace them.

Install the plugins for the asset types you'll be building:

Asset TypePlugin Install Command
Dataverse/plugin install dataverse@claude-plugins-official
Canvas Apps/plugin install canvas-apps@power-platform-skills
Model-Driven Generative Pages/plugin install model-apps@power-platform-skills
Power Pages (Code Sites)/plugin install power-pages@power-platform-skills
Code Apps (preview)/plugin install code-apps@power-platform-skills
Copilot Studio (experimental)/plugin install copilot-studio@skills-for-copilot-studio

Listing Skills

Inside a Claude Code session:

code
/help

Or from the terminal:

bash
ls ~/.claude/skills/power-platform/
ls .claude/skills/

How Claude Code Works: Explore, Plan, Code, Commit

Before you start using Claude Code on a real Power Platform project, it helps to understand the rhythm it follows. Claude Code doesn't just write code — it works in a four-stage agentic loop that mirrors how experienced developers approach a task. Understanding this loop lets you intervene at the right moments and set expectations correctly.

Diagram 3

Figure 2.3 — The four-stage loop Claude Code follows on every task.

Explore

Claude Code starts by reading — not writing. It reads your CLAUDE.md for project standards, any relevant existing files (existing Canvas YAML, solution XML, flow JSON), and if MCP servers are configured, it queries your live Dataverse schema. This is how it knows your publisher prefix, your actual column names, and your environment's topology before it generates a single line.

If you skip the Explore stage by giving Claude Code a task with no context, it invents. Column names, table names, and environment assumptions will be plausible but wrong. The MCP servers and CLAUDE.md from Part 2 and Part 3 of this chapter exist specifically to make the Explore stage accurate.

Plan

Before writing any files, Claude Code proposes an approach. In interactive mode, it tells you what it intends to do and waits for your confirmation. This is the moment to:

  • Redirect if the approach is wrong
  • Add constraints you forgot to mention
  • Ask Claude Code to explain its reasoning if you're uncertain

You can trigger an explicit plan before any task by prefixing your prompt:

code
Think step by step about what you'd need to do to generate the Technician Canvas app 
from the requirements in requirements.md, then tell me your plan before writing anything.

This produces a plan you can review, adjust, and approve — rather than discovering the wrong approach after 200 lines of YAML have been written.

Code

Once the plan is confirmed, Claude Code generates the assets: .pa.yaml files, flow JSON, Dataverse schema XML, Liquid templates, or whatever the task requires. It also runs PAC CLI commands directly — pac solution pack, pac canvas validate, pac pages upload — as part of the generation loop. You don't need to run these manually.

During the Code stage, Claude Code may iterate: generate, validate, read the error, correct, validate again. For Canvas apps, this compile-fix-compile loop runs automatically until the asset is valid or Claude Code surfaces an error it can't resolve without your input.

Commit

After a successful generation, Claude Code stages and commits the output to git. This gives you a clean rollback point at each working state. If the next iteration produces something broken, git reset --hard HEAD~1 takes you back to the last good state.

Make sure your Power Platform solution folder is inside the git repository. Claude Code commits what's in the working tree. If your .pa.yaml files and solution XML live outside the repo, the commit loop has nothing to capture. Chapter 3 sets up the standard folder structure.

The dotted arrow in the diagram represents the most important aspect of this loop: it repeats. One task does not equal one iteration. "Build a Technician Canvas app" will likely run through Explore → Plan → Code → Commit three to five times as Claude Code generates the screens, validates them, fixes delegation issues, adds navigation, and refines based on your feedback. Each commit captures a stable increment.

Part 2: MCP Servers for Power Platform

MCP (Model Context Protocol) servers give Claude Code real-time access to external systems. Without MCP servers, Claude Code generates generic Power Platform code. With them, it generates code that matches your actual live environment.

What MCP Servers Do

Each MCP server exposes a set of tools that Claude Code can call during a session. Claude Code discovers available tools at session start and uses them automatically when relevant — you don't need to explicitly invoke them.

Dataverse MCP Server

Gives Claude Code read/write access to your Dataverse environment's schema and data.

Capabilities: List tables, read column definitions, query data, understand relationships.

Impact: Canvas apps generated with the Dataverse MCP use your actual column schema names. Without it, Claude Code invents column names that don't exist.

bash
npm install -g @microsoft/dataverse-mcp-server

Configuration in ~/.claude/settings.json:

jsonc
{
  "mcpServers": {
    "dataverse": {
      "command": "dataverse-mcp-server",
      "args": [],
      "env": {
        "DATAVERSE_URL": "https://yourorg.crm.dynamics.com",
        "DATAVERSE_CLIENT_ID": "your-app-id",
        "DATAVERSE_CLIENT_SECRET": "your-secret",
        "DATAVERSE_TENANT_ID": "your-tenant-id"
      }
    }
  }
}

App registration setup:

  1. Azure Portal → App registrations → New registration
  2. Name: Claude Code MCP - Dev
  3. After creation: API permissions → Add → Dynamics CRM → user_impersonation
  4. Certificates & secrets → New client secret — copy the value immediately
  5. In Dataverse: Settings → Security → Application Users → New — register the app ID

Canvas Authoring MCP Server

Gives Claude Code awareness of every available Canvas control, their properties, and valid values — enabling accurate .pa.yaml generation.

Capabilities: List controls, describe control properties, list available APIs, describe connectors.

Impact: Generated Canvas app YAML uses correct property names and valid values. Without it, Claude Code may use outdated or invented property names.

jsonc
{
  "mcpServers": {
    "canvas-authoring": {
      "command": "npx",
      "args": ["-y", "@microsoft/canvas-authoring-mcp"]
    }
  }
}

Power Pages MCP Server

Provides documentation and code samples for Power Pages development.

Capabilities: Search Microsoft Learn docs for Power Pages, fetch full doc pages, search code samples.

Impact: Claude Code generates Liquid templates, Web API calls, and table permission configurations with accurate, current syntax.

jsonc
{
  "mcpServers": {
    "power-pages-docs": {
      "command": "npx",
      "args": ["-y", "@microsoft/power-pages-mcp"]
    }
  }
}

Microsoft Learn MCP Server

Gives Claude Code access to the full Microsoft documentation library — Power Platform, Azure, Microsoft 365.

Capabilities: Search docs, fetch specific doc pages, search code samples.

Impact: When generating anything that touches Microsoft APIs, Claude Code can verify current syntax against live documentation rather than training data.

jsonc
{
  "mcpServers": {
    "microsoft-docs": {
      "command": "npx",
      "args": ["-y", "@microsoft/learn-mcp"]
    }
  }
}

Context7 MCP Server

Resolves library documentation on demand — React, Vite, Fluent UI, TypeScript, and more. Essential for Code App development.

Capabilities: Resolve a library ID, fetch current docs for any npm package.

Impact: When building Code Apps, Claude Code checks current Fluent UI React v9 API signatures rather than relying on potentially stale training data.

jsonc
{
  "mcpServers": {
    "context7": {
      "command": "npx",
      "args": ["-y", "@context7/mcp"]
    }
  }
}

Complete ~/.claude/settings.json with All MCP Servers

jsonc
{
  "model": "claude-sonnet-4-6",

  "mcpServers": {
    "dataverse": {
      "command": "dataverse-mcp-server",
      "args": [],
      "env": {
        "DATAVERSE_URL": "https://yourorg.crm.dynamics.com",
        "DATAVERSE_CLIENT_ID": "your-client-id",
        "DATAVERSE_CLIENT_SECRET": "your-secret",
        "DATAVERSE_TENANT_ID": "your-tenant-id"
      }
    },
    "canvas-authoring": {
      "command": "npx",
      "args": ["-y", "@microsoft/canvas-authoring-mcp"]
    },
    "power-pages-docs": {
      "command": "npx",
      "args": ["-y", "@microsoft/power-pages-mcp"]
    },
    "microsoft-docs": {
      "command": "npx",
      "args": ["-y", "@microsoft/learn-mcp"]
    },
    "context7": {
      "command": "npx",
      "args": ["-y", "@context7/mcp"]
    }
  },

  "permissions": {
    "allow": [
      "Bash(pac solution:*)",
      "Bash(pac canvas:*)",
      "Bash(pac pages:*)",
      "Bash(pac auth:*)",
      "Bash(pac dataverse:*)",
      "Bash(pac flow:*)",
      "Bash(pac pcf:*)",
      "Bash(npm install:*)",
      "Bash(npm run:*)",
      "Bash(git status)",
      "Bash(git diff:*)",
      "Bash(git log:*)",
      "Bash(git add:*)",
      "Bash(git commit:*)"
    ],
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(git push --force:*)",
      "Bash(git reset --hard:*)"
    ]
  }
}

Part 3: PAC CLI Setup

Installation

bash
npm install -g @microsoft/powerplatform-cli
pac --version   # verify

Authentication Profiles

PAC CLI stores named authentication profiles so you can switch between environments without re-entering credentials.

bash
# Create a profile for each environment
pac auth create --name "Dev" \
  --url https://contosodev.crm.dynamics.com \
  --kind CdsOrg

pac auth create --name "UAT" \
  --url https://contosouat.crm.dynamics.com \
  --kind CdsOrg

pac auth create --name "Prod" \
  --url https://contoso.crm.dynamics.com \
  --kind CdsOrg

# List all profiles
pac auth list

# Switch active profile
pac auth select --name "Dev"

Claude Code can switch profiles on your behalf:

code
> Switch to the UAT environment and run solution checker

It will execute pac auth select --name "UAT" then the checker command.

Service Principal Authentication (for CI/CD)

For non-interactive environments (pipelines, Claude Code in scripts):

bash
pac auth create --name "Pipeline" \
  --url https://contosodev.crm.dynamics.com \
  --applicationId "your-app-id" \
  --clientSecret "your-secret" \
  --tenant "your-tenant-id"

Part 4: GitHub Copilot

Installation

Prerequisites: VS Code (latest stable), a GitHub account, a GitHub Copilot subscription.

  1. VS Code → Extensions (Ctrl+Shift+X)
  2. Install GitHub Copilot
  3. Install GitHub Copilot Chat
  4. Sign in with GitHub when prompted

Verify: open any file, start typing — you should see grey inline completions.

.github/copilot-instructions.md — Project Instructions

This is GitHub Copilot's equivalent of CLAUDE.md. Copilot Chat reads it as project context. It affects Copilot Chat responses and Copilot's inline suggestion quality for your project.

Create it at .github/copilot-instructions.md:

markdown
# GitHub Copilot Instructions — Contoso Field Service App

## Project Overview
Power Platform solution for field service management.
Publisher prefix: fs_
Primary tables: fs_workorder, fs_technician, fs_servicelocation, fs_partsused, fs_part

## Dataverse Column Reference
When writing Power Fx, OData filters, or FetchXML, use these schema names:
- Work Order: fs_workorderid, fs_name, fs_status (Choice: 1=Scheduled, 2=InProgress, 3=Completed, 4=Cancelled), fs_priority (Choice: 1=Low, 2=Medium, 3=High, 4=Critical), fs_scheduleddate, fs_completiondate
- Technician: fs_technicianid, fs_name, fs_skilllevel, fs_availabilitystatus, fs_email
- Service Location: fs_servicelocationid, fs_name, fs_addressline1, fs_city, fs_postcode, fs_restrictedaccess (Boolean)

## Canvas App Conventions
- Naming: scrScreenName, galName, btnName, txtName, lblName, drpName
- Variables: varVariableName (Set), colCollectionName (Collect)
- Use App.Formulas for repeated expressions
- Never use App.OnStart for data loading — use OnVisible on each screen

## Flow Conventions  
- Connection references: shared_commondataservice, shared_office365, shared_teams
- Environment variables: DispatcherEmail, ManagerEmail, ModelDrivenAppUrl
- Error handling required on all HTTP and email actions

## TypeScript / React (Code Apps)
- Framework: React 18 + TypeScript + Fluent UI React v9
- Use async/await (not .then() chains)
- Custom hooks in src/hooks/, services in src/services/, types in src/types/

## Do Not
- Do not hardcode GUIDs
- Do not use deprecated Fluent UI v8 APIs (use v9)
- Do not use App.OnStart in Canvas apps
- Do not use direct connections in flows (use connection references)

.vscode/settings.json — Workspace Copilot Settings

jsonc
// .vscode/settings.json
{
  // Copilot inline completions
  "github.copilot.enable": {
    "*": true,
    "yaml": true,       // for .pa.yaml Canvas app files
    "markdown": true,   // for CLAUDE.md, skill files
    "liquid": true,     // for Power Pages templates
    "xml": true         // for PCF manifest, FetchXML
  },

  // Show inline suggestions automatically
  "editor.inlineSuggest.enabled": true,
  "editor.suggestSelection": "first",

  // Associate Power Platform file types
  "files.associations": {
    "*.pa.yaml": "yaml",
    "*.pa.yml": "yaml",
    "ControlManifest.Input.xml": "xml"
  },

  // Copilot Chat
  "github.copilot.chat.localeOverride": "en"
}

Commit this so all team members get prompted to install the same extensions:

jsonc
// .vscode/extensions.json
{
  "recommendations": [
    // GitHub Copilot
    "GitHub.copilot",
    "GitHub.copilot-chat",

    // Power Platform
    "microsoft-IsvExpTools.powerplatform-vscode",

    // Language support
    "redhat.vscode-yaml",
    "ms-vscode.vscode-typescript-next",

    // Markdown
    "yzhang.markdown-all-in-one",
    "bierner.markdown-mermaid",    // render Mermaid diagrams

    // Git
    "eamodio.gitlens",

    // Formatting
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint"
  ]
}

Copilot Chat Participants

GitHub Copilot Chat has built-in participants you can direct with @:

ParticipantWhat It DoesPower Platform Use
@workspaceScopes answers to your open project files"Show me all galleries in my Canvas app that are missing empty-state handling"
@vscodeAnswers VS Code-specific questions"How do I configure YAML schema validation for .pa.yaml files?"
@terminalHelps with terminal commands"What's the PAC CLI command to export a managed solution?"
@githubSearches your repo"Find all flows that reference the DispatcherEmail environment variable"

Use @workspace constantly. It's the most useful participant for Power Platform work — it reads your actual project files before answering.

Complete Project Structure

A properly configured Power Platform AI development project:

code
MyProject/
│
├── .claude/
│   ├── settings.json          # Project MCP config + permissions (committed)
│   ├── settings.local.json    # Secrets and local overrides (gitignored)
│   └── skills/                # Project-specific skills
│       └── my-custom-skill.md
│
├── .github/
│   └── copilot-instructions.md    # GitHub Copilot project context
│
├── .vscode/
│   ├── settings.json              # Workspace editor + Copilot settings
│   └── extensions.json            # Recommended extensions
│
├── CLAUDE.md                      # Project context for Claude Code
│
├── .gitignore                     # Must include: .claude/settings.local.json
│
├── solutions/
│   └── MySolution/                # PAC CLI solution folder
│
├── canvas-apps/
│   └── MyApp/                     # Unpacked Canvas app (.pa.yaml files)
│       ├── App.pa.yaml
│       └── Src/
│           ├── Screen1.pa.yaml
│           └── Screen2.pa.yaml
│
├── pages/                         # Power Pages site (pac pages download)
│   ├── website.yml
│   ├── web-templates/
│   ├── web-files/
│   └── basic-forms/
│
├── flows/                         # Exported flow JSON files
│   └── WorkOrderAssignment.json
│
├── connectors/                    # Custom connector definitions
│   └── anthropic-claude.json
│
├── code-apps/                     # React + Vite Code Apps
│   └── DispatcherDashboard/
│       ├── package.json
│       ├── vite.config.ts
│       └── src/
│
└── scripts/                       # Deployment + utility scripts
    ├── deploy-dev.ps1
    ├── deploy-uat.ps1
    └── run-solution-checker.ps1

.gitignore for Power Platform AI Projects

gitignore
# Claude Code secrets — never commit
.claude/settings.local.json

# PAC CLI auth cache
.pac/

# Node modules
node_modules/

# Build output
dist/
build/
*.msapp

# Anthropic API key (if stored in .env)
.env
.env.local

# OS files
.DS_Store
Thumbs.db

Verification Checklist

Run through this after setup to confirm everything works:

markdown
## Setup Verification

### Claude Code
- [ ] `claude --version` returns a version number
- [ ] `claude` opens an interactive session
- [ ] Ask "list my Dataverse tables" — returns actual table names (not generic)
- [ ] Ask "what Canvas controls are available?" — returns control list (Canvas MCP)
- [ ] Ask "show me the Power Pages Web API documentation" — returns doc content (Pages MCP)
- [ ] `pac --version` runs from within a Claude Code session without a permission prompt

### PAC CLI
- [ ] `pac auth list` shows at least one environment profile
- [ ] `pac auth select --name "Dev"` switches without error
- [ ] `pac solution list` returns solutions from your dev environment

### GitHub Copilot
- [ ] Inline suggestions appear when typing in a .pa.yaml file
- [ ] `Ctrl+Shift+I` opens Copilot Chat
- [ ] `@workspace` in Copilot Chat returns answers referencing your project files
- [ ] `.github/copilot-instructions.md` content is reflected in Copilot answers
    (ask: "what is the publisher prefix for this project?" — should answer fs_)

### Skills
- [ ] `/help` inside Claude Code lists available skills including Power Platform ones
- [ ] `/generate-canvas-app` starts the Canvas app generation workflow
- [ ] `/dv-metadata` shows Dataverse table metadata

Quick Reference Card

code
CLAUDE CODE
  Start session:        claude
  Non-interactive:      claude "your prompt" 
  Pipeline mode:        claude --print "prompt"
  List skills:          /help (in session)
  
  Global config:        ~/.claude/settings.json
  Global memory:        ~/.claude/CLAUDE.md
  Global skills:        ~/.claude/skills/
  
  Project config:       .claude/settings.json      (commit)
  Project secrets:      .claude/settings.local.json (gitignore)
  Project context:      CLAUDE.md                   (commit)
  Project skills:       .claude/skills/             (commit)

PAC CLI
  Auth profiles:        pac auth create / list / select
  Canvas pack/unpack:   pac canvas pack / unpack
  Pages upload:         pac pages upload / download
  Solution:             pac solution export / import / check

GITHUB COPILOT (VS CODE)
  Accept suggestion:    Tab
  Dismiss:              Esc
  Next suggestion:      Alt+]
  Open Chat:            Ctrl+Shift+I
  Inline chat:          Ctrl+I
  
  Project context:      .github/copilot-instructions.md
  Workspace settings:   .vscode/settings.json
  Chat participants:    @workspace  @vscode  @terminal  @github
  • Claude Code is free to install; you pay per API token. Set a monthly spend limit in the Anthropic console before any heavy use. Typical Power Platform sessions cost cents, not dollars.
  • GitHub Copilot Individual ($10/month) covers everything in this book. Business adds policy controls for teams; Enterprise adds pull request intelligence at scale. Check your existing Microsoft/GitHub agreements first — you may already have access.
  • PAC CLI and MCP servers are free. No additional Power Platform licensing is needed to use the development tools covered here.
  • Claude Code has a layered configuration model: global → project → local. Secrets go in the local layer (gitignored); structure goes in the project layer (committed); personal preferences go in the global layer.
  • CLAUDE.md is your project brief. Write it with table names, naming conventions, connection reference names, and hard prohibitions. Every session that reads it generates better output.
  • MCP servers are what make Claude Code environment-aware. Configure all five: Dataverse, Canvas Authoring, Power Pages, Microsoft Docs, and Context7. They stack — Claude Code uses whichever is relevant for the task.
  • Permissions eliminate friction. Pre-authorise all PAC CLI and git operations. Claude Code should be able to deploy a solution without asking for permission on every command.
  • GitHub Copilot has its own project context file. .github/copilot-instructions.md is as important for Copilot as CLAUDE.md is for Claude Code. Both should be populated before your team starts using these tools.

What's Next

Configuration complete. Part II starts building. Chapter 3 generates a complete Dataverse data model for a field service app — from plain-language requirements to deployed tables — without opening the maker portal once.