skills/formae-plugin-new/SKILL.md
Use when the user wants to create a new formae resource plugin, build a provider integration, or extend formae with support for a new cloud service
npx skillsauth add platform-engineering-labs/formae-mcp formae-plugin-newInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create a complete formae resource plugin for a cloud provider or service, following the plugin SDK tutorial and using TDD for the implementation.
After ANY code changes to the plugin, you MUST run make install before running conformance tests. The conformance tests run against the INSTALLED plugin binary, not the source code. Skipping this step means you're testing stale code.
Ask the user an open-ended question: what provider or service do they want to build a plugin for, and which resource types should it support? Do NOT present a multiple-choice list of providers — there are thousands of possible targets and we cannot guess. Just ask.
Collect the following from the user:
AWS, GCP, ATLAS). The scaffolder will uppercase mixed-case input automatically and emit a notice when it does so.Research the provider's API to understand:
Look at how Terraform or Pulumi model equivalent resources for schema design reference.
If resources have polymorphic structures (like DNS record types with different field shapes), design the schema to accommodate all variants.
Guided mode checkpoint: present API research findings and proposed resource model to the user for approval before continuing.
If your plugin shells out to an external binary (e.g., atlas, helm, kubectl), the binary must be available in the formae agent's $PATH at runtime. The plugin SDK does not yet ship a first-class mechanism for bundling extra binaries with plugin distributions; the conventions below are the current stop-gap.
Prior art. Formae core ships the pkl-reader-helm external binary using the pattern at formae/scripts/install-helm-reader.sh. This is the canonical reference for any plugin that depends on a runtime binary — read it before designing your own.
Plugin-side convention. On plugin initialization, call exec.LookPath("<binary>") and fail fast with a clear error message naming both the binary and the install path. Example error:
plugin atlas: required binary `atlas` not found in $PATH.
Install with: /path/to/install-atlas.sh
See: https://atlasgo.io/getting-started
Optionally expose a health-check endpoint that reports binary availability so operators can diagnose deployment issues without invoking real CRUD operations.
Multi-arch handling. Mirror the uname -s / uname -m mapping pattern from formae/scripts/install-helm-reader.sh to select the correct release asset per platform.
Dev-mode bootstrap. Until the SDK supports bundled binaries, mirror the install script in your plugin's own repository (e.g., scripts/install-atlas.sh). Have make install invoke it so fresh dev machines and CI runners can bootstrap automatically.
Known SDK limitation. Track the follow-up "plugin ships extra binaries" SDK enhancement — when that lands, plugins will declare their binary dependencies in formae-plugin.pkl and the agent host will install them at plugin registration time.
Run the scaffolding command:
formae plugin init --no-input --name <name> --namespace <NS> --description "<desc>" --author "<author>" --module-path "<path>" --license Apache-2.0
Verify the scaffolded project:
ls -Rformae-plugin.pklmake buildFetch the plugin SDK tutorial from https://docs.formae.io/en/latest/plugin-sdk/tutorial/ and follow it start to finish, adapting each lesson to the target provider.
Reference prior art plugins for general examples (single resource, simple CRUD): AWS, Azure, GCP, OCI, OVH — each at https://github.com/platform-engineering-labs/formae-plugin-<provider>.
For specific advanced patterns, the canonical references are:
| Pattern | Canonical reference |
|---|---|
| Resolvable computed outputs (custom Read, output-port story) | formae-plugin-aws/schema/pkl/ses/emailidentity.pkl |
| Polymorphic Target auth (abstract + discriminated subclasses) | formae-plugin-k8s/schema/pkl/main/k8s.pkl |
| Cross-plugin Target Resolvables (Target Config field accepts upstream resolvable) | formae-plugin-grafana/schema/pkl/grafana.pkl |
| Collection Resolvables (Mapping<String, formae.Resolvable>) | formae-plugin-compose — see the Target Config file with the Mapping field |
| Synthetic identifiers (identifier = "Label" for logical resources without natural server-side IDs) | formae-plugin-atlas — Migration resource schema |
Tutorial lessons to follow (adapt to target provider):
@ResourceType, @CreateOnly, @ReadOnly)OperationErrorCode patterns from the SDKmake conformance-testTarget Config field serialization (G-6). Plugin Go structs SHOULD declare camelCase json tags on Config fields (e.g., `json:"host"`). PKL fields should be single-name camelCase. Do NOT use the hidden lowercase / fixed PascalCase = lowercase pattern preserved in older plugins (k8s, Grafana) — that's a wart from Go structs lacking json tags, not a convention. Canonical reference for the clean pattern: the AWS plugin's Target Config classes.
Target Config field immutability (G-8). @formae.ConfigFieldHint.createOnly defaults to true (immutable), the opposite of @formae.FieldHint on resource fields (defaults to false, mutable). This is by-design: a Target's identity is typically defined by immutable environment fields (AWS account ID, region, server URL), so changing one means replacing the Target — and everything in it. Always declare createOnly explicitly on ConfigFieldHint annotations so intent is visible in PKL:
@formae.ConfigFieldHint { createOnly = false } // mutable
hidden host: String
@formae.ConfigFieldHint { createOnly = true } // immutable (also the default)
hidden region: String
MANDATORY: TDD for steps 4–8. 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. If you implement Create without first writing TestCreate, you are doing it wrong.
Guided mode checkpoints (skip all in autonomous mode):
In guided mode, do not proceed past a checkpoint until the user approves. If the user requests changes, make them and re-present.
Run make install && make conformance-test.
Fix any failures and re-run. All CRUD and discovery tests must pass before continuing.
Create a test project and verify the full lifecycle:
formae project init in a temporary directoryformae apply --mode reconcile --simulate to verify the planformae apply --mode reconcile to create real resourcesformae inventory to verify resources are managedformae destroy to clean upexamples/ directoryREADME.md with:
Before reporting completion, verify each item:
make install && make conformance-test)examples/make install before make conformance-test — tests run against the installed binarymake install and check the outputdevelopment
Use when the user wants to set, remove, or inspect a TTL or auto-reconcile policy on a stack — e.g. 'expire X in 20 minutes', 'reject out-of-band changes on Y', 'auto-reconcile production every 5 minutes', 'remove the TTL on dev', 'what policies are on lifeline?'
devops
Use when the user asks about their cloud targets, configured regions, provider accounts, or which cloud accounts are set up
devops
Use when the user asks about running commands, deployment progress, recent operations, command history, or what failed
devops
Use when the user asks about their infrastructure stacks, how infrastructure is organized, or needs a stack overview with resource counts