Agent skill
add-policy
Use when adding, modifying, or reviewing VS Code configuration policies. Covers the full policy lifecycle from registration to export to platform-specific artifacts. Run on ANY change that adds a `policy:` field to a configuration property.
Install this agent skill to your Project
npx add-skill https://github.com/microsoft/vscode/tree/main/.github/skills/add-policy
SKILL.md
Adding a Configuration Policy
Policies allow enterprise administrators to lock configuration settings via OS-level mechanisms (Windows Group Policy, macOS managed preferences, Linux config files) or via Copilot account-level policy data. This skill covers the complete procedure.
When to Use
- Adding a new
policy:field to any configuration property - Modifying an existing policy (rename, category change, etc.)
- Reviewing a PR that touches policy registration
- Adding account-based policy support via
IPolicyData
Architecture Overview
Policy Sources (layered, last writer wins)
| Source | Implementation | How it reads policies |
|---|---|---|
| OS-level (Windows registry, macOS plist) | NativePolicyService via @vscode/policy-watcher |
Watches Software\Policies\Microsoft\{productName} (Windows) or bundle identifier prefs (macOS) |
| Linux file | FilePolicyService |
Reads /etc/vscode/policy.json |
| Account/GitHub | AccountPolicyService |
Reads IPolicyData from IDefaultAccountService.policyData, applies value() function |
| Multiplex | MultiplexPolicyService |
Combines OS-level + account policy services; used in desktop main |
Key Files
| File | Purpose |
|---|---|
src/vs/base/common/policy.ts |
PolicyCategory enum, IPolicy interface |
src/vs/platform/policy/common/policy.ts |
IPolicyService, AbstractPolicyService, PolicyDefinition |
src/vs/platform/configuration/common/configurations.ts |
PolicyConfiguration — bridges policies to configuration values |
src/vs/workbench/services/policies/common/accountPolicyService.ts |
Account/GitHub-based policy evaluation |
src/vs/workbench/services/policies/common/multiplexPolicyService.ts |
Combines multiple policy services |
src/vs/workbench/contrib/policyExport/electron-browser/policyExport.contribution.ts |
--export-policy-data CLI handler |
src/vs/base/common/defaultAccount.ts |
IPolicyData interface for account-level policy fields |
build/lib/policies/policyData.jsonc |
Auto-generated policy catalog (DO NOT edit manually) |
build/lib/policies/policyGenerator.ts |
Generates ADMX/ADML (Windows), plist (macOS), JSON (Linux) |
build/lib/test/policyConversion.test.ts |
Tests for policy artifact generation |
Procedure
Step 1 — Add the policy field to the configuration property
Find the configuration registration (typically in a *.contribution.ts file) and add a policy object to the property schema.
Required fields:
Determining minimumVersion: Always read version from the root package.json and use the major.minor portion. For example, if package.json has "version": "1.112.0", use minimumVersion: '1.112'. Never hardcode an old version like '1.99'.
policy: {
name: 'MyPolicyName', // PascalCase, unique across all policies
category: PolicyCategory.InteractiveSession, // From PolicyCategory enum
minimumVersion: '1.112', // Use major.minor from package.json version
localization: {
description: {
key: 'my.config.key', // NLS key for the description
value: nls.localize('my.config.key', "Human-readable description."),
}
}
}
Optional: value function for account-based policy:
If this policy should also be controllable via Copilot account policy data (from IPolicyData), add a value function:
policy: {
name: 'MyPolicyName',
category: PolicyCategory.InteractiveSession,
minimumVersion: '1.112', // Use major.minor from package.json version
value: (policyData) => policyData.my_field === false ? false : undefined,
localization: { /* ... */ }
}
The value function receives IPolicyData (from src/vs/base/common/defaultAccount.ts) and should:
- Return a concrete value to override the user's setting
- Return
undefinedto not apply any account-level override (falls through to OS policy or user setting)
If you need a new field on IPolicyData, add it to the interface in src/vs/base/common/defaultAccount.ts.
Optional: enumDescriptions for enum/string policies:
localization: {
description: { key: '...', value: nls.localize('...', "...") },
enumDescriptions: [
{ key: 'opt.none', value: nls.localize('opt.none', "No access.") },
{ key: 'opt.all', value: nls.localize('opt.all', "Full access.") },
]
}
Step 2 — Ensure PolicyCategory is imported
import { PolicyCategory } from '../../../../base/common/policy.js';
Existing categories in the PolicyCategory enum:
ExtensionsIntegratedTerminalInteractiveSession(used for all chat/Copilot policies)TelemetryUpdate
If you need a new category, add it to PolicyCategory in src/vs/base/common/policy.ts and add corresponding PolicyCategoryData localization.
Step 3 — Validate TypeScript compilation
Check the VS Code - Build watch task output, or run:
npm run compile-check-ts-native
Step 4 — Export the policy data
Regenerate the auto-generated policy catalog:
npm run export-policy-data
This script handles transpilation, sets up GITHUB_TOKEN (via gh CLI or GitHub OAuth device flow), and runs --export-policy-data. The export command reads extension configuration policies from the distro's product.json via the GitHub API and merges them into the output.
This updates build/lib/policies/policyData.jsonc. Never edit this file manually. Verify your new policy appears in the output. You will need code review from a codeowner to merge the change to main.
Policy for extension-provided settings
Extension authors cannot add policy: fields directly—their settings are defined in the extension's package.json, not in VS Code core. Instead, policies for extension settings are defined in vscode-distro's product.json under the extensionConfigurationPolicy key.
How it works
- Source of truth: The
extensionConfigurationPolicymap lives invscode-distroundermixin/{quality}/product.json(stable, insider, exploration). - Runtime: When VS Code starts with a distro-mixed
product.json,configurationExtensionPoint.tsreadsextensionConfigurationPolicyand attaches matchingpolicyobjects to extension-contributed configuration properties. - Export/build: The
--export-policy-datacommand fetches the distro'sproduct.jsonat the commit pinned inpackage.jsonand merges extension policies into the output. Usenpm run export-policy-datawhich sets up authentication automatically.
Distro format
Each entry in extensionConfigurationPolicy must include:
"extensionConfigurationPolicy": {
"publisher.extension.settingName": {
"name": "PolicyName",
"category": "InteractiveSession",
"minimumVersion": "1.99",
"description": "Human-readable description."
}
}
name: PascalCase policy name, unique across all policiescategory: Must be a validPolicyCategoryenum value (e.g.,InteractiveSession,Extensions)minimumVersion: The VS Code version that first shipped this policydescription: Human-readable description string used to generate localization key/value pairs for ADMX/ADML/macOS/Linux policy artifacts
Adding a new extension policy
- Add the entry to
extensionConfigurationPolicyin all three qualityproduct.jsonfiles invscode-distro(mixin/stable/,mixin/insider/,mixin/exploration/) - Update the
distrocommit hash inpackage.jsonto point to the distro commit that includes your new entry — the export command fetches extension policies from the pinned distro commit - Regenerate
policyData.jsoncby runningnpm run export-policy-data(see Step 4 above) - Update the test fixture at
src/vs/workbench/contrib/policyExport/test/node/extensionPolicyFixture.jsonwith the new entry
Test fixtures
The file src/vs/workbench/contrib/policyExport/test/node/extensionPolicyFixture.json is a test fixture that must stay in sync with the extension policies in the checked-in policyData.jsonc. When extension policies are added or changed in the distro, this fixture must be updated to match — otherwise the integration test will fail because the test output (generated from the fixture) won't match the checked-in file (generated from the real distro).
Downstream consumers
| Consumer | What it reads | Output |
|---|---|---|
policyGenerator.ts |
policyData.jsonc |
ADMX/ADML (Windows GP), .mobileconfig (macOS), policy.json (Linux) |
vscode-website (gulpfile.policies.js) |
policyData.jsonc |
Enterprise policy reference table at code.visualstudio.com/docs/enterprise/policies |
vscode-docs |
Generated from website build | docs/enterprise/policies.md |
Examples
Search the codebase for policy: to find all the examples of different policy configurations.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
component-fixtures
Use when creating or updating component fixtures for screenshot testing, or when designing UI components to be fixture-friendly. Covers fixture file structure, theming, service setup, CSS scoping, async rendering, and common pitfalls.
memory-leak-audit
Audit code for memory leaks and disposable issues. Use when reviewing event listeners, DOM handlers, lifecycle callbacks, or fixing leak reports. Covers addDisposableListener, Event.once, MutableDisposable, DisposableStore, and onWillDispose patterns.
fix-ci-failures
Investigate and fix CI failures on a pull request. Use when CI checks fail on a PR branch — covers finding the PR, identifying failed checks, downloading logs and artifacts, extracting the failure cause, and iterating on a fix. Requires the `gh` CLI.
azure-pipelines
Use when validating Azure DevOps pipeline changes for the VS Code build. Covers queueing builds, checking build status, viewing logs, and iterating on pipeline YAML changes without waiting for full CI runs.
chat-customizations-editor
Use when working on the Chat Customizations editor — the management UI for agents, skills, instructions, hooks, prompts, MCP servers, and plugins.
accessibility
Primary accessibility skill for VS Code. REQUIRED for new feature and contribution work, and also applies to updates of existing UI. Covers accessibility help dialogs, accessible views, verbosity settings, signals, ARIA announcements, keyboard navigation, and ARIA labels/roles.
Didn't find tool you were looking for?