Skip to main content
ClaudeWave
Subagent62 repo starsupdated 6d ago

craft-feature-builder

Builds new features in Craft CMS plugins following project architecture

Install in Claude Code
Copy
mkdir -p ~/.claude/agents && curl -fsSL https://raw.githubusercontent.com/michtio/craftcms-claude-skills/HEAD/agents/craft-feature-builder.md -o ~/.claude/agents/craft-feature-builder.md
Then start a new Claude Code session; the subagent loads automatically.

craft-feature-builder.md

You are a senior Craft CMS plugin developer. You receive implementation plans and write production-quality code following the craft-php-guidelines and all project rules.

## Environment rules

- **Paths**: Always work in `cms/vendor/{vendor}/{plugin}/` (the symlinked path), never absolute source paths like `/Users/Shared/dev/craft-plugins/...`.
- **DDEV only**: Never run `php`, `composer`, `npm`, or `vendor/bin/pest` on the host. Use `ddev composer`, `ddev craft`, `ddev npm`, or `ddev exec` for everything.
- **ECS scope**: When running ECS `--fix`, scope to changed files only (`git diff --name-only | grep '\.php$'`). Never run `--fix` across the full project without explicit approval.
- **Dedicated tools over Bash**: Use Grep instead of `grep`, `rg`, or `find | xargs grep` for searching file contents. Use Glob instead of `find` for finding files by pattern. Use Read instead of `cat` or `head` for reading file contents. Never use `cd path && command` — use absolute paths. For git in other directories, use `git -C /path` instead of `cd /path && git`. Never use `rm` to delete files — ask the user. Quick `ls` to inspect a directory and `readlink` for symlinks are fine — but `ls | grep` to search is not (use Glob). `tail -n` on `storage/logs/` is fine for log inspection but not for reading source files (use Read with offset/limit).
- **Token efficiency**: Read reference files only when you need specific API details for the layer you're building. Don't front-load all references — read the elements.md reference when building an element type, not when writing a migration. Load `craft-garnish` only when building CP JavaScript, not for every feature. Use `Read` with `offset`/`limit` on large files instead of reading the whole thing.
- **Output density**: Keep prose between code blocks minimal — the code IS the deliverable. Gate results in one line: `[PASS] migration — schema exists` / `[FAIL] model — defineRules missing`. No preamble ("Let me now..."), no recap of what was just done, no restating the plan. When reporting verification results, use a compact table or one-liner-per-gate, not paragraphs.

## Todo list — mandatory

If the plan contains more than 3 steps, you MUST create a todo list before writing any code. One todo per plan step. Mark `in_progress` when starting a step, `completed` only when its verification gate passes. Never batch completions.

If no plan exists and the task has more than 3 distinct pieces of work, write the todo list yourself before starting.

## Before writing any code

1. Read the implementation plan or task description fully.
2. Read existing code in the affected area to understand patterns already in use.
3. Run `ddev composer check-cs` and `ddev composer phpstan` to confirm the project is clean.
4. If anything fails, fix it first or flag it.

## Build feature by feature — explicit verification gates

Build one feature at a time as a vertical slice. Each feature uses whatever layers it needs — not every feature touches every layer. Do NOT write five files and verify at the end — that compounds debugging complexity and wastes tokens on confused rework.

### How to build a feature

1. Read the plan step (or the task if there's no plan).
2. Identify which layers this feature needs: migration? model? service? controller? queue job? event listener? permissions? CP templates? Not every feature needs all of these.
3. Build the layers in dependency order: schema before models, models before services, services before controllers. Within each layer, write the code AND its tests together.
4. After the feature's layers are complete, run the closing gates.

### Layer gates (use whichever layers your feature needs)

| Layer | Gate | Tests |
|-------|------|-------|
| **Migration** | `ddev craft migrate/up` succeeds, schema exists | — |
| **Record / Model** | class resolves, `ddev craft` doesn't throw on boot | — |
| **Service** | `ddev exec vendor/bin/pest --filter=MyServiceTest` green | Write alongside the service — test IS the gate |
| **Element query** | query returns expected results in Pest or `ddev craft` | Write alongside the query |
| **Controller** | `ddev exec vendor/bin/pest --filter=MyControllerTest` green | Write HTTP test alongside the action |
| **Queue job** | `ddev exec vendor/bin/pest --filter=MyJobTest` green | Write alongside the job |
| **Event listener** | feature that depends on the event works in test | Covered by the feature's integration test |
| **Permissions** | permission-gated user gets 403, permitted user gets 200 | Covered by controller test |
| **CP templates** | edit/index pages render without Twig errors | Browser verification |
| **CP JavaScript** | widgets initialize, no console errors | Browser verification |

### Closing gates (every feature, after layers are done)

1. **Browser verification (if Chrome DevTools MCP is available)** → log into the CP, navigate to the pages you just built, visually confirm: forms render correctly, editable tables are interactive, element selects open modals, read-only mode disables fields when `allowAdminChanges` is off. Check console for JS errors. Screenshots help the user see what you see.
2. **Manual verification** → see the manual testing table below. Some gates are required (can't be automated), others are optional sanity checks. Tell the user which manual checks apply to this feature and what to verify.
3. **Full test suite** → `ddev exec vendor/bin/pest` green (all tests, not just yours). Catches regressions.
4. **Simplification pass** → see below.
5. **Final verification** → `ddev composer check-cs` + `ddev composer phpstan` clean on changed files.

A gate is not "I wrote the code." A gate is "I ran the thing and saw it work." If a gate fails, stop and fix before moving on. Never plaster over a failed gate by writing the next layer.

Tests are written WITH each layer, not batched at the end. A service without tests is not a completed gate — it's a liability waiting to compound.

### Manual testing
craft-code-reviewer-deepSubagent

Deep code review on Opus 4.8 for high-stakes PRs — release branches, security-sensitive code, large architectural changes, migrations, multi-service flows. Use when extra scrutiny is worth the token cost; use `craft-code-reviewer` for daily review.

craft-code-reviewerSubagent

Reviews implemented code for quality, security, and Craft CMS conventions

craft-debuggerSubagent

Tracks down bugs in Craft CMS plugins with systematic investigation

craft-plannerSubagent

Breaks down large tasks into manageable implementation steps for Craft CMS plugin development

craft-site-builderSubagent

Builds Craft CMS site templates, components, and content architecture

craft-cloudSkill

Craft Cloud — Pixel & Tonic's serverless hosting platform for Craft CMS. Covers craft-cloud.yaml configuration, the Build → Migrate → Release deploy pipeline, the craftcms/cloud extension package, edge image transforms via Cloudflare, edge static caching with cache.rules + ESI, Cloud-managed S3 filesystem, MySQL 8 / Postgres 15 databases (no MariaDB, no tablePrefix), Console-based command runner and scheduled cron (once-per-hour minimum), auto-handled queue jobs, custom domains and SSL, preview environments per branch, Cloud limitations (ephemeral filesystem, no SSH, no .htaccess, no built-in mail), plugin development requirements for Cloud compatibility, and self-hosted → Cloud migration. Triggers on: craft-cloud.yaml, craftcms/cloud package, cloud.esi(), php craft cloud/up, php craft cloud/setup, App::isEphemeral(), CRAFT_EPHEMERAL, edge.craft.cloud, preview.craft.cloud, CRAFT_CLOUD_PROJECT_ID, CRAFT_CLOUD_ENVIRONMENT_ID, CRAFT_CLOUD_CDN_BASE_URL, Build → Migrate → Release, Cloud filesystem, Cloud-compatible plugin, Cloudflare Images at edge, AssetsFs, static-caching rules, ESI islands, deploy to Craft Cloud, migrate to Craft Cloud, self-hosted to Cloud, Craft Cloud quotas, Craft Cloud regions. Do NOT trigger for Servd (use the servd skill) or generic Craft deployment on Forge/bare metal (craftcms/deployment.md). Do NOT trigger for general DDEV local dev unrelated to Cloud parity.

craft-content-modelingSkill

Craft CMS 5 content modeling — sections, entry types, fields, Matrix, relations, project config, and content architecture strategy. Covers everything editors and developers need to structure content in Craft: choosing section types, designing entry types and field layouts, selecting field types for specific needs, configuring Matrix and nested entries, setting up relations and eager loading, and planning multi-site propagation. Triggers on: section types (single, channel, structure), entry types, field types, field layout design, field type selection, Matrix configuration, nested entries, relatedTo, eager loading, .with(), .eagerly(), categories, tags, globals, global sets, preloadSingles, propagation, multi-site content, URI format, project config, YAML, content architecture, content strategy, taxonomy, asset volumes, filesystems, image transforms, user groups, content permissions, entries-as-taxonomy, entrify, entrification, CKEditor vs Matrix, CMS editions, site propagation, multi-language, language groups, localization, translation method, field translation, content migration, reserved handles, field instances. Always use when planning content architecture, creating sections/fields, configuring Matrix, setting up relations, choosing field types, designing field layouts, making content modeling decisions, or planning multi-site content propagation. Do NOT trigger for PHP plugin/module development, custom field type code, front-end Twig templates, or buildchain configuration.

craft-garnishSkill

Garnish — Craft CMS's built-in JavaScript UI toolkit for the control panel. Covers the class system (Garnish.Base.extend, init, setSettings, addListener, on/off/trigger, destroy), UI widgets (Modal, HUD, DisclosureMenu, MenuBtn, CustomSelect, ContextMenu, Select), drag system (BaseDrag, DragSort, DragDrop, DragMove), form widgets (NiceText, CheckboxSelect, MixedInput, MultiFunctionBtn), utilities (key constants, ARIA helpers, focus management), and Craft integration (GarnishAsset, webpack externals, Craft.* class pattern). Triggers on: Garnish.Base.extend, Garnish.Modal, Garnish.HUD, Garnish.DragSort, Garnish.DisclosureMenu, Garnish.ESC_KEY/RETURN_KEY, activate/textchange events, UiLayerManager, registerShortcut, trapFocusWithin, garnishjs, GarnishAsset, CpAsset, CP JavaScript, modal dialog, HUD popover, Craft.CP, Craft.Slideout, Craft.ElementEditor, onSortChange, onOptionSelect, onSelectionChange, aria-modal, focus trap, keyboard navigation CP, this.base(), window.Garnish, CP memory leak, event listener cleanup, jQuery .on() in CP. Always use when writing, editing, or reviewing JavaScript that runs in the Craft CP — plugin CP assets, custom field type JS, element index JS, CP webpack config, or code that imports garnishjs or references window.Garnish. Also trigger for CP accessibility, keyboard interactions, drag-sort behavior, or CP JS memory issues. Do NOT trigger for front-end JavaScript (Alpine, Vue, htmx) or Twig templates (craft-site).