metadata-diff-between-sandboxes
Use when comparing metadata between two Salesforce orgs (UAT vs Prod, dev sandbox vs full copy, fork sandbox vs source) to surface drift, identify items needing deployment, or build a destructive-changes manifest. Triggers: 'compare two sandboxes', 'org diff tool', 'metadata drift between UAT and prod', 'find missing metadata in target org'. NOT for code-level diffs in version control or for deploying packages.
Best use case
metadata-diff-between-sandboxes is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when comparing metadata between two Salesforce orgs (UAT vs Prod, dev sandbox vs full copy, fork sandbox vs source) to surface drift, identify items needing deployment, or build a destructive-changes manifest. Triggers: 'compare two sandboxes', 'org diff tool', 'metadata drift between UAT and prod', 'find missing metadata in target org'. NOT for code-level diffs in version control or for deploying packages.
Teams using metadata-diff-between-sandboxes should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/metadata-diff-between-sandboxes/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How metadata-diff-between-sandboxes Compares
| Feature / Agent | metadata-diff-between-sandboxes | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when comparing metadata between two Salesforce orgs (UAT vs Prod, dev sandbox vs full copy, fork sandbox vs source) to surface drift, identify items needing deployment, or build a destructive-changes manifest. Triggers: 'compare two sandboxes', 'org diff tool', 'metadata drift between UAT and prod', 'find missing metadata in target org'. NOT for code-level diffs in version control or for deploying packages.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Metadata Diff Between Sandboxes Activate when an engineer needs to know "what's different between Org A and Org B at the metadata level" — typically before a deploy, after a hotfix, or when investigating mysterious behavior that diverges between environments. The skill produces a categorized diff (source-only / target-only / changed), a deployable manifest, and a drift inventory. --- ## Before Starting Gather this context before working on anything in this domain: - The two org auth contexts. DX auth aliases (`sf org list`) are the simplest. Long-lived integration users with API-only profiles are safer than personal credentials. - The metadata types in scope. A "full diff" requests every type and is slow (>30 minutes for large orgs); a focused diff (Apex + LWC + Flow + custom objects) is usually enough. - Whether the goal is *deploy* (build a package.xml and ship), *destructive* (delete from target what no longer exists in source), *audit* (just inventory drift), or some combination. --- ## Core Concepts ### Approach families | Approach | Tool | Best for | Cost | |---|---|---|---| | Retrieve both orgs to local dirs and `git diff` | `sf project retrieve start` × 2 + `git diff --no-index` | Generic, unbeaten clarity | Two retrieve cycles | | Manifest-only diff | `sf project retrieve preview` | Quick inventory of what would be retrieved | Misses content-level diffs | | Tooling-specific | sfdx-hardis `org:diff`, Gearset, Copado | Mature workflows, UI, dependencies | License or third-party trust | | API-level | Tooling API SOQL on `MetadataContainer` / `*Member` objects | Programmatic checks of single types | Doesn't cover all types | ### Drift classes The diff is meaningful only when categorized. Always emit four buckets: 1. **Source-only** — exists in Org A, missing in Org B. Candidate for deploy. 2. **Target-only** — exists in Org B, missing in Org A. Candidate for destructive change *or* a hotfix you need to back-port. 3. **Changed** — exists in both, content differs. Candidate for deploy with merge review. 4. **Identical** — drop from the report. Noise. ### Ignore lists Some metadata types diff dirty by design: profiles (auto-edited by Setup), installed packages, environmental fields (org-specific custom labels). Honor `.forceignore` and add a separate `diff-ignore.txt` for items that exist in both orgs intentionally. --- ## Common Patterns ### Pattern: pre-deploy "what's missing" diff **When to use:** Before promoting a UAT-tested change to production, confirm production has all transitive dependencies. **How it works:** Retrieve from UAT and Prod in parallel. `git diff --name-status` between the two retrieves. Filter to source-only items. Build a deployable `package.xml` for those items. **Why not the alternative:** Deploying without this check often fails on a missing dependency (custom field, perm set) that wasn't in the change set. ### Pattern: post-hotfix drift inventory **When to use:** Production hotfix landed; UAT and Dev sandboxes don't have it yet. **How it works:** Run the diff with Prod as source and Dev as target. Source-only items are the hotfix; target-only items are work-in-progress that needs to be reconciled. ### Pattern: destructive-changes generator **When to use:** Cleanup PR removing 12 unused custom fields. Source repo is the source of truth. **How it works:** Run diff with the repo (or a fresh sandbox built from repo) as source and Prod as target. Target-only items become the destructiveChanges.xml entries. --- ## Decision Guidance | Situation | Recommended Approach | Reason | |---|---|---| | One-off check, two orgs, you trust git | Retrieve + `git diff` | Cheapest, no plugin | | Recurring, audited, multi-team | sfdx-hardis or commercial tool | Reproducible, UI for non-engineers | | Need diff of one specific type (e.g., flows) | Targeted retrieve with `-m Flow:*` | Avoid 30-minute full retrieve | | Profile drift specifically | Use a profile-aware diff (sfdx-hardis) | Standard `git diff` is noise on profile XML | --- ## Recommended Workflow 1. Identify the two orgs and authenticate (`sf org login web --alias prod` etc.). Confirm both auth contexts have read access to the metadata in scope. 2. Choose the metadata-type scope. Start narrow (Apex + LWC + Flow + custom objects). Expand if drift surfaces in another type. 3. Retrieve both orgs to separate working directories. Use the same package.xml for both retrievals so the type set is symmetric. 4. Diff: `git diff --no-index --name-status orgA-source/ orgB-source/`. Pipe through a categorizer that maps to source-only / target-only / changed. 5. Apply the ignore list. Profiles, packageVersions, and any team-defined exclusions drop here. 6. Render the categorized report (Markdown table). For deploy intent, emit `package.xml`. For destructive intent, emit `destructiveChanges.xml`. 7. Hand to the deploy pipeline (or stop here for audit-only). --- ## Review Checklist - [ ] Both orgs authenticated; auth survives the full retrieve duration - [ ] Symmetric retrieve manifests (same types requested from both) - [ ] Categorized output (not a single flat list) - [ ] Ignore list applied (profiles, installed packages, sandbox-only artifacts) - [ ] Generated `package.xml` validated against target org with `sf project deploy preview` - [ ] `destructiveChanges.xml` reviewed by humans before any apply --- ## Salesforce-Specific Gotchas 1. **Profile XML is auto-edited by Setup** — Permissions on a field that was added in one org are silently rewritten when an admin opens the profile UI in the other. Diff-ignore profiles or use a profile-aware tool. 2. **Retrieve does not bring everything** — Some metadata types are not retrievable via Metadata API (or require Tooling API). The Metadata API Coverage report is the source of truth; assume gaps exist. 3. **Folder-bound types** (Reports, Dashboards, Email Templates) require both folder and item retrieve. A naive `Report:*` misses items in folders not enumerated. 4. **Custom labels are translation-aware** — A custom label translated in one org but not the other shows as a "changed" diff, even though the source-language version is identical. --- ## Output Artifacts | Artifact | Description | |---|---| | diff-report.md | Categorized table of source-only / target-only / changed items | | package.xml | Deployable manifest of source-only items | | destructiveChanges.xml | Manifest of items to remove from target (audit before apply) | | ignore-applied.log | What was filtered and why | --- ## Related Skills - devops/metadata-api-retrieve-deploy — for the underlying retrieve mechanics and limits - devops/metadata-api-coverage-gaps — for which types cannot be retrieved/diffed - devops/destructive-changes-deployment — to safely apply the destructiveChanges.xml output - devops/sandbox-refresh-and-templates — when post-refresh drift is the actual problem to solve
Related Skills
metadata-api-retrieve-deploy
Metadata API retrieve/deploy via sf CLI and package.xml: manifest authoring, destructiveChanges, deploy options (checkOnly, testLevel, rollbackOnError), CI scripting. NOT for DX source format conversions (use salesforce-dx-source-tracking). NOT for unlocked packages (use unlocked-packages).
metadata-api-coverage-gaps
Use this skill when a deployment, source push, or package version fails because a metadata type is unsupported, partially supported, or behaves differently across Metadata API, source tracking, unlocked packages, and 2GP managed packages. Covers identifying coverage gaps, building release runbooks for manual post-deployment steps, and choosing workarounds such as post-deploy scripts, Tooling API calls, or manual configuration. NOT for general deployment error troubleshooting, Metadata API usage tutorials, or architecture-level metadata dependency mapping.
feature-flag-custom-metadata
Implement environment-safe feature flags using Custom Metadata Types for Apex, LWC, and Flow. NOT for user-level entitlements or permission sets.
omnistudio-metadata-management
Use this skill when tracking, auditing, or cleaning up OmniStudio component dependencies and cross-references — covering the four OmniStudio metadata API types (OmniProcess, OmniDataTransform, OmniUiCard, OmniInteractionConfig), dependency graph construction from embedded JSON bodies, impact analysis before deleting or modifying a component, and stale-component cleanup. Trigger keywords: OmniStudio metadata types, OmniStudio dependency tracking, FlexCard DataRaptor dependency, OmniScript Integration Procedure reference, OmniStudio component cleanup, metadata impact analysis. NOT for DataPack export/import mechanics (use data/omnistudio-datapack-migration), standard Salesforce Metadata API coverage (use a metadata coverage skill), or OmniStudio CI/CD pipeline automation.
metadata-coverage-and-dependencies
Assessing metadata type coverage across Salesforce deployment channels (Metadata API, SFDX, unlocked packages, managed packages) and mapping component dependency graphs using Tooling API MetadataComponentDependency. Use when planning packaging strategies, evaluating deployment risk, performing impact analysis before component deletion, or mapping tightly coupled metadata for modular architecture. Trigger keywords: metadata coverage report, dependency graph, MetadataComponentDependency, impact analysis, unsupported metadata types, packaging eligibility. NOT for deployment mechanics (use destructive-changes-deployment). NOT for CI/CD pipeline design (use continuous-integration-testing).
metadata-api-and-package-xml
Metadata API concepts, package.xml manifest structure, retrieve and deploy workflows, what metadata types can and cannot be retrieved, deployment order dependencies, and destructiveChanges.xml for deletions. NOT for SFDX source-format details or sf CLI command syntax (use sf-cli-and-sfdx-essentials), and NOT for CI/CD pipeline automation (use devops skills).
custom-metadata-in-apex
Use when Apex must read, interpret, or deploy Custom Metadata Type configuration, or when deciding between Custom Metadata Types, Custom Settings, and Custom Labels. Triggers: 'Custom Metadata Type', '__mdt', 'getInstance', 'Apex Metadata API', 'protected custom metadata'. NOT for setup-only administration with no Apex behavior, packaging, or deployment concern.
apex-metadata-api
Use when Apex code must create or update metadata programmatically at runtime — custom fields, objects, picklist values, labels, or other supported types — using the Metadata namespace (Metadata.Operations, Metadata.DeployCallback). Triggers: 'Metadata.Operations', 'Metadata.CustomField from Apex', 'deploy metadata from Apex', 'enqueueDeployment', 'create a custom field programmatically', 'post-install script metadata setup'. NOT for Metadata API REST/SOAP (use metadata-api-and-package-xml) and NOT for reading Custom Metadata Type configuration rows in Apex (use custom-metadata-in-apex).
custom-metadata-types
Use when designing deployable Salesforce configuration with Custom Metadata Types, especially when choosing between CMTs, Custom Settings, and Custom Objects, protecting packaged defaults, or exposing config to Apex, Flow, and formulas. Triggers: 'custom metadata vs custom settings', 'deployable config', 'protected custom metadata', 'feature flags in Salesforce'. NOT for high-churn transactional data, user-managed business records, or secret storage that should live in Named Credentials.
xss-and-injection-prevention
Use when writing or reviewing Visualforce pages, Apex controllers, or LWC components that output user-supplied data, build dynamic queries, or construct HTTP responses. Triggers: 'XSS in Visualforce', 'SOQL injection vulnerability', 'how to encode output in Apex', 'JSENCODE Visualforce', 'open redirect prevention'. NOT for Apex CRUD/FLS enforcement (use soql-security or apex-crud-and-fls), NOT for Shield encryption (use shield-encryption-key-management), NOT for AppExchange security review process (use secure-coding-review-checklist).
visualforce-security-and-modernization
Use when hardening or modernizing legacy Visualforce pages — covers the platform CSRF token model and when disabling it is a security regression, view state encryption guarantees and the 170 KB ceiling, FLS/CRUD enforcement gaps on `<apex:outputField>` and on getters that return sObjects, `<apex:includeScript>` interaction with the org Content Security Policy, hosting LWC inside a VF page via `lightning:container` / `lightning-out`, and the retire-vs-harden-vs-leave-alone decision for an inventory of legacy pages. Triggers: 'should I rewrite this Visualforce page in LWC', 'CSRF protection disabled on Visualforce page is that safe', 'community user sees a field they should not on a Visualforce page', 'view state encryption is that enough for sensitive data', 'how do I host an LWC inside a Visualforce page', 'apex:dynamicComponent and apex:actionFunction safe to keep'. NOT for greenfield Visualforce architecture (use apex/visualforce-fundamentals — controller types, view state pattern selection, PDF rendering); NOT for Visualforce email template authoring (use apex/visualforce-email-templates if/when that skill is authored); NOT for general Apex security review across triggers and async (use apex/soql-security and security/secure-coding-review-checklist).
transaction-security-policies
Transaction Security policy creation and configuration: condition builder, enhanced policies, enforcement actions (block, MFA, notification, end session), real-time monitoring mode, and policy troubleshooting. NOT for Event Monitoring log analysis or Shield Event Monitoring setup (use event-monitoring). NOT for Apex testing or debug-log analysis.