internals/skills/skills/SKILL.md
Skill maintenance guidelines: when and how to update skills, CLAUDE.md, and README.md. Use when updating documentation, feeding back operational insights, or auditing skill coverage.
npx skillsauth add overthinkos/overthink-plugins skillsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Skills are living documents at plugins/<plugin>/skills/<name>/SKILL.md. They are the primary knowledge source for Claude Code — always invoked before codebase exploration. This skill covers when and how to update them.
The trigger → skill dispatcher is the table in CLAUDE.md "Skill Dispatcher"
(Part I, immediately after R0) — the SOLE copy, deliberately mirrored nowhere
(duplication drifts). When multiple triggers apply, load ALL matching skills
in ONE message (parallel Skill calls). Full index: plugins/README.md.
| Trigger | Action |
|---------|--------|
| Deployment step fails or needs undocumented workaround | Update the relevant /charly-core:*, /charly-build:*, /charly-check:*, /charly-automation:*, kind plugin (/charly-image:*, /charly-vm:*, /charly-kubernetes:*, /charly-local:*, /charly-pod:*), per-pod plugin (/charly-jupyter:*, /charly-coder:*, …), or split-foundation plugin (/charly-distros:*, /charly-languages:*, /charly-infrastructure:*, /charly-tools:*) |
| Verification check missing from image skill | Add to the image skill's Verification section |
| Skill's recommended defaults are wrong | Fix in the skill, not CLAUDE.md |
| New feature added to charly CLI | Update /charly-core:<cmd> or /charly-build:<cmd> skill + /charly-internals:go source map |
| New candy or box added | Create skill via charly box new candy scaffold or manual SKILL.md |
| Bug fix changes behavior | Document the fix in affected skills |
| Cross-skill behavior discovered | Update Cross-References in all affected skills |
| A doc / skill / comment diverges from observed reality (discovered by ANY means — not only a bed or a deleted identifier) | Treat as an incident (R1): RCA it, then sweep EVERY sibling doc/skill/comment carrying the same false/outdated/misleading claim and fix them all in the CURRENT cutover (blocking, R2). The two rows below are special cases of this |
| A live bed contradicts a skill's claim (Risk Driven Development found it stale) | Fix the stale skill in the SAME change — RDD keeps the living docs honest; for a high-risk claim the running system is ground truth, not the doc |
| Removed identifier still referenced in skill paragraph (R5 self-test failed) | Update / delete the paragraph in the SAME commit as the removal (R5) |
| CLAUDE.md heading / R-number / clause name changes (they are a public API) | Sweep every mirroring surface in the SAME commit — see "Mirroring surfaces" below (R5) |
| Rule DETAIL accretes inside CLAUDE.md (matrix, catalog, worked example growing in place) | Move the detail to its owning skill (see the Authoritative-copy registry); CLAUDE.md keeps the mandate + a *Detail:* pointer |
CHANGELOG/ (one file per calendar month, YYYY-MM.md), NEVER a skill or CLAUDE.md. Skills describe current behavior in present tense only. When a cutover lands, append its narrative to the current month's CHANGELOG/YYYY-MM.md and state the new standing rule forward-looking in the skill, with no history.plugins/<plugin>/skills/<skill-name>/SKILL.md---
name: <skill-name>
description: |
One-sentence description of when to invoke this skill.
For layers: "Use when working with <component>."
For images: "MUST be invoked before building, deploying, or troubleshooting the <image> image."
---
# <Title>
## Overview / Properties
## Key Sections (varies by type)
## Cross-References (related skills)
## When to Use This Skill
| Content type | Where it belongs |
|-------------|-----------------|
| Project philosophy, architecture, key rules | CLAUDE.md |
| Command usage, flags, examples | /charly-core:<cmd> or /charly-build:<cmd> skill |
| Layer properties, packages, ports | per-pod plugin (/charly-jupyter:<name>, /charly-coder:<name>, …) or split-foundation plugin (/charly-distros:*, /charly-languages:*, /charly-infrastructure:*, /charly-tools:*) for base layers |
| Image composition, deployment, verification | per-pod plugin or /charly-distros:<name> / /charly-infrastructure:<name> for base images |
| Skill disambiguation (which skill to use) | CLAUDE.md R0 "Skill Dispatcher" (the sole copy; never mirrored) |
| Detailed operational patterns | Relevant /charly-core:* / /charly-build:* / /charly-check:* / /charly-automation:* / kind-plugin skill |
| Hard rule / gate / mandate (the WHAT and the MUST) | CLAUDE.md — stated ONCE, in mandate form, with a *Detail:* pointer |
| Operationalization / matrix / catalog / worked example (the HOW) | The ONE owning skill (see the Authoritative-copy registry below) |
| Version history / past changes / renames / cutover narration | the repo's CHANGELOG/ (monthly YYYY-MM.md) — never CLAUDE.md or a skill |
| Long-term thesis / vision / aspiration ("why & where it's going") | VISION.md (repo root) — never restating command usage, architecture, or history |
The canonical split for every rule: CLAUDE.md states the rule ONCE, in
mandate form (≤ a few lines), and points at exactly ONE owning skill via a
*Detail:* pointer; the owning skill carries the operationalization —
forbidden-pattern catalogs, decision matrices, worked examples, command
sequences. Every other document links to the owner and NEVER restates it
(restated copies drift; the linked original cannot).
Named exceptions where CLAUDE.md itself is the canonical copy (skills link TO it, never duplicate it): the Skill Dispatcher table, the canonical RDD and ADE definitions (strict-policy operationalizes them but the definition lives in CLAUDE.md), the Acceptance checklist, and the AI Attribution tier table.
| Matrix / catalog / definition | Sole owner |
|---|---|
| "R10 gate by change class" matrix (incl. the class → gate → tier cross-walk) + "Flag discipline" catalog | /charly-check:check |
| R1–R5, RDD, ADE operationalization (forbidden patterns, risk table, worked examples) | /charly-internals:strict-policy |
| Hard-cutover workflow, forbidden patterns, deliverables | /charly-internals:cutover-policy |
| disposable: / preemptible: flag semantics, "What counts as an R10 run" | /charly-internals:disposable |
| Landing mechanics (branch loop, multi-repo order, CalVer tags, PR path) | /charly-internals:git-workflow |
| Agent/workflow/team primitives, hooks doctrine | /charly-internals:agents |
| Skill Dispatcher, RDD/ADE definitions, Acceptance checklist, attribution tiers (incl. documentation reviewed), Documentation-only change class anchor, Key Rules index | CLAUDE.md |
CLAUDE.md's section headings, R-numbers, and named clauses ("flag-override clause", "gate by change class", "Documentation-only change class", "documentation reviewed" tier, "Acceptance checklist", "Post-Execution Policies", …) are a public API. These surfaces reference them and MUST be swept in the SAME commit as any rename or removal (R5):
.claude/hooks/ (runtime-verification-reminder.sh,
end-of-turn-challenge.sh, team-coordination-reminder.sh,
pre-commit-gate.sh, pre-push-gate.sh),plugins/internals/agents/*.md,CLAUDE.md files (charly/, candy/,
plugins/, each box/<distro>),.claude/workflows/*.js,The sweep test: grep -rn '<old phrase>' across the superproject + submodules
returns only CHANGELOG/ context afterwards. Prefer keeping headings and
clause names STABLE when rewording content — a stable name keeps every
mirroring surface valid for free.
Most skills under plugins/charly-core/skills/ and plugins/charly-build/skills/
map 1:1 to a top-level charly command (e.g. /charly-build:build ↔ charly box build,
/charly-core:charly-status ↔ charly status).
Topic skills are the exception: they don't correspond to a
top-level command but cover a cross-cutting concept surfaced by flags
or layer composition. Today's topic skills:
| Skill | Surfaced via | What it covers |
|---|---|---|
| /charly-automation:enc | charly config --encrypt, charly config mount, charly config unmount, charly config passwd | Encrypted-volume (gocryptfs) semantics, keyring resolution, charly-enc-<image>-<volume>.scope lifecycle |
| /charly-automation:openclaw-deploy | Composing openclaw-* layers | OpenClaw AI gateway deployment story |
| /charly-automation:sidecar | charly config --sidecar tailscale | Sidecar-container model, pod networking, env-var routing |
When adding a new command, always create a matching command skill. Consider a topic skill when a concept spans multiple commands or layers and the natural home isn't any single command's skill. Keep the frontmatter description: explicit about the topic nature (the blocking Skill: tool dispatcher matches on description keywords).
Plugins are sorted into four use-case buckets. Directory names live at
plugins/<name>/ (no charly- prefix); plugin.json name: fields keep the
charly- prefix; every skill is invoked as /charly-<plugin>:<skill>.
The authoritative per-plugin skill counts and purposes are the bucket tables
in plugins/README.md — point there, never copy them (counts drift).
plugins/<plugin>/agents/<name>.md)Sub-agents are markdown + YAML frontmatter (name, description, tools,
model, …), discovered from a plugin's agents/ directory (currently only
charly-internals/agents/). Plugin-loaded agents IGNORE the hooks,
mcpServers, and permissionMode frontmatter fields — keep those out of
plugin agents (use .claude/agents/ or settings.json if you genuinely
need them). The charly roster splits into enforcers (root-cause-analyzer,
layer-validator, testing-validator — gate claims) and executors
(check-bed-runner, deploy-verifier — drive charly check and return verbatim
proof). Full story: /charly-internals:agents. Dynamic workflows are NOT plugin
content — they live in the superproject's .claude/workflows/*.js.
The repo-root CLAUDE.md is the single canonical R0–R10 rule-set.
Per-directory CLAUDE.md files (charly/, candy/, plugins/, and each
box/<distro> submodule) are THIN signposts only: they name the skills to
load for that area and point back to root. They MUST NOT restate any rule body —
duplication drifts (an earlier layer-validator and the reminder hooks both drifted
exactly this way; the reminder hooks now name rules as pointers/triggers, never
restating their bodies). Subagents and teammates load the full CLAUDE.md
hierarchy from their working directory, so a signpost reaches a worker scoped
to that subtree without bloating root.
The project uses two complementary sync mechanisms with .gitignore as the
boundary:
| What | Synced by | Visibility |
|------|-----------|------------|
| Code, CLAUDE.md, skills, layers, images | Git | Public (committed) |
| .claude/memory/ (auto-memory) | Syncthing | Private (gitignored) |
| .claude/settings.local.json (personal overrides) | Syncthing | Private (gitignored) |
| .claude/settings.json (project policy) | Git | Public (committed) |
Memory setup: autoMemoryDirectory: ".claude/memory" in
.claude/settings.local.json. Both settings.local.json and memory/
propagate via Syncthing so your working state follows you across machines
without polluting the public repo.
Rule of thumb: if it's useful to every contributor, it lives in git (skills, CLAUDE.md, code). If it's useful only to you, it lives in the Syncthing-synced half (memory, personal settings).
Many skills carry a source map of the Go code — Source: frontmatter, file-listing
tables (| charly/foo.go | … |), and inline identifier references (type/function names).
These silently desync when the code is refactored (a renamed file or symbol that no
skill's grep self-test caught). Audit and fix them as follows:
charly/*.go filename reference and identifier
reference out of the skills, and check each against the live source — file exists?
symbol still defined? (gopls/grep confirm.)plugins/ is a git submodule, so a superproject
git grep -- plugins is a FALSE ZERO (git grep does not cross the gitlink). Use
git -C plugins grep or filesystem grep -rn.pkg.go.dev, dl.google.com → matches .go),mcp.go contains p.go; localpkg.go contains pkg.go),storage_dest.go),deprecated.go as a thing to avoid).git -C plugins grep '<claim>' returns only
CHANGELOG context afterwards.documentation reviewed (no beds); plugins commit → superproject pointer bump → CalVer
tag (plugins is tag-exempt). See /charly-internals:git-workflow.The code-side companion (golangci-lint, the .go compliance checklist) is
/charly-internals:go-quality.
/charly-internals:go — Source code structure, adding new commands/charly-internals:generate-source — Understanding generated Containerfiles/charly-internals:agents — Sub-agents, dynamic workflows, agent teams; how they drive the charly check beds; the hooks doctrine; the signpost convention/charly-build:validate — Validation rules/charly:* skills — Individual command documentationInvoke when updating documentation, creating new skills, auditing skill coverage, or deciding where new information belongs (CLAUDE.md vs skill vs memory).
tools
Use when authoring or modifying a charly PLUGIN — a candy with a `plugin:` block that contributes Providers (verbs/kinds/deploy-targets/steps/builders/commands), its own CUE schema, builtin (compiled-in) or external (out-of-tree git repo). Covers the unified Provider model, the per-plugin CUE-schema contract (single source → Go params for dev + schema-over-Describe RPC for runtime), the SDK, and the loader.
tools
The CUE data-validation / configuration CLI (cue), pinned to v0.16.1. Use when working with the cue candy, installing the cue binary into a box or onto a target:local dev host, or running the offline schema-vendoring pipeline that feeds charly's egress validation.
tools
CUE EGRESS validation — validating (and, where it adds value, generating) the config files charly WRITES to a system BEFORE the bytes hit disk. MUST be invoked before working on charly/egress.go, the vendored schemas under candy/plugin-egress/egress-schemas/vendor/, the ValidateEgress / registerVendoredEgressKind path, the offline `task cue:vendor` pipeline, or adding an egress schema for any written artifact (cloud-init, k8s manifests, traefik routes, runtime config, install ledger, systemd/quadlet units, ssh_config, libvirt XML).
tools
Kubernetes cluster-probe declarative check verb — the `kube:` check verb (nodes, pods, ingress, storage class, addon health, apply/delete, and arbitrary resource GETs) served out-of-process by the candy/plugin-kube plugin (vendored client-go; no external kubectl required).