Not yet assessed
Review the original instructions and requested permissions before installing.
No security review is available for this catalog entry yet.
Generate Salesforce package and destructive-change manifests from source or org metadata.
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).
Review the original instructions and requested permissions before installing.
No security review is available for this catalog entry yet.
How clearly the skill guides your agent, how complete its workflow is, and how you can check the outcome.
No quality assessment is available for this catalog entry yet.
Original instructions from the publisher’s SKILL.md
# 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.xml` from 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`, or `destructiveChangesPost.xml` for a deletion
- Producing both a `package.xml` and 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
```bash
# 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:
1. Resolve the components yourself (e.g. parse `git diff --name-only` and map paths back to metadata types).
2. Group by metadata type.
3. Emit the XML inline using the schema below.
4. Always cross-check by running `sf project deploy start --manifest <file> --dry-run` (hand off to `platform-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
<?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 use `Object.Name` notation.
- `destructiveChanges.xml`, `destructiveChangesPre.xml`, and `destructiveChangesPost.xml` use 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
<?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:**
1. Read `sourceApiVersion` from `sfdx-project.json` at the project root.
2. If `--api-version` was passed by the user, use that instead.
3. 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 set `sourceApiVersion` in `sfdx-project.json` for reproducibility.
4. Never silently hardcode a value (e.g. `62.0`) into output without surfacing the source.
```bash
# 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:
```xml
<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](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/`"
```bash
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"
```bash
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`"
```bash
# 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
```text
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>
```