Agent Skills: sf-apex: Salesforce Apex Code Generation and Review

>

UncategorizedID: Jaganpro/sf-skills/sf-apex

Skill Files

Browse the full folder contents for sf-apex.

Download Skill

Loading file tree…

sf-apex/SKILL.md

Skill Metadata

Name
sf-apex
Description
>

sf-apex: Salesforce Apex Code Generation and Review

Expert Apex developer specializing in clean code, SOLID principles, and 2025 best practices. Generate production-ready, secure, performant, and maintainable Apex code.

Core Responsibilities

  1. Code Generation: Create Apex classes, triggers (TAF), tests, async jobs from requirements
  2. Code Review: Analyze existing Apex for best practices violations with actionable fixes
  3. Validation & Scoring: Score code against 8 categories (0-150 points)
  4. Deployment Integration: Validate and deploy via sf-deploy skill

Workflow (5-Phase Pattern)

Phase 1: Requirements Gathering

Use AskUserQuestion to gather:

  • Class type (Trigger, Service, Selector, Batch, Queueable, Test, Controller)
  • Primary purpose (one sentence)
  • Target object(s)
  • Test requirements

Then:

  1. Check existing code: Glob: **/*.cls, Glob: **/*.trigger
  2. Check for existing Trigger Actions Framework setup: Glob: **/*TriggerAction*.cls
  3. Create TodoWrite tasks

Phase 2: Design & Template Selection

Select template: | Class Type | Template | |------------|----------| | Trigger | templates/trigger.trigger | | Trigger Action | templates/trigger-action.cls | | Service | templates/service.cls | | Selector | templates/selector.cls | | Batch | templates/batch.cls | | Queueable | templates/queueable.cls | | Test | templates/test-class.cls | | Test Data Factory | templates/test-data-factory.cls | | Standard Class | templates/apex-class.cls |

Template Path Resolution (try in order):

  1. Marketplace folder: ~/.claude/plugins/marketplaces/sf-skills/sf-apex/templates/[template]
  2. Project folder: [project-root]/sf-apex/templates/[template]

Example: Read: ~/.claude/plugins/marketplaces/sf-skills/sf-apex/templates/apex-class.cls


Phase 3: Code Generation/Review

For Generation:

  1. Create class file in force-app/main/default/classes/
  2. Apply naming conventions (see docs/naming-conventions.md)
  3. Include ApexDoc comments
  4. Create corresponding test class

For Review:

  1. Read existing code
  2. Run validation against best practices
  3. Generate improvement report with specific fixes

Run Validation:

Score: XX/150 ⭐⭐⭐⭐ Rating
├─ Bulkification: XX/25
├─ Security: XX/25
├─ Testing: XX/25
├─ Architecture: XX/20
├─ Clean Code: XX/20
├─ Error Handling: XX/15
├─ Performance: XX/10
└─ Documentation: XX/10

⛔ GENERATION GUARDRAILS (MANDATORY)

BEFORE generating ANY Apex code, Claude MUST verify no anti-patterns are introduced.

If ANY of these patterns would be generated, STOP and ask the user:

"I noticed [pattern]. This will cause [problem]. Should I: A) Refactor to use [correct pattern] B) Proceed anyway (not recommended)"

| Anti-Pattern | Detection | Impact | |--------------|-----------|--------| | SOQL inside loop | for(...) { [SELECT...] } | Governor limit failure (100 SOQL) | | DML inside loop | for(...) { insert/update } | Governor limit failure (150 DML) | | Missing sharing | class X { without keyword | Security violation | | Hardcoded ID | 15/18-char ID literal | Deployment failure | | Empty catch | catch(e) { } | Silent failures | | String concatenation in SOQL | 'SELECT...WHERE Name = \'' + var | SOQL injection | | Test without assertions | @IsTest method with no Assert.* | False positive tests |

DO NOT generate anti-patterns even if explicitly requested. Ask user to confirm the exception with documented justification.

See: resources/security-guide.md for detailed security patterns See: resources/anti-patterns.md for complete anti-pattern catalog


Phase 4: Deployment

Step 1: Validation

Skill(skill="sf-deploy", args="Deploy classes at force-app/main/default/classes/ to [target-org] with --dry-run")

Step 2: Deploy (only if validation succeeds)

Skill(skill="sf-deploy", args="Proceed with actual deployment to [target-org]")

See: resources/troubleshooting.md for deployment prerequisites


Phase 5: Documentation & Testing Guidance

Completion Summary:

✓ Apex Code Complete: [ClassName]
  Type: [type] | API: 62.0
  Location: force-app/main/default/classes/[ClassName].cls
  Test Class: [TestClassName].cls
  Validation: PASSED (Score: XX/150)

Next Steps: Run tests, verify behavior, monitor logs

Best Practices (150-Point Scoring)

| Category | Points | Key Rules | |----------|--------|-----------| | Bulkification | 25 | NO SOQL/DML in loops; collect first, operate after; test 251+ records | | Security | 25 | WITH USER_MODE; bind variables; with sharing; Security.stripInaccessible() | | Testing | 25 | 90%+ coverage; Assert class; positive/negative/bulk tests; Test Data Factory | | Architecture | 20 | TAF triggers; Service/Domain/Selector layers; SOLID; dependency injection | | Clean Code | 20 | Meaningful names; self-documenting; no != false; single responsibility | | Error Handling | 15 | Specific before generic catch; no empty catch; custom business exceptions | | Performance | 10 | Monitor with Limits; cache expensive ops; scope variables; async for heavy | | Documentation | 10 | ApexDoc on classes/methods; meaningful params |

Thresholds: ✅ 90+ (Deploy) | ⚠️ 67-89 (Review) | ❌ <67 (Block - fix required)

Deep Dives:


Trigger Actions Framework (TAF)

Quick Reference

When to Use: If TAF package is installed in target org (check: sf package installed list)

Trigger Pattern (one per object):

trigger AccountTrigger on Account (before insert, after insert, before update, after update, before delete, after delete, after undelete) {
    new MetadataTriggerHandler().run();
}

Action Class (one per behavior):

public class TA_Account_SetDefaults implements TriggerAction.BeforeInsert {
    public void beforeInsert(List<Account> newList) {
        for (Account acc : newList) {
            if (acc.Industry == null) {
                acc.Industry = 'Other';
            }
        }
    }
}

⚠️ CRITICAL: TAF triggers do NOTHING without Trigger_Action__mdt records! Each action class needs a corresponding Custom Metadata record.

Installation:

sf package install --package 04tKZ000000gUEFYA2 --target-org [alias] --wait 10

Fallback: If TAF is NOT installed, use standard trigger pattern (see resources/patterns-deep-dive.md)

See: resources/patterns-deep-dive.md for complete TAF patterns and Custom Metadata setup


Async Decision Matrix

| Scenario | Use | |----------|-----| | Simple callout, fire-and-forget | @future(callout=true) | | Complex logic, needs chaining | Queueable | | Process millions of records | Batch Apex | | Scheduled/recurring job | Schedulable | | Post-queueable cleanup | Queueable Finalizer |

See: resources/patterns-deep-dive.md for detailed async patterns


Modern Apex Features (API 62.0)

  • Null coalescing: value ?? defaultValue
  • Safe navigation: record?.Field__c
  • User mode: WITH USER_MODE in SOQL
  • Assert class: Assert.areEqual(), Assert.isTrue()

Breaking Change (API 62.0): Cannot modify Set while iterating - throws System.FinalException

See: resources/bulkification-guide.md for collection usage


Flow Integration (@InvocableMethod)

Apex classes can be called from Flow using @InvocableMethod. This pattern enables complex business logic, DML, callouts, and integrations from declarative automation.

Quick Pattern

public with sharing class RecordProcessor {

    @InvocableMethod(label='Process Record' category='Custom')
    public static List<Response> execute(List<Request> requests) {
        List<Response> responses = new List<Response>();
        for (Request req : requests) {
            Response res = new Response();
            res.isSuccess = true;
            res.processedId = req.recordId;
            responses.add(res);
        }
        return responses;
    }

    public class Request {
        @InvocableVariable(label='Record ID' required=true)
        public Id recordId;
    }

    public class Response {
        @InvocableVariable(label='Is Success')
        public Boolean isSuccess;
        @InvocableVariable(label='Processed ID')
        public Id processedId;
    }
}

Template: Use templates/invocable-method.cls for complete pattern

See:


Testing Best Practices

The 3 Test Types (PNB Pattern)

Every feature needs:

  1. Positive: Happy path test
  2. Negative: Error handling test
  3. Bulk: 251+ records test

Example:

@IsTest
static void testPositive() {
    Account acc = new Account(Name = 'Test', Industry = 'Tech');
    insert acc;
    Assert.areEqual('Tech', [SELECT Industry FROM Account WHERE Id = :acc.Id].Industry);
}

@IsTest
static void testNegative() {
    try {
        insert new Account(); // Missing Name
        Assert.fail('Expected DmlException');
    } catch (DmlException e) {
        Assert.isTrue(e.getMessage().contains('REQUIRED_FIELD_MISSING'));
    }
}

@IsTest
static void testBulk() {
    List<Account> accounts = new List<Account>();
    for (Integer i = 0; i < 251; i++) {
        accounts.add(new Account(Name = 'Bulk ' + i));
    }
    insert accounts;
    Assert.areEqual(251, [SELECT COUNT() FROM Account]);
}

See:


Common Exception Types

When writing test classes, use these specific exception types:

| Exception Type | When to Use | |----------------|-------------| | DmlException | Insert/update/delete failures | | QueryException | SOQL query failures | | NullPointerException | Null reference access | | ListException | List operation failures | | LimitException | Governor limit exceeded | | CalloutException | HTTP callout failures |

Example:

@IsTest
static void testExceptionHandling() {
    try {
        insert new Account(); // Missing required Name
        Assert.fail('Expected DmlException was not thrown');
    } catch (DmlException e) {
        Assert.isTrue(e.getMessage().contains('REQUIRED_FIELD_MISSING'),
            'Expected REQUIRED_FIELD_MISSING but got: ' + e.getMessage());
    }
}

See: resources/testing-patterns.md for complete reference


LSP-Based Validation (Auto-Fix Loop)

The sf-apex skill includes Language Server Protocol (LSP) integration for real-time syntax validation. This enables Claude to automatically detect and fix Apex syntax errors during code authoring.

How It Works

  1. PostToolUse Hook: After every Write/Edit operation on .cls or .trigger files, the LSP hook validates syntax
  2. Apex Language Server: Uses Salesforce's official apex-jorje-lsp.jar (from VS Code extension)
  3. Auto-Fix Loop: If errors are found, Claude receives diagnostics and auto-fixes them (max 3 attempts)
  4. Two-Layer Validation:
    • LSP Validation: Fast syntax checking (~500ms)
    • 150-Point Validation: Semantic analysis for best practices

Prerequisites

For LSP validation to work, users must have:

  • VS Code Salesforce Extension Pack: VS Code → Extensions → "Salesforce Extension Pack"
  • Java 11+: https://adoptium.net/temurin/releases/

Graceful Degradation: If LSP is unavailable, validation silently skips - the skill continues to work with only 150-point semantic validation.

See: resources/troubleshooting.md for complete LSP guide


Cross-Skill Integration

| Skill | When to Use | Example | |-------|-------------|---------| | sf-metadata | Discover object/fields before coding | Skill(skill="sf-metadata") → "Describe Invoice__c" | | sf-data | Generate 251+ test records after deploy | Skill(skill="sf-data") → "Create 251 Accounts for bulk testing" | | sf-deploy | Deploy to org - see Phase 4 | Skill(skill="sf-deploy", args="Deploy to [org]") | | sf-flow | Create Flow that calls your Apex | See @InvocableMethod section above | | sf-lwc | Create LWC that calls your Apex | @AuraEnabled controller patterns |


Reference Documentation

Quick Guides (resources/)

| Guide | Description | |-------|-------------| | patterns-deep-dive.md | TAF, @InvocableMethod, async patterns, service layer | | security-guide.md | CRUD/FLS, sharing, SOQL injection, guardrails | | bulkification-guide.md | Governor limits, collections, monitoring | | testing-patterns.md | Exception types, mocking, Test Data Factory, coverage | | anti-patterns.md | Code smells, red flags, refactoring patterns | | troubleshooting.md | LSP validation, deployment errors, debug logs |

Full Documentation (docs/)

| Document | Description | |----------|-------------| | best-practices.md | Bulkification, collections, null safety, guard clauses, DML performance | | code-smells-guide.md | Code smells detection and refactoring patterns | | design-patterns.md | 12 patterns including Domain Class, Abstraction Levels | | trigger-actions-framework.md | TAF setup and advanced patterns | | security-guide.md | Complete CRUD/FLS and sharing reference | | testing-guide.md | Complete test patterns and mocking | | naming-conventions.md | Variable, method, class naming rules | | solid-principles.md | SOLID principles for Apex | | code-review-checklist.md | 150-point scoring criteria | | flow-integration.md | Complete @InvocableMethod guide | | triangle-pattern.md | Flow-LWC-Apex integration |

Path: ~/.claude/plugins/marketplaces/sf-skills/sf-apex/docs/


Dependencies

All optional: sf-deploy, sf-metadata, sf-data. Install: /plugin install github:Jaganpro/sf-skills/[skill-name]


Notes

  • API Version: 62.0 required
  • TAF Optional: Prefer TAF when package is installed, use standard trigger pattern as fallback
  • Scoring: Block deployment if score < 67
  • LSP: Optional but recommended for real-time syntax validation

License

MIT License. See LICENSE file. Copyright (c) 2024-2025 Jag Valaiyapathy