| name | espocrm |
| description | Comprehensive guide for developing on EspoCRM - metadata-driven CRM with service layer architecture |
| user-invocable | false |
| disable-model-invocation | true |
| version | 1.2.0 |
| updated | 2026-06-15 |
| category | development |
| author | Claude MPM Team |
| license | MIT |
| progressive_disclosure | {"entry_point":{"summary":"Metadata-driven CRM development using service layer, ORM EntityManager, and hook-based business logic","when_to_use":"When developing custom modules, entities, hooks, or integrations for EspoCRM","quick_start":"1. Understand metadata-driven architecture 2. Use EntityManager for data access 3. Implement business logic in Services 4. Register hooks for lifecycle events 5. Rebuild cache after changes"},"references":["architecture.md","development-workflow.md","hooks-and-services.md","frontend-customization.md","common-tasks.md","testing-debugging.md","select-builder.md","api-actions.md","custom-field-types.md","extension-packages.md","php-quality-antipatterns.md"]} |
| context_limit | 800 |
| tags | ["espocrm","php","crm","metadata-driven","orm"] |
| requires_tools | [] |
EspoCRM Development
Overview
EspoCRM is a metadata-driven CRM platform where configuration lives in JSON files, business logic belongs in Services, and data access happens through ORM EntityManager. This skill enforces architectural patterns to prevent common mistakes like passing Container dependencies, bypassing the service layer, or implementing business logic in hooks.
When to Use This Skill
Activate when developing custom EspoCRM modules, entities, relationships, hooks, services, API endpoints, or integrations. Use especially when: working with ORM (EntityManager required), implementing business logic (belongs in Services), creating hooks (use interfaces), modifying metadata (requires cache rebuild), building custom field types, creating complex queries with SelectBuilder, implementing custom API actions, or packaging extensions.
The Iron Law
BUSINESS LOGIC IN SERVICES, NOT HOOKS | DATA ACCESS VIA ENTITYMANAGER, NEVER DIRECT PDO | NEVER PASS CONTAINER AS DEPENDENCY
Accessing Container directly or writing business logic in hooks violates architecture.
Core Architecture Principles
- Metadata-Driven: Entity definitions, layouts, field configs live in JSON
- Service Layer: All business logic implemented in Service classes
- ORM EntityManager: Central access point for all database operations
- Dependency Injection: Constructor injection, never pass Container
- Hook System: Lifecycle events for validation and side effects (not business logic)
- Repository Pattern: Entities accessed through repositories
Quick Start
-
Setup Development Environment - Use ext-template, work in src/ directory (EspoCRM 7.4+), understand metadata structure: custom/Espo/Modules/{ModuleName}/Resources/metadata/
-
Access Data with EntityManager
use Espo\ORM\EntityManager;
public function __construct(private EntityManager $entityManager) {}
= ->entityManager->(, );
= ->entityManager
->()
->([ => ])
->();