skills/sf-metadata-management/SKILL.md
Use when working with Salesforce metadata types, package.xml, or .forceignore. Source vs metadata format, retrieval, deployment, and org comparison.
npx skillsauth add jiten-singh-shahi/salesforce-claude-code sf-metadata-managementInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Reference: @../_reference/METADATA_TYPES.md
.forceignore to control which files are tracked by SF CLIforce-app/
main/
default/
classes/
AccountService.cls
AccountService.cls-meta.xml
triggers/
AccountTrigger.trigger
AccountTrigger.trigger-meta.xml
lwc/
accountCard/
accountCard.js
accountCard.html
accountCard.css
accountCard.js-meta.xml
objects/
Account/
fields/
Status__c.field-meta.xml
recordTypes/
Enterprise.recordType-meta.xml
validationRules/
RequirePhone.validationRule-meta.xml
unpackaged/
classes/
AccountService.cls
AccountService.cls-meta.xml
objects/
Account.object <-- single file with ALL fields, validation rules, etc.
package.xml
Key difference: in source format, each component has its own file. In metadata format, objects are a single monolithic XML file.
# Convert metadata format to source format
sf project convert mdapi --root-dir unpackaged --output-dir force-app
# Convert source format to metadata format
sf project convert source --source-dir force-app --output-dir unpackaged
{
"packageDirectories": [
{
"path": "force-app",
"default": true,
"package": "MyApp",
"versionName": "ver 1.0",
"versionNumber": "1.0.0.NEXT",
"definitionFile": "config/project-scratch-def.json"
},
{
"path": "force-app-config",
"default": false
}
],
"namespace": "",
"sourceApiVersion": "66.0",
"sfdcLoginUrl": "https://login.salesforce.com",
"pushPackageDirectoriesSequentially": false,
"packageAliases": {
"MyApp": "0Ho...",
"[email protected]": "04t..."
}
}
| Property | Purpose |
|-----------------------------|-------------------------------------------------------|
| packageDirectories | Directories containing Salesforce source |
| path | Relative path to source directory |
| default | Whether this is the default deploy target |
| namespace | Org namespace (empty string for most orgs) |
| sourceApiVersion | Metadata API version (update annually) |
| pushPackageDirectoriesSequentially | Deploy directories in order (for dependencies) |
Controls which files SF CLI ignores during push/pull/deploy operations. Syntax mirrors .gitignore.
# .forceignore
# Profiles -- use Permission Sets instead
**/profiles/**
# Standard Value Sets (cannot deploy, org-managed)
**/standardValueSets/**
# Managed Package components -- read-only
**/force-app/main/default/classes/fflib_*
**/force-app/main/default/classes/NPSP_*
# Experience Cloud templates (large, rarely need deploying)
**/experiences/**
# Reports and Dashboards (manage via UI)
**/reports/**
**/dashboards/**
# Translations (if not managing)
**/translations/**
# Retrieve all Apex classes
sf project retrieve start \
--metadata ApexClass \
--target-org myOrg \
--output-dir force-app
# Retrieve specific component
sf project retrieve start \
--metadata "ApexClass:AccountService" \
--target-org myOrg
# Retrieve multiple types
sf project retrieve start \
--metadata "ApexClass,ApexTrigger,LightningComponentBundle,CustomObject" \
--target-org myOrg
sf project retrieve start \
--manifest manifest/package.xml \
--target-org myOrg \
--output-dir force-app
# Only retrieves what changed in org since last sync
sf project retrieve start \
--source-dir force-app \
--target-org myScratch
sf org list metadata-types --target-org myOrg
sf org list metadata --metadata-type ApexClass --target-org myOrg
sf org list metadata --metadata-type Flow --target-org myOrg
# Retrieve from source and target orgs
sf project retrieve start --manifest manifest/package.xml --target-org sourceOrg --output-dir /tmp/source-org
sf project retrieve start --manifest manifest/package.xml --target-org targetOrg --output-dir /tmp/target-org
# Diff using standard tools
diff -r /tmp/source-org /tmp/target-org
Deploying a Profile from source replaces the entire profile definition in the target org. Any permissions that exist in the org but are not in your source file will be revoked. Use Permission Sets instead of Profiles for deployable permission management.
# Add profile to .forceignore to stop tracking
echo "**/profiles/**" >> .forceignore
# Deploy permission sets instead
sf project deploy start \
--metadata "PermissionSet:Sales_Manager_Permissions" \
--target-org myOrg
When profiles cannot be avoided:
# Retrieve ONLY the profile
sf project retrieve start \
--metadata "Profile:Admin" \
--target-org myOrg
--ignore-conflictssilently overwrites without prompting. Rundeploy previewfirst to review what will be overwritten. Using--ignore-conflictson a shared org can destroy another developer's uncommitted work.
# Preview conflicts before deploying
sf project deploy preview --source-dir force-app --target-org myScratch
# Force deploy (local wins)
sf project deploy start \
--source-dir force-app \
--ignore-conflicts \
--target-org myScratch
# Force retrieve (org wins)
sf project retrieve start \
--source-dir force-app \
--ignore-conflicts \
--target-org myScratch
Custom Metadata Type records are metadata -- deploy them, not import them.
<!-- force-app/main/default/customMetadata/Service_Config.Production.md-meta.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<CustomMetadata xmlns="http://soap.sforce.com/2006/04/metadata">
<label>Production Config</label>
<protected>false</protected>
<values>
<field>Endpoint_URL__c</field>
<value xsi:type="xsd:string">https://api.example.com</value>
</values>
<values>
<field>Timeout_Ms__c</field>
<value xsi:type="xsd:double">10000</value>
</values>
</CustomMetadata>
Benefits over Custom Settings: deployable, available in flows and formula fields, no governor limit on reads, can be packaged.
sf-deployment-constraints -- deployment safety rulesdevelopment
Update Salesforce platform reference docs with latest release features and deprecation announcements. Use when SessionStart hook warns docs are outdated or a new Salesforce release has shipped. Do NOT use for Apex or LWC development.
development
Use when syncing documentation after Salesforce Apex code changes. Update README, API docs, and deploy metadata references to match the current org codebase.
development
Use when managing context during long Salesforce Apex development sessions. Suggests manual compaction at logical intervals to preserve deploy and org context across phases.
tools
Visualforce development — pages, controllers, extensions, ViewState, JS Remoting, LWC migration. Use when maintaining VF pages, building PDFs, or planning VF-to-LWC migration. Do NOT use for LWC, Aura, or Flow.