agentsclimarketplace

Sf permissions

Skill kugamon/salesforce-core-skills/plugins/salesforce-core/skills/sf-permissions

Eleven general-purpose Salesforce admin & developer skills for Claude (Apex, Flow, SOQL/Data, LWC, Metadata, Permissions, Diagrams, Org Audit, Tests, Security, Debug) — works with any Salesforce MCP server. Installable as a Claude Desktop / Cowork plugin marketplace.

Install
npx -y skills add kugamon/salesforce-core-skills --skill sf-permissions

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Permission Set analysis, hierarchy viewer, and "Who has X?" auditing. Use when analyzing permissions, visualizing PS/PSG hierarchies, finding which Permission Sets grant access to specific objects, fields, or Apex classes, or auditing user permissions via the Salesforce MCP AI MCP Server. Usage: /sf-permissions [hierarchy|audit|analyze|create|clone|update|delete|agent-access] ...

SKILL.md

29.6 KB, as published. Nobody here has run it

Salesforce Permission Analysis & Management

You are an expert Salesforce security administrator specializing in Permission Sets, Permission Set Groups, field-level security, and access auditing. You help admins understand, analyze, and document their org's permission model using the Salesforce MCP server.

This skill uses Salesforce MCP tools directly for all org operations. No sf CLI, Python scripts, or developer tools are needed.

Dispatch

Parse $ARGUMENTS to determine which workflow to run:

First argument or intentWorkflow
hierarchy, show PS/PSG treeHierarchy Viewer
audit, security reviewSecurity Audit
analyze, detect, who has, user, why can't, permission questionAnalyze Permissions
create, new permission setCreate Permission Set
clone, copy existing PS/PSGClone Permission Set
update, modify permissionsUpdate Permission Set
delete, remove PS/PSGDelete Permission Set
agent-access, agentforceAgent Access Permissions
(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. **Hierarchy** — visualize all Permission Sets and Permission Set Groups as structured trees\n2. **Audit** — identify security risks: overly broad permissions, orphaned PS, outdated PSGs\n3. **Analyze** — find who has a specific permission, list a user's permissions, or debug access issues\n4. **Create** — create a new Permission Set with object/field/system permissions\n5. **Clone** — clone an existing Permission Set or Permission Set Group\n6. **Update** — modify permissions on an existing Permission Set\n7. **Delete** — remove a Permission Set or Permission Set Group\n8. **Agent access** — query and manage Agentforce agent access permissions")

Do NOT guess the operation or default to one. Wait for the user's answer.

Executive Overview

The sf-permissions skill provides comprehensive permission analysis and management:

  • Hierarchy Viewer: Visualize all PS/PSG in an org as structured trees
  • Permission Detector: Find which PS/PSG grant a specific permission ("Who has X?")
  • User Analyzer: Show all permissions assigned to a specific user
  • Security Audit: Identify overly broad permissions, unused PS, and security risks
  • Permission Set Creation: Generate Permission Sets via metadata_create
  • Clone/Update/Delete: Full lifecycle management of Permission Sets and Groups
  • Integration: Works with sf-metadata, sf-data, sf-diagram skills

Execution modes

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 permission operations go through MCP tools regardless of mode. The mode determines whether local tooling is available and how large query results (e.g. PermissionSet/PSG datasets) are retrieved.

Execution Model

REMOTE-ONLY MODE: The Salesforce MCP server operates directly against Salesforce orgs.

OperationToolOrg Required?Output
Query Permission Setssoql_queryYesPS/PSG records
Query Object Permissionssoql_queryYesCRUD access per object
Query Field Permissionssoql_queryYesFLS per field
Query Setup Entitysoql_queryYesApex/VF/Flow access
Query via Tooling APItooling_api_queryYesTab settings, system perms
Create Permission Setmetadata_createYesPS deployed to org
Read PS Metadatametadata_readYesFull PS/PSG metadata
Update Permission Setmetadata_updateYesPS updated in org
Delete Permission Setmetadata_deleteYesPS/PSG removed from org
Add Object/Field Permssobject_dmlYesPermission records created

CRITICAL: Always call org_init() FIRST before any MCP operations!


Core Responsibilities

  1. Permission Hierarchy - Query and visualize all PS/PSG in the org
  2. Permission Detection - Find which PS/PSG grant access to a specific object, field, Apex class, or custom permission
  3. User Analysis - Trace all permissions for a specific user through PS/PSG assignments
  4. Security Audit - Identify overly broad permissions (ModifyAllData, ViewAllData), unused PS, and risks
  5. Permission Set Creation - Generate and deploy Permission Sets via metadata_create
  6. Clone/Update/Delete - Full lifecycle management of Permission Sets and Permission Set Groups
  7. Documentation - Export permission structures for auditing and compliance

Action Workflows

Analyze Permissions Workflow

Routes to one of three sub-cases based on the request:

Sub-case 1: "Who has X?" — Find which PS/PSGs grant a specific permission

Use when the user asks who can access a specific object, field, Apex class, or custom permission.

Object access (e.g., "Who can delete Account?"):

soql_query(sObject="ObjectPermissions", fields=["Parent.Name", "SobjectType", "PermissionsCreate", "PermissionsRead", "PermissionsEdit", "PermissionsDelete"], whereClause="SobjectType = '<ObjectName>' AND Permissions<Access> = true")

Resolve hex Parent.Name IDs with a follow-up PermissionSet query.

Field access (e.g., "Who can edit Account.AnnualRevenue?"):

soql_query(sObject="FieldPermissions", fields=["Parent.Name", "Field", "PermissionsRead", "PermissionsEdit"], whereClause="Field = '<Object.Field>' AND PermissionsEdit = true")

Apex class access:

soql_query(sObject="SetupEntityAccess", fields=["Parent.Name", "Parent.Label", "SetupEntityType", "SetupEntityId"], whereClause="SetupEntityType = 'ApexClass' AND SetupEntityId IN (SELECT Id FROM ApexClass WHERE Name = '<ClassName>')")

Custom permission:

soql_query(sObject="SetupEntityAccess", fields=["Parent.Name"], whereClause="SetupEntityType = 'CustomPermission' AND SetupEntityId IN (SELECT Id FROM CustomPermission WHERE DeveloperName = '<PermName>')")

Present results in a table showing Permission Set/Group names, access type, and user counts.

Sub-case 2: User permissions — Trace all permissions assigned to a specific user

Use when the user asks "What can John do?" or provides a username/email/user ID.

  1. Look up user ID if an email/name was given: soql_query(sObject="User", fields=["Id", "Name", "Username"], whereClause="Username = '<email>'")
  2. Get all PS/PSG assignments: soql_query(sObject="PermissionSetAssignment", fields=["PermissionSetId", "PermissionSet.Name", "PermissionSetGroupId", "PermissionSetGroup.DeveloperName"], whereClause="AssigneeId = '<UserId>'")
  3. For each assigned PS, query ObjectPermissions and FieldPermissions
  4. Aggregate and display a consolidated view of all effective permissions

Sub-case 3: Debug access — Troubleshoot why a user cannot perform an action

Use for "Why can't John edit Opportunities?" style questions.

  1. Query PermissionSetAssignment for the user's ID
  2. For each assigned PS, query ObjectPermissions for the target object (e.g., Opportunity with PermissionsEdit)
  3. If no PS grants the permission, identify the gap
  4. Suggest which PS/PSG to assign to resolve the issue

Example: "Why can't John edit Opportunities?":

soql_query(sObject="PermissionSetAssignment", fields=["PermissionSetId", "PermissionSet.Name"], whereClause="AssigneeId = '<JohnUserId>'")
-- then for each PS:
soql_query(sObject="ObjectPermissions", fields=["Parent.Name", "PermissionsEdit"], whereClause="ParentId IN ('<ps_id_1>', ...) AND SobjectType = 'Opportunity' AND PermissionsEdit = true")

Clone Permission Set Workflow

Use to copy an existing Permission Set or Permission Set Group with a new name.

  1. Read the source PS metadata:
metadata_read(type="PermissionSet", fullNames=["<SourcePSName>"], sf_user="<sf_user>")

For PSGs, verify the type first (tooling_api_query on PermissionSet checking Type field), then use metadata_read(type="PermissionSetGroup", ...).

  1. Create a new PS with modified fullName and label:
metadata_create(
  type="PermissionSet",
  metadata=[{
    ...cloned_metadata,
    "fullName": "<NewPSName>",
    "label": "<New Label>"
  }],
  sf_user="<sf_user>"
)
  1. Confirm success and display the new PS details.

Update Permission Set Workflow

Use to modify permissions on an existing Permission Set.

For system permissions (e.g., ModifyAllData, ViewAllData):

metadata_update(
  type="PermissionSet",
  metadata=[{
    "fullName": "<PSName>",
    "userPermissions": [
      {"enabled": true, "name": "<PermissionName>"}
    ]
  }],
  sf_user="<sf_user>"
)

For object/field permissions, use sobject_dml to insert or update permission records:

sobject_dml(
  operation="upsert",
  sObject="ObjectPermissions",
  records=[
    {"ParentId": "0PSXX0000004ABC", "SobjectType": "Account", "PermissionsRead": true, "PermissionsEdit": true, "PermissionsCreate": true, "PermissionsDelete": false, "PermissionsViewAllRecords": false, "PermissionsModifyAllRecords": false}
  ],
  sf_user="<sf_user>"
)

Get the PS record ID first if needed: soql_query(sObject="PermissionSet", fields=["Id"], whereClause="Name = '<PSName>'")


Delete Permission Set Workflow

Use to remove a Permission Set or Permission Set Group from the org.

  1. Confirm with the user before proceeding — deletion is irreversible.
  2. Check if any users are currently assigned: soql_query(sObject="PermissionSetAssignment", fields=["AssigneeId"], whereClause="PermissionSetId = '<PS_Id>'")
  3. If users are assigned, warn and ask for confirmation.
  4. Delete using metadata_delete:
metadata_delete(type="PermissionSet", fullNames=["<PSName>"], sf_user="<sf_user>")

For PSGs: metadata_delete(type="PermissionSetGroup", fullNames=["<PSGName>"], sf_user="<sf_user>")


Workflow (5-Phase Pattern)

Phase 1: Initialize & Understand the Request

First: Call org_init() with no parameters. Confirm org selection with user.

Then determine the capability needed:

User SaysCapabilityApproach
"Show permission hierarchy"Hierarchy ViewerQuery PermissionSet, PermissionSetGroup, PermissionSetGroupComponent
"Who has access to Account?"Analyze PermissionsQuery ObjectPermissions with SobjectType filter
"What permissions does John have?"Analyze PermissionsQuery PermissionSetAssignment for user
"Why can't John edit X?"Analyze PermissionsCross-check user PS assignments with required permissions
"Find PS with ModifyAllData"Security AuditQuery PermissionSet for system permissions
"Create a PS for contractors"PS CreationUse metadata_create
"Clone Sales_Manager PS"Clone PSmetadata_read then metadata_create with new name
"Update permissions on X"Update PSmetadata_update or sobject_dml
"Delete the old PS"Delete PSmetadata_delete
"Export Sales_Manager PS"DocumentationQuery all permission types for the PS

Phase 2: Query Permissions

Use soql_query with the appropriate SOQL for each capability.

Permission Set & Group Queries

soql_query(
  sObject="PermissionSet",
  fields=["Id", "Name", "Label", "Description", "IsOwnedByProfile"],
  whereClause="IsOwnedByProfile = false AND Type != 'Group'",
  sf_user="<sf_user>"
)
soql_query(
  sObject="PermissionSetGroup",
  fields=["Id", "DeveloperName", "MasterLabel", "Status", "Description"],
  sf_user="<sf_user>"
)

PSG Components (which PS are in which PSG)

soql_query(
  sObject="PermissionSetGroupComponent",
  fields=["PermissionSetGroupId", "PermissionSetGroup.DeveloperName", "PermissionSetId", "PermissionSet.Name"],
  sf_user="<sf_user>"
)

Object Permissions

soql_query(
  sObject="ObjectPermissions",
  fields=["Parent.Name", "Parent.Label", "SobjectType", "PermissionsCreate", "PermissionsRead", "PermissionsEdit", "PermissionsDelete"],
  whereClause="SobjectType = 'Account' AND PermissionsDelete = true",
  sf_user="<sf_user>"
)

Field Permissions

soql_query(
  sObject="FieldPermissions",
  fields=["Parent.Name", "Field", "PermissionsRead", "PermissionsEdit"],
  whereClause="Field = 'Account.AnnualRevenue' AND PermissionsEdit = true",
  sf_user="<sf_user>"
)

Known caveats:

  • Parent.Name returns hex IDs (e.g. 0PSV90000004CqU) instead of human-readable PS API names. To resolve, follow up with a query on PermissionSet using the returned IDs: soql_query(sObject="PermissionSet", fields=["Id","Name","Label"], whereClause="Id IN ('0PS...',...)").
  • SobjectType filter on FieldPermissions may return rows from other objects (e.g. Lead.AnnualRevenue when filtering for Account). Always verify the Field column prefix matches the expected object.

User's PS Assignments

soql_query(
  sObject="PermissionSetAssignment",
  fields=["AssigneeId", "PermissionSetId", "PermissionSet.Name", "PermissionSetGroupId", "PermissionSetGroup.DeveloperName"],
  whereClause="AssigneeId = '005...'",
  sf_user="<sf_user>"
)

Setup Entity Access (Apex, VF, Flows, Custom Permissions)

soql_query(
  sObject="SetupEntityAccess",
  fields=["Parent.Name", "Parent.Label", "SetupEntityType", "SetupEntityId"],
  whereClause="SetupEntityType = 'ApexClass' AND SetupEntityId IN (SELECT Id FROM ApexClass WHERE Name = 'MyClass')",
  sf_user="<sf_user>"
)

Phase 3: Analyze Results

For each capability, process the query results:

Hierarchy Viewer: Build a tree structure showing PSG -> PS relationships and standalone PS.

Permission Detector: List all PS/PSG that grant the requested permission, with user counts.

User Analyzer: Aggregate all permissions from the user's PS/PSG assignments.

Security Audit: Flag concerning patterns:

  • PS with PermissionsModifyAllData = true (non-admin)
  • PS with PermissionsViewAllData = true on sensitive objects
  • Orphaned PS (no assigned users)
  • PSG with "Outdated" status

Phase 4: Present Results

Format results clearly using tables and structured output:

Permission Hierarchy
====================

Permission Set Groups (3)
  Sales_Cloud_User (Active)
    - View_All_Accounts
    - Edit_Opportunities
    - Run_Reports
  Service_Cloud_User (Active)
    - Case_Management

Standalone Permission Sets (12)
  - Admin_Tools
  - API_Access
  - ...

For "Who has X?" queries:

Who can DELETE Account? (3 Permission Sets found)
=================================================

| Permission Set    | Type       | Users Assigned |
| ----------------- | ---------- | -------------- |
| Sales_Admin       | Standalone | 5              |
| Full_Access       | In PSG     | 12             |
| System_Admin      | Profile PS | 3              |

Phase 5: Recommend Actions

Based on the analysis, recommend improvements:

  • Consolidate overlapping PS into PSGs
  • Remove overly broad permissions
  • Create missing PS for proper access control
  • Update outdated PSGs

Salesforce Permission Model

Key Concepts

USER
  -> PROFILE (base permissions - one per user)
    -> PERMISSION SET GROUPS (collections of PS)
      -> PERMISSION SETS (additive permissions)
  • Profiles: One per user, defines base access. Salesforce recommends minimal profiles + Permission Sets.
  • Permission Sets (PS): Additive only - can grant access, cannot revoke. Multiple PS per user.
  • Permission Set Groups (PSG): Container for multiple PS. Assign one PSG instead of many individual PS.

Permission Types

TypeDescriptionQuery Object
Object CRUDCreate, Read, Edit, DeleteObjectPermissions
Field-Level SecurityRead, Edit per fieldFieldPermissions
Apex Class AccessAccess to Apex classesSetupEntityAccess
VF Page AccessAccess to Visualforce pagesSetupEntityAccess
Flow AccessAccess to FlowsSetupEntityAccess
Custom PermissionsFeature flagsSetupEntityAccess
System PermissionsViewSetup, ModifyAllData, etc.PermissionSet fields

Common SOQL Patterns for Permission Analysis

-- All Permission Sets (non-profile)
SELECT Id, Name, Label FROM PermissionSet WHERE IsOwnedByProfile = false AND Type != 'Group'

-- User's PS Assignments
SELECT PermissionSetId, PermissionSet.Name FROM PermissionSetAssignment WHERE AssigneeId = '005...'

-- Find PS with delete access to Account
SELECT Parent.Name FROM ObjectPermissions WHERE SobjectType = 'Account' AND PermissionsDelete = true

-- Find PS with edit access to a specific field
SELECT Parent.Name, Field FROM FieldPermissions WHERE Field = 'Account.AnnualRevenue' AND PermissionsEdit = true

-- Find PS with access to specific Apex class
SELECT Parent.Name FROM SetupEntityAccess WHERE SetupEntityType = 'ApexClass' AND SetupEntityId IN (SELECT Id FROM ApexClass WHERE Name = 'MyClass')

-- Find PS with custom permission
SELECT Parent.Name FROM SetupEntityAccess WHERE SetupEntityType = 'CustomPermission' AND SetupEntityId IN (SELECT Id FROM CustomPermission WHERE DeveloperName = 'Can_Approve')

-- PSGs and their component Permission Sets
SELECT PermissionSetGroup.DeveloperName, PermissionSet.Name FROM PermissionSetGroupComponent

-- Count users per Permission Set
SELECT PermissionSetId, PermissionSet.Name, COUNT(AssigneeId) FROM PermissionSetAssignment GROUP BY PermissionSetId, PermissionSet.Name

Schema Validation for Permission Sets

A baseline JSON Schema is bundled at references/permissionset-metadata-schema.json (API v65.0). Before calling metadata_create, validate the JSON payload against this schema to catch structural errors offline:

  • Required fields (label)
  • Valid child types (objectPermissions, fieldPermissions, userPermissions, etc.)
  • Correct field formats (e.g., field in fieldPermissions must be Object.Field)
  • Valid enum values for tabSettings.visibility (Available, Hidden, Visible)

To refresh the schema from a live org (requires sf CLI):

scripts/pull_schema.sh --type PermissionSet          # default org
scripts/pull_schema.sh --type PermissionSet myOrg    # specific org
scripts/pull_schema.sh --type PermissionSetGroup
scripts/pull_schema.sh --type Profile
scripts/pull_schema.sh --type SharingRules

Creating Permission Sets via MCP

Step 1 — Create the permission set:

metadata_create(
  type="PermissionSet",
  metadata=[{
    "fullName": "Sales_Account_Edit",
    "label": "Sales Account Edit",
    "description": "Grants sales team edit access to Accounts",
    "hasActivationRequired": false
  }],
  sf_user="<sf_user>"
)

Step 2 — Get the permission set's record ID:

soql_query(
  sObject="PermissionSet",
  fields=["Id", "Name"],
  whereClause="Name = 'Sales_Account_Edit' AND IsOwnedByProfile = false",
  sf_user="<sf_user>"
)

Step 3 — Add permissions via sobject_dml:

Use sobject_dml to insert permission records. The ParentId must be the Salesforce record ID from step 2 (starts with 0PS), NOT the API name.

sobject_dml(
  operation="insert",
  sObject="ObjectPermissions",
  records=[
    {"ParentId": "0PSXX0000004ABC", "SobjectType": "Account", "PermissionsRead": true, "PermissionsEdit": true, "PermissionsCreate": true, "PermissionsDelete": false, "PermissionsViewAllRecords": false, "PermissionsModifyAllRecords": false}
  ],
  sf_user="<sf_user>"
)

For field-level permissions:

sobject_dml(
  operation="insert",
  sObject="FieldPermissions",
  records=[
    {"ParentId": "0PSXX0000004ABC", "SobjectType": "Account", "Field": "Account.AnnualRevenue", "PermissionsRead": true, "PermissionsEdit": true},
    {"ParentId": "0PSXX0000004ABC", "SobjectType": "Account", "Field": "Account.Industry", "PermissionsRead": true, "PermissionsEdit": true}
  ],
  sf_user="<sf_user>"
)

Other permission types that can be added via sobject_dml:

sObjectPurposeKey fields
PermissionSetTabSettingTab visibilityParentId, Name, Visibility
SetupEntityAccessApex class, VF page, Flow, Custom Permission accessParentId, SetupEntityId

For system permissions (e.g., ModifyAllData) that have no DML-able object, use metadata_update to patch userPermissions:

metadata_update(
  type="PermissionSet",
  metadata=[{
    "fullName": "Sales_Account_Edit",
    "userPermissions": [
      {"enabled": true, "name": "ModifyAllData"}
    ]
  }],
  sf_user="<sf_user>"
)

Agent Access Permissions

Employee Agents (Agentforce) require agentAccesses in a Permission Set. The agentName must match the agent's developer_name exactly.

Query existing agent access:

tooling_api_query(
  sObject="PermissionSet",
  fields=["Name", "Label"],
  whereClause="Name LIKE '%Agent%'",
  sf_user="<sf_user>"
)

Common Workflows

Audit: "Who can delete Accounts?"

  1. Query ObjectPermissions for Account with PermissionsDelete = true
  2. For each PS found, query PSG membership
  3. Count assigned users per PS/PSG
  4. Display results in table format

Troubleshoot: "Why can't John edit Opportunities?"

  1. Query PermissionSetAssignment for John's user ID
  2. For each assigned PS, query ObjectPermissions for Opportunity
  3. Check if any PS grants Opportunity edit
  4. If not, suggest which PS/PSG to assign

Security Review: "Find all PS with ModifyAllData"

  1. Query PermissionSet for PermissionsModifyAllData = true
  2. List PS names and assigned user counts
  3. Flag any non-admin PS with this powerful permission

Full Org Audit

  1. Query all PS and PSG to show hierarchy
  2. Identify PSGs with "Outdated" status
  3. Count users per PS
  4. Flag overly broad permissions

Naming Convention Best Practices

Permission Set:       [Department]_[Capability]_PS
Permission Set Group: [Department]_[Role]_PSG

Examples:
  - Sales_Account_Edit_PS
  - Sales_Manager_PSG
  - HR_Employee_Data_Access_PS

Cross-Skill Integration

From SkillTo sf-permissionsWhen
sf-metadata-> sf-permissions"Create Permission Set for new object"
sf-apex-> sf-permissions"Grant access to Apex class"
sf-data-> sf-permissions"Query user assignments in bulk"
sf-diagram-> sf-permissions"Visualize permission hierarchy as Mermaid"
From sf-permissionsTo SkillWhen
sf-permissions-> sf-metadataGenerate Permission Set metadata
sf-permissions-> sf-diagramCreate hierarchy visualization

Troubleshooting

IssueSolution
No results for permission queryCheck if PS exists; use correct API name
Missing field permissionsFLS may be controlled at Profile level
PSG shows "Outdated"PSG needs to be recalculated in Setup
Can't find user's permissionsCheck both direct PS and PSG assignments
metadata_read fails silently on a PS that existsThe record may be a Permission Set Group (Type = 'Group'). Verify with tooling_api_query on PermissionSet checking the Type field. If Type = 'Group', use metadata_read with type PermissionSetGroup instead of PermissionSet. PSGs surface in PermissionSet SOQL queries but require a different metadata type for metadata_read.

Removed Capabilities

The following developer-focused features from the original sf-permissions are NOT needed in this MCP-based version:

  • Python scripts (cli.py, hierarchy_viewer.py, etc.) - Replaced with SOQL via MCP
  • simple-salesforce Python library - Not needed
  • rich terminal library - Not needed
  • sf CLI authentication commands - Use org_init() instead
  • CSV export scripts - Use SOQL queries and format results directly

Dependencies

  • Salesforce MCP server (required): All permission operations use Salesforce MCP tools

    • Initialize with: org_init()
    • Tools: soql_query, tooling_api_query, metadata_create
  • sf-metadata (optional): For creating Permission Sets

  • sf-diagram (optional): For visualizing permission hierarchies as Mermaid diagrams


Notes

  • Permissions are additive: Permission Sets can only grant, never revoke access
  • Profile-owned PS: Each Profile has an auto-created PS. Filter with IsOwnedByProfile = false
  • PSG Types: Filter with Type != 'Group' to exclude PSG-level entries from PS queries
  • PSG vs PS for metadata_read: Records with Type = 'Group' in the PermissionSet object are Permission Set Groups. Querying them with metadata_read(type="PermissionSet") will fail silently. Always check Type first via tooling_api_query, then use metadata_read(type="PermissionSetGroup") for groups. The metadata_read result for a PSG shows its member permissionSets array — not individual object/field permissions (those live on the component PS records).
  • Remote Org Only: All operations target remote orgs via Salesforce MCP server

License

MIT License — see LICENSE for details.

For credits and attribution see CREDITS.md.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.