skills-freshness
Skill0 starsChanged 5 months agoMITView on GitHub
Audit Claude Code skills (project + global) for staleness. A stdlib Python pre-pass does sha256 change detection, so only new/changed/removed skills enter context — unchanged ones are never re-read. Skills can declare TOML freshness checks under '# Freshness check'; otherwise the LLM reviews frontmatter, description-vs-behavior, and broken refs. Asks before editing. Use for "are my skills up to date", "check for skill drift", or `/mikko-skills-freshness`.
In this repository15 other files it gives its agents.
- ai-codegen-smell-auditSkill
- auditSkill
- dotnet-auditSkill
- llm-injection-auditSkill
- mikko-audit-suiteSkill
- mikko-helpSkill
- mikko-installSkill
- mikko-skillsSkill
- react-anti-patterns-auditSkill
- readme-drift-syncSkill
- security-auditSkill
- session-costSkill
- skill-calibrationSkill
- skills-qualitySkill
- skill-usageSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 11
NOT for every commit. Cadence: when you suspect a referenced path has moved, after a refactor that renamed things, or quarterly.
- Very specific: line 42
If the table is All skills up to date - nothing to review., STOP.
- Very specific: line 106
Default: scope_root for project skills, skill_dir for global skills.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
When to use
User says "are my skills up to date", "audit my skills", "check for skill drift", invokes /mikko-skills-freshness.
NOT for every commit. Cadence: when you suspect a referenced path has moved, after a refactor that renamed things, or quarterly.
Workflow
0. First run — baseline first
Fresh install with no manifest yet? Run --update BEFORE the review loop. The script writes the manifest unconditionally and the next invocation starts from "all up to date." Skip step 1; jump to step 5 syntax with --update.
1. Run the audit
Pick the right script path for how the skill was installed:
| Install method | Script path |
install-mikko.sh (prefixed) | python ~/.claude/skills/mikko-skills-freshness/skills-freshness.py |
install.sh skills-freshness --target user (unprefixed) | python ~/.claude/skills/skills-freshness/skills-freshness.py |
| Library checkout (no install) | python skills/skills-freshness/skills-freshness.py (from claude-skills repo root) |
Windows PowerShell — same paths with $env:USERPROFILE instead of ~ and \ separators.
Defaults: both scopes (project under cwd/.claude/skills/, global under ~/.claude/skills/), no manifest write.
2. Read the table
SCOPE SKILL STATUS CHECKS / ISSUE
project equipment changed 2 pass, 1 FAIL
project new-mission changed no declared criteria - needs LLM review
global mikko-audit new 3 passIf the table is All skills up to date - nothing to review., STOP. Nothing further to do.
3. Per-row action
| Row says | What to do |
N pass only | Tell the user it's clean. Don't load the SKILL.md. |
M FAIL / K ERROR | Inspect the failing checks under "Failures / errors", read the cited paths, propose a fix or explain why the check itself is wrong. Don't auto-fix. |
no declared criteria - needs LLM review | Read the SKILL.md once with limit=80 (frontmatter + first one or two sections is all you need — no deep read). Verify: (a) frontmatter has name + description; (b) the description still matches what the skill does; (c) no broken file/command references in the body — cap path verification at one ls per finding, max 3 traces total, don't spelunk into source repos. Surface anything off. |
removed | Confirm the deletion was intentional; the manifest update will drop the entry. |
TOML parse error: ... | Quote the error verbatim to the user. Don't guess fixes. |
4. Ask before editing
Present findings as a short table first. Do not modify any skill file without explicit user approval.
5. Baseline once accepted
Same path as step 1, plus --update:
python <path-from-step-1> --updateWrites the manifest at each scope root. The next audit treats today's state as baseline.
The project manifest is per-machine, not committable across mixed-OS teams — a sha256 over CRLF (Windows checkout) differs from LF (Unix checkout) of the same skill. Mixed-OS contributors should gitignore .claude/skills-freshness.manifest.json.
How to declare freshness criteria in a skill
In any SKILL.md, add a section under the exact heading # Freshness check (or ##/###) followed by a fenced TOML block:
[[check]]
kind = "path_exists"
path = "src/game/data/weapons.json"
[[check]]
kind = "file_contains"
path = "src/lib/schemas/save.ts"
pattern = "WEAPON_IDS"
[[check]]
kind = "no_broken_md_links"Check kinds
| kind | required | optional | passes when |
path_exists | path | root | file or dir exists |
file_contains | path, pattern | root | regex matches (first 1 MB scanned) |
file_lacks | path, pattern | root | regex does NOT match (catches deprecated refs) |
no_broken_md_links | — | path, root | every relative [text](path) link resolves (default path is SKILL.md) |
command_exists | command | — | binary is on PATH |
pattern is a Python re regex, evaluated multiline.
root selects the path anchor:
skill_dir— this skill's own directoryscope_root— the repo root (project scope) or$HOME(global scope)home—$HOMEabsolute—pathmust be absolute (~expanded)
Default: scope_root for project skills, skill_dir for global skills. Paths cannot escape their resolved root.
Content-reading checks (file_contains, file_lacks, no_broken_md_links) are restricted to skill_dir and scope_root — they reject root="home" / root="absolute" to prevent a skill from probing arbitrary files via a regex oracle. file_lacks on a missing file PASSES (use path_exists + file_lacks together to assert both).
Freshness check
[[check]]
kind = "path_exists"
path = "skills-freshness.py"
root = "skill_dir"
[[check]]
kind = "file_contains"
path = "skills-freshness.py"
pattern = "SCRIPT_VERSION"
root = "skill_dir"
[[check]]
kind = "no_broken_md_links"Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

