CtrlK
BlogDocsLog inGet started
Tessl Logo

config-as-data

Use whenever the user is authoring or modifying Kubernetes configuration stored in ConfigHub, or is about to reach for Helm, Kustomize, Jsonnet, cdk8s, or a values file. This skill enforces the "configuration as data" doctrine — Units contain fully-materialized, literal YAML, mutated in place via cub functions or direct edits, never re-rendered from templates. Load this proactively any time the user says things like "add a chart", "values file", "overlay", "template this", "parameterize", "set up Helm for this", "make this reusable across envs", or starts generating K8s YAML that will be stored in ConfigHub. Do not load for: pure import-from-helm / import-from-kustomize flows (those have their own skills that handle one-shot render + store), or authoring config outside ConfigHub.

89

Quality

88%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Passed

No known issues

SKILL.md
Quality
Evals
Security

config-as-data

Authoring discipline for Kubernetes configuration stored in ConfigHub.

The rule

A ConfigHub Unit contains fully materialized YAML with literal values for every field. Code (functions) operates on data. Data is the source of record. This is not a style preference — it's what makes ConfigHub's query, validation, mutation-graph, and revision-history features work. Re-rendered or templated Units break all of those.

If you're tempted to reach for Helm, Kustomize, Jsonnet, cdk8s, or a values file to author new configuration for ConfigHub, stop and re-read this skill.

When to use

  • User is creating a new Kubernetes resource to store in a Unit.
  • User is about to add a Helm chart or Kustomize overlay to a Unit's source.
  • User asks how to "parameterize" a Unit, share config across environments, or keep a values file alongside YAML.
  • User asks how to do something "like Helm values" or "like Kustomize overlays" in ConfigHub.
  • User starts templating YAML ({{ .Values.x }}, ${VAR}, <% %>) that will end up in a Unit.

Do not load for

  • One-shot import-from-helm / import-from-kustomize (those skills render once, then this discipline takes over for subsequent edits).
  • Authoring config that will live in git or a chart repo, not in ConfigHub.
  • Pure read / query tasks.

Preflight gates

  1. cub organization list succeeds (proves a valid token; cub context get / cub info / cub version don't require one) and cub context get returns a default space.
  2. User has write permission on the target Space.
  3. If authoring new config, confirm with the user which Space this Unit belongs to. Best practice: one Space per app × environment/region.

The loop

1. Establish intent — authoring or migrating?

  • New resource from scratch. Go to step 2.
  • Migrating existing Helm/Kustomize. The right skill is import-from-helm or import-from-kustomize (future). If those aren't available, render once with helm template or kustomize build, strip runtime-only fields, and store the output as a Unit — then never re-render.

2. Produce literal YAML

First, check if the skill-examples Space has a relevant example Unit to use as a starting point:

cub unit get <example-slug> --space skill-examples -o yaml 2>/dev/null

The skill-examples-bootstrap skill seeds Units for common resource types (hello-app, hello-statefulset, hello-daemonset, hello-job, hello-cronjob, hello-ingress, hello-netpol, hello-rbac, hello-hpa, hello-pdb). If a matching example exists, adapt it. If not, scaffold from Kubernetes or hand-author:

kubectl create deployment my-app --image=confighubplaceholder:confighubplaceholder \
  --dry-run=client -o yaml \
  | yq 'del(.metadata.creationTimestamp, .status)' > my-app.yaml

Use confighubplaceholder for string fields and 999999999 for numeric fields that need to be supplied later. vet-placeholders will block apply while any remain.

For fields kubectl create doesn't cover, hand-author literal YAML — don't template. Consult references/yaml-patterns.md for common shapes. For specific resource types (StatefulSet, Ingress, NetworkPolicy, etc.), use the kubernetes-resources skill.

3. Store in a Unit

cub unit create --space <space> <unit-slug> my-app.yaml \
  --change-desc "<summary>

User prompt: <verbatim>
Clarifications: <condensed or 'none'>"

4. Fill in defaults via functions (not by hand)

Prefer the defaults functions over hand-editing — they're hermetic, idempotent, and record a clean revision:

cub function set --space <space> --unit <unit-slug> \
  set-container-resources-defaults --change-desc "..."

cub function set --space <space> --unit <unit-slug> \
  set-container-probe-defaults --change-desc "..."

cub function set --space <space> --unit <unit-slug> \
  set-pod-container-security-context-defaults --change-desc "..."

For Namespaces: set-pod-security-defaults. To guarantee namespace: is set: ensure-namespaces.

5. Make env-specific variations via Units, not templates

To vary config across environments:

  • Create one Space per app × environment/region.
  • Use upstream → downstream Unit relationships to clone baseline.
  • Apply differences via functions: set-container-image, set-replicas, set-env-var, etc. — each recorded as a revision.

Don't introduce a values file. Don't introduce an overlay. The Space is the parameterization boundary.

For deeper guidance on Space layout (app-home Spaces, per-env Spaces, platform Spaces, naming conventions, and the upstream/downstream topology), load space-topology.

Tool boundary

  • Allowed: cub (mutations), kubectl create --dry-run=client and kubectl explain (scaffolding only), reading existing chart/overlay content for one-shot import.
  • Not allowed: helm install/upgrade, kustomize build piped into ongoing editing, writing values files alongside a Unit's YAML, introducing template syntax into a Unit's data.

Change description

Every cub unit create, cub unit update, cub function set, cub run call must pass --change-desc:

<summary line>

User prompt: <verbatim user prompt>
Clarifications: <condensed: "user confirmed target env is prod" / "user chose bundle granularity per-app" / "none">

Stop conditions

  • User insists on keeping a values file or template in the Unit. Explain the rule once; if they still want it, stop and hand back — this isn't the skill for that.
  • Required field can only be filled correctly at apply time (e.g., a rendered secret from an external system). Use a placeholder + a function that fills it at apply — don't template.

Verify chain

  1. cub unit get <slug> --space <space> — inspect the stored YAML; confirm it is literal.

  2. If the Space has validation Triggers wired up (see triggers-and-applygates for the setup), every cub unit create / cub unit update / cub functionset / cub run already runs them against the new revision — no extra step needed. If not, run the vet functions directly:

    • cub function vet --space <space> --unit <slug> vet-placeholders — no remaining placeholders (unless intentional for later fill).
    • cub function vet --space <space> --unit <slug> vet-schemas — valid against the target K8s version.
    • cub function vet --space <space> --unit <slug> vet-format — clean YAML.
  3. To re-run a specific Trigger against a Unit — useful for validators whose arguments are awkward to retype on the CLI, like vet-cel and vet-starlark, where the configured Trigger already carries the CEL/Starlark expression:

    cub function vet --space <space> --unit <slug> --trigger <trigger-space>/<trigger-slug>

    The Trigger supplies the function name and its arguments, so the result matches what automatic validation would produce on a write. Less valuable for validators that take no arguments (vet-schemas, vet-placeholders, vet-format) — just call those directly.

Evidence

  • cub unit get <slug> --space <space> --web — opens the Unit in the GUI so the user can see the literal YAML and revision history.

References

  • references/cub-cli.md
  • references/functions-catalog.md
  • references/yaml-patterns.md — ConfigHub-native YAML patterns for all common resource types.
  • Companion skills: kubernetes-resources (authoring specific resource types), space-topology (Space layout, upstream/downstream conventions), triggers-and-applygates (automatic validation on writes, running Triggers explicitly), skill-examples-bootstrap (seeds live examples in skill-examples Space).
  • https://docs.confighub.com/markdown/background/config-as-data.md
Repository
confighub/confighub-skills
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.