ptr727/plexcleaner/skill-lifecycle
Claude Code and agent skill by ptr727/plexcleaner
- community
Checking that the SKILL.md file is still in the repository.
Governs the lifecycle of the fleet's own skills in ptr727/ProjectTemplate. It covers creating, changing, splitting, and retiring a skill under .agents/skills/. It covers the source-versus-generated split with .github/skills/ and .claude-plugin/. It covers the regenerate and --check semantics of scripts/build_dist.py. It covers the include regions that scripts/build_dist.py fills from a rule's home so a skill carries the rule's text without a copy. It covers the install and stamp semantics of scripts/skills_install.py. It covers the doc-packaging pattern that keeps a law doc and its skill in agreement. It covers the trigger-description conventions that make a skill fire. Use this whenever about to create, edit, move, or delete anything under .agents/skills/, .github/skills/, or .claude-plugin/. Use it also whenever packaging a doc or a doc section as a skill, and whenever deciding whether a topic deserves a skill at all. Triggers even when the edit looks trivial, such as fixing a typo in one SKILL.md. That is because the generated distributions desync the moment the source changes without a build_dist.py run. It is also because CI fails the pull request on exactly that. Hub-context only, since .agents/skills/ exists only in the hub.
Install
npx vskill@latest install ptr727/plexcleaner/skill-lifecycleSKILL.md
Skill Lifecycle
Why This Exists
The agent most likely to get a skill wrong is the one editing a skill. Before this skill existed nothing watched that moment. The regenerate and install semantics lived in scripts/ docstrings and scattered prose, so the procedure was rediscovered per session. The standing hazards are mechanical and silent. A hand-edit to the generated .claude-plugin/ tree is overwritten by the next regenerate. A source edit without a regenerate ships a plugin that no longer matches its source. The CI --check gate fails that mismatch rather than anyone noticing it in review.
The Pipeline
- `.agents/skills/<name>/SKILL.md` is the only tree a skill is authored in, with optional
references/andscripts/directories beside it. The one part of that tree not written by hand is the text inside an include region, described below. Codex and opencode read this tree directly, project-local, and also read the global~/.agents/skills/copy the installer materializes. - Generated distributions serve GitHub Copilot and Claude Code.
scripts/build_dist.pygenerates.github/skills/for GitHub Copilot and a Claude-plugin-compatible copy at.claude-plugin/fleet-skills/, published through.claude-plugin/marketplace.json. No generated tree is hand-edited, andbuild_dist.py --checkexits non-zero when any tree differs from.agents/skills/. - The skill set is implicit. Every
.agents/skills/<name>/directory carrying aSKILL.mdis a skill. The generatedplugin.jsonderives its list from those directories, so adding or retiring a skill edits no manifest by hand.marketplace.jsonnames the plugin, not the skills, and is untouched by ordinary lifecycle work. - A rule's text reaches a skill as a generated include, never as a copy. A region is opened by a line holding only
<!-- include: <path> > <heading> -->and closed by a line holding only<!-- /include -->, each indented at most three spaces.build_dist.pyfills it with the body under that heading. The key is the root-relative path, spelled as the tree spells it, then>, then the heading text at any level from two, matched case-insensitively. The body runs to the next top-level#heading at that level or above, level one included. So a key naming a level-two heading carries every subsection under it. The fill lands in.agents/skills/itself, since Codex and opencode read that tree directly. Another reason is that a region left empty there is a skill with a hole in it. The generated trees mirror the filled source. A region is filled only in a file the generator walks. Those are the*.mdfiles under each.agents/skills/<name>/directory carrying aSKILL.md, plus the filesbuild_dist.py'sINCLUDE_DESTINATIONStuple declares. A Markdown file sitting in.agents/skills/but not under such a directory is walked no more than a file elsewhere is..agents/skills/README.mdis one such file. That tuple is how a hub surface that is not a skill carries a rule's text rather than restating it. Each entry is declared by hand and held to the same path rules a source is held to. A filespec/files.jsoncarries content from is refused as a declared entry. The tuple is empty today because the surfaces that would qualify restate a rule in their own words rather than copying it. It is empty also because a pointer is what each of those needs. Because the tuple is empty,tests/test_build_dist.pyrather than any shipped declaration is where the shape of one is exercised. A source is any regular file under the repository root outside the two generated trees and reached through no symlink. So a key may name aGOVERNANCE.mdsection, anAGENTS.mdsubsection, or a section of a sibling skill. A region filled from a file carrying regions of its own reads that file's filled text. Regenerating after a source edit changes the bytes of every skill unit including it, and--checkfails the pull request until that regenerate runs. Those units then read as moved past the pass that covered them, which is the periodic sweep's work rather than this change's, perGOVERNANCE.md"Verification Discipline". - `--check` holds every region to its source. It fails when a region differs from what its source renders now. So a hand edit inside one and a source edit nobody regenerated for both fail the pull request the same way a stale mirror does.
uv run --no-project --script scripts/build_dist.py, with no flag, is what clears either. A failure regenerating cannot repair is exit 2 rather than 1, whether or not a region is what it is about: - a key with no
>or an empty heading - a path naming no file
- a heading that no longer resolves or that recurs in its source
- a body with nothing in it or leaving a code fence open
- a region in a file the generator does not walk, reached through a key
- a declared destination refused by the same path rules a source is held to, or carried by the manifest
- a
spec/files.jsonthat cannot be read or parsed while a destination is declared, since a check that cannot run must not wave one through - a symlink at or under a skill's own directory
- a region that opens inside another or never closes
- a close marker with no region open
- a cycle
- a path that is empty, absolute, carries a
..component, or is spelled otherwise than the tree spells it - a path outside the root, through a symlink, or under a generated tree
- a file that is not UTF-8 wherever the run decodes one
- a file holding a region while mixing line endings
- a line outside a code block that begins like a marker and matches neither form, which read as content would leave a region unfilled
An unreadable file is exit 2 as well, and it is the one cause that is not a refusal. --check catches the operating system's own error beside the refusals. So a permissions failure or a file removed mid-run is reported rather than read as a stale result. Every code here is --check's. The no-flag run reports a refusal as exit 1.
- `scripts/skills_install.py`, run from a hub checkout, installs each form per machine: an overlay copy into
~/.agents/skills/for Codex and opencode. The copy is marked per skill so a retired skill is removed on the next run and a foreign skill is never touched. The other form is a user-scope plugin install for Claude Code via theclaudeCLI. Each run stamps the hub commit into~/.agents/skills-install-stamp.json.--reportanswers each channel separately. One answer is which commit the copy was taken from, judged against the promotedmain. The other is which branch and commit the checkout Claude Code loads in place is serving now.--reportexits non-zero when the copy is not current. The install is global per user, and per-repo pinning is a settled non-goal (docs/fleet-map.md"Skills Install Model").
Deciding a Topic Deserves a Skill
A skill surfaces at a trigger moment. A rule that binds every action all the time, or a short reference section a task reads once, gains nothing from being one. The always-on layer is the carried instruction set (AGENTS.md and the sections it maps). Packaging such a rule or section as a skill duplicates it and spends the tokens the delegation rules exist to save. The AGENTS.md "Where the Rules Live" map records the disposition either way, a skill annotation on the row or the deliberate absence of one. So a topic with no skill reads as a decision rather than an oversight.
Creating a Skill
- Name the directory in kebab-case and set the frontmatter
name:to the same string. - Write the `description:` to carry the trigger, since it is the only part an agent reads before deciding to load the skill. State what the skill governs, then the concrete moments it applies ("Use this whenever..."). Then state the routine phrasings that precede the failure it guards against ("Triggers even when..."), naming a real incident where one exists. Disambiguate against sibling skills by name, the way
standup-a-repo,resync-a-repo, andcheck-this-repoeach state which of them a session is in. - Author the body per the `comment-and-doc-style` skill: LF (the repo default), present tense, ASCII tiers, no semicolon in prose. Name hub paths as plain code spans rather than repo-relative links, because an installed copy resolves no repo path. Say "from a hub checkout" for anything the reader must run.
- Split bulk into `references/` when the source doc is large: the SKILL.md carries the summary and the binding rules. Each
references/*.mdcarries one topic read on demand. That split is the shapecomment-and-doc-styleuses. - Apply the doc-packaging pattern below in the same change when the skill packages a law doc or one of its sections.
- Regenerate and commit all trees together:
uv run --no-project --script scripts/build_dist.py, then, once authorized, commit the source and the generated trees in one commit, pergit-commit-conventions. CI runs--checkon every pull request and fails a desynced distribution.uv run --no-project --with-requirements tests/requirements.txt python tests/test_build_dist.pycovers the generator itself. - Record the surfacing: annotate the
AGENTS.md"Where the Rules Live" row when the skill packages a GOVERNANCE section. Annotate the closing paragraph of theAGENTS.md"Where the Rules Live" section when the skill is new content. Each annotation exists so the map stays the one place coverage is read from. - Refresh the machines after promotion, per machine, as
docs/host-setup.md"Fleet Skills Install" states. Until then each machine's Codex and opencode copy holds the previous skill set, which--reportsays, while Claude Code serves whatever the hub checkout holds.
Changing or Retiring a Skill
- Edit only the source tree, and outside its include regions. Any skill-content change under
.github/skills/or.claude-plugin/that did not come from abuild_dist.pyrun is a defect, whatever it fixes. The text inside an include region is generated too. So a change there is made at the region's source and regenerated, never typed into the region. - Retiring is deleting the source directory and regenerating. A region in a sibling keyed on the retired skill stops that regenerate, since its key no longer resolves, so re-key or remove it first. The derived
plugin.jsonlist shrinks with it, and the installer's per-skill markers remove the retired skill from~/.agents/skills/on each machine's next run. - A deletion sweeps the prose that references the skill, in the same change rather than as follow-up. That prose is the
AGENTS.mdmap row or paragraph naming the skill, and any law-doc packaging pointer to the skill. It is also any sibling skill that disambiguates against the skill. A law-doc section that had moved its full rules into the skill takes them back, or is retired with it. That way no rule is silently lost with the skill that carried it. - Renaming is a retire plus a create as far as the installer's markers and the plugin list are concerned, so sweep references the same way. An include key spelling the old path is such a reference. One left behind fails
--checkas a region it cannot render rather than as a stale mirror.
The Doc-Packaging Pattern
Packaging keeps one topic in one authoritative place while the skill makes it surface automatically. It has these shapes, and each pairing states which it uses:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryChecking.github/skills/skill-lifecycle/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/ptr727/plexcleaner/skill-lifecycle)