Awesome-claude-code create-command
Generates CQRS Commands and Handlers for PHP 8.4. Creates immutable command DTOs with handlers that modify state. Includes unit tests.
install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/create-command" ~/.claude/skills/dykyi-roman-awesome-claude-code-create-command && rm -rf "$T"
manifest:
skills/create-command/SKILL.mdsource content
Command Generator
Generate CQRS-compliant Commands and Command Handlers with tests.
Command Characteristics
- Immutable:
final readonly class - Imperative naming: Verb + noun (CreateOrder, ConfirmPayment)
- Self-validating: Validates invariants in constructor
- Intent-revealing: Name describes what should happen
- Returns void or ID: Never returns data
Generation Process
Step 1: Generate Command
Path:
src/Application/{BoundedContext}/Command/
— Immutable command DTO{Name}Command.php
Step 2: Generate Handler
Path:
src/Application/{BoundedContext}/Handler/
— Command processor{Name}Handler.php
Step 3: Generate Tests
Path:
tests/Unit/Application/{BoundedContext}/
File Placement
| Component | Path |
|---|---|
| Command | |
| Handler | |
| Unit Tests | |
Command Naming Conventions
| Action | Command Name | Returns |
|---|---|---|
| Create new | | ID |
| Confirm/Approve | | void |
| Cancel/Reject | | void |
| Update property | | void |
| Add child | | void |
| Remove child | | void |
Quick Template Reference
Command
final readonly class {Name}Command { public function __construct( public {ValueObject} $id, public string $data ) { if (empty($data)) { throw new \InvalidArgumentException('Data is required'); } } public static function fromArray(array $data): self { return new self( id: new {ValueObject}($data['id']), data: $data['data'] ); } }
Handler (Update Flow)
final readonly class {Name}Handler { public function __construct( private {Repository}Interface $repository, private EventDispatcherInterface $events ) {} public function __invoke({Name}Command $command): void { $aggregate = $this->repository->findById($command->id); if ($aggregate === null) { throw new NotFoundException($command->id); } $aggregate->doSomething($command->data); $this->repository->save($aggregate); foreach ($aggregate->releaseEvents() as $event) { $this->events->dispatch($event); } } }
Handler (Create Flow)
public function __invoke(CreateCommand $command): AggregateId { $aggregate = Aggregate::create( id: $this->repository->nextIdentity(), ... ); $this->repository->save($aggregate); foreach ($aggregate->releaseEvents() as $event) { $this->events->dispatch($event); } return $aggregate->id(); }
Anti-patterns to Avoid
| Anti-pattern | Problem | Solution |
|---|---|---|
| Returning Data | Query through command | Use Query for reads |
| No Validation | Invalid commands | Validate in constructor |
| Business Logic | Handler has decisions | Delegate to aggregate |
| Missing Events | Events not dispatched | Always dispatch after save |
| Direct Persistence | Bypassing aggregate | Always use aggregate methods |
References
For complete PHP templates and examples, see:
— Command, Handler, Test templates with patternsreferences/templates.md
— CreateOrder, ConfirmOrder, CancelOrder examples and testsreferences/examples.md