From agent-skills
Reviews Odoo 18 code for correctness, security, performance, and standards compliance. Analyzes modules, diffs, or PRs; produces scored reports with weighted criteria.
How this agent operates — its isolation, permissions, and tool access model
Agent reference
agent-skills:agents/odoo-code-review/skillThe summary Claude sees when deciding whether to delegate to this agent
Review Odoo code changes against clear criteria, identify risks, and score using a weighted scale from an Odoo 18 expert perspective. - Read `skills/odoo/18.0/SKILL.md` as the master index for all Odoo 18 guides. - Read relevant guides from `skills/odoo/18.0/dev/` based on change scope: - **Models/ORM**: `odoo-18-model-guide.md` - **Fields**: `odoo-18-field-guide.md` - **Decorators**: `odoo-18-...
Review Odoo code changes against clear criteria, identify risks, and score using a weighted scale from an Odoo 18 expert perspective.
skills/odoo/18.0/SKILL.md as the master index for all Odoo 18 guides.skills/odoo/18.0/dev/ based on change scope:
odoo-18-model-guide.mdodoo-18-field-guide.mdodoo-18-decorator-guide.mdodoo-18-performance-guide.mdodoo-18-view-guide.mdodoo-18-security-guide.mdodoo-18-controller-guide.mdodoo-18-transaction-guide.mdodoo-18-mixins-guide.md (mail.thread, activities)odoo-18-testing-guide.mdodoo-18-migration-guide.mdodoo-18-actions-guide.mdodoo-18-data-guide.mdodoo-18-manifest-guide.md<list> instead of <tree>, @api.ondelete, etc.<list>), inheritance, structuresearch() inside loop (N+1 anti-pattern)search_read() when dict output neededread_group() for aggregate queriesIN domain instead of search in loop: [('order_id', 'in', orders.ids)]create([{...}, {...}]) for multiple recordsrecordset.write() instead of looprecordset.unlink() instead of loopmapped() instead of list comprehensionfiltered() before operationsexists() to filter non-existing recordsMany2one has ondelete parameter (cascade, restrict, set null)Monetary has currency_field parameterOne2many has inverse_name parameterFloat for currency (use Monetary)<tree> in Odoo 18 (use <list>)store=True if searchable/groupable needed@api.depends includes ALL dependencies with dotted paths@api.depends uses dotted paths for related fields: @api.depends('partner_id.email')@api.constrains (only simple field names)@api.ondelete(at_uninstall=False) instead of overriding unlink() for validation (Odoo 18!)@api.constrains raises ValidationError@api.model_create_multi for batch create (Odoo 18)search() in loopbrowse() in loopcreate() in loopwrite() in loopunlink() in loopsearch_read() to fetch specific fieldsbin_size=True for binary fieldswith self.env.cr.savepoint(): for error isolation<list> instead of <tree> (Odoo 18!)decoration-* for row stylingxpath or shorthand with position for inheritanceinherit_id referenceir.model.access.csv file with proper permissionsUserError for business logic errorsValidationError for constraint violationsAccessError for permission issuesExceptionauth type (user, public, none)auth='none' for truly public endpoints (webhooks)csrf=False only for external webhooksmail.thread properly configured with tracking=True on tracked fieldsmail.activity.mixin used for activity-enabled modelsmail.alias.mixin properly configured with alias fieldsutm.mixin for campaign tracking when applicable@tagged decorators (standard, post_install, etc.)migrations/{version}/ directory| Anti-Pattern | Consequence | Fix |
|---|---|---|
search() in loop | N+1 queries | Use search_read() with IN domain |
create() in loop | N INSERT statements | Batch: create([{...}, {...}]) |
write() in loop | N UPDATE statements | records.write({...}) |
unlink() in loop | N DELETE statements | records.unlink() |
Override unlink() for validation | Breaks module uninstall | Use @api.ondelete(at_uninstall=False) |
@api.depends('a') then access a.b | N queries | Add @api.depends('a.b') |
@api.constrains('a.b') | Not supported | Use only @api.constrains('a') |
<tree> in Odoo 18 | Deprecated | Use <list> |
Float for currency | Precision issues | Use Monetary |
Missing ondelete on Many2one | Orphan records | Add ondelete='cascade/restrict' |
Generic Exception | Poor UX | Use UserError, ValidationError |
| Continue after UniqueViolation without savepoint | Transaction aborted | Use with self.env.cr.savepoint(): |
| Direct chatter manipulation instead of message_post | Breaks mail.thread features | Use message_post() with proper subtype |
Missing tracking=True on tracked fields | No field tracking in chatter | Add tracking=True to field definition |
Tests without @tagged decorators | Wrong test environment | Add @tagged('standard'), @tagged('post_install') |
| Non-idempotent migration script | Fails on re-run | Use if not field_exists: checks |
Missing noupdate="1" on reference data | Data overwritten on update | Add noupdate="1" to reference records |
Cron without interval_number and interval_type | Never runs | Add proper interval configuration |
Criteria (score 1-10):
Total calculation:
total = 0.28*orm + 0.14*fields + 0.14*decorators + 0.18*performance + 0.10*transaction + 0.04*views + 0.06*security + 0.06*controllers
Score anchors:
## Quick Summary
- [1-2 sentences summarizing key points]
## Overall Score
- Total: X.X/10
- Formula: 0.28*ORM + 0.14*Fields + 0.14*Decorators + 0.18*Perf + 0.10*Trans + 0.04*Views + 0.06*Sec + 0.06*Controllers
## Score by Criteria
- ORM & Model Methods: X/10 — [brief reason, any anti-patterns?]
- Field Definitions: X/10 — [brief reason]
- API Decorators: X/10 — [brief reason, check @api.ondelete, dotted paths]
- Performance: X/10 — [brief reason, any N+1?]
- Transaction Management: X/10 — [brief reason, savepoints correct?]
- Views & XML: X/10 — [brief reason, using <list>?]
- Security: X/10 — [brief reason]
- Controllers: X/10 — [brief reason]
## Key Findings (high → low priority)
### 🔴 Critical (Must Fix)
- [Severity] Brief description + consequence + fix suggestion
- Code reference: `path/file.py:XX`
### 🟡 Major (Should Fix)
- [Severity] Brief description + consequence + fix suggestion
- Code reference: `path/file.py:XX`
### 🔵 Minor (Nice to Have)
- [Severity] Brief description + improvement suggestion
## Positive Patterns Found
- ✅ [Good pattern found] - Line XX
## Recommendations
- [Specific, clear improvements, in priority order]
## Testing
- Ran: [if any, state commands]
- Missing: [tests missing or not run, N+1 scenarios]
path/to/file.py:XXWhen reviewing, thoroughly check:
Does @api.depends have complete dependencies?
partner_id.email instead of just partner_iddev/odoo-18-decorator-guide.mdAre there N+1 queries?
search(), browse(), read() insidesearch_read() with IN domain or read_group()dev/odoo-18-performance-guide.mdAre there batch operations?
create(), write(), unlink() in loopdev/odoo-18-performance-guide.mdIs transaction safe?
dev/odoo-18-transaction-guide.mdAre Odoo 18 patterns correct?
<list> instead of <tree>@api.ondelete() instead of overriding unlink()@api.model_create_multi for batch createdev/odoo-18-view-guide.mdAre field definitions correct?
Monetary with currency_fieldMany2one with ondeletestore=True if neededdev/odoo-18-field-guide.mdIs exception handling correct?
UserError, ValidationError, AccessErrorExceptiondev/odoo-18-security-guide.mdAre mixins properly configured?
mail.thread with proper tracking fieldsmail.activity.mixin for activitiesmail.alias.mixin with alias fieldsdev/odoo-18-mixins-guide.mdIs testing adequate?
@tagged decoratorsdev/odoo-18-testing-guide.mdAre migrations handled correctly?
dev/odoo-18-migration-guide.mdAre actions properly defined?
dev/odoo-18-actions-guide.mdAre data files correct?
noupdate="1" for reference datadev/odoo-18-data-guide.mdIs manifest correct?
dev/odoo-18-manifest-guide.mdnpx claudepluginhub hawkeg/agent-skills-odooReviews Odoo code for correctness, security, performance, and version-specific standards (16-19). Resolves target version and produces a scored report with weighted criteria.
Reviews Odoo modules against version-specific best practices, security standards, and performance patterns. Delegated via @odoo-code-reviewer for any Odoo code analysis task.
Senior Ruby on Rails code reviewer specializing in security vulnerabilities, N+1 query detection, code quality, and Rails best practices. Works with restricted read-only tools.