From odh-ai-helpers
Generates a complete ODH module operator repository with CRD types, controller skeleton, Helm chart, Makefile, CI config, and AGENTS.md. Use when starting a new ODH module from scratch.
How this skill is triggered — by the user, by Claude, or both
Slash command
/odh-ai-helpers:module-scaffold <component-name><component-name>This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate a complete standalone module operator repository for the ODH platform.
Generate a complete standalone module operator repository for the ODH platform.
Extract the component name from $ARGUMENTS. If not provided, ask the user.
Derive these values from the component name (example: model-registry):
| Variable | Example Value |
|---|---|
COMPONENT | model-registry |
COMPONENT_SNAKE | model_registry |
COMPONENT_PASCAL | ModelRegistry |
COMPONENT_LOWER | modelregistry |
COMPONENT_LOWER_PLURAL | modelregistries |
MODULE_REPO | <COMPONENT>-operator |
API_GROUP | components.platform.opendatahub.io |
API_VERSION | v1alpha1 |
SINGLETON_NAME | default-<COMPONENT> |
Ask the user:
components.platform.opendatahub.io or
services.platform.opendatahub.io? Default: components../<MODULE_REPO>.Generate this layout:
<MODULE_REPO>/
├── api/<API_VERSION>/
│ ├── <COMPONENT_SNAKE>_types.go
│ ├── <COMPONENT_SNAKE>_common.go
│ ├── groupversion_info.go
│ └── doc.go
├── internal/
│ ├── controller/
│ │ ├── <COMPONENT_SNAKE>_controller.go
│ │ └── <COMPONENT_SNAKE>_controller_actions.go
│ └── webhook/
│ └── singleton.go
├── charts/<MODULE_REPO>/
│ ├── Chart.yaml
│ ├── values.yaml
│ └── templates/
│ ├── deployment.yaml
│ ├── serviceaccount.yaml
│ ├── clusterrole.yaml
│ ├── clusterrolebinding.yaml
│ ├── webhook-service.yaml
│ ├── webhook-certificate.yaml
│ └── _helpers.tpl
├── cmd/
│ └── main.go
├── config/
│ └── samples/
│ └── <COMPONENT_SNAKE>.yaml
├── go.mod
├── Makefile
├── Containerfile
├── .github/workflows/
│ └── ci.yaml
├── .rules/
│ ├── api-types.md
│ ├── controller.md
│ ├── helm-chart.md
│ ├── security.md
│ └── testing.md
├── AGENTS.md
├── README.md
└── .gitignore
Use the templates from ${CLAUDE_SKILL_DIR}/references/templates.md to
generate each file. Key requirements:
api/<API_VERSION>/<COMPONENT_SNAKE>_types.goThe CR type must:
metav1.TypeMeta and metav1.ObjectMetaSpec field using <COMPONENT_PASCAL>SpecStatus field using <COMPONENT_PASCAL>Status+kubebuilder:object:root=true,
+kubebuilder:subresource:status, +kubebuilder:resource:scope=Clustervar _ common.PlatformObject = (*<COMPONENT_PASCAL>)(nil)The status struct must embed common.Status and
common.ComponentReleaseStatus both as anonymous (unnamed) fields with
json:",inline" tags. Use common.ComponentReleaseStatus \json:",inline"`instead of a named field likeReleases common.ComponentReleaseStatus json:"releases,omitempty"because a named field serializes as a nested object{releases: {releases: [...]}}instead of the flat array{releases: [...]}` the CRD expects, causing
status update failures.
api/<API_VERSION>/<COMPONENT_SNAKE>_common.goDefine <COMPONENT_PASCAL>CommonSpec with common.ManagementSpec embedded
inline. This struct is inlined into <COMPONENT_PASCAL>Spec.
api/<API_VERSION>/groupversion_info.goStandard kubebuilder groupversion registration using the chosen API group and version.
api/<API_VERSION>/doc.goPackage doc comment with +groupName=<API_GROUP> marker.
internal/controller/<COMPONENT_SNAKE>_controller.goThe controller setup must:
reconciler.NewReconciler with functional options patternReconcilerFor builder pattern with WithReconcilerOpts for release
info. The default conditions (Ready + ProvisioningSucceeded) are sufficient
for the scaffold. Add WithConditions("Degraded") only when real actions
explicitly manage it via rr.Conditions.MarkFalse/MarkTrueodh-platform-utilities packages:
framework/controller/reconciler for reconciler setupframework/controller/conditions for condition managementframework/controller/actions/deploy for resource deploymentframework/controller/actions/gc for garbage collectionframework/controller/actions/render for manifest renderingframework/api for Release typepkg/cluster for platform detectionpkg/metadata for label/annotation constantsinternal/controller/<COMPONENT_SNAKE>_controller_actions.goDefine three action functions:
framework/controller/actions/renderframework/controller/actions/deploy with SSA modeframework/controller/actions/gcEach action follows the signature:
func(ctx context.Context, rr *types.ReconciliationRequest) error
charts/<MODULE_REPO>/Chart.yamlapiVersion: v2
name: <MODULE_REPO>
description: Helm chart for the <COMPONENT_PASCAL> module controller
version: 0.1.0
appVersion: "0.1.0"
type: application
charts/<MODULE_REPO>/values.yamlProvide defaults for: image repository/tag, replicas (1), resources (requests: 100m CPU, 128Mi memory; limits: 500m CPU, 512Mi memory), service account name, node selector, tolerations.
Generate ONLY controller infrastructure manifests:
Do NOT generate application-level manifests.
cmd/main.goStandard controller-runtime manager setup with:
MakefileInclude targets: build, test, lint, manifests, generate, fmt,
vet, docker-build, docker-push, helm-lint.
ContainerfileMulti-stage build: Go builder stage + distroless runtime stage.
.github/workflows/ci.yamlGitHub Actions workflow with: lint, test, build jobs. Pin actions to full
commit SHAs. Set permissions: read-all.
AGENTS.mdUse the comprehensive template from
${CLAUDE_SKILL_DIR}/../module-compliance/references/agents-md-template.md
as a starting point. Replace <COMPONENT_PASCAL> and other placeholders with
the actual component values. This file provides passive guidance to AI agents
working in the module repo -- covering PlatformObject contract, controller
patterns, Helm chart rules, security, and separation of concerns.
.rules/ directoryCopy the rule files from
${CLAUDE_SKILL_DIR}/../module-compliance/references/rules/ into the
generated repo's .rules/ directory. These are path-scoped rules that
fire automatically when agents edit matching files (e.g., api/**/*.go,
internal/controller/**/*.go, charts/**). Files to copy:
api-types.md -- CRD type conventionscontroller.md -- Controller patterns and GC orderinghelm-chart.md -- Chart content restrictionssecurity.md -- Webhook, TLS, RBAC, and metadata rulestesting.md -- Test patterns and conventionsconfig/samples/<COMPONENT_SNAKE>.yamlA sample CR manifest with the singleton name and managementState: Managed.
README.mdBrief README with: project description, prerequisites (Go 1.25+, controller-runtime, cert-manager), build instructions, usage instructions.
.gitignoreStandard Go gitignore (bin/, vendor/, *.exe, etc.).
Run the following commands in the generated directory:
cd <MODULE_REPO>
go mod init github.com/opendatahub-io/<MODULE_REPO>
go mod edit -require github.com/opendatahub-io/[email protected]
go mod edit -require github.com/opendatahub-io/odh-platform-utilities/[email protected]
The root module (api/common, pkg/) is tagged at v0.1.0. The framework
sub-module has its own go.mod and requires a separate dependency line.
Note: go mod tidy will fail until the controller code compiles. Inform the
user that they should run go mod tidy after filling in the controller
implementation details and installing controller-gen.
Suggest the user run the module-compliance skill against the generated repo
to verify all contract rules pass. Also suggest running make lint and
make test once the Go dependencies are resolved.
go mod tidy will fail until controller-gen generates deepcopy methods and
all placeholder code compiles. Run make generate first.github.com/openshift/api for ManagementState. The shared
library uses a plain string type that is wire-compatible..WithAction() in the reconciler
builder chain. Deploy stamps annotations that GC reads -- reversing the
order deletes resources that were just deployed.default-<component>.common.ComponentReleaseStatus MUST be an anonymous inline embed in the
status struct: common.ComponentReleaseStatus \json:",inline"`. A named field like Releases common.ComponentReleaseStatuswraps the innerreleasesarray in an extra JSON object, producing{releases: {releases: [...]}}` which fails CRD validation.<component>-operator-manager-role and will overwrite any resource with
the same name via SSA, stripping the standalone controller's permissions.
Use the Helm fullname helper (which defaults to the chart name) to
generate unique names like <MODULE_REPO> instead of common patterns
like *-manager-role.npx claudepluginhub opendatahub-io/ai-helpersChecks an ODH module operator repository for contract violations, validating CRD structure, Helm chart content, webhook ownership, metadata conventions, and reconciler ordering. Use during code review or after scaffolding.
Scaffolds Kubernetes operators: CRDs, Go controllers, webhooks via Kubebuilder; sets up Tilt dev loop, Kind clusters, Kustomize for fast iteration and validation.
Generates Helm charts with Chart.yaml, values.yaml, templates, and helpers for Kubernetes workloads like Deployments, StatefulSets, and DaemonSets.