ptr727/plexcleaner/skill-lifecycle

Claude Code and agent skill by ptr727/plexcleaner

Trust tier 3
  • community
Source check pending

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-lifecycle

SKILL.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/ and scripts/ 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.py generates .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, and build_dist.py --check exits non-zero when any tree differs from .agents/skills/.
  • The skill set is implicit. Every .agents/skills/<name>/ directory carrying a SKILL.md is a skill. The generated plugin.json derives its list from those directories, so adding or retiring a skill edits no manifest by hand. marketplace.json names 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.py fills 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 *.md files under each .agents/skills/<name>/ directory carrying a SKILL.md, plus the files build_dist.py's INCLUDE_DESTINATIONS tuple 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.md is 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 file spec/files.json carries 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.py rather 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 a GOVERNANCE.md section, an AGENTS.md subsection, 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 --check fails 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, per GOVERNANCE.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.json that 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 the claude CLI. Each run stamps the hub commit into ~/.agents/skills-install-stamp.json. --report answers each channel separately. One answer is which commit the copy was taken from, judged against the promoted main. The other is which branch and commit the checkout Claude Code loads in place is serving now. --report exits 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

  1. Name the directory in kebab-case and set the frontmatter name: to the same string.
  2. 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, and check-this-repo each state which of them a session is in.
  3. 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.
  4. Split bulk into `references/` when the source doc is large: the SKILL.md carries the summary and the binding rules. Each references/*.md carries one topic read on demand. That split is the shape comment-and-doc-style uses.
  5. Apply the doc-packaging pattern below in the same change when the skill packages a law doc or one of its sections.
  6. 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, per git-commit-conventions. CI runs --check on every pull request and fails a desynced distribution. uv run --no-project --with-requirements tests/requirements.txt python tests/test_build_dist.py covers the generator itself.
  7. Record the surfacing: annotate the AGENTS.md "Where the Rules Live" row when the skill packages a GOVERNANCE section. Annotate the closing paragraph of the AGENTS.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.
  8. 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 --report says, 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 a build_dist.py run 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.json list 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.md map 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 --check as 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

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
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/ptr727/plexcleaner/skill-lifecycle/badge)](https://verified-skill.com/skills/ptr727/plexcleaner/skill-lifecycle)

Something wrong with this skill or its page? Tell us.