ソース情報
- リポジトリ
- leroyguillaume/claude
- ソースの最終更新活動
- 2026年7月27日 12:36
- 検出された SKILL.md の言語
- 英語
- スター
- 4
- フォーク
- 2
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/leroyguillaume/claude --skill helm-conventionsコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
SKILL.md を表示中
SOC 職業分類に基づく
| name | helm-conventions |
| description | Helm chart conventions (values structure, security context, |
Always:
extraEnv, extraVolumes, and extraVolumeMounts in values.yaml
with empty defaults ([]) and wire them into every relevant workload
template (Deployment, StatefulSet, Job, etc.).values.yaml, defaulting to
a restricted profile aligned with Kubernetes Pod Security Standards:
podSecurityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
The IDs must be > 10000 (Trivy KSV-0020 / KSV-0021: a low container
UID collides with the host's user table). 65532 is the nonroot UID used
by distroless and Chainguard images — keep it in sync with the USER baked
into the image (see docker-conventions), otherwise a
readOnlyRootFilesystem pod hits permission errors on its own state
directory.templates/ with one Kubernetes object per file, and
derive every filename from the object's kind in kebab-case (split
CamelCase on word boundaries, replace spaces with hyphens, lowercase —
e.g. ClusterRoleBinding → cluster-role-binding.yaml,
MutatingWebhookConfiguration → mutating-webhook-configuration.yaml).
How files are grouped depends on how many objects a component renders:
templates/<component>/ (matching its values.yaml
block), with one kind-named file per object — e.g.
templates/api/deployment.yaml, templates/api/service.yaml.templates/<component>/<kind>/<qualifier>.yaml. The directory carries
the Kind, so each file is named by its distinguishing qualifier only —
e.g. four Secrets become templates/api/secret/database.yaml,
.../jwt.yaml, .../oidc.yaml, .../bootstrap-admin.yaml. This is
Kind-agnostic: it applies equally to multiple Services
(templates/api/service/grpc.yaml, .../http.yaml), ConfigMaps,
Jobs, etc. A Kind with a single instance in that component stays flat
as templates/<component>/<kind>.yaml (one Service → service.yaml,
not service/http.yaml).Ingress, a Gateway route, or a database
Cluster — gets no directory: put the file at the root,
templates/<kind>.yaml (e.g. templates/ingress.yaml,
templates/http-route.yaml, templates/cnpg-cluster.yaml). Qualify
the bare Kind with the component name when the Kind alone would be
ambiguous (the generic Cluster → cnpg-cluster.yaml).
Never place one component's template under another component's directory.ServiceAccount (and its own
ClusterRole + ClusterRoleBinding, in separate files, when it needs
cluster RBAC) so components stay least-privilege and independent.values.yaml. This applies to
Gateway API and Envoy (AI) Gateway: create the MCPRoute / HTTPRoute /
GRPCRoute, but never the Gateway or GatewayClass. Make the
gateway name required (required in the template / helper) so the
chart fails fast when it is missing, and default the gateway namespace to
the release namespace. The Gateway and GatewayClass are
cluster-shared infrastructure owned outside the app chart.values.yaml as exactly two kinds of top-level blocks: a
global: block holding values shared by more than one component, plus
one <component>: block per app/component holding that component's
own values. As soon as a knob is needed by two or more components,
it must live in global: at the top level — never duplicated across
the component blocks, and never moved into one component's block
"because that's where it's mostly used". Conversely, values used by a
single component live only in that component's block. Every global.*
key must be overridable per component by setting the same key in
that component's block (resolve via a deep-merge helper:
mergeOverwrite (deepCopy global) (pick component …)), so a component
can deviate from a shared default without forcing the value to move
out of global.global: or a
component), when more than one key relates to the same domain
(database, OIDC, TLS, signing keys, a sidecar, …), nest them under a
single object named for that domain instead of leaving a flat run of
prefixed scalars. Drop the now-redundant prefix from each sub-key —
the object name carries it. For example, prefer
database:
# -- (string) Connection string. Unset → built from the managed cluster.
url: ~
existingSecret:
# -- (string) Name of a pre-existing Secret holding the connection string. Set → takes precedence over the generated one.
name: ~
# -- Key in that Secret holding the connection string.
key: DATABASE_URL
# -- Maximum size of the connection pool.
maxConns: 25
# -- Minimum number of idle pooled connections.
minConns: 5
over the flat databaseUrl / databaseUrlSecret / dbMaxConns /
dbMinConns. A lone key for a domain stays flat — only group once the
second related key appears (the rule of two for grouping). The object's
shape still maps cleanly onto its env vars / flags at the template
boundary (e.g. database.maxConns → DATABASE_MAX_CONNS); grouping is a
values.yaml ergonomics rule, it does not change the wire/env contract.existingSecret value is always an object { name, key }, never a
bare string. Whenever a chart lets the user point at a pre-existing
Secret instead of generating one, model it as a nested object: name
(default ~ — unset means "generate the Secret from the inline value")
and key (the entry to read, defaulting to the same key the generated
Secret would use, e.g. DATABASE_URL / UPSTREAM_HEADERS). A bare
existingSecret: ~ string hardcodes the key and cannot consume a Secret
whose entry is named differently — which is exactly the case
pre-existing Secrets (sealed-secrets, External Secrets, cloud-synced
ones) hit. Wire it through two template helpers — a …SecretName (the
existing name, else the generated name) and a …SecretKey (the
existing key, else the generated default) — and reference both in the
secretKeyRef. Gate the generated-Secret template and any
checksum/… annotation on not .Values.<path>.existingSecret.name.caCerts override for any workload that makes outbound
TLS connections (calling an upstream API, an S3/object-store endpoint, an
OIDC/JWKS server, fetching a document, …). Users behind a corporate MITM
proxy or with a private CA need to add a trust anchor without rebuilding the
image. Model it like an existingSecret: an inline bundle that generates a
Secret, or an existing resource the user already manages — and crucially
allow that existing resource to be a ConfigMap (the natural home for
non-secret public CA certs) as well as a Secret:
# -- Extra CA certificates to trust for every outbound TLS connection. Added
# on top of the built-in public roots — supply only your private/corporate CA.
caCerts:
# -- (string) Inline PEM bundle. Stored in a Secret and mounted. Ignored when `existing.name` is set.
inline: ~
# -- Mount the PEM bundle from a resource you already manage, instead of `inline`. Takes precedence over `inline` when `name` is set.
existing:
# -- (string) Kind of the resource: `ConfigMap` or `Secret`.
kind: ConfigMap
# -- (string) Name of the resource. Set → mounts from it instead of generating a Secret from `inline`.
name: ~
# -- Key in the resource holding the PEM bundle (also the mounted file name).
key: ca-certificates.crt
Wire it through helpers mirroring the existingSecret pattern —
caCertsEnabled (inline or existing set), caCertsValidate (fail fast if
existing.kind is neither ConfigMap nor Secret), caCertsFromConfigMap,
caCertsGenerateSecret (inline and no existing), caCertsSecretName,
caCertsKey, and a caCertsPath for the mount. Gate the generated Secret
and the checksum/ca-certs pod annotation on caCertsGenerateSecret; the
volume picks vs from . — match the language/SDK: Python → ,
, and (boto3); Go → ;
Node → ; a Rust/other app that reads its own var → that
var. Honour the established standard name; never prefix it with the app name.rules (and an appended extraRules: []) in values.yaml,
not hardcoded in the ClusterRole template.values.yaml with a helm-docs # --
annotation immediately above it — no value is allowed to ship
undocumented, including nested keys and empty defaults ([], {},
~). The comment must describe what the value does, not just restate
its name.values.yaml, use ~ (YAML
null) rather than an empty string, a placeholder, or omitting the
key. For an empty collection, use {} for an unset dict and []
for an unset list — never ~ for those, so the consumer knows the
shape they are overriding. Whenever the default is ~, {}, or [],
helm-docs cannot infer the type from the value, so you must
annotate it explicitly with # -- (<type>) … (e.g. (string),
(int), (bool), (object), (list), (tpl/string)). Examples:
# -- (string) Optional override for the image tag. Defaults to `.Chart.AppVersion`.
imageTag: ~
# -- (object) Extra labels merged into every workload's pod template.
extraPodLabels: {}
# -- Extra environment variables to inject into every workload.
extraEnv: []
# -- Pod-level security context applied to all workloads.
podSecurityContext:
# -- Run all containers as a non-root user.
runAsNonRoot: true
norwoodj/helm-docs pre-commit hook (or a local hook invoking
the installed helm-docs binary) to .pre-commit-config.yaml. The hook
must regenerate the chart README.md from values.yaml and fail when
the regenerated file differs from the committed one, so an undocumented
or stale value blocks the commit. Likewise, any generated manifest
committed to the chart (e.g. a CRD) must have a pre-commit hook that
regenerates it and fails if it was out of date.helm lint hook in .pre-commit-config.yaml (local hook) that
runs against every chart directory. If lint needs placeholder values,
keep them in a values-lint.yaml passed with -f and excluded from the
packaged chart via .helmignore — never bake them into values.yaml.podSecurityContext /
securityContext shown above is the baseline; do not ship a chart that
weakens it.trivy config and fix every KSV-xxxx
finding. The KSV checks are the reference for what a hardened workload
looks like (KSV-0020/KSV-0021 UID/GID > 10000, KSV-0003 drop
capabilities, KSV-0014 read-only root filesystem, KSV-0030 seccomp,
KSV-0125 trusted registry, …). Treat them as errors, fix at the source,
and — same rule as hadolint and image scanning — never add a
.trivyignore or an inline ignore on your own initiative. Wire it into CI:
trivy config --exit-code 1 --helm-values charts/<chart>/values-lint.yaml charts/<chart>
Two traps worth knowing:
required value or fail in a template silently
disables the whole scan — the CI job goes green having checked nothing.
That's why a dedicated values-lint.yaml supplying the required values is
part of the chart, and why CI should assert the report is non-empty rather
than trusting the exit code.KSV-0011 (resources.limits.cpu) — see the resources rule below;
CPU limits cause throttling and we intentionally omit them.KSV-0110 (metadata.namespace is default) — a chart takes its
namespace from helm install --namespace; hardcoding it in templates is
the actual anti-pattern.
Both are documented, chart-wide exceptions agreed up front — not a licence
to silence the next finding that's inconvenient.resources.requests for CPU, memory, and ephemeral
storage, and resources.limits for memory and ephemeral storage
only. Memory and ephemeral storage are non-compressible and must be
capped to protect the node; CPU is compressible and a limits.cpu
causes unnecessary throttling, so leave CPU unlimited. Every workload
must declare all five values — requests.cpu, requests.memory,
requests.ephemeral-storage, limits.memory,
limits.ephemeral-storage. Example default:
resources:
requests:
cpu: 50m
memory: 64Mi
ephemeral-storage: 64Mi
limits:
memory: 128Mi
ephemeral-storage: 256Mi
revisionHistoryLimit on every workload that keeps a
rollout history — Deployment, StatefulSet, DaemonSet,
ReplicaSet. Expose it as a documented key in the component's
values.yaml block (default 3) and reference it from the template;
never hardcode it and never leave it out. Kubernetes defaults to 10,
so an unset field silently piles up ten stale ReplicaSets per workload
— noise in kubectl get rs, and etcd objects nobody will ever roll back
to. Three is enough history for a realistic rollback.
# values.yaml
# -- Number of old ReplicaSets the Deployment keeps for rollback.
revisionHistoryLimit: 3
# templates/<component>/deployment.yaml
spec:
replicas: {{ .replicaCount }}
revisionHistoryLimit: {{ .revisionHistoryLimit }}
The equivalent knobs on other kinds are not this field and are not
covered by this rule: a CronJob uses
successfulJobsHistoryLimit / failedJobsHistoryLimit, and a Job has
no history at all.Never:
values.yaml without a helm-docs # -- comment
above it, and never ship a chart whose README.md is out of sync with
values.yaml — the helm-docs pre-commit hook must catch both.null, "", or a placeholder string
— use ~ for a scalar, {} for a dict, [] for a list. Whenever the
default is ~, {}, or [], never omit the # -- (<type>) … type
hint, otherwise the generated README.md shows no type at all.databaseUrl,
databaseUrlSecret, dbMaxConns, …) when two or more keys share a
domain — nest them under a domain object (database: { url, … }) and
drop the redundant prefix.values.yaml — promote it to global: instead.templates/<component>/ directory for a component that
renders only one object — put it at templates/<kind>.yaml at the root.
Conversely, never leave two-or-more objects of the same Kind
ungrouped at a component's top level — nest them in a
templates/<component>/<kind>/ subdirectory. Never mix two components'
objects under one <component>/ directory.extraEnv / extraVolumes / extraVolumeMounts.caCerts override, never restrict the existing CA source to Secret only
(a ConfigMap must be accepted for public CA certs), and never point at the
bundle with an invented env var when the app's runtime already honours a
standard one (SSL_CERT_FILE, AWS_CA_BUNDLE, NODE_EXTRA_CA_CERTS, …).Gateway or GatewayClass from an application chart —
these are shared cluster infrastructure. Create only the route
( / / …) and attach it to an existing, named
gateway.configMap:secret:caCertsFromConfigMapSSL_CERT_FILEREQUESTS_CA_BUNDLEAWS_CA_BUNDLESSL_CERT_FILENODE_EXTRA_CA_CERTSMCPRouteHTTPRouteDeployment / StatefulSet / DaemonSet / ReplicaSet
without revisionHistoryLimit, and never hardcode it in the template
instead of exposing it in values.yaml — the Kubernetes default of 10
leaves a heap of dead ReplicaSets behind every rollout.resources.limits.cpu. Memory and ephemeral-storage limits
only.requests.cpu, requests.memory,
requests.ephemeral-storage, limits.memory, or
limits.ephemeral-storage — workloads without requests are best-effort
QoS and will be evicted first under pressure, and an unbounded
ephemeral-storage write can fill the node disk.