Apex review
Skill gvago/unofficial-qodo-review-skills/skills/apex-review
Unofficial agent skills for Qodo Merge PR review. Includes terraform-review (adapted from antonbabenko/terraform-skill).
npx -y skills add gvago/unofficial-qodo-review-skills --skill apex-reviewAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 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
Use when a PR diff adds or modifies Salesforce Apex (.cls / .trigger) or SOQL/SOSL — flags governor-limit killers (SOQL/DML inside loops), missing CRUD/FLS & sharing enforcement, SOQL injection, hardcoded IDs, trigger anti-patterns, and swallowed exceptions in the CHANGED code only. Skip for non-Apex diffs.
The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
10.7 KB, ~2.7k tokens by cl100k_base, as published. Nobody here has run it
Apex Review Skill
Review lens for Salesforce Apex and SOQL/SOSL changes in a pull request. Every rule below is a concrete violation you can point at in the diff.
Apex is the single highest-value language for an LLM-backed reviewer to get right: it is under-represented in training data, and its governor limits make patterns that look perfectly fine in Java/C# (a query inside a loop) silently brick production once data volume crosses a threshold. A generic reviewer misses these constantly. This skill encodes the Apex-specific failure modes — sourced from the PMD Apex ruleset (BSD-2) and Salesforce's own governor-limit guidance — as diff-checkable rules.
How to apply this skill (read first)
You are reviewing a unified diff, not a live org. Therefore:
- You cannot run anything. No
sf project deploy, no anonymous Apex, no test run, no PMD execution. Judge from the changed lines alone. Never emit a finding whose justification is "run X to confirm." - Findings apply to the diff, not the whole org. Only flag Apex that was added or modified in this PR.
- Every finding must trace to a rule below. If you cannot point to a specific rule in this file that the changed code violates, drop it — the generic "issues" agent handles ordinary bugs. This skill only fires on the Apex-specific rules enumerated here.
- Loops include hidden ones.
for,while,do-while, and trigger bodies (a trigger processes up to 200 records per invocation — its top level is effectively a loop overTrigger.new). A query in a method called from inside a loop counts too.
Mapping a finding to the SkillsFinding contract
| This skill's severity | action_level | category (typical) |
|---|---|---|
| Blocking — will hit a governor limit, leak data, or allow injection | action_required | Correctness or Security |
| Recommended — likely wrong, context-dependent | remediation_recommended | Correctness / Maintainability |
| Optional — maintainability nudge | informational | Maintainability |
Each finding's evidence.citations MUST include a SkillCitation with
source = "apex-review". Put the offending span in diff_pointer. Give a concrete
fix_suggestion (the Fix line of each rule is your starting point).
Rule set
1. Governor limits — the #1 Apex footgun (mostly Blocking)
Apex runs in a multi-tenant environment with hard per-transaction limits: 100 SOQL queries, 150 DML statements, 50,000 rows retrieved, plus CPU time. Code that performs these per record instead of in bulk works in a unit test with one record and dies in production on a 200-record batch. This is the mistake LLMs make most.
- SOQL or SOSL query inside a loop. → Blocking (Correctness). [PMD
OperationWithLimitsInLoop]. Hits the 100-query limit. Fix: move the query outside the loop; query once with a bulkWHERE id IN :ids, build aMap<Id, SObject>, look up inside the loop. - DML statement (
insert/update/delete/upsert/Database.*) inside a loop. → Blocking (Correctness). [PMDOperationWithLimitsInLoop]. Hits the 150-DML limit. Fix: accumulate records into aList<SObject>in the loop, perform a single DML on the list after the loop. - Other limit-consuming calls inside a loop —
@future/Queueable/Batch enqueue,Approval.process,Messaging.sendEmail, async scheduling. → Blocking (Correctness). [PMDOperationWithLimitsInLoop]. Fix: hoist out of the loop; batch the work. - Expensive Schema/describe calls inside a loop (
Schema.getGlobalDescribe(),getDescribe()per iteration). → Recommended (Performance). [PMDOperationWithHighCostInLoop]. Fix: call once before the loop, cache the result. - Unfiltered SOQL/SOSL —
SELECT ... FROM Xwith noWHEREand noLIMITon a large object. → Recommended (Correctness). [PMDAvoidNonRestrictiveQueries]. Risks the 50k-row limit. Fix: add a selectiveWHEREand/orLIMIT.
2. Security — CRUD / FLS / sharing / injection (mostly Blocking)
- DML or SOQL in a class with no explicit sharing declaration. → Blocking
(Security). [PMD
ApexSharingViolations]. Withoutwith sharingthe code runs in system context and ignores record-level access. Fix: declarewith sharing(orinherited sharingfor library classes) on classes that perform DML/SOQL. - Object/field access without a CRUD/FLS check — direct
insert/update/SELECTon user-reachable objects with noSchema.sObjectType.X.isCreateable()/isAccessible()/...guard orWITH SECURITY_ENFORCED/Security.stripInaccessible. → Blocking (Security). [PMDApexCRUDViolation]. Fix: add the CRUD/FLS check, or useWITH SECURITY_ENFORCEDin the SOQL, orSecurity.stripInaccessiblebefore DML. - Dynamic SOQL built by string-concatenating an untrusted variable —
Database.query('... ' + var + ' ...'). → Blocking (Security). [PMDApexSOQLInjection]. Fix: use bind variables (:var), orString.escapeSingleQuotes()for identifiers that cannot be bound. - Hardcoded credentials / endpoints in callouts. → Blocking (Security). [PMD
ApexSuggestUsingNamedCred]. Fix: use a Named Credential. - Plain
http://endpoint in a callout. → Blocking (Security). [PMDApexInsecureEndpoint]. Fix: usehttps://. - Redirect to a user-controlled location (open redirect). → Blocking (Security).
[PMD
ApexOpenRedirect]. Fix: validate/whitelist the target. - URL parameter used without escaping (
ApexPages.currentPage().getParameters().get(..)flowing into output). → Blocking (Security). [PMDApexXSSFromURLParam]. Fix: escape/sanitize before use. addError()called with escaping disabled (escape=false). → Blocking (Security). [PMDApexXSSFromEscapeFalse]. Fix: leave escaping on.- Hardcoded crypto keys/IVs in
Cryptocalls. → Blocking (Security). [PMDApexBadCrypto]. Fix: use randomly generated keys/IVs.
3. Triggers & error-prone patterns
- Hardcoded Salesforce ID (
'001...','00D...', record-type/profile IDs as string literals). → Blocking (Correctness). [PMDAvoidHardcodingId]. IDs differ across sandbox/prod/orgs and break on deploy. Fix: query the record dynamically or use a Custom Setting/Metadata. - Direct indexed access to
Trigger.new[0]/Trigger.old[0]instead of iterating the collection. → Recommended (Correctness). [PMDAvoidDirectAccessTriggerMap]. Assumes a single record; breaks on bulk. Fix: iterateTrigger.new, key intoTrigger.oldMap. - Business logic written directly in a trigger body. → Recommended (Maintainability).
[PMD
AvoidLogicInTrigger]. Fix: delegate to a handler class. - DML in a constructor or initializer. → Recommended (Correctness). [PMD
ApexCSRF]. Merely loading a page executes it — a CSRF surface. Fix: move DML out of the constructor. - Empty
catchblock (exception swallowed, nothing logged/rethrown). → Recommended (Correctness). [PMDEmptyCatchBlock]. Fix: handle, log with context, or rethrow. Mapkeyed by an interface type where an abstract class definesequals/hashCode. → Recommended (Correctness). [PMDAvoidInterfaceAsMapKey]. Lookups misbehave. Fix: key by a concrete type / stable field.- Class/enum/interface named the same as a
SystemorSchemabuiltin. → Recommended (Correctness). [PMDTypeShadowsBuiltInNamespace]. Shadows the namespace. Fix: rename.
4. Async & global surface
Queueableimplemented without attaching aFinalizer. → Recommended (Reliability). [PMDQueueableWithoutFinalizer]. No failure handling for the async job. Fix:System.attachFinalizer(...).- New
@futuremethod where Queueable would be more capable. → Optional (Maintainability). [PMDAvoidFutureAnnotation].@futureis legacy (no chaining, limited args). Fix: prefer Queueable. - New
globalclass/method outside a managed-package boundary. → Recommended (Maintainability). [PMDAvoidGlobalModifier].globalsignatures can never be changed or deleted. Fix: usepublicunless the cross-package surface is truly required.
5. Tests (lower severity, but real)
- New
@isTestclass usingseeAllData=true. → Recommended (Correctness). [PMDApexUnitTestShouldNotUseSeeAllDataTrue]. Tests then depend on org data and break unpredictably. Fix: create test data in the test (or@testSetup). - New test method with no assertion at all. → Recommended (Correctness). [PMD
ApexUnitTestClassShouldHaveAsserts]. Fix: assert the actual outcome. testMethodkeyword instead of the@isTestannotation. → Optional (Maintainability). [PMDApexUnitTestMethodShouldHaveIsTestAnnotation].testMethodis deprecated. Fix: use@isTest.
What NOT to flag
- Generic bugs, logic errors, or non-Apex issues — those belong to the issues agent.
- Code style/formatting unless a rule above names it.
- Anything in files not changed by this PR.
- Anything requiring deployment or a test run to confirm (you have no org).
- A "SOQL in loop" finding when the query is demonstrably already bulkified (collected before the loop, looked up via a Map inside it) — read the surrounding changed lines before flagging.
Source & attribution
Rules are derived from the PMD Apex ruleset
(https://github.com/pmd/pmd, BSD-2-Clause) — specifically the performance, security,
errorprone, and bestpractices categories — and from Salesforce's published Apex
governor-limit guidance. Rule identifiers in brackets (e.g. OperationWithLimitsInLoop) map
back to PMD rules so a reviewer can consult the upstream rationale and examples. This skill
is original prose authored for PR review and is licensed Apache-2.0; it copies no PMD source
text verbatim.
For writing Salesforce code (Apex, LWC, OmniStudio, Data Cloud, Agentforce), see Salesforce's official skills at https://github.com/forcedotcom/sf-skills — those are authoring/generation skills and complement this review-only skill.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.