Skill Maintainer

SkillAI & models

Track upstream drift and sync adapted skill libraries

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Skill Maintainer skill

What this skill tells your AI

The instructions your AI receives, as published by moonlight-lupin/agent-skills in agent-ops/skill-maintainer/SKILL.md and read by ahel’s review.

Overview

A meta-skill for agents who maintain a library of skills — their own, adapted from external repos, or published to a shared repo. Covers the full lifecycle: authoring → curating → tracking → syncing → publishing.

This skill encodes a workflow built and battle-tested across dozens of skills. It is agent-agnostic: replace tool names (e.g. write_file, terminal, delegate_task) with your platform's equivalents. The patterns — manifest tracking, layered sync, parallel diff dispatch, cron-based drift detection — transfer to any agent runtime.

When to Use

  • Creating a new skill from scratch
  • Importing/adapting skills from an external repo or collection
  • Checking if local skills have drifted from upstream
  • Scanning for untracked external tool dependencies
  • Publishing a local skill to a shared repo
  • Setting up automated monthly sync checks
  • Tightening/pruning an accumulated skill library

Don't use for: one-off skill creation with no upstream tracking need (just use your platform's skill-authoring tool directly). This skill adds value when you have ≥5 skills or ≥1 external dependency to track.

Core Concepts

The three sync layers

LayerDirectionWhat driftsExample
1. External → LocalUpstream repo → your skillUpstream adds features, fixes bugs, changes APIbaoyu-skills v1.56 → v1.117
2. Local → Published repoYour skill → your GitHub repoYou improve locally; repo copy goes staleskill gets new flags locally; repo doesn't
3. Local → Standalone repoYour skill → a code project repoSkill documents a workflow; the code evolvesskill describes CLI v1; CLI is now v3

All three need tracking. Layer 1 is the most common concern. Layer 2 is the most commonly forgotten — publish once, keep improving, repo goes stale.

The manifest

A single UPSTREAM_MANIFEST.md file at your skills root tracks every skill with external provenance. One row per skill, covering all three layers. See templates/upstream-manifest.md for the file format.

The cron job

An automated script (scripts/upstream_check.py) runs monthly, fetches upstream versions, and reports drift. See the Cron Setup section.


Skill Authoring Workflow

0. Check for overlap before creating

Before creating a new skill:

  1. List existing skills in the target category
  2. Check if any cover the same capability — if so, extend the existing skill rather than creating a sibling
  3. Check if any disabled/retired skill covers it — re-enable instead of duplicating

1. Survey peers

Read 2–3 existing skills in the target category to match tone, structure, and frontmatter conventions.

2. Frontmatter

Every skill needs:

---
name: my-skill-name         # lowercase, hyphens, ≤64 chars
description: >              # ≤1024 chars, starts with trigger context
  Use when <trigger>. <one-line behavior>.
license: MIT
metadata:
  version: 1.0.0            # spec allows only name/description/license/
  author: your-name         # compatibility/metadata/allowed-tools top-level
  platforms: [linux, macos, windows]
---

3. Structure

# <Title>

## Overview          — what and why (1-2 paragraphs)
## When to Use       — bullet triggers + "Don't use for"
## <Topic sections>  — quick-reference tables, exact commands, recipes
## Common Pitfalls   — numbered list of mistakes and fixes
## Verification Checklist — checkbox list

4. Size guidelines

  • Description: ≤1024 chars
  • Total SKILL.md: ≤100k chars (aim for 8–15k)
  • Bulky/branch-specific material → references/*.md, linked from SKILL.md
  • Scripts → scripts/*.py, deterministic, pure stdlib where possible

5. Quality principles

  1. Optimize for process predictability — if a line doesn't change agent behavior, cut it
  2. End steps with completion criteria — "every modified file accounted for" beats "summarize changes"
  3. Co-locate rules with the concept they govern — don't scatter one idea across the file
  4. Use strong leading words — "tight loop," "tracer bullet," "root cause" over long explanations
  5. Prune duplication and no-ops — keep each meaning in one source of truth
  6. Watch for premature completion — if agents rush a step, sharpen its completion criterion

Common quality failures: premature completion, duplication, sediment (stale lines), sprawl (too much always-visible material), no-op prose.

6. Validate

  • Frontmatter parses as YAML, starts at byte 0, closes with \n---\n
  • name and description present, description ≤1024 chars
  • Non-empty body after closing ---

7. Update the manifest

If the skill has external provenance (adapted from upstream, wraps a third-party tool, or published to a repo), add a row to UPSTREAM_MANIFEST.md. This is mandatory — an untracked skill is invisible to the monthly sync check. Skip the manifest only for original skills with zero external dependency.


Skill Curation Workflow

1. Inventory and classify

When porting skills from an external collection, classify each:

ClassAction
Keep — unique, valuable, no overlapAdapt to your format
Duplicate — you already have an equivalentMerge unique parts or skip
Thin/pointer — just a URL, no real contentSkip
Novelty — joke/toy, no practical valueSkip
Capability-layer/router — installer + router delegating to upstream CLIsEvaluate each backend; don't wholesale replace native skills

2. Assess overlap

Compare each candidate against existing skills. When two overlap, prefer your native one unless the external one adds clear value. If merging: patch the existing skill with unique content, discard the external copy.

3. Adapt to your format

Frontmatter: strip all framework-specific fields. Keep name, description, version (bump for adapted), author (e.g. "Source (adapted)").

Body: full rewrite, not copy-paste:

  • Translate all non-English content to English
  • Strip framework-specific references, sandbox paths, proprietary tool names
  • Restructure into your standard sections (When to use, body, pitfalls, verification)
  • Preserve all domain detail — exact hex codes, pixel dimensions, font names, timing, forbidden patterns — these ARE the skill's value
  • Add practical trigger words

4. Quality audit

# Non-English characters remaining (if source was non-EN)
grep -cP '[\x{4e00}-\x{9fff}]' SKILL.md
# Framework jargon remaining
grep -c 'framework-specific-term\|upstream-field' SKILL.md
# Version/author consistency
grep '^version:\|^author:' SKILL.md

5. Place in correct category

Use existing categories. Don't invent new top-level categories casually.

6. Update manifest

Add a row to UPSTREAM_MANIFEST.md for every adapted skill. See the Upstream Tracking section for entry types.


Upstream Tracking Manifest

Maintain UPSTREAM_MANIFEST.md at your skills root. One row per skill with external provenance. See templates/upstream-manifest.md for the full template.

Entry types — pick the right table

TypeWhat it tracksAudit method
Adapted skillSkill content adapted from an upstream skill repoDiff upstream SKILL.md, compare version fields
Engine dependencySkill wraps a third-party CLI/pip tooltool --version vs GitHub releases
Engine-tracking skillOriginal skill built around a third-party enginepip show <pkg> + GitHub releases
Third-party skillAdapted from external repo (not a skill repo per se)Fetch README/latest, compare concepts
Published skillLocal skill pushed to your repodiff local vs repo copy

Skip the manifest for original skills with zero external dependency.

The PORT_NOTES pattern (gold standard for complex adaptations)

For skills with significant structural changes, maintain PORT_NOTES.md inside the skill directory:

# Port Notes — <skill-name>

Ported from <repo-url> v<upstream-version>.

## Changes from upstream
| Change | Upstream | Ours |

### What was preserved
<list of verbatim-copied files>

## Syncing with upstream
<exact curl/diff commands>
<files safe to overwrite vs requiring manual merge>

Sync Audit Workflow

Run monthly or when prompted.

1. Read the manifest

Note last-checked dates. Identify stale rows (last sync >60 days).

2. Layer 1 — External → Local

For each adapted skill:

  1. Fetch upstream version (raw GitHub URL or GitHub API)
  2. Compare to pinned version in manifest
  3. If different, classify the source and apply the right sync strategy:
Source typeSync approach
Versioned, verbatim-heavyOverwrite verbatim files, merge adapted files
Unversioned, full rewriteKeep ours — diff for new domain content only
Actively evolvingContent merge — add upstream sections, preserve local wiring
Archived/movedUpdate URLs only — upstream may have changed format
Low activityOne-time check, usually nothing to do

3. Layer 2 — Local → Published repo

For each published skill, diff local vs repo copy. If local is ahead, re-publish (debrand, generalize, push).

4. Layer 3 — Local → Standalone repo

For skills tied to code repos, check if the repo's workflow/CLI has changed.

5. Engine dependency scan

# List installed CLI binaries
for tool in <your-tools>; do
  path=$(which $tool 2>/dev/null) && echo "$tool: $path" || echo "$tool: not installed"
done

# List pip packages
for pkg in <your-packages>; do
  pip show $pkg 2>/dev/null | grep -E '^Version:'
done

# Check latest releases
curl -s https://api.github.com/repos/<owner>/<repo>/releases/latest | grep tag_name

Cross-reference with manifest — any installed tool that powers a skill but isn't in the manifest is an untracked dependency. Add it.

6. Update manifest

Record last-checked date, new upstream version, any sync actions taken.

Parallel diff dispatch

When auditing multiple upstream sources simultaneously:

  1. Fetch all upstream files in one batch
  2. Dispatch parallel subagents per source to diff and classify
  3. Handle simple updates (URL fixes, verbatim overwrites) yourself
  4. Collect structured recommendations (keep/merge/re-port)
  5. Execute merges based on recommendations

This turns a serial 30-minute audit into a 5-minute parallel one.


Publishing Skills to a Public Repo

Debranding

When publishing a skill derived from a client/org-specific source:

  1. Grep for brand references across all files
  2. Remove or genericize: brand names, proprietary palettes, regulatory references, org-internal file paths, house styles
  3. Remove brand-specific reference files
  4. Replace specific dollar amounts with generic terms
  5. Verify clean with grep
  6. Bump version for the published version

Generalizing

Platform-specific termReplace with
Platform tool names (image_generate, etc.)Generic description
Platform metadata fieldsRemove from frontmatter
Hardcoded pathsEnv var with fallback, or <skill_dir>/...
Sibling skill dependenciesEnv var resolution with fallbacks
Platform-specific deliveryGeneric "send via the user's channel"

Testing the published version

  • Scripts parse: python3 -c "import ast; ast.parse(open('scripts/main.py').read())"
  • Imports resolve: python3 -c "from script import main_func"
  • Graceful degradation works (simulate missing optional deps)

Mutual exclusivity

In a pick-and-choose repo, each skill must be self-contained and runnable standalone, even at the cost of code duplication across siblings. Do NOT extract shared modules — a user who clones only one skill should not need a file from another.


Cron Setup — Automated Drift Detection

Set up a monthly cron job to automatically check for upstream drift.

1. Copy the manifest template

cp templates/upstream-manifest.md /path/to/your/skills/UPSTREAM_MANIFEST.md

Edit it to list your actual skills, upstream repos, and versions.

2. Copy the check script

cp scripts/upstream_check.py /path/to/your/scripts/

The script reads Layer 1 and Layer 2 tables directly from UPSTREAM_MANIFEST.md. No hardcoded skill lists — the manifest is the single source of truth.

Engine dependencies (ENGINE_DEPS) are configured in the script file itself, not in the manifest. This is a deliberate security boundary: manifest content is markdown that could be externally edited, so we don't execute shell commands derived from it. Add entries like:

ENGINE_DEPS = [
    {"name": "my-cli-tool", "command": ["my-cli", "--version"], "version_regex": r"(\d+\.\d+\.\d+)"},
    {"name": "my-pip-pkg", "command": ["pip", "show", "my-pip-pkg"], "version_regex": r"(\d+\.\d+\.\d+)"},
]

Commands are passed as lists (never shell=True) to prevent shell injection from untrusted config.

You may also need to set SKILLS_ROOT and LAYER_2_REPO at the top of the script, or via the SKILLS_ROOT and LAYER_2_REPO env vars.

3. Set up the cron job

Using a generic cron scheduler (adapt to your platform):

# Monthly upstream sync check — 9am on the 1st
0 9 1 * * /path/to/python3 /path/to/scripts/upstream_check.py

Or using an agent platform's cron tool:

{
  "name": "Monthly Upstream Sync Check",
  "schedule": "0 9 1 * *",
  "prompt": "Run the upstream sync check script at /path/to/scripts/upstream_check.py. Report any drift detected. If drift is found, summarize which skills need attention and what changed upstream.",
  "no_agent": true
}

The script exits 0 if all in sync, 1 if drift detected. Non-empty stdout is delivered as the message; empty stdout means silent (nothing to report).

4. What the script checks

  • Layer 1: parses manifest table, fetches upstream SKILL.md from GitHub, compares version fields. For sources without version fields, reports last commit date via GitHub API. Uses the repo's default branch (falls back to master). The upstream file location is guessed as skills/<name>/SKILL.md unless the manifest row carries an optional Upstream path column — add that column for upstreams with a different layout, or the check will warn "could not fetch upstream" every run.
  • Layer 2: compares local vs published repo using both version fields and SHA-256 content hashes. Catches version drift (different version numbers) AND content drift (same version, different content — e.g. you edited locally but didn't bump the version or re-publish).
  • Engine deps: runs configured version-check commands (list-form, no shell) and extracts version strings.

5. Handling drift reports

When the cron reports drift:

  1. Read the report — which skills changed, what's the version delta
  2. Fetch upstream files to a temp directory
  3. Classify each file as verbatim (overwrite) or adapted (merge)
  4. For merges: take upstream as base, re-apply local adaptations
  5. Run jargon check — grep for upstream-specific terms that should be absent
  6. Update PORT_NOTES.md with sync log
  7. Update manifest with new version, date, and status

Extending vs Creating New Skills

When a new capability overlaps with an existing skill:

  1. Does an existing skill cover the core capability? → Extend it with the missing piece (reference file, script, routing entry)
  2. Does it need a fundamentally different workflow/toolset? → New skill may be warranted, but justify it first
  3. Is it a thin layer on existing infrastructure? → Reference file + optional script, not a new skill

When a sub-topic grows large enough to warrant a dedicated skill, the umbrella skill MUST point to the new skill, not keep duplicate content. Replace inline detail with a pointer: "→ See dedicated <skill-name> skill for: ..." Duplicate content drifts; a pointer ensures one source of truth.


Pitfalls

  1. Shallow ports are worthless — a skill with source jargon, missing triggers, and no restructuring helps no one. Always do a full adaptation pass.
  2. Skill inflation — don't port 139 skills when 35 are valuable. Ruthlessly delete thin/pointer/duplicate/novelty skills before adapting.
  3. Copy-paste trap — the source format is never the target format. Restructure the body, don't just translate headers.
  4. Missing domain detail — exact hex codes, pixel sizes, font weights, forbidden patterns ARE the skill. Stripping them destroys the value.
  5. Overlap blind spot — always check existing skills before adding. Two skills doing the same thing is worse than one.
  6. Reverse-sync blind spot (Layer 2) — after publishing, you keep improving locally. Without manifest tracking, the repo copy silently goes stale. Always record push dates.
  7. "Keep ours" is valid — not every upstream diff requires a merge. When your version is a superset, record the decision and move on.
  8. Merge subagents need explicit preserve lists — without listing what must NOT be removed, a merge subagent may overwrite everything with upstream.
  9. Engine-tracking skills need different sync — compare installed version vs latest release, not SKILL.md content. A stale binary breaks the skill even if the SKILL.md is current.
  10. Silent auth dependency — a backend that "just works" on a developer's desktop may require cookies, QR login, or a browser extension impossible on a server. Surface the auth boundary explicitly.
  11. Atomic skills principle — keep skills atomic (one capability per skill). The agent chains skills at runtime, not at design time.
  12. Mutual exclusivity in portable repos — each skill must be self-contained. Don't extract shared modules; duplication is the price of independence.
  13. Sediment — a skill should get shorter or sharper over time. When adding a rule, remove the old wording it replaces.
  14. No-op prose — "be careful," "be thorough" rarely change behavior. Replace with checkable completion criteria.

Verification Checklist

  • Overlap checked — no existing skill covers the same capability
  • Frontmatter valid — starts with ---, closes with \n---\n, parses as YAML
  • name (≤64 chars, lowercase+hyphens) and description (≤1024 chars) present
  • Structure: Overview → When to Use → body → Pitfalls → Verification
  • Each step has a checkable completion criterion
  • No no-op prose or duplicated rules
  • Total file ≤100k chars (aim for 8–15k)
  • Bulky reference material in linked references/*.md files
  • Scripts are deterministic, pure stdlib where possible
  • UPSTREAM_MANIFEST.md updated if skill has external provenance
  • PORT_NOTES.md created for complex adaptations
  • Jargon check passed — no upstream-specific terms in adapted files
  • Published version debranded + generalized + tested
  • Cron job configured for monthly drift detection
  • tests/test_upstream_check.py (this skill's own suite) passes — run python3 -m pytest tests/ -q from the skill directory

Signals

GitHub stars
65
Forks
11
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
skill-maintainer
Source
github.com/moonlight-lupin/agent-skills