Turn .env, properties, YAML, JSON, TOML, INI, or text into an AppConfig Unit and rendered ConfigMap via Upsert + render-configmap, or hash a hand-authored mutable ConfigMap with set-hash so linked workloads roll. Use for "use my .env", configMapGenerator-like config, envFrom, and a Deployment that never restarts on a ConfigMap change.
Execution mode: follow references/execution-modes.md. This Skill grants no automatic tool permission. In standalone use, submit each exact requested write once to the host permission system; a stricter external overlay may stop it before Bash.
For an existing Unit, read its current HeadRevisionNum and DataHash/ContentHash immediately before the write and disclose that the stock convenience command does not carry those reviewed values as atomic preconditions. That race limits the claim you can make; it does not make this standalone Skill read-only.
Turn a user's application configuration file — .env, .properties, .yaml, .json, .toml, .ini, or plain text — into a versioned ConfigHub Unit, then render it into a Kubernetes ConfigMap via an Upsert link carrying a render-configmap Invocation. No server worker and no Target are needed — rendering is a normal ConfigHub function that runs during link resolution.
Canonical doc: https://docs.confighub.com/markdown/guide/app-config.md. Confirm flags with cub <verb> --help before composing.
ConfigHub's AppConfig/* toolchains let the user keep config in its native format (devs read .properties like .properties, not wrapped YAML) while everything else still works: revision history, set-string-path / set-int-path / set-bool-path mutations, vet-jsonschema validation, variants / upstream-downstream, Needs/Provides. The render step ships it as a ConfigMap — either an immutable hashed one (Kustomize-style; old pods keep reading old ConfigMaps during a rolling update) or a mutable stable-named one (with a content-hash annotation on the pod template to trigger rolling restarts).
| Toolchain | File | When |
|---|---|---|
AppConfig/Env | .env | envFrom injection (pair with --as-key-value true on the Invocation); simple key=value. |
AppConfig/Properties | .properties | Java apps. |
AppConfig/YAML | .yaml | Most frameworks; full structured config. |
AppConfig/JSON | .json | Node / JVM apps that prefer JSON. |
AppConfig/TOML | .toml | Rust / Python apps. |
AppConfig/INI | .ini | Legacy apps. |
AppConfig/Text | .txt | Plain text; metadata in YAML frontmatter delimited by ---. |
Pick the format before creating the Unit — ToolchainType is set at Unit-create and not changeable afterward. Match what the app already reads.
Every AppConfig file carries two ConfigHub metadata fields — stripped when rendering the ConfigMap:
configHub.configName — unique name for this config file. Also becomes the ConfigMap data key (with the file suffix appended: MyApplicationConfig.ini).configHub.configSchema — a schema identifier, conceptually like a Kubernetes resource type. Used with vet-jsonschema, and as the first positional argument to set-*-path functions.Syntax by format: YAML/JSON top-level configHub: key; TOML/INI [configHub] section; Properties/Env dotted configHub.configName=...; Text YAML frontmatter under a configHub key. See the doc for side-by-side examples.
kubectl rollout restart.kubectl create configmap" / "like configMapGenerator" / "versioned ConfigMap.".env as container env vars via envFrom.vet-jsonschema).set-hash path below, no AppConfig Unit involved.ConfigMap YAML directly (use kubernetes-resources + cub-mutate) — fine for small static ConfigMaps with no rendering or history story. If such a ConfigMap does need to roll its workload, come back for set-hash.references/yaml-patterns.md).ConfigMaps — the chart already renders them; use import.cub auth status succeeds — it contacts the server's /me endpoint to confirm the token is still valid (not just local login state). If it fails, ask the user to run cub auth login (an interactive browser sign-in an agent cannot complete).confighub.com/Hash annotation). Default to immutable for workload-config-with-rolling-updates; mutable for simpler cases or when a single stable name matters.envFrom vs volume decided — .env with --as-key-value true is consumed via envFrom; other formats mount as a volume file.Include the two metadata fields. Example app.env:
configHub.configName=MyApplicationConfig
configHub.configSchema=SimpleApp
APP_NAME=MyApplication
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_SSL_ENABLED=trueAppConfig/Env treats all values as strings; the other formats (except AppConfig/Text) also support int and bool.
cub unit create --space <space> <config-slug> <file> --toolchain AppConfig/<Fmt> \
--change-desc 'Seed application config from reviewed file'ToolchainType is locked in here. Edit later with cub function set, not by re-creating (you'd lose history).
set-*-path takes the configSchema first, then the dotted path, then the value:
cub function set --space <space> --unit <config-slug> --toolchain AppConfig/Env -o mutations \
--change-desc 'Point DATABASE_HOST at prod' \
-- set-string-path SimpleApp DATABASE_HOST postgres.prod.internal
cub function set --space <space> --unit <config-slug> --toolchain AppConfig/Properties \
--change-desc 'Disable reviewed database SSL setting' \
-- set-bool-path SimpleApp database.ssl.enabled falseValidate against a registered schema (works for all AppConfig formats):
cub function vet --space <space> --unit <config-slug> --toolchain AppConfig/INI -- vet-jsonschemacub unit create --space <space> <configmap-slug>
cub link create --space <space> - <configmap-slug> <namespace-slug> # Needs/Provides fills the namespace placeholderOne Invocation per (toolchain, mode) combination. --immutable true (default) or --immutable false; add --as-key-value true for .env + envFrom:
cub invocation create --space <space> render-<fmt>-immutable AppConfig/<Fmt> render-configmap --immutable truecub link create --space <space> --wait - <configmap-slug> <config-slug> \
--update-type Upsert --auto-update \
--transform-invocation <space>/render-<fmt>-immutableThe render runs during link resolution — no runtime publication of the AppConfig Unit, worker, or Target is involved. Inspect the result:
cub unit data --space <space> <configmap-slug> # the rendered ConfigMap--auto-update re-renders the ConfigMap into <configmap-slug> whenever <config-slug> changes.
Upsert appends a new immutable ConfigMap each time upstream changes. Cap retention with a Mutation Trigger on the Space:
cub trigger create --space <space> prune-configmaps Mutation Kubernetes/YAML prune-configmaps \
--where-unit "ConfigHub.ResourceType = 'v1/ConfigMap'" --revision-history-limit 10It groups ConfigMaps by confighub.com/ResourceNameStableCore, keeps the newest (tagging the latest confighub.com/RenderRevision: Latest), removes the rest; mutable ConfigMaps are ignored.
cub link create --space <space> - <workload-slug> <configmap-slug>Immutable — name changes per revision; reference confighubplaceholder:
spec:
template:
spec:
volumes:
- name: config-volume
configMap:
name: confighubplaceholder # resolved to the latest hashed nameOptionally scope the workload→configmap link to the latest revision: --where-resource "metadata.annotations.confighub~1com/RenderRevision = 'Latest'" (~1 is the JSON-Pointer-like escape for /).
Mutable — stable name; a hash annotation drives rolling updates:
spec:
template:
metadata:
annotations:
confighub.com/Hash: confighubplaceholder # resolved to the content hash
spec:
volumes:
- name: config-volume
configMap:
name: <config-slug> # stable, no hash suffixenvFrom (either mode — confighubplaceholder immutable, stable name mutable):
spec:
template:
spec:
containers:
- name: main
envFrom:
- configMapRef:
name: confighubplaceholderAfter the host permits and the Skill verifies each wiring step, delivery uses a separate whole-Space release-publish call. This Skill owns the AppConfig/render/link/workload steps and their read-only postconditions, not publication.
set-hash)The rendering path above is for config that lives in an AppConfig Unit. When the user instead has a plain, mutable ConfigMap Unit they author and edit directly, and the problem is that changing it doesn't restart the Deployment that reads it, the answer is the same annotation the render path uses — just set by hand.
confighub.com/Hash is registered as a provided attribute on v1/ConfigMap and as a needed attribute on every workload's pod-template annotations, under the attribute name configmap-hash. So the wiring is: hash the ConfigMap, then let Needs/Provides copy the hash onto the pod template. A changed pod template is what makes Kubernetes roll the workload — the same trick a kubectl rollout restart performs manually, but driven by content.
cub function set --space <space> --unit <configmap-slug> \
--where-resource "ConfigHub.ResourceType = 'v1/ConfigMap'" \
--change-desc 'Hash ConfigMap contents for linked workload rollout' \
-o mutations \
-- set-hash dataset-hash <path> computes a SHA-256 over every value at <path> and writes the first 10 hex characters to metadata.annotations.confighub.com/Hash. For a ConfigMap the path is data. Scope it with --where-resource — set-hash matches any resource type, so an unscoped run in a Unit holding more than one resource hashes all of them.
It is hermetic and idempotent: identical content always yields the same hash, so re-running changes nothing. Re-run it after every edit to the ConfigMap — or, better, register it as a Mutation Trigger on the Space so the hash is never stale:
cub trigger create --space <space> hash-configmaps Mutation Kubernetes/YAML \
--where-resource "ConfigHub.ResourceType = 'v1/ConfigMap'" \
-- set-hash data--where-resource restricts which resources the Trigger's function touches; --where-unit would
restrict which Units it runs on. Confirm both against cub trigger create --help before composing.
Put a placeholder in the workload's pod template and link the two Units:
spec:
template:
metadata:
annotations:
confighub.com/Hash: confighubplaceholder # resolved to the ConfigMap's content hash
spec:
containers:
- name: main
envFrom:
- configMapRef:
name: <configmap-slug> # stable name; no hash suffixcub link create --space <space> - <workload-slug> <configmap-slug>Resolution replaces the placeholder with the hash. When the ConfigMap's data changes, the hash changes, the pod-template annotation changes, and the next publish rolls the workload.
Limitation: when a workload references more than one ConfigMap, each hash is propagated separately — combining several into one annotation is not yet supported. Say so rather than wiring something that silently drops one.
When to prefer the immutable render path instead: if old pods must keep reading the old config through the rollout, use render-configmap --immutable true (the default) from the loop above. Hashing a mutable ConfigMap replaces its contents in place, so a pod that restarts mid-rollout for any reason picks up the new config.
--change-desc where supported.kubectl create/edit configmap (bypasses ConfigHub), raw ConfigMap YAML in an AppConfig/* Unit (wrong toolchain), multiple schemas in one Unit (configSchema is one per Unit), rendering Secrets this way (use a SecretStore).ToolchainType is immutable post-create; migrating means a new Unit + relink. Call it out.configHub.configName / configHub.configSchema — stop; fix the file first.confighub-core or import first.cub unit data --space <space> <configmap-slug> — the rendered ConfigMap resource is present (immutable: hashed-name entries; mutable: one stable-named ConfigMap).cub unit data <configmap-slug> reflects it (auto-update re-rendered).kubectl get configmap -n <ns> shows the hashed name (immutable) or stable name (mutable); mutable-mode pod template confighub.com/Hash matches the ConfigMap's hash. Bind this runtime read to the Release/manifest through verify-apply.cub space open <space> --print-url — AppConfig Space.cub unit open <config-slug> --space <space> --print-url — AppConfig Unit.cub unit open <configmap-slug> --space <space> --revisions --print-url — rendered ConfigMap provenance.https://docs.confighub.com/markdown/guide/app-config.md — canonical walkthrough (Upsert path + legacy path).references/cub-cli.md — --change-desc / -o mutations / four Unit views.references/yaml-patterns.md — confighubplaceholder + Needs/Provides receivers.references/functions-catalog.md — set-string-path / set-int-path / set-bool-path / vet-jsonschema / render-configmap / prune-configmaps / set-hash.kubernetes-resources (raw-ConfigMap authoring), confighub-core (Links / Needs-Provides doctrine), cub-mutate (bulk AppConfig edits), triggers-and-applygates (the set-hash Mutation Trigger), release-publish (whole-Space OCI Release proposal), verify-apply (post-release checks).ba61249
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.