| name | salesforce-apex-generator-skill |
| description | Generates production-grade Apex classes with Service-Selector-Domain layering, correct sharing models (with sharing / without sharing / inherited sharing per class type), async patterns (Queueable, Batchable, Schedulable), and governor-limit awareness. T0 static generation — no org connection required. TRIGGER when: user asks to write an Apex class or trigger, generate a service/selector/domain layer, create an async job, implement a REST resource, scaffold a .cls file, or port business logic to Apex. Trigger phrases: write apex class, generate apex trigger, create apex service, .cls file, implement queueable, create batch job. DO NOT TRIGGER when: live test execution needed (use salesforce-apex-test-runner-skill), generating test classes specifically (use salesforce-apex-test-generator-skill), debugging an existing class from log evidence (use salesforce-apex-log-analyzer-skill), or the user needs a live deployment (use salesforce-deployment-validator-skill). |
| license | MIT |
| allowed-tools | Read Grep Glob |
| metadata | {"author":"github: Raishin","version":"0.1.0","updated":"2026-05-21","category":"generation","lifecycle":"experimental","execution_tier":"static-review","mcp_servers":[],"oauth_scopes":[],"run_as_permissions":{"required":[],"denied":[]}} |
salesforce-apex-generator-skill
T0 static code generation for production-grade Apex. This skill is a forge, not a
flashlight — it authors correct, deployable Apex with the right sharing model, governor-limit
safety, and security defaults for each class type. No org connection required.
When This Skill Owns the Task
Use salesforce-apex-generator-skill when the work requires authoring new Apex code:
- "Write an AccountService class that queries all Accounts by owner"
- "Generate a Queueable that sends platform events for Order updates"
- "Create a Schedulable wrapper for a batch job"
- "Scaffold the Selector layer for the Contact object"
- "Implement a Domain class with trigger logic for Opportunity"
- "Write a REST resource endpoint for an external integration"
- "Create a .cls file for our deduplication logic"
Delegate elsewhere when:
| Situation | Skill to use |
|---|
| User needs test classes specifically | salesforce-apex-test-generator-skill |
| User wants to run tests against a live org | salesforce-apex-test-runner-skill |
| User is debugging a log file or stack trace | salesforce-apex-log-analyzer-skill |
| User needs to deploy and validate | salesforce-deployment-validator-skill |
| Static code review of existing Apex | salesforce-apex-lwc-code-review-skill |
Required Context to Gather First
Before generating, confirm:
- Class type — service, selector, domain, batch, queueable, schedulable, invocable,
trigger, trigger-handler, REST resource, DTO, utility, interface, exception
- Target object(s) — the SObject API names involved (e.g.,
Account, Opportunity__c)
- Business goal — what the class must accomplish
- Class name — derive from naming conventions if not provided
- Existing patterns — does the project use a trigger framework (TAF, MetadataTriggerHandler)?
Service-Selector-Domain already in place?
- API version — default
62.0 minimum
- Test class expected? — always recommend pairing with
salesforce-apex-test-generator-skill
If the user provides a clear, complete request, generate immediately without unnecessary
back-and-forth. Apply defaults (see Rules section) for anything not specified.
Recommended Workflow
Step 1 — Identify class type and infer defaults
Map the request to a class type using the type table below. Set defaults:
- Sharing:
with sharing unless type-specific exception applies
- Access modifier:
public unless global is required
- ApexDoc: always include
- API version meta XML: always generate
Step 2 — Choose the minimal correct pattern
Consult references/apex-patterns.md for Service-Selector-Domain conventions,
async patterns, and type-specific templates.
Step 3 — Apply all hard-stop constraints
Before writing a single line, verify every constraint in the Rules section would be
satisfied. If a constraint would be violated by the user's request, explain the problem
and propose the correct approach.
Step 4 — Generate the class file
Produce {ClassName}.cls with:
- Correct
with sharing / without sharing / inherited sharing declaration
- ApexDoc comment block (purpose, author placeholder, version)
- All SOQL outside loops
- All DML outside loops
- No
@future methods — use Queueable
- Bind variables for any dynamic SOQL
- Proper exception handling
- No hardcoded Ids or credentials
Step 5 — Generate the metadata XML
Produce {ClassName}.cls-meta.xml using the correct apiVersion and status: Active.
Step 6 — Score against the quality rubric
Run the 100-point scoring rubric (see below). If the score is below 80, revise before
presenting. Document score and notes in the output.
Step 7 — Recommend test class pairing
Always end with an explicit recommendation to generate a companion test class using
salesforce-apex-test-generator-skill, noting the class name and key scenarios to cover.
Class Type Reference
| Class Type | Sharing Model | Access | Key Rules |
|---|
| Service | with sharing | public | No SOQL/DML in loops; inject Selector |
| Selector | with sharing | public | Returns typed lists; no business logic |
| Domain | with sharing | public | Trigger-context aware; delegates to Service |
| Trigger | N/A (handler delegates) | — | One trigger per object; delegates to Domain/handler |
| Batchable | without sharing or with sharing | public | Implements Database.Batchable; Database.Stateful only if required |
| Queueable | with sharing | public | Implements Queueable; use System.Finalizer for chaining; replaces @future |
| Schedulable | with sharing | public | Implements Schedulable; delegates to Queueable or Batch |
| Invocable | with sharing | public | @InvocableMethod; typed inner request/result classes |
| REST Resource | without sharing (framework handles sharing) | global | @RestResource; @HttpGet/@HttpPost etc. |
| DTO / Wrapper | N/A | public | No methods with side effects; serializable |
| Utility | with sharing | public | Static methods only; no instance state |
| Exception | N/A | public |
Rules
Hard-Stop Constraints (Must Enforce)
| Constraint | Rationale |
|---|
| Place all SOQL outside loops | Avoid query governor limit (100 queries per transaction) |
| Place all DML outside loops | Avoid DML statement governor limit (150 per transaction) |
| Declare sharing keyword on every class | Prevent unintended without sharing defaults and data leakage |
| Use Custom Metadata / Labels / describe calls instead of hardcoded Ids | Portability across orgs |
| Always handle exceptions (log, rethrow, or recover) | Prevent silent failures |
| Use bind variables for all dynamic SOQL accepting user input | Prevent SOQL injection |
| Use Apex-native collection types | Prevent compile errors from Java-style types |
Never use @future methods | Use Queueable with System.Finalizer; @future cannot chain or accept non-primitive types |
No System.debug in main code paths | Debug statements consume CPU; use a logging framework |
Security: use WITH USER_MODE on SOQL in classes that touch user-controlled data | Enforces FLS/CRUD at query time |
Apply Security.stripInaccessible when constructing SObjects from user input | Strips fields the user cannot access |
Naming Conventions
| Type | Pattern | Example |
|---|
| Service | {SObject}Service | AccountService |
| Selector | {SObject}Selector | AccountSelector |
| Domain | {SObject}Domain | AccountDomain |
| Handler | {SObject}TriggerHandler | AccountTriggerHandler |
| Batch | {Purpose}Batch | AccountDeduplicationBatch |
| Queueable | {Purpose}Queueable | OrderEventQueueable |
| Schedulable | {Purpose}Scheduler | NightlyCleanupScheduler |
| DTO | {Purpose}Dto or {Purpose}Wrapper | OrderResponseDto |
Quality Scoring Rubric (100-point)
Score the generated class before presenting. Threshold: 80+ pass, 60–79 caveat with explanation, below 60 revise before presenting.
| Dimension | Points | What earns full marks |
|---|
| Sharing model correctness | 25 | Every class has an explicit sharing declaration; with sharing is used wherever FLS/CRUD enforcement is appropriate; without sharing is justified with a comment |
| Governor-limit safety | 25 | No SOQL in loops; no DML in loops; bulkified with List/Map patterns; Collections used correctly |
| Security defaults | 20 | WITH USER_MODE or Security.stripInaccessible applied where appropriate; no hardcoded Ids or credentials; no SOQL injection vectors |
| Naming conventions | 15 | Class and method names follow conventions table; ApexDoc present; XML meta generated |
| Test class recommendation | 15 | Companion test class explicitly recommended with key scenarios listed |
Scoring penalties:
- SOQL inside a loop: -20 (immediate caveat)
- DML inside a loop: -20 (immediate caveat)
- Missing sharing declaration: -15
@future used instead of Queueable: -10
- Hardcoded Salesforce Id literal: -10
- No exception handling in a method with DML: -10
- Missing ApexDoc: -5
T0 Contract
This skill operates exclusively at T0 — static generation only.
- No org connection: No
sf CLI calls, no MCP tool calls, no live query or execution.
- No OAuth required: Zero-scope, zero-credential, zero-network.
- Output is draft code: All generated Apex is a starting point for human review and
org-specific adaptation. No generated file should be deployed without a human reviewing
the sharing model, naming conventions, and test coverage.
- Handoff to T1/T2 for validation: Pair with
salesforce-apex-test-generator-skill for
test authoring, then salesforce-apex-test-runner-skill (T1) for execution, then
salesforce-deployment-validator-skill (T2) for sandbox dry-run before any deployment.
Refusal Triggers
Stop and do not generate if:
- The requested logic would require hardcoding a production org Id or session token —
explain and ask for Custom Metadata or Label approach instead.
- The request is to generate Apex that intentionally bypasses FLS/CRUD for user-visible
data without a documented justification — explain the security risk and require
explicit acknowledgment before generating
without sharing on a user-data class.
- The user requests
@future — explain the Queueable alternative and generate Queueable
instead unless the user explicitly overrides with a documented reason.
Output Format
verdict: "pass | caveat | reject"
quality_score: <0-100>
quality_notes: "<scoring rationale>"
generated_files:
- path: "{ClassName}.cls"
content: |
<apex code>
- path: "{ClassName}.cls-meta.xml"
content: |
<meta xml>
sharing_model_used: "with sharing | without sharing | inherited sharing"
sharing_model_rationale: "<why this model was chosen>"
governor_limit_notes: "<any limit-adjacent patterns noted>"
security_notes: "<WITH USER_MODE / stripInaccessible usage>"
test_class_recommendation:
companion_skill: "salesforce-apex-test-generator-skill"
class_to_test: "{ClassName}"
key_scenarios:
- "<positive path>"
- "<negative/exception path>"
- "<bulk path (200+ records)>"
assumptions:
- "<list of assumptions made>"
missing_context:
- "<what the user should provide to improve the output>"
Handoff Rules
| Output | Hand off to |
|---|
| Generated Apex needing test class | salesforce-apex-test-generator-skill |
| Generated Apex ready for test execution | salesforce-apex-test-runner-skill (T1) |
| Ready for sandbox validation | salesforce-deployment-validator-skill (T2) |
| Code review of existing/generated Apex | salesforce-apex-lwc-code-review-skill |
Stop Conditions
Stop and do not continue if:
- The requested class type is not in the class type table and cannot be safely categorized —
ask for clarification.
- The request would produce Apex that violates a hard-stop constraint and the user insists
on the violating pattern after explanation — document the refusal and stop.
- The request requires live org data (field names, object relationships, current Apex) that
the user has not provided — ask for the specific context needed.
Security Notes
- T0 static generation only: No org connection, no OAuth, no secrets.
- Sharing by default: Every generated class has an explicit sharing declaration.
with sharing
is the default; without sharing only where explicitly required by class type (REST resource,
certain batch contexts) and documented.
- No credential generation: This skill never generates hardcoded credentials, org Ids,
user Ids, or session tokens in Apex code. All external references use Custom Metadata,
Custom Labels, or Named Credentials.
- Security-first patterns:
WITH USER_MODE, Security.stripInaccessible, and
bind variables are applied by default to all user-data-touching code.
- Draft status: All generated code is a starting point. Human review of sharing model,
FLS patterns, and business logic correctness is required before deployment.
Reference File Index
| File | When to read |
|---|
references/apex-patterns.md | Service-Selector-Domain pattern, sharing models, async patterns, type templates |
references/governor-limits.md | Governor limit values, bulkification strategies, async fallback patterns |
references/security-defaults.md | WITH SHARING default policy, USER_MODE, stripInaccessible, no hardcoded credentials |