skill-inject (ski)
Local, model-agnostic automatic skill injection for Claude Code
and opencode.
Why this exists
Agent skill systems advertise every skill's description to the model and trust it to
notice the relevant one and invoke it. In practice that leaks:
- Missed triggers. When a skill's description shares no vocabulary with your prompt,
the model overlooks it — the match is semantic, not lexical. The more skills you
install, the more often the right one hides in the crowd.
- Model-dependent. "Pick the skill from a wall of descriptions" is something even
frontier models do unevenly, and smaller or local models do worse. Which skill fires
drifts with whatever model is driving the session.
- Always-on cost. Every description sits in the context window every turn, relevant
or not.
ski replaces the guesswork with a deterministic local retriever: it embeds your prompt
on CPU, ranks it against your skill descriptions, and injects the matched skill only
when one is genuinely relevant — the same result no matter which model runs, with no
API call and nothing leaving your machine. The model still chooses which files a skill
points to; ski only guarantees the right skill is in the room when it matters.
Skills the model loads on its own are tracked and never re-injected.
See it decide
ski scores every installed skill against your prompt and injects only the ones
above a fixed cutoff (-2.50 below); a higher score is a stronger match. Real ski why
output against a live library of 57 skills (reproduce with ski index then
ski why "<prompt>"):
$ ski why "clean up this messy CSV"
xlsx -0.59 <- injected (clear winner)
pre-commit-setup -3.72 <- skipped
clean up this messy CSV never says spreadsheet or xlsx — the match is on meaning,
not vocabulary, and it lands far ahead of every other skill. Keyword or description
matching can't bridge that gap, and a model scanning 57 descriptions can easily miss it.
$ ski why "what time is the meeting tomorrow"
handoff -3.08 <- best skill, still below the cutoff
An off-topic prompt leaves every skill under the cutoff, so ski injects nothing — no
false positives, no context pollution.
This repo is a single Rust binary (ski) plus the thin host adapters that drive it,
packaged as a one-plugin Claude Code marketplace. See DEVELOPING.md
for the dev workflow.
Benchmarks
100% local — no API call, no token cost, nothing leaves your machine. The whole
pipeline (embed → retrieve → rerank) runs on CPU — around half a second per prompt on
the machine benchmarked below. Real samples, ranked against a live library of 57 skills:
| your prompt | skill ski injects | match score |
|---|
set up a python project with uv | uv-setup | 2.76 |
scaffold a new react typescript frontend | react-ts-setup | 3.38 |
how do I credit Claude in this git commit | git-attribution | 1.21 |
make an animated gif for slack | slack-gif-creator | 1.63 |
write a Word doc with a table of contents | docx | 0.12 |
extract tables from a pdf | pdf | 0.67 |
Every row is a real ski why result. A higher match score means a stronger match;
anything below -2.50 is left out entirely (as in the off-topic example above).
| operation (cold — every hook is a fresh process) | time |
|---|
rank + inject one prompt (ski hook) | ~0.54 s median |
| full index rebuild (57 skills) | ~0.78 s |
| incremental reindex, no change | ~0.19 s |
bge-small-en-v1.5 (384-dim) retrieval + jina-reranker-v1-turbo-en rerank, ~270 MB RAM.
Measured CPU-only on an AMD Ryzen AI MAX+ 395 — cold runs with model load included,
not warm microbenchmarks. Reproduce with ski index then ski why "<your prompt>".
Install (Claude Code)
The plugin is hooks-only and needs the ski binary on disk.
-
Get the binary. Easiest — install the latest prebuilt release into
~/.local/bin (Linux x86_64):
curl -fsSL https://raw.githubusercontent.com/bcmyguest/skill-injector/main/scripts/install.sh | sh
.deb / .rpm packages are on the Releases
page too. Or build from source — default build = real embedder + reranker
(downloads the model once, then offline):
cargo install --path . # -> ~/.cargo/bin/ski
Or the offline bag-of-words build (no deps, no model download):
cargo install --path . --no-default-features
-
Enable the plugin from this marketplace:
/plugin marketplace add bcmyguest/skill-injector # or a local path to this repo
/plugin install skill-inject@skill-inject