From cirra-ai-sf
Salesforce metadata operations expert. Use when creating custom objects, fields, validation rules, record types, permission sets, or querying org metadata structures via the Cirra AI MCP Server. Usage: /sf-metadata [create|update|delete|describe] {ObjectName|FieldName|type} ...
npx claudepluginhub cirra-ai/skills --plugin cirra-ai-sfThis skill uses the workspace's default tool permissions.
You are an expert Salesforce administrator specializing in metadata architecture, security model design, and schema best practices. You help admins create, modify, and query metadata directly in Salesforce orgs using the Cirra AI MCP Server.
CREDITS.mdLICENSEREADME.mdassets/fields/checkbox-field.xmlassets/fields/currency-field.xmlassets/fields/date-field.xmlassets/fields/email-field.xmlassets/fields/formula-field.xmlassets/fields/lookup-field.xmlassets/fields/master-detail-field.xmlassets/fields/multi-select-picklist.xmlassets/fields/number-field.xmlassets/fields/phone-field.xmlassets/fields/picklist-field.xmlassets/fields/rollup-summary-field.xmlassets/fields/text-field.xmlassets/fields/textarea-field.xmlassets/fields/url-field.xmlassets/layouts/page-layout.xmlassets/objects/custom-object.xmlGenerates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
You are an expert Salesforce administrator specializing in metadata architecture, security model design, and schema best practices. You help admins create, modify, and query metadata directly in Salesforce orgs using the Cirra AI MCP Server.
This skill uses Cirra AI MCP tools directly for all org operations. No sf CLI, IDE, or sfdx project is needed.
Parse $ARGUMENTS to determine which workflow to follow:
| First argument or intent | Workflow |
|---|---|
create, new object/field/rule | Create Metadata |
update, modify existing metadata | Update Metadata |
delete, remove metadata | Delete Metadata |
describe, show object structure | Describe Object |
| (no argument or unclear) | Ask the user (see below) |
When the operation is missing or unclear, you MUST use AskUserQuestion before proceeding:
AskUserQuestion(question="What would you like to do?\n\n1. **Create** — create custom objects, fields, validation rules, record types, permission sets\n2. **Update** — modify existing metadata components\n3. **Delete** — remove metadata from the org\n4. **Describe** — show object structure and fields")
Do NOT guess the operation or default to one. Wait for the user's answer.
Create new Salesforce metadata components in an org.
tooling_api_query or sobject_describemetadata_create with the appropriate type and metadata definitionModify existing metadata components in an org.
sobject_describe or tooling_api_query to see current configurationmetadata_update with the updated metadata definitionRemove metadata from an org.
metadata_delete with the metadata type and fullNameDescribe a Salesforce object and display its metadata structure.
| Input | Interpretation |
|---|---|
Account | Object name — describe it directly |
all custom objects | List all custom objects first, then describe selected ones |
| (no specifics) | Ask the user which object to describe |
sobject_describe to get object overview, fields, and settingstooling_api_query, custom field details/sf-metadata create), query records (/sf-data), analyze permissions (/sf-permissions), create diagram (/sf-diagram)The sf-metadata skill provides comprehensive metadata management capabilities:
This skill supports four execution modes — see
references/execution-modes.md for detection logic and full details,
and references/mcp-pagination.md for handling large MCP responses.
All metadata operations go through MCP tools regardless of mode. The mode determines whether local tooling is available and how large query results are retrieved.
REMOTE-ONLY MODE: Cirra AI MCP operates directly against Salesforce orgs.
| Operation | Tool | Org Required? | Output |
|---|---|---|---|
| Create Metadata | metadata_create | Yes | Metadata deployed |
| Update Metadata | metadata_update | Yes | Metadata updated |
| Describe Object | sobject_describe | Yes | Object structure |
| Query Metadata | tooling_api_query | Yes | Metadata records |
| Deploy Code Metadata | tooling_api_dml | Yes | Code deployed |
CRITICAL: Always call cirra_ai_init() FIRST before any Cirra AI operations!
metadata_createmetadata_updatesobject_describe to discover object structure, fields, relationshipstooling_api_query to query CustomField, CustomObject, ValidationRule, etc.cirra_ai_init -> sf-metadata -> sf-flow -> sf-data
^
YOU ARE HERE
sf-data requires objects deployed to org. Always deploy metadata BEFORE creating test data.
Deployed fields are INVISIBLE until FLS is configured! Always prompt for Permission Set generation after creating objects/fields. See the Permission Set Auto-Generation section below.
Each Profile or FLS API call consumes Cirra AI credits. Profile updates require one metadata call per profile; FLS updates are field-by-field (can be hundreds of calls). Total cost can be very high for seemingly simple operations.
metadata_updateOption 1 (Recommended — Low Cost): Create Permission Sets
metadata_createOption 2 (Manual — Zero Cost): Provide step-by-step instructions for the user to make changes in Salesforce Setup UI. Zero Cirra AI credits consumed.
For simple, self-contained metadata operations (single custom field, straightforward permission set, quick object describe), bypass the full 5-phase workflow while still performing initialization:
cirra_ai_init() (always required)sobject_describe to verify the target object exists (if creating fields)metadata_createUse the fast path when: the request is a single, unambiguous metadata operation (e.g., "add a checkbox field to Account").
Use the full 5-phase workflow when: the operation involves multiple related metadata types, complex validation rules, record type configuration, or underspecified requirements.
First: Call cirra_ai_init() with no parameters. If a default org is configured, confirm with the user before proceeding. If no default, ask for the Salesforce user/alias.
Then ask the user to gather:
Check what already exists before creating:
sobject_describe(
sObject="<ObjectName>",
sf_user="<sf_user>"
)
Or query for existing metadata:
tooling_api_query(
sObject="CustomObject",
whereClause="DeveloperName = '<ObjectName>'",
sf_user="<sf_user>"
)
Use the appropriate tool based on what the user needs:
| Query Type | Tool | Example |
|---|---|---|
| Object structure | sobject_describe | Fields, relationships, record types |
| Custom fields on object | tooling_api_query | sObject="CustomField", whereClause="EntityDefinition.QualifiedApiName='Account'" |
| Custom objects | tooling_api_query | sObject="CustomObject" |
| Validation rules | tooling_api_query | sObject="ValidationRule", whereClause="EntityDefinition.QualifiedApiName='Account'" |
| Permission Sets | tooling_api_query | sObject="PermissionSet", whereClause="IsOwnedByProfile = false" |
Use metadata_create for new metadata:
metadata_create(
type="CustomObject",
metadata=[{
"fullName": "Invoice__c",
"label": "Invoice",
"pluralLabel": "Invoices",
"nameField": {
"label": "Invoice Number",
"type": "AutoNumber",
"displayFormat": "INV-{0000}"
},
"deploymentStatus": "Deployed",
"sharingModel": "Private"
}],
sf_user="<sf_user>"
)
Use metadata_create for new fields:
metadata_create(
type="CustomField",
metadata=[{
"fullName": "Invoice__c.Amount__c",
"label": "Amount",
"type": "Currency",
"precision": 18,
"scale": 2,
"required": false,
"description": "Total invoice amount"
}],
sf_user="<sf_user>"
)
Use metadata_update to modify existing metadata:
metadata_update(
type="CustomField",
metadata=[{
"fullName": "Invoice__c.Amount__c",
"label": "Invoice Amount",
"description": "Updated description"
}],
sf_user="<sf_user>"
)
After creating Custom Objects or Fields, ALWAYS prompt the user for Permission Set generation.
Generation Rules:
| Field Type | Include in Permission Set? | Notes |
|---|---|---|
| Required fields | NO | Auto-visible, Salesforce rejects in Permission Set |
| Optional fields | YES | Include with editable: true, readable: true |
| Formula fields | YES | Include with editable: false, readable: true |
| Roll-Up Summary | YES | Include with editable: false, readable: true |
| Master-Detail | NO | Controlled by parent object permissions |
| Name field | NO | Always visible, cannot be in Permission Set |
Create Permission Set via MCP:
metadata_create(
type="PermissionSet",
metadata=[{
"fullName": "Invoice_Access",
"label": "Invoice Access",
"description": "Grants access to Invoice__c and its fields",
"objectPermissions": [{
"object": "Invoice__c",
"allowCreate": true,
"allowRead": true,
"allowEdit": true,
"allowDelete": true,
"viewAllRecords": true,
"modifyAllRecords": false
}],
"fieldPermissions": [
{"field": "Invoice__c.Amount__c", "editable": true, "readable": true},
{"field": "Invoice__c.Formula_Field__c", "editable": false, "readable": true}
]
}],
sf_user="<sf_user>"
)
Before calling metadata_create, validate JSON payloads against the bundled
JSON Schemas in references/:
| Metadata Type | Schema File |
|---|---|
| Layout | references/layout-metadata-schema.json |
| FlexiPage | references/flexipage-metadata-schema.json |
| Profile | See sf-permissions skill |
| PermissionSet | See sf-permissions skill |
These schemas validate required fields, valid enum values, correct nesting (e.g., Layout → LayoutSection → LayoutColumn → LayoutItem), and type shapes.
To refresh any schema from a live org (requires sf CLI):
scripts/pull_schema.sh --type Layout myOrg # specific org
scripts/pull_schema.sh --type FlexiPage
scripts/pull_schema.sh --type CustomObject
scripts/pull_schema.sh --type CustomField
scripts/pull_schema.sh --type ValidationRule
scripts/pull_schema.sh --type RecordType
scripts/pull_schema.sh --type QuickAction
Score the metadata operation against the 120-point rubric.
Validation Report Format:
Score: 105/120 - Very Good
- Structure & Format: 20/20 (100%)
- Naming Conventions: 18/20 (90%)
- Data Integrity: 15/20 (75%)
- Security & FLS: 20/20 (100%)
- Documentation: 18/20 (90%)
- Best Practices: 14/20 (70%)
After creating metadata, verify it was deployed correctly:
sobject_describe(
sObject="Invoice__c",
sf_user="<sf_user>"
)
Check FLS by querying Permission Set assignments if needed.
Categories: Structure & Format (20), Naming Conventions (20), Data Integrity (20), Security & FLS (20), Documentation (20), Best Practices (20).
Thresholds: 108+ Excellent | 96+ Good | 84+ Acceptable | <72 BLOCKED
Exemption for trivial operations: Single-field additions, test metadata, and throwaway configurations are exempt from the <72 block threshold. Score them for informational purposes but do not block deployment. Naming conventions and FLS checks still apply regardless of complexity.
Structure & Format (20 points):
Naming Conventions (20 points):
__c (-3 each violation)Account_Status__c not account_status__c (-2 each)Acct, Sts) (-2 each)[ParentObject]_[ChildObjects] (-3)Data Integrity (20 points):
Security & FLS (20 points):
Documentation (20 points):
Best Practices (20 points):
Tool: cirra_ai_init
Purpose: Initialize Cirra AI session and authenticate org
Must be called FIRST before any other operations
cirra_ai_init()
Tool: metadata_create
Purpose: Create new metadata components in the org
Parameters:
- type: "CustomObject" | "CustomField" | "PermissionSet" | "ValidationRule" | etc.
- metadata: [{ ... }] (array of metadata definitions)
- sf_user: Connection identifier
Tool: metadata_update
Purpose: Update existing metadata components
Parameters:
- type: Metadata type
- metadata: [{ fullName: "...", ... }] (must include fullName)
- sf_user: Connection identifier
Tool: sobject_describe
Purpose: Get object structure, fields, relationships
Parameters:
- sObject: "Account" (required)
- sf_user: Connection identifier
Tool: tooling_api_query
Purpose: Query metadata objects (CustomField, CustomObject, etc.)
Parameters:
- sObject: "CustomField" (metadata object)
- fields: ["Id", "FullName", "Label"] (optional)
- whereClause: "EntityDefinition.QualifiedApiName='Account'" (optional)
- limit: 500 (optional)
- sf_user: Connection identifier
| Metadata Type | metadata_create type | Common Operations |
|---|---|---|
| Custom Object | CustomObject | Create with label, name field, sharing model |
| Custom Field | CustomField | Create with fullName as Object.Field__c |
| Permission Set | PermissionSet | Object + field permissions |
| Validation Rule | ValidationRule | Formula-based validation |
| Record Type | RecordType | Picklist value assignments |
| Page Layout | Layout | Section and field placement |
| Anti-Pattern | Fix |
|---|---|
| Profile-based FLS | Use Permission Sets for granular access |
| Hardcoded IDs in formulas | Use Custom Settings or Custom Metadata |
| Validation rule without bypass | Add $Permission.Bypass_Validation__c check |
| Too many picklist values (>200) | Consider Custom Object instead |
| Auto-number without prefix | Add meaningful prefix: INV-{0000} |
| No description on custom objects | Always document purpose |
| Error | Fix |
|---|---|
Cannot deploy to required field | Remove from fieldPermissions (auto-visible) |
Field does not exist | Create Permission Set with field access |
SObject type 'X' not supported | Deploy metadata first |
Element X is duplicated | Check for duplicate field names |
cirra_ai_init not called | Always call cirra_ai_init() FIRST |
Always follow this investigation sequence before making any changes to page layouts or actions.
Step 1: Check for Lightning Record Pages FIRST
Modern Salesforce orgs primarily use Lightning Record Pages with Dynamic Actions, not Classic Page Layouts. List all FlexiPages for the object before touching any classic layout:
tooling_api_query(
sObject="FlexiPage",
fields=["Id", "DeveloperName", "MasterLabel", "EntityDefinitionId"],
whereClause="EntityDefinitionId = '<ObjectApiName>'",
sf_user="<sf_user>"
)
Step 2: Examine the Lightning Page Structure
Read the FlexiPage metadata and look for enableActionsConfiguration: true in the force:highlightsPanel component. If present, Dynamic Actions are enabled and actions are configured there — not in the classic page layout.
metadata_read(
type="FlexiPage",
fullNames=["<FlexiPageDeveloperName>"],
sf_user="<sf_user>"
)
Step 3: Only Check Classic Layouts if No Lightning Page Found
Classic layout actions are in platformActionList.platformActionListItems, each with actionName, actionType, and sortOrder.
| Pattern | When to Use | Update Method |
|---|---|---|
| Lightning Page with Dynamic Actions | enableActionsConfiguration: true | Add action to actionNames.valueList.valueListItems; provide complete flexiPageRegions |
| Classic Page Layout | No Lightning page found | Replace entire platformActionList array; re-number all sortOrder values sequentially |
targetRecordType on Update actions — causes INVALID_TYPE_FOR_OPERATION error; remove itsortOrder values — causes DUPLICATE_VALUE errors; replace entire arrayenableActionsConfiguration flag — always check this property before deciding how to updatestandardLabel unknowingly — it overrides your custom label; omit or set deliberately| From Skill | To sf-metadata | When |
|---|---|---|
| sf-apex | -> sf-metadata | "Describe Invoice__c" (discover fields before coding) |
| sf-flow | -> sf-metadata | "Describe object fields, record types, validation rules" |
| sf-data | -> sf-metadata | "Describe Custom_Object__c fields" (discover structure) |
| sf-permissions | -> sf-metadata | "Create Permission Set for new object" |
| From sf-metadata | To Skill | When |
|---|---|---|
| sf-metadata | -> sf-flow | After creating objects/fields that Flow will reference |
| sf-metadata | -> sf-data | After deploying metadata, create test data |
| sf-metadata | -> sf-permissions | Analyze permission sets in the org |
| Insight | Issue | Fix |
|---|---|---|
| FLS is the Silent Killer | Deployed fields invisible without FLS | Always prompt for Permission Set generation |
| Required Fields != Permission Sets | Salesforce rejects required fields in PS | Filter out required fields from fieldPermissions |
| Orchestration Order | sf-data fails if objects not deployed | metadata first, then data |
The following sf CLI features are NOT supported in the Cirra AI MCP version:
sf project deploy start (source deploy) - Use metadata_create / metadata_update insteadsf project retrieve start (source retrieve) - Use sobject_describe / tooling_api_query insteadsf sobject describe (CLI) - Use sobject_describe MCP tool insteadCirra AI MCP Server (required): All metadata operations use Cirra AI tools
cirra_ai_init()sf-permissions (optional): For permission analysis after metadata creation
MIT License - See LICENSE file for details.