acc-create-action

Generates ADR Action classes for PHP 8.5. Creates single-responsibility HTTP endpoint handlers with PSR-7 support. Includes unit tests.

16 stars

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

$curl -o ~/.claude/skills/acc-create-action/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/acc-create-action/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/acc-create-action/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How acc-create-action Compares

Feature / Agentacc-create-actionStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/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 examples

Related Skills

acc-create-bulkhead

16
from diegosouzapw/awesome-omni-skill

Generates Bulkhead pattern for PHP 8.5. Creates resource isolation with semaphore-based concurrency limiting and thread pool isolation. Includes unit tests.

acc-create-anti-corruption-layer

16
from diegosouzapw/awesome-omni-skill

Generates DDD Anti-Corruption Layer for PHP 8.5. Creates translation layer between bounded contexts or external systems. Includes adapters, translators, facades, and unit tests.

acc-check-leaky-abstractions

16
from diegosouzapw/awesome-omni-skill

Detects leaky abstractions in PHP code. Identifies implementation details exposed in interfaces, concrete returns from abstract methods, framework leakage into domain, and infrastructure concerns in application layer.

abaqus-interaction

16
from diegosouzapw/awesome-omni-skill

Define contact and interactions - contact pairs, tie constraints, connectors. Use when user mentions contact, friction, tie, parts touching, or bonded surfaces.

ui-design-create-component

16
from diegosouzapw/awesome-omni-skill

Guided component creation with proper patterns Use when: the user asks to run the `create-component` workflow and the task requires multi-step orchestration. Do not use when: the task is small, single-step, and can be completed directly without orchestration overhead.

process-needs-action

16
from diegosouzapw/awesome-omni-skill

This skill should be used when you need to process pending action items from a designated folder and generate detailed implementation plans based on organizational rules. Ideal for task management workflows that require systematic processing of pending items, plan creation, and dashboard updates. Use when the user asks to process action items, review pending tasks, or generate plans from a backlog.

pattern-extraction

16
from diegosouzapw/awesome-omni-skill

Extract design systems, architecture patterns, and methodology from codebases into reusable skills and documentation. Use when analyzing a project to capture patterns, creating skills from existing code, extracting design tokens, or documenting how a project was built. Triggers on "extract patterns", "extract from this repo", "analyze this codebase", "create skills from this project", "extract design system".

create-rule

16
from diegosouzapw/awesome-omni-skill

Create project rules for persistent AI guidance. Use when the user wants to create a rule, add coding standards, set up project conventions, configure file-specific patterns, create RULE.md files, or asks about the workspace rules directory or AGENTS.md.

create-design-system-rules

16
from diegosouzapw/awesome-omni-skill

Generates custom design system rules for the user's codebase. Use when user says "create design system rules", "generate rules for my project", "set up design rules", "customize design system guidelines", or wants to establish project-specific conventions for Figma-to-code workflows. Requires Figma MCP server connection.

asyncredux-sync-actions

16
from diegosouzapw/awesome-omni-skill

Creates AsyncRedux (Flutter) synchronous actions that update state immediately by implementing reduce() to return a new state.

asyncredux-action-status

16
from diegosouzapw/awesome-omni-skill

Checks an AsyncRedux (Flutter) action's completion status using ActionStatus right after the dispatch returns. Use only when you need to know whether an action completed, whether it failed with an error, what error it produced, or how to navigate based on success or failure.

ai-interaction-patterns

16
from diegosouzapw/awesome-omni-skill

AI-specific interaction design patterns covering wayfinding, prompt UX, human-in-the-loop controls, trust & transparency, AI identity, and context management. Based on Shape of AI (shapeof.ai). Use when asking about 'AI UX', 'AI interaction', 'prompt UX', 'AI trust', 'AI disclosure', 'AI avatar', 'AI personality', 'AI memory UX', 'action plan UX', 'stream of thought', 'AI citations', 'AI controls', 'AI wayfinding', 'AI suggestions', 'gallery pattern', 'follow-up pattern', 'draft mode', 'AI variations', 'AI consent', 'AI caveat', 'human-in-the-loop', 'AI transparency', 'AI state', 'prompt design', 'AI onboarding', or 'generative UI'.