Skillssf-apex
S

sf-apex

Generates and reviews Salesforce Apex code with 2025 best practices and 150-point scoring. Use when writing Apex classes, triggers, test classes, batch jobs, or reviewing existing Apex code for bulkification, security, and SOLID principles.

Jaganpro
41 stars
1.2k downloads
Updated 1w ago

Readme

sf-apex follows the SKILL.md standard. Use the install command to add it to your agent stack.

---
name: sf-apex
description: >
  Generates and reviews Salesforce Apex code with 2025 best practices and 150-point
  scoring. Use when writing Apex classes, triggers, test classes, batch jobs, or
  reviewing existing Apex code for bulkification, security, and SOLID principles.
license: MIT
metadata:
  version: "1.1.0"
  author: "Jag Valaiyapathy"
  scoring: "150 points across 8 categories"
hooks:
  SessionStart:
    - type: command
      command: "${SHARED_HOOKS}/check-env-weekly.sh"
      timeout: 5000
  PreToolUse:
    - matcher: Bash
      hooks:
        - type: command
          command: "python3 ${SHARED_HOOKS}/scripts/guardrails.py"
          timeout: 5000
  PostToolUse:
    - matcher: "Write|Edit"
      hooks:
        - type: command
          command: "python3 ${SKILL_HOOKS}/apex-lsp-validate.py"
          timeout: 15000
        - type: command
          command: "python3 ${SKILL_HOOKS}/post-tool-validate.py"
          timeout: 120000
        - type: command
          command: "python3 ${SHARED_HOOKS}/suggest-related-skills.py sf-apex"
          timeout: 5000
  SubagentStop:
    - type: command
      command: "python3 ${SHARED_HOOKS}/scripts/chain-validator.py sf-apex"
      timeout: 5000
---

# 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](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](resources/security-guide.md) for detailed security patterns
**See**: [resources/anti-patterns.md](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](resources/troubleshooting.md#cross-skill-dependency-checklist) for deployment prerequisites

---

### Phase 5: Documentation & Testing Guidance

**Completion Summary**:
```
✓ Apex Code Complete: [ClassName]
  Type: [type] | API: 65.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**:
- [resources/bulkification-guide.md](resources/bulkification-guide.md) - Governor limits, collection handling
- [resources/security-guide.md](resources/security-guide.md) - CRUD/FLS, sharing, injection prevention
- [resources/testing-patterns.md](resources/testing-patterns.md) - Exception types, mocking, coverage
- [resources/patterns-deep-dive.md](resources/patterns-deep-dive.md) - TAF, @InvocableMethod, async patterns

---

## 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):
```apex
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):
```apex
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**:
```bash
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](resources/patterns-deep-dive.md#standard-trigger-pattern))

**See**: [resources/patterns-deep-dive.md](resources/patterns-deep-dive.md#trigger-actions-framework-taf) 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](resources/patterns-deep-dive.md#async-patterns) 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](resources/bulkification-guide.md#collection-handling-best-practices) 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

```apex
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**:
- [resources/patterns-deep-dive.md](resources/patterns-deep-dive.md#flow-integration-invocablemethod) - Complete @InvocableMethod guide
- [docs/flow-integration.md](docs/flow-integration.md) - Advanced Flow-Apex patterns
- [docs/triangle-pattern.md](docs/triangle-pattern.md) - Flow-LWC-Apex triangle

---

## 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**:
```apex
@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**:
- [resources/testing-patterns.md](resources/testing-patterns.md) - Exception types, mocking, Test Data Factory
- [docs/testing-guide.md](docs/testing-guide.md) - Complete testing reference

---

## 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**:
```apex
@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](resources/testing-patterns.md#common-exception-types) 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](resources/troubleshooting.md#lsp-based-validation-auto-fix-loop) 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](resources/patterns-deep-dive.md) | TAF, @InvocableMethod, async patterns, service layer |
| [security-guide.md](resources/security-guide.md) | CRUD/FLS, sharing, SOQL injection, guardrails |
| [bulkification-guide.md](resources/bulkification-guide.md) | Governor limits, collections, monitoring |
| [testing-patterns.md](resources/testing-patterns.md) | Exception types, mocking, Test Data Factory, coverage |
| [anti-patterns.md](resources/anti-patterns.md) | Code smells, red flags, refactoring patterns |
| [troubleshooting.md](resources/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 |
| `llm-anti-patterns.md` | **NEW**: Common LLM code generation mistakes (Java types, non-existent methods, Map patterns) |

**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](LICENSE) file.
Copyright (c) 2024-2025 Jag Valaiyapathy

Install

Requires askill CLI v1.0+

Metadata

LicenseUnknown
Version-
Updated1w ago
PublisherJaganpro

Tags

apici-cdgithubgithub-actionsllmobservabilitysecuritytesting