Work

aiusage-skills: using other people's agent skills without surprises

An agent skill is a set of instructions for an agent that can already read your files. How do you use skills written by others without those instructions changing underneath you?

How third-party skills enter the plugin Skills from an upstream repository are copied into vendor/, pinned to an upstream commit. Only 35 of 145 were taken, and their scripts stay quarantined until a written decision promotes them. The plugin ships from vendor/. Two checks run alongside: CI compares the whole vendor/ tree with a SHA-256 baseline, and a nightly job compares vendor/ with upstream and keeps one issue per source. Upstream skill repository vendor/ pinned, 35 of 145 scripts quarantined Plugin what ships Nightly drift job one issue per source SHA-256 baseline CI fails on any change pinned copy compare
How third-party skills enter the plugin. Blue: the decision · dashed: checks.
Status
Open source. The decisions described here are implemented; the gaps are listed at the end.
My role
Author. aiusage-skills is my own project.
Scope
How third-party skills get into the plugin, and how changes upstream are noticed
Last reviewed
29 September 2026

aiusage-skills is a Claude Code plugin with twelve skills of my own, for planning, test-driven development and reviewing changes, plus a selection of skills from other authors. It goes together with aiusage.guide: the guide describes the working practices, the plugin puts them into the agent, and the two feed into each other.

Where it started

A skill from a marketplace isn't a library. It's a set of instructions for an agent that already has your files and your credentials. Installing it from a marketplace means the upstream author decides when those instructions change, and the change arrives without anyone reading it.

Decisions

Copy and pin instead of installing. Third-party skills are copied into vendor/, pinned to an upstream commit, together with their licence. Only the areas the plugin was missing were taken: 35 of 145 upstream skills. The rejected alternative was a marketplace install that updates itself. The decision record says what that costs:

Updates become a ritual (NOTICE.md) instead of an event. That is the point. The tree is 35 skills, not 145; absence is a decision.

From ADR-0001, "Vendor third-party skills instead of installing from marketplaces", accepted. Last changed 9 September 2026.

Scripts don't run until someone has read them. Scripts arrive in scripts.quarantine/ without execute permission. A script is only enabled through a written decision. ADR-0019 enabled 54 reviewed scripts and kept four quarantined, among them one that clones twelve third-party rule repositories at scan time without pinning. Reading the scripts also showed that several skills failed on a path error several steps in, although their descriptions said they stopped on purpose.

Freeze the whole vendor tree. Holding the vendored skills to my own lint rules would fail every one of them and drown the real findings. So CI compares the entire vendor/ tree with a SHA-256 baseline instead. Any change fails the build until someone accepts it with a deliberate --write-baseline commit after reading it.

Report upstream changes, never apply them. A nightly job compares vendor/ with each upstream source and keeps exactly one issue per source that has moved on. On the day the first full read was finished, three of the four sources were already behind.

It does not copy anything into vendor/, does not open merge requests, and does not read upstream file contents — --name-status needs trees, not blobs. Fetched content is diffed, never executed. Copying and reading stay with the human, per ADR-0001; the job only says that there is something to read.

From ADR-0018, "A nightly job compares vendor/ with upstream and keeps one issue per source", accepted. Last changed 9 September 2026.

Verification

Four CI jobs enforce this:

  • validate:skills checks my own skills against the rules: allowed tools, no fetching or installing at runtime, a length limit.
  • validate:self-test runs the validator against fixtures that must fail, for example a skill that runs curl (runs-curl) or tells the agent to fetch something in prose (prose-fetch), and one that must pass because it only mentions curl (mentions-curl).
  • validate:vendor checks the quarantine, the manifests and the SHA-256 baseline of vendor/.
  • vendor:drift is the nightly comparison with upstream.

Not done yet

  • The CI images are referenced by tag, not by digest. ADR-0014 calls this "the one unpinned input in a repository whose argument is pinning".
  • The validator doesn't follow skills that call other skills.
  • The checks are pattern matching. Semantic attacks the patterns miss, and prompt injection in the content an agent is pointed at, are outside what this protects against. The threat model says so explicitly.
  • The script that clones rule repositories unpinned stays quarantined until there is a decision on it.

Stack: Python (standard library only), GitLab CI.