acc-create-action
Generates ADR Action classes for PHP 8.5. Creates single-responsibility HTTP endpoint handlers with PSR-7 support. Includes unit tests.
Best use case
acc-create-action is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Generates ADR Action classes for PHP 8.5. Creates single-responsibility HTTP endpoint handlers with PSR-7 support. Includes unit tests.
Teams using acc-create-action should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/acc-create-action/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How acc-create-action Compares
| Feature / Agent | acc-create-action | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Generates ADR Action classes for PHP 8.5. Creates single-responsibility HTTP endpoint handlers with PSR-7 support. Includes unit tests.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Action Generator
Generate ADR-compliant Action classes for HTTP endpoints.
## Action Characteristics
- **Single Responsibility**: One action = one HTTP endpoint
- **Input Parsing**: Collects and parses request input
- **Domain Invocation**: Calls UseCase/Handler
- **Response Delegation**: Passes result to Responder
- **No Business Logic**: Thin coordination layer
- **Invokable**: Single `__invoke()` method
## Template
```php
<?php
declare(strict_types=1);
namespace Presentation\Api\{Context}\{Action};
use Application\{Context}\UseCase\{Action}\{Action}Command;
use Application\{Context}\UseCase\{Action}\{Action}Handler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class {Action}Action
{
public function __construct(
private {Action}Handler $handler,
private {Action}Responder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
{inputParsing}
$command = new {Action}Command(
{commandProperties}
);
$result = $this->handler->handle($command);
return $this->responder->respond($result);
}
{privateMethods}
}
```
## Test Template
```php
<?php
declare(strict_types=1);
namespace Tests\Unit\Presentation\Api\{Context}\{Action};
use Application\{Context}\UseCase\{Action}\{Action}Command;
use Application\{Context}\UseCase\{Action}\{Action}Handler;
use Application\{Context}\UseCase\{Action}\{Action}Result;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
use Presentation\Api\{Context}\{Action}\{Action}Action;
use Presentation\Api\{Context}\{Action}\{Action}Responder;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\StreamInterface;
#[Group('unit')]
#[CoversClass({Action}Action::class)]
final class {Action}ActionTest extends TestCase
{
private {Action}Handler $handler;
private {Action}Responder $responder;
private {Action}Action $action;
protected function setUp(): void
{
$this->handler = $this->createMock({Action}Handler::class);
$this->responder = $this->createMock({Action}Responder::class);
$this->action = new {Action}Action($this->handler, $this->responder);
}
public function testInvokesHandlerWithCommand(): void
{
$request = $this->createRequest([{testData}]);
$result = $this->createMock({Action}Result::class);
$response = $this->createMock(ResponseInterface::class);
$this->handler
->expects($this->once())
->method('handle')
->with($this->callback(fn ({Action}Command $cmd) =>
{commandAssertions}
))
->willReturn($result);
$this->responder
->expects($this->once())
->method('respond')
->with($result)
->willReturn($response);
$actual = ($this->action)($request);
self::assertSame($response, $actual);
}
private function createRequest(array $body): ServerRequestInterface
{
$stream = $this->createMock(StreamInterface::class);
$request = $this->createMock(ServerRequestInterface::class);
$request->method('getParsedBody')->willReturn($body);
$request->method('getBody')->willReturn($stream);
return $request;
}
}
```
## Action Patterns by HTTP Method
### GET (Read Single)
```php
<?php
declare(strict_types=1);
namespace Presentation\Api\User\GetById;
use Application\User\UseCase\GetUserById\GetUserByIdQuery;
use Application\User\UseCase\GetUserById\GetUserByIdHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class GetUserByIdAction
{
public function __construct(
private GetUserByIdHandler $handler,
private GetUserByIdResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$userId = $request->getAttribute('id');
$query = new GetUserByIdQuery(userId: $userId);
$result = $this->handler->handle($query);
return $this->responder->respond($result);
}
}
```
### GET (List with Pagination)
```php
<?php
declare(strict_types=1);
namespace Presentation\Api\User\ListAll;
use Application\User\UseCase\ListUsers\ListUsersQuery;
use Application\User\UseCase\ListUsers\ListUsersHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class ListUsersAction
{
public function __construct(
private ListUsersHandler $handler,
private ListUsersResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$queryParams = $request->getQueryParams();
$query = new ListUsersQuery(
page: (int) ($queryParams['page'] ?? 1),
perPage: (int) ($queryParams['per_page'] ?? 20),
search: $queryParams['search'] ?? null,
);
$result = $this->handler->handle($query);
return $this->responder->respond($result);
}
}
```
### POST (Create)
```php
<?php
declare(strict_types=1);
namespace Presentation\Api\User\Create;
use Application\User\UseCase\CreateUser\CreateUserCommand;
use Application\User\UseCase\CreateUser\CreateUserHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class CreateUserAction
{
public function __construct(
private CreateUserHandler $handler,
private CreateUserResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$body = (array) $request->getParsedBody();
$command = new CreateUserCommand(
email: $body['email'] ?? '',
name: $body['name'] ?? '',
);
$result = $this->handler->handle($command);
return $this->responder->respond($result);
}
}
```
### PUT/PATCH (Update)
```php
<?php
declare(strict_types=1);
namespace Presentation\Api\User\Update;
use Application\User\UseCase\UpdateUser\UpdateUserCommand;
use Application\User\UseCase\UpdateUser\UpdateUserHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class UpdateUserAction
{
public function __construct(
private UpdateUserHandler $handler,
private UpdateUserResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$userId = $request->getAttribute('id');
$body = (array) $request->getParsedBody();
$command = new UpdateUserCommand(
userId: $userId,
name: $body['name'] ?? null,
email: $body['email'] ?? null,
);
$result = $this->handler->handle($command);
return $this->responder->respond($result);
}
}
```
### DELETE
```php
<?php
declare(strict_types=1);
namespace Presentation\Api\User\Delete;
use Application\User\UseCase\DeleteUser\DeleteUserCommand;
use Application\User\UseCase\DeleteUser\DeleteUserHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
final readonly class DeleteUserAction
{
public function __construct(
private DeleteUserHandler $handler,
private DeleteUserResponder $responder,
) {
}
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$userId = $request->getAttribute('id');
$command = new DeleteUserCommand(userId: $userId);
$result = $this->handler->handle($command);
return $this->responder->respond($result);
}
}
```
## File Placement
| Component | Path |
|-----------|------|
| Action | `src/Presentation/Api/{Context}/{Action}/{Action}Action.php` |
| Action Interface | `src/Presentation/Shared/Action/ActionInterface.php` |
| Test | `tests/Unit/Presentation/Api/{Context}/{Action}/{Action}ActionTest.php` |
## Generation Instructions
When asked to create an Action:
1. **Identify HTTP method** (GET, POST, PUT, DELETE)
2. **Determine input source** (body, query params, route attributes)
3. **Identify Command/Query DTO** (what to pass to handler)
4. **Generate Action class** with proper namespace
5. **Generate test** with mocked dependencies
## Naming Conventions
| HTTP Method | Action Name | Command/Query |
|-------------|-------------|---------------|
| GET (single) | Get{Resource}ByIdAction | Get{Resource}ByIdQuery |
| GET (list) | List{Resource}sAction | List{Resource}sQuery |
| POST | Create{Resource}Action | Create{Resource}Command |
| PUT | Update{Resource}Action | Update{Resource}Command |
| PATCH | Patch{Resource}Action | Patch{Resource}Command |
| DELETE | Delete{Resource}Action | Delete{Resource}Command |
## References
For detailed patterns and examples:
- `references/templates.md` — Additional Action templates
- `references/examples.md` — Real-world Action examplesRelated Skills
adr-decision-extraction
Extract architectural decisions from conversations. Identifies problem-solution pairs, trade-off discussions, and explicit choices. Use when analyzing session transcripts for ADR generation.
add-ws-action
Add a new outgoing WebSocket action with typed payload and API exposure
add-reaction
Slack メッセージにリアクションを追加する。「リアクション追加」「リアクションつけて」「👍つけて」「絵文字で反応」「リアクションで返信」「いいねして」「リアクション送って」などで起動。User Token があればユーザーとしてリアクション、なければ Bot としてリアクション。
github-actions
Create and configure GitHub Actions. Use when building custom actions, setting up runners, implementing security practices, or publishing to the marketplace.
actions-pattern
Garante que novas Actions sigam o padrão de classes actions reutilizáveis do Easy Budget.
actions-debugger
GitHub Actions のワークフロー実行エラーを調査し、原因を特定して解決策を提案する。「Actions エラー」「ワークフロー失敗」「CI が落ちた」「ビルド失敗」「テスト失敗」「Actions を調べて」「CI のエラーを見て」などで起動。失敗したジョブのログを分析し、具体的な修正方法を提示。
actions-cicd-practices
GitHub Actions and CI/CD best practices for automated testing, building, and deployment.
actionbook
This skill should be used when the user needs to automate multi-step website tasks. Activates for browser automation, web scraping, UI testing, or building AI agents. Provides complete action manuals with step-by-step instructions and verified selectors.
actionable-review-format-standards
Standardized output format for code reviews with severity labels, file:line references, and fix code snippets. Use when generating review reports that need consistent, actionable feedback structure.
actionable-alerting-runbook-design
Designing effective alerts and runbooks for incident response. PROACTIVELY activate for: (1) Creating alerting rules, (2) Writing runbooks, (3) Reducing alert fatigue, (4) On-call escalation setup, (5) Incident response procedures. Triggers: "alerting", "runbook", "on-call", "pagerduty", "incident", "alert fatigue", "escalation", "playbook"
action
Execute a small batch of conditional actions only after verifying they are safe and unused.
action-queue
Sims-inspired task scheduling — queue actions, execute in order