Scaffolds a new module under src/php/<ModuleName>/ following the project Gacela pattern.
Context
!ls src/php/
Instructions
Validate $ARGUMENTS: must be PascalCase, not clash with an existing dir. If missing, ask.
Read a reference module (pick a small one, e.g. src/php/Filesystem/ or src/php/Formatter/) to mirror its layout. Record:
Facade method shape
#[ServiceMap(...)] pillar mappings
#[Provides(...)] dependency keys
CLAUDE.md section order
Create the following files under src/php/<ModuleName>/:
<ModuleName>Facade.php # final class extending \Gacela\Framework\AbstractFacade
<ModuleName>Factory.php # final class extending AbstractFactory (only if module needs internal wiring)
<ModuleName>Provider.php # only if the module depends on another module's Facade
Domain/ # pure business logic (no framework deps)
Infrastructure/ # adapters, CLI commands, IO
CLAUDE.md # one-line purpose, Gacela pattern, public API, deps, structure, constraints
Facade contract: every public call must return from the Factory; never instantiate dependencies inline in the Facade.
Explicit pillar services: import Gacela\Framework\ServiceResolver\ServiceMap and declare:
Do not register the module anywhere — Gacela auto-discovers via PSR-4.
Run static analysis on the new files only:
composer test-quality
Constraints
No classes instantiated across module boundaries — always go through another module's Facade.
Do not rely on Gacela's deprecated source/docblock service-resolution fallback; every inherited pillar accessor has an explicit #[ServiceMap].
Provider entries use Gacela 2.0 #[Provides(...)]; key facade dependencies by the consumer-facing interface when one exists.
Mark classes final unless inheritance is explicitly justified.
Use readonly properties where possible (per .claude/rules/php.md).
1---2name: module-new3description: Module New4---56# New Gacela Module78Scaffolds a new module under `src/php/<ModuleName>/` following the project Gacela pattern.910## Context1112!`ls src/php/`1314## Instructions15161. **Validate `$ARGUMENTS`**: must be PascalCase, not clash with an existing dir. If missing, ask.17182. **Read a reference module** (pick a small one, e.g. `src/php/Filesystem/` or `src/php/Formatter/`) to mirror its layout. Record:19 - Facade method shape20 - `#[ServiceMap(...)]` pillar mappings21 - `#[Provides(...)]` dependency keys22 - CLAUDE.md section order23243. **Create the following files** under `src/php/<ModuleName>/`:25 ```26 <ModuleName>Facade.php # final class extending \Gacela\Framework\AbstractFacade27 <ModuleName>Factory.php # final class extending AbstractFactory (only if module needs internal wiring)28 <ModuleName>Provider.php # only if the module depends on another module's Facade29 Domain/ # pure business logic (no framework deps)30 Infrastructure/ # adapters, CLI commands, IO31 CLAUDE.md # one-line purpose, Gacela pattern, public API, deps, structure, constraints32 ```33344. **Facade contract**: every public call must return from the Factory; never instantiate dependencies inline in the Facade.35365. **Explicit pillar services**: import `Gacela\Framework\ServiceResolver\ServiceMap` and declare:37 - Facade: `#[ServiceMap(method: 'getFactory', className: <ModuleName>Factory::class)]`38 - Factory: `#[ServiceMap(method: 'getConfig', className: <ModuleName>Config::class)]`39 - Provider: the same `getConfig` mapping; use `AbstractConfig::class` only when the module intentionally has no custom Config40416. **CLAUDE.md template** (keep scannable — no prose):42 ```markdown43 # <ModuleName>4445 <one-line purpose>4647 ## Gacela pattern4849 Facade → Factory → Domain5051 ## Public API5253 - `<ModuleName>Facade::method()` — <one line>5455 ## Dependencies5657 - `<OtherFacadeInterface>::class` (via Provider)5859 ## Structure6061 <ModuleName>/62 Domain/63 Infrastructure/6465 ## Constraints6667 - <key invariant or rule>68 ```69707. **Do not** register the module anywhere — Gacela auto-discovers via PSR-4.71728. **Run static analysis** on the new files only:73 ```bash74 composer test-quality75 ```7677## Constraints7879- No classes instantiated across module boundaries — always go through another module's Facade.80- Do not rely on Gacela's deprecated source/docblock service-resolution fallback; every inherited pillar accessor has an explicit `#[ServiceMap]`.81- Provider entries use Gacela 2.0 `#[Provides(...)]`; key facade dependencies by the consumer-facing interface when one exists.82- Mark classes `final` unless inheritance is explicitly justified.83- Use `readonly` properties where possible (per `.claude/rules/php.md`).
Run npx skillmds@latest add phel-lang/module-new in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Module New It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
phel-lang (@phel-lang) published this skill. Their other Agent Skills are listed on their SkillMD profile.