원클릭으로
formae-plugin-add-resource
Use when the user wants to add support for a new resource type to an existing formae plugin
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when the user wants to add support for a new resource type to an existing formae plugin
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
Use when the user wants to check for infrastructure drift, see what changed out-of-band, or absorb/overwrite out-of-band changes into their IaC codebase
Use when the user wants to bring unmanaged/discovered resources under formae management, import resources into their IaC codebase, or absorb cloud resources into existing forma files
Use when the user wants to rename a managed resource, relabel a resource, change a resource's label, or give a discovery-named resource a readable name — a rename on its own never destroys or recreates the cloud object
Use when the user wants to deploy infrastructure, apply a forma file, reconcile a stack, update a stack, or make planned infrastructure changes
Use when the user wants to start authoring formae infrastructure or deploy something NEW with formae — e.g. 'I want to deploy X with formae', 'build a k8s app with formae', 'set up infrastructure for Y', 'create a new forma file for my service', 'write formae IaC for Z'. The front door that triages where the work happens, sets up plugin schema deps, and dispatches to focused authoring skills. NOT for applying an existing forma file (use formae-apply) or operating existing infra.
Use when the user wants to add or remove a plugin schema dependency in an existing formae project's PklProject — e.g. 'add the grafana plugin', 'I need cloudflare DNS', 'drop the azure dependency'.
| name | formae-plugin-add-resource |
| description | Use when the user wants to add support for a new resource type to an existing formae plugin |
Add support for a new resource type to an existing formae resource plugin, following the plugin SDK tutorial and using TDD.
After ANY code changes to the plugin, you MUST run make install before running tests. Integration tests and conformance tests run against the INSTALLED plugin binary, not the source code. Skipping this step means you're testing stale code.
Ask the user where their plugin lives. Check that the directory exists and contains a valid plugin project (look for formae-plugin.pkl, Makefile, and the plugin Go source). Run /init so you have full context on the codebase.
Ask the user which resource type they want to add. Then research the provider's API for that resource thoroughly:
Look at how Terraform or Pulumi model the equivalent resource for schema design reference.
Present your research findings and a proposed resource schema to the user for approval before proceeding.
Fetch the plugin SDK tutorial from https://docs.formae.io/en/latest/plugin-sdk/tutorial/ and follow steps 2–10, adapting each lesson to the new resource type. Study the existing resource implementations in the plugin for patterns and conventions to follow.
Reference prior art plugins for real-world patterns:
https://github.com/platform-engineering-labs/formae-plugin-awshttps://github.com/platform-engineering-labs/formae-plugin-azurehttps://github.com/platform-engineering-labs/formae-plugin-gcphttps://github.com/platform-engineering-labs/formae-plugin-ocihttps://github.com/platform-engineering-labs/formae-plugin-ovhSteps to follow:
@ResourceType, @CreateOnly, @ReadOnly)OperationErrorCode patterns from the SDKErrors go in the result, not the error return. Domain-level failures — NotFound, AlreadyExists, InvalidRequest, ServiceInternalError — are reported through an OperationErrorCode on the result, not the Go error return. Where that code lives depends on the result type: ReadResult has a top-level ErrorCode; CreateResult, UpdateResult, DeleteResult, and StatusResult carry it on their nested ProgressResult (ProgressResult.ErrorCode, set alongside OperationStatus: OperationStatusFailure); ListResult has no error-code field — a list-level failure is the one case that returns a Go error. The Go error return is otherwise reserved for transport-level failures where you can't construct a meaningful result at all (e.g., transport.NewClient failing, context cancellation).
Concretely:
Read against a missing resource: return &resource.ReadResult{ErrorCode: resource.OperationErrorCodeNotFound}, nil — not nil, errors.New("not found").Create with bad input properties: return &resource.CreateResult{ProgressResult: &resource.ProgressResult{OperationStatus: OperationStatusFailure, ErrorCode: OperationErrorCodeInvalidRequest, StatusMessage: "..."}}, nil.ErrorCode before returning.Returning a non-nil error from a CRUD method bypasses formae's retry/state-machine logic and the agent treats it as an unrecoverable plugin bug. Review every return nil, err and ask "could this be a result with ErrorCode instead?"
MANDATORY: TDD for steps 3–7. Each tutorial lesson includes integration tests (e.g., TestCreate, TestRead, TestReadNotFound, TestUpdate, TestDelete, TestDeleteNotFound, TestList). For EVERY CRUD operation you MUST follow this exact loop:
https://docs.formae.io/en/latest/plugin-sdk/tutorial/05-create/)make install && go test -tags=integration ./... — confirm the test passes.NEVER write implementation code before its corresponding test. NEVER skip writing tests.
Run make install && make conformance-test.
Fix any failures and re-run. All CRUD and discovery tests must pass before continuing.
Ask the user if they want to do a manual end-to-end test. If yes:
formae apply --mode reconcile --simulate to verify the planformae apply --mode reconcile to create real resourcesformae inventory to verify resources are managedformae destroy to clean upUpdate the plugin's README.md:
Before reporting completion, verify each item:
make install && make conformance-test)make install before running tests — tests run against the installed binarypkl eval to evaluate forma files — ALWAYS use formae eval --output-consumer machine