platform-manifest-generate
forcedotcom/sf-skills
Generate Salesforce package.xml and destructive manifests from source, component lists, or org introspection.
What is platform-manifest-generate?
Creates Salesforce metadata manifests (package.xml, destructiveChanges.xml, and variants) for deployment and deletion operations. Use this to author manifest files from local source directories, explicit component lists, or by introspecting a live org—then hand off to deployment skills for execution.
- Generate package.xml from a source directory (e.g., force-app/main/default)
- Build manifests from explicit component lists (e.g., ApexClass:AccountService, CustomObject:Account)
- Introspect an org and create a manifest of all (or filtered) metadata types
- Produce destructiveChanges.xml, destructiveChangesPre.xml, or destructiveChangesPost.xml for deletions
- Generate both package.xml and destructive manifests in a single operation
- Encode wildcard-vs-explicit-member rules per Salesforce metadata type
How to install platform-manifest-generate
npx skills add https://github.com/forcedotcom/sf-skills --skill platform-manifest-generate- Salesforce CLI (sf) version 2.0.0 or higher
- sfdx-project.json file in the project root (for sourceApiVersion)
- For --from-org: authenticated org alias or username
How to use platform-manifest-generate
- 1.Run `sf project generate manifest --source-dir <path>` to scan a local directory for metadata
- 2.Or run `sf project generate manifest --metadata ApexClass:Name CustomObject:Name` to specify components explicitly
- 3.Or run `sf project generate manifest --from-org <alias>` to introspect an org
- 4.Use `--type destroy` (or `pre`/`post`) to generate destructive manifests instead of package.xml
- 5.Specify `--output-dir` to control where the manifest file is written
- 6.Review the generated manifest file before handing off to platform-metadata-deploy or platform-destructive-deploy
Use cases
- Create a deployment manifest from a feature branch containing new Apex classes and custom fields
- Generate a destructive manifest to remove deprecated custom fields and validation rules from production
- Build a manifest by querying an org to capture all current metadata for backup or comparison
- Create pre- and post-deployment destructive manifests for complex refactoring operations
- Generate a manifest from a git diff to deploy only changed components
- Salesforce developers preparing metadata for deployment
- DevOps engineers automating manifest generation in CI/CD pipelines
- Release managers creating manifests for production deployments
- Admins managing metadata deletions and org cleanup
platform-manifest-generate FAQ
Use this skill to generate the manifest file itself. Once the manifest exists, hand off to platform-metadata-deploy to execute the deployment. This skill is purely about authoring the manifest.
Yes, but you must run the CLI twice—once with `--type package` (or default) and once with `--type destroy`. Each run produces one manifest file.
destructiveChanges.xml deletes components during the main deployment. destructiveChangesPre.xml deletes before the main deployment, and destructiveChangesPost.xml deletes after. Use pre/post when deletion order matters.
It reads sourceApiVersion from sfdx-project.json first, then respects any --api-version flag you pass, then falls back to the CLI's bundled version (with a warning). Never hardcode a version.
The CLI path never emits wildcards—it produces explicit member lists per metadata type, which is the canonical approach. The hand-built fallback also avoids wildcards to prevent ambiguity.
Full instructions (SKILL.md)
Source of truth, from forcedotcom/sf-skills.
name: platform-manifest-generate description: "Use to generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir, a component list, or org introspection. Trigger on 'generate a package.xml from this folder', 'create a manifest for these classes', 'I need a deploy manifest', or 'destructiveChanges.xml for deletions'. Encodes wildcard-vs-explicit-member rules per metadata type. DO NOT TRIGGER to deploy (platform-metadata-deploy), delete (platform-destructive-deploy), or retrieve (platform-metadata-retrieve)." metadata: version: "1.0" relatedSkills: - "platform-metadata-deploy" - "platform-metadata-retrieve" - "platform-destructive-deploy" - "platform-deploy-validate" cliTools: - tool: ["sf"] semver: ">=2.0.0"
platform-manifest-generate
Produce a Salesforce metadata manifest — package.xml (or one of the destructive variants) — from local source, an org, or an explicit component list. This skill is purely about authoring the manifest file. Hand off to platform-metadata-deploy or platform-destructive-deploy once the file exists.
Tool Restrictions
Use ONLY the Bash tool to run sf project generate manifest, and the Write tool for the hand-built fallback path. Do NOT use MCP tools.
When This Skill Owns the Task
Use platform-manifest-generate when the work involves any of:
- Building a
package.xmlfrom a source directory (e.g.force-app/main/default/classes/) - Building a manifest from an explicit list of components (e.g.
AccountService,ContactSelector,Account) - Building a manifest by introspecting an org via
--from-org - Producing
destructiveChanges.xml,destructiveChangesPre.xml, ordestructiveChangesPost.xmlfor a deletion - Producing both a
package.xmland a destructive manifest in one operation
Delegate elsewhere when the user is:
- Running the deploy itself →
platform-metadata-deploy - Validating before a prod release →
platform-deploy-validate - Executing the destructive deploy →
platform-destructive-deploy(that skill uses the manifest this skill generates) - Retrieving metadata to local →
platform-metadata-retrieve
Two Generation Paths
Path A — CLI-driven (recommended)
Wrap sf project generate manifest. Always prefer this path; it knows about every metadata type and produces canonical XML — and never emits *, sidestepping the wildcard hazard entirely.
The CLI offers three input modes (mutually exclusive):
| Input | Flag | Use when |
|---|---|---|
| Source directory | --source-dir (-p) | User points to a folder containing already-on-disk metadata |
| Component list | --metadata (-m) | User names specific components, e.g. ApexClass:AccountService CustomObject:Account |
| Org introspection | --from-org | User wants every component currently in an org (or a filtered subset) |
You can specify either --source-dir or --metadata, not both. --from-org may be combined with --metadata (filter included types) or --excluded-metadata (filter out types).
Verified flags (do not invent flags — verify with sf project generate manifest --help if unsure):
| Flag | Purpose |
|---|---|
--source-dir, -p | Local source paths to scan |
--metadata, -m | Component names to include (e.g. ApexClass:AccountService) |
--from-org | Username or alias of org to introspect |
--name, -n | Custom output filename (mutually exclusive with --type) |
--type, -t | Predefined manifest kind: package | pre | post | destroy |
--output-dir, -d | Directory to write the manifest into |
--api-version | Override the API version for the request |
--include-packages, -c | Include managed and/or unlocked package metadata when using --from-org |
--excluded-metadata | Types to exclude when using --from-org |
--json | Machine-readable output |
Manifest filename by --type:
--type | Output file |
|---|---|
package (default) | package.xml |
pre | destructiveChangesPre.xml |
post | destructiveChangesPost.xml |
destroy | destructiveChanges.xml |
You can specify either --type or --name, not both.
Canonical CLI examples
# Build package.xml from a source dir
sf project generate manifest \
--source-dir force-app/main/default \
--name package.xml \
--output-dir manifest \
--json
# Build package.xml from an explicit component list
sf project generate manifest \
--metadata ApexClass:AccountService \
--metadata ApexClass:ContactSelector \
--metadata CustomObject:Account \
--name package.xml \
--output-dir manifest \
--json
# Build destructiveChanges.xml from a component list
sf project generate manifest \
--metadata CustomField:Account.OldField__c \
--metadata CustomField:Account.OldStatus__c \
--type destroy \
--output-dir manifest \
--json
# Build a manifest by introspecting an org (filtered)
sf project generate manifest \
--from-org <alias> \
--metadata ApexClass,CustomObject,CustomLabels \
--output-dir manifest \
--json
If both a package.xml and a destructive manifest are needed, run the CLI twice — once with --type package (or default), once with --type destroy / pre / post.
Path B — Hand-built fallback
Use this only when the CLI cannot express the user's intent — e.g. they want "just the Apex classes I changed today" and the change set is derived from git diff rather than a clean directory or component list. In that case:
- Resolve the components yourself (e.g. parse
git diff --name-onlyand map paths back to metadata types). - Group by metadata type.
- Emit the XML inline using the schema below.
- Always cross-check by running
sf project deploy start --manifest <file> --dry-run(hand off toplatform-metadata-deploy).
Manifest XML schema
Root element is <Package> in the metadata namespace. Each metadata type gets one <types> block containing one <members> per component plus a single <name>. The trailing <version> declares the API version for the manifest.
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>AccountService</members>
<members>ContactSelector</members>
<name>ApexClass</name>
</types>
<types>
<members>Account</members>
<name>CustomObject</name>
</types>
<types>
<members>Account.Status__c</members>
<name>CustomField</name>
</types>
<version>62.0</version>
</Package>
Notes:
- For component-bound types like
CustomField,BusinessProcess,RecordType,Layout,ListView,ValidationRule,WebLink, members useObject.Namenotation. destructiveChanges.xml,destructiveChangesPre.xml, anddestructiveChangesPost.xmluse the same XML structure — only the filename and intent differ.- An empty manifest (no
<types>blocks) is legal and is sometimes paired with a destructive manifest:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<version>62.0</version>
</Package>
API Version Handling
The <version> element at the bottom of every manifest must reflect the project's API version.
Resolution order:
- Read
sourceApiVersionfromsfdx-project.jsonat the project root. - If
--api-versionwas passed by the user, use that instead. - If neither is available, fall back to the value reported by
sf --version(the CLI's bundled API version) — but warn the user and recommend they setsourceApiVersioninsfdx-project.jsonfor reproducibility. - Never silently hardcode a value (e.g.
62.0) into output without surfacing the source.
# Quick read of sourceApiVersion
jq -r '.sourceApiVersion' sfdx-project.json
When using the CLI path, omit --api-version unless the user explicitly overrides — the CLI already reads sourceApiVersion.
Wildcard Members (<members>*</members>)
A wildcard member matches every component of that metadata type. It is not legal for every type. Using * for a disallowed type causes deploy/retrieve errors like Wildcards are not supported for this metadata type.
Wildcard NOT allowed (must enumerate)
These types require explicit member names. Common examples: Profile, PermissionSet, PermissionSetGroup, CustomLabels, CustomObjectTranslation, Layout, Workflow (in some package configurations), SharingRules, StandardValueSet, ManagedTopics, and most "container" types whose contents are object-bound (CustomField, RecordType, BusinessProcess, ListView, ValidationRule, WebLink, CompactLayout).
For these, enumerate explicitly:
<types>
<members>Admin</members>
<members>Standard User</members>
<name>Profile</name>
</types>
Wildcard generally allowed
Most "self-contained" component types accept *. Examples: ApexClass, ApexTrigger, ApexComponent, ApexPage, AuraDefinitionBundle, LightningComponentBundle, CustomApplication, CustomTab, StaticResource, EmailTemplate, Report, Dashboard, Flow, FlexiPage, CustomMetadata. See references/wildcard-allowlist.md for the full enumeration and edge cases.
Rule of thumb: if you are not certain, list the components explicitly. The CLI path (--source-dir / --metadata) sidesteps this problem because it never emits *.
Examples
Example 1 — Build package.xml from a directory
"Generate package.xml from
force-app/main/default/classes/"
sf project generate manifest \
--source-dir force-app/main/default/classes \
--name package.xml \
--output-dir manifest \
--json
Result: manifest/package.xml listing every Apex class in that folder.
Example 2 — Build a manifest covering specific components
"Build a manifest covering AccountService, ContactSelector, and the Account custom object"
sf project generate manifest \
--metadata ApexClass:AccountService \
--metadata ApexClass:ContactSelector \
--metadata CustomObject:Account \
--name package.xml \
--output-dir manifest \
--json
Result: manifest/package.xml containing exactly those three components.
Example 3 — Generate both package.xml and destructiveChanges.xml for deletions
"Create both package.xml and destructiveChanges.xml for these deletions:
Account.OldField__c,Account.OldStatus__c"
# Empty/minimal package.xml (deletion-only deploy still needs a package descriptor)
sf project generate manifest \
--metadata CustomLabels \
--name package.xml \
--output-dir manifest \
--json
# destructiveChanges.xml
sf project generate manifest \
--metadata CustomField:Account.OldField__c \
--metadata CustomField:Account.OldStatus__c \
--type destroy \
--output-dir manifest \
--json
After generation, hand off to platform-destructive-deploy to validate and execute the deletion.
Failure Modes
| Symptom | Likely cause | Recovery |
|---|---|---|
Path does not exist: <dir> | --source-dir points at a missing folder | Confirm the path; use ls to verify; default to force-app/main/default if the user is vague |
| Generated manifest is empty | Source dir contained no recognizable metadata, or all files were ignored | Check .forceignore; verify the path actually contains metadata files (*.cls, *-meta.xml, etc.) |
Wildcards are not supported for this metadata type at deploy time | Hand-built manifest used * for a disallowed type | See the wildcard allowlist above; enumerate the components explicitly |
<version> missing or mismatched | sfdx-project.json lacks sourceApiVersion | Add sourceApiVersion to sfdx-project.json, or pass --api-version to the CLI |
You can specify either --type or --name, but not both | CLI invocation passed both flags | Drop one; use --type for predefined names, --name for a custom one |
You can specify either --source-dir or --metadata, but not both | CLI invocation passed both | Pick one input mode |
Components missing from --from-org output | Org introspection batched too aggressively, or the type is in a managed package | Set SF_LIST_METADATA_BATCH_SIZE lower; add --include-packages managed if intended |
Cross-Skill Integration
| Need | Delegate to | Reason |
|---|---|---|
| Run a deploy with the generated manifest | platform-metadata-deploy | This skill stops at file generation |
| Validate before a prod release | platform-deploy-validate | Pre-flight test against prod |
| Actually delete the components in the destructive manifest | platform-destructive-deploy | That skill validates and executes the destructive deploy |
| Retrieve metadata listed in the manifest | platform-metadata-retrieve | Pulls org metadata to local |
| Author the metadata being listed in the manifest | Other platform-* generators (e.g. platform-custom-object-generate) | The manifest just lists what already exists on disk |
Completion Format
Manifest goal: <package | pre | post | destroy>
Input mode: <source-dir | metadata list | from-org | hand-built>
Output: <path/to/manifest.xml>
API version: <value> (source: sfdx-project.json | --api-version | CLI default)
Component count: <N> across <M> metadata types
Next step: <platform-metadata-deploy | platform-deploy-validate | platform-destructive-deploy>
Related skills
More from forcedotcom/sf-skills and the wider catalog.

platform-mcp-tool-widget-coordinate
Orchestrate Lightning Type + HXL widget generation for custom MCP server tool output backed by Apex Invocable Actions.

platform-metadata-api-context-get
Authoritative Salesforce Metadata API schema and XML structure for 604 metadata types — required companion for metadata generation.

platform-metadata-deploy
Salesforce DevOps automation: deploy metadata, manage orgs, and orchestrate CI/CD pipelines with sf CLI v2.

platform-metadata-retrieve
Retrieve Salesforce metadata from an org to your local project using sf project retrieve start.

platform-models-api-configure
Configure Claude Code or Claude Agent SDK to use Salesforce Models API with OrgJWT authentication.

platform-permission-set-generate
Generate correct, deployable Salesforce permission set metadata with object, field, and user permissions.