---
title: "Kubernetes support — design"
description: "- **Feature:** kubernetes-support - **Status:** in-design - **Branch:** `k8s_support` - **Closes:** [issue #64 — Enhance review-code skill with support for k8s](https://github.com/serpro69/claude-toolbox/issues/64) (narrow) — expanded to the whole plugin flow per the originating discussion - **Implementation plan:** [implementation.md](implementation.md) - **Task list:** [tasks.md](tasks.md) - **A"
type: skill
canonical_url: https://claudary.paisolsolutions.com/skills/design-6
source: "Claudary"
difficulty: intermediate
author: "Claude Code Knowledge Pack"
date: 2026-07-10T11:19:46.863Z
license: CC-BY-4.0
attribution: "Kubernetes support — design — Claudary (https://claudary.paisolsolutions.com/skills/design-6)"
---

# Kubernetes support — design
- **Feature:** kubernetes-support - **Status:** in-design - **Branch:** `k8s_support` - **Closes:** [issue #64 — Enhance review-code skill with support for k8s](https://github.com/serpro69/claude-toolbox/issues/64) (narrow) — expanded to the whole plugin flow per the originating discussion - **Implementation plan:** [implementation.md](implementation.md) - **Task list:** [tasks.md](tasks.md) - **A

## Overview

# Kubernetes support — design

- **Feature:** kubernetes-support
- **Status:** in-design
- **Branch:** `k8s_support`
- **Closes:** [issue #64 — Enhance review-code skill with support for k8s](https://github.com/serpro69/claude-toolbox/issues/64) (narrow) — expanded to the whole plugin flow per the originating discussion
- **Implementation plan:** [implementation.md](implementation.md)
- **Task list:** [tasks.md](tasks.md)
- **ADRs:** [0001](../../adr/0001-profile-detection-model.md), [0002](../../adr/0002-profile-content-organization.md), [0003](../../adr/0003-plugin-root-referenced-content.md)

## Overview

Kubernetes becomes a first-class *profile* that every phase of the plugin's design → implement → review → test → document flow can consult when the artifacts under work are Kubernetes resources (plain manifests, Helm charts, Kustomize overlays). The feature also refactors the plugin's content organization so that Kubernetes is the first instance of a general pattern, not a special case — future profiles (Terraform, Ansible, Dockerfile, others) drop into the same slots without further architectural change.

The literal text of issue #64 is narrow: "enhance `review-code` with support for k8s". The chosen scope is broader — the whole flow, phased — because fixing only `review-code` would leave design, implementation, test, and documentation skills unable to deploy the same Kubernetes awareness, forcing per-project duplication of concerns that the plugin exists to provide.

## Motivation

The plugin currently handles programming languages (Go, Python, Java, JS/TS, Kotlin) as the only axis of per-project variation. When the code under review is Kubernetes YAML, the language-detection step returns nothing, and the reviewer falls back to generic guidance that is blind to Kubernetes-specific concerns (RBAC least privilege, probe correctness, PodDisruptionBudget presence, secret handling, image-tag immutability, Helm chart hygiene, Kustomize composition). The same blindness affects every other skill in the flow.

Three architectural decisions (recorded as ADRs [0001](../../adr/0001-profile-detection-model.md), [0002](../../adr/0002-profile-content-organization.md), [0003](../../adr/0003-plugin-root-referenced-content.md)) must be settled before Kubernetes content can land coherently, and they apply beyond Kubernetes. This feature adopts them in-feature rather than deferring, so that the Kubernetes content lands in its final shape and is not migrated later.

## Scope

### In scope (this feature)

- **Kubernetes manifests.** Core resources: Deployment, StatefulSet, DaemonSet, Job, CronJob, Service, Ingress, ConfigMap, Secret, RBAC (Role/ClusterRole/RoleBinding/ClusterRoleBinding/ServiceAccount), NetworkPolicy, HorizontalPodAutoscaler, PodDisruptionBudget, SecurityContext, probes, resource requests/limits.
- **Helm chart hygiene.** `Chart.yaml` metadata, `values.yaml` schema, `templates/` correctness, dependency pinning.
- **Kustomize composition.** `kustomization.yaml`, base/overlay structure, patch targets, generator options.
- **Profile-first plugin architecture.** `klaude-plugin/profiles/<name>/` top-level directory; migration of the existing programming-language reference sets into the new layout.
- **Index-driven content loading.** `index.md` routing inside each profile's per-phase subdirectory.
- **Cross-skill plumbing.** `klaude-plugin/skills/_shared/profile-detection.md` as a shared mechanism; plugin-root path references from skills to profile content.
- **Conventions.** `CLAUDE.md` additions documenting profiles, skill description budgets, and ADR location. Three ADRs under `docs/adr/`.

### Out of scope (explicit deferrals)

- **GitOps resources** (ArgoCD `Application`/`ApplicationSet`, Flux `Kustomization`/`HelmRelease`). Most GitOps rules reduce to "does the synced manifest pass the manifest rules?"; the ArgoCD-vs-Flux split would add noise without a clear payoff at this stage. A follow-up feature can add a `gitops/` slot inside the Kubernetes profile or a separate GitOps profile.
- **Service mesh** (Istio, Linkerd, Gateway API). Too stack-specific for a shipped generic profile; better captured per-project as `kk:project-conventions`.
- **Observability CRDs** (`ServiceMonitor`, `PrometheusRule`). Same reasoning.
- **Policy engines** (Kyverno, OPA/Gatekeeper) as baseline content. The `test` phase auto-detects policy toolchains via project markers (see §[test skill integration](#test-skill-integration)); hard-coding any single engine into the profile is out of scope.
- **Dockerfile.** Conceptually adjacent but distinct. A future container profile can address Dockerfiles; conflating would widen the Kubernetes profile beyond its focus.
- **Programming-language profile authoring.** Existing Go/Python/Java/JS-TS/Kotlin checklists migrate unchanged in content; no new per-language content is added by this feature.

## Architecture overview

Three concepts, described here and expanded in their own sections below.

### A single, additive detection axis

[ADR 0001](../../adr/0001-profile-detection-model.md) records that detection remains a single axis — all detectable artifact types (programming languages, IaC DSLs, config schemas) are equal rows in one detection table. Matching a file contributes that row's reference directory to the set loaded for the current task. Multiple matches are additive.

**`%LANGUAGE%` placeholder semantics:**
- When one or more programming-language profiles are active, `%LANGUAGE%` resolves to the primary programming language (existing behavior).
- When no programming-language profile is active but an IaC/config-schema profile is (pure-K8s repo, pure-Terraform repo), `%LANGUAGE%` resolves to the dominant non-language profile's natural tongue — Kubernetes → "Kubernetes", Terraform → "Terraform", Helm → "Helm". Prose like "a highly-skilled %LANGUAGE% developer" remains readable ("a highly-skilled Kubernetes developer").
- When no profile matches at all, `%LANGUAGE%` falls back to generic guidance (existing behavior).

Profile content is consulted additively regardless of how `%LANGUAGE%` resolves.

The term "language" is retained. Editor tooling (LSP, VS Code) already treats YAML, Dockerfile, HCL, and others as "languages" under an umbrella-term usage. Adopting that framing keeps the existing prose honest.

### Profile-first content layout

[ADR 0002](../../adr/0002-profile-content-organization.md) records that profile content lives in a new top-level `klaude-plugin/profiles/<name>/` directory, peer to `klaude-plugin/skills/`. Each profile is self-contained (`DETECTION.md`, `overview.md`, per-phase subdirectories). Existing `review-code/reference/<lang>/` directories migrate in. Skills discover content via `index.md` routers inside per-phase subdirectories — not via hardcoded filenames.

### Plugin-root references instead of outside-tree symlinks

[ADR 0003](../../adr/0003-plugin-root-referenced-content.md) records that skills and agents reference profile content via plugin-root-relative paths: `${CLAUDE_PLUGIN_ROOT}/profiles/<name>/...`. No symlinks are created from skills into `profiles/`. The existing `_shared/` symlink pattern, which stays inside `skills/`, is unchanged. The choice of variable-referenced paths for outside-skills-directory content prototypes a pattern that may later replace `_shared/` symlinks entirely (see ADR 0003's "prototype for future work" section).

## Detection mechanics

Detection is the responsibility of each profile, declared in `klaude-plugin/profiles/<name>/DETECTION.md`. Skills consume detection through a shared procedure (see [Shared mechanisms](#shared-mechanisms)), not by replicating per-profile logic.

### Signal model

Every profile's `DETECTION.md` uses a mandatory, structured three-section schema so that six consuming skills interpret the rule identically. Prose-only detection rules are insufficient — cross-consumer drift is a real risk ([ADR 0002 context](../../adr/0002-profile-content-organization.md)).

Required sections (each may be empty if the profile has no signals of that kind):

- **`## Path signals`** — path globs that promote a file to a candidate. Path signals are a *fast pre-filter* only; they do not activate the profile on their own.
- **`## Filename signals`** — literal filenames or filename globs that are *authoritative*: any matching file activates the profile regardless of path.
- **`## Content signals`** — content-inspection rules (anchors, regexes, presence-of-keys) that are *authoritative* for files not already resolved by filename signals. Inspection is bounded to the first N KB per file (each profile declares N in its `DETECTION.md`); within that bound, multi-document YAML is handled per `---`-separated block. Profiles whose content rule is naturally per-block describe that handling explicitly.

The two-dimensional framing: signals are **ordered by evaluation cost** (path → filename → content; cheapest first), but **authority follows a different order** (filename > content > path; path alone is insufficient). A file not caught by filename or content signals, regardless of any path hit, does not activate the profile.

The `_shared/profile-detection.md` procedure (see [Shared mechanisms](#shared-mechanisms)) applies this fixed algorithm against the per-profile values declared in each `DETECTION.md`.

### Kubernetes detection rule

Path signals:

- `k8s/`, `manifests/`, `charts/`, `kustomize/`, `deploy/`, `templates/` — case-insensitive match anywhere in the path. Candidate pre-filter only.

Filename signals (authoritative):

- `Chart.yaml` → Helm chart root. Authoritative.
- `values*.yaml` (any filename starting with `values` in a directory that also contains `Chart.yaml`) → Helm values by adjacency. Authoritative.
- Files with `.yaml`, `.yml`, or `.tpl` extension inside `<dir>/templates/` where `<dir>` itself contains a `Chart.yaml` as a direct child → Helm template. Authoritative by adjacency. The `templates/` directory must sit directly next to a `Chart.yaml` — at a chart root or at a subchart root under `<parent>/charts/<subchart>/`. A `templates/` nested elsewhere in the tree (e.g., `docs/templates/`, `ci/templates/`) does NOT activate this rule even when a `Chart.yaml` exists higher up at the repo root, because those intermediate directories do not themselves contain a `Chart.yaml`. Avoids the monorepo false-positive (umbrella root `Chart.yaml` spuriously claiming unrelated `templates/` directories) and still avoids the trap where a standalone edit to a chart's `templates/deployment.yaml` contains `{{ if ... }}` directives before any `apiVersion:` and would otherwise fail the content signal.
- `kustomization.yaml`, `kustomization.yml`, or `Kustomization` (exact filenames) → Kustomize. Authoritative.

Content signals (authoritative for generic YAML not caught by filename):

- For any `.yaml` or `.yml` file, scan each `---`-separated document block. A document containing both a top-level `apiVersion:` *and* a top-level `kind:` at zero indent → Kubernetes manifest. A file may contain multiple documents; one matching document activates the profile. If the first document lacks the markers but a later document has them, the profile still activates. Inspection is bounded to the first ~16 KB per file to avoid runaway reads on large generated manifests.
- A file with no matching document in any block → not Kubernetes (the file may still match some other profile; generic YAML belongs to no profile by default).

Multi-profile and no-profile outcomes:

- **Multiple profiles match in the same diff.** Every matching profile's reference directory is loaded. A Go + Kubernetes diff consults `profiles/go/review-code/` and `profiles/k8s/review-code/` both. Findings are emitted grouped by (profile, checklist).
- **No profile matches.** The skill proceeds with generic guidance, identical to today's "no language detected" fallback.

### Dockerfile non-trigger

A Dockerfile on its own — even under a `deploy/` or `k8s/` directory — does NOT activate the Kubernetes profile. Dockerfiles have no K8s signal: they are not `Chart.yaml`/`values*.yaml`/`kustomization.yaml`, and they do not contain `apiVersion:` + `kind:`. When a Dockerfile appears in the same diff as Kubernetes manifests, the Kubernetes profile activates on the K8s manifests' signals; the Dockerfile is not reviewed by this profile. A future container profile may own Dockerfiles independently.

### Detection output shape

Detection emits a list of records, one per matched profile: `{profile: <name>, triggered_by: [<signal descriptions>], files: [<paths>]}`. The `triggered_by` list names which signal type fired for each file (e.g., `"filename: Chart.yaml"`, `"content: apiVersion+kind in block 2"`). Downstream skills use the `files` field to scope behavior — for example, the `test` skill runs `helm lint` only on files triggered under Helm signals, not on every YAML.

## File structure

Per-profile layout is uniform. Every profile under `klaude-plugin/profiles/` follows the same shape:

```
klaude-plugin/profiles/<name>/
  DETECTION.md             # authoritative trigger rule (see §Detection mechanics)
  overview.md              # human-readable profile summary + dependency-lookup targets
  review-code/             # consumed by review-code
    index.md               # router: always-load entries, conditional entries, one-liners
    <checklist files>      # named to fit the profile's content; no fixed schema
  design/                  # consumed by design (populated per-profile as needed)
  test/                    # consumed by test (populated per-profile as needed)
  implement/               # consumed by implement (populated per-profile as needed)
  document/                # consumed by document (populated per-profile as needed)
  review-spec/             # consumed by review-spec (populated per-profile as needed)
```

Not every profile populates every phase subdirectory. A programming-language profile may only ever need `review-code/`; an IaC profile like Kubernetes populates all six. The plugin structure test (`test/test-plugin-structure.sh`) asserts the *presence* of each directory and file a profile declares — not that every profile populates every slot.

**Phase-subdirectory contents.** A phase subdirectory contains only its `index.md` and the checklist/content files the index references. Human-facing documentation (authoring notes, READMEs) lives at the profile root — typically inside `overview.md`, or as a sibling file next to it — never inside a phase subdirectory. This keeps the bidirectional index invariant (§Test suite updates) sharp: an unreferenced `.md` inside a phase dir is always a bug, never a README.

### The Kubernetes profile, concretely

After both P0 and P1 have landed:

```
klaude-plugin/profiles/k8s/
  DETECTION.md
  overview.md
  review-code/
    index.md
    security-checklist.md           # RBAC, Pod Security, NetworkPolicy, secrets, image provenance
    archite

---

Source: [Claudary](https://claudary.paisolsolutions.com/skills/design-6) · https://claudary.paisolsolutions.com
