Expand description
§agent-skill-installer
A Rust library that installs an Agent Skill shipped inside your program into the skill directories of the AI coding tools on the user’s machine, so those tools know what your program is for and how to use it. It finds the tools that are installed, plans the fewest copies that reach all of them, installs only after the user agreed, and later keeps its own unchanged copies current without asking. The crate decides what would happen and carries it out; your program asks the user in its own CLI, TUI or GUI.
§Features
- Only where a tool is present. A tool counts as installed when its home directory exists, and a skill directory is only created inside such a home. The crate never creates a tool’s home.
- The fewest copies that reach every tool. The planner compares every combination of directories and picks the one that leaves the fewest tools seeing the skill twice, then needs the fewest copies, and names any tool that will see it twice anyway. Symlinks are resolved, so two names for one directory are one target.
- Consent first. The first installation into a directory happens only after the user agreed. A “no” is kept in a file your program chooses, and that directory is not asked about again.
- Silent updates of its own work only. The skill’s frontmatter records which program installed it, the version and a digest over every file. A newer program updates an unchanged copy without asking, also inside a git working tree, which is reported with its root.
- Never half-written. A new version is written beside the skills directory and renamed into place; on a failure the old one is put back.
- Extensible. The built-in list covers six tools; a program can add its own tools and directories, and the planner treats them like the built-in ones.
- Small. Depends on
semverandsha2only. No YAML parser, no network access, no terminal input or output.
§Toolchain support
The minimum supported Rust version (MSRV) is 1.95. The crate targets a
rolling window of stable Rust minus four releases, reviewed with each minor
release. MSRV increases are made only in minor releases and noted in the
changelog. CI builds and tests the crate against exactly the version in
rust-version on every change.
§Installation
cargo add agent-skill-installeror in Cargo.toml:
[dependencies]
agent-skill-installer = "0.1"§Quick start
use agent_skill_installer::{AgentSkill, Program, Skill};
let skill = Skill::new(
"devserial",
"Serial terminal with a SQLite-buffered capture. Use it to read, search and write serial ports.",
"# devserial\n\nRead the capture with `devserial read PORT --tail 50`.\n",
)?
.with_field("license", "GPL-3.0-or-later")?
.with_file("references/cli.md", "# Commands\n")?;
let program = Program::new("devserial", env!("CARGO_PKG_VERSION"))?;
let agent = AgentSkill::new(skill, program, "/path/in/your/data/dir/skill-consent")?;
// At every start: keep earlier installations current. Asks nobody.
agent.update()?;
// Once, when a place exists nobody has decided on: ask in your own surface.
if let Some(offer) = agent.offer()? {
for step in offer.steps() {
println!("{} (read by {})", step.place.display(), step.tools.join(", "));
}
let agreed = true; // the user's answer
if agreed {
offer.accept()?;
} else {
offer.decline()?; // these places are not offered again
}
}A command line can show agent.status(), install with
agent.install_everywhere(), which also goes where the user declined before,
and take the skill out with agent.remove().
status writes nothing. It returns one step per place with what is there
(Found) and what would happen (Action): install, update, nothing and why,
or a problem to report. The Plan inside it lists the installed tools, the
tools that will see the skill twice, and any tool that cannot be served, with
the reason. A program that wants to decide place by place uses
agent.installer(), whose assess and apply take an Approval of its own.
To add a tool the built-in list leaves out:
use agent_skill_installer::{Catalog, Location, SkillDir, Tool};
let mut catalog = Catalog::builtin();
catalog
.add_dir(
SkillDir::new("kiro", Location::home(".kiro/skills"))
.requires(Location::home(".kiro")),
)?
.add_tool(Tool::new("kiro", "Kiro", Location::home(".kiro")).reads(["kiro"]))?;AgentSkill::with_catalog(catalog) then uses it.
§Consent and updates
Consent is given for a place, not for a version. What assess decides for a
place depends on what it finds there under the skill’s name:
| Found | Action |
|---|---|
| Nothing, the place is planned | Install once the user approves (Action::Install) |
| Nothing, the user declined the place | Nothing (Why::Declined) |
| This program’s copy, unchanged, older | Update without asking (Action::Update) |
| This program’s copy, unchanged, same or newer | Nothing; an older program never downgrades |
| This program’s copy, changed by somebody | Reported (Problem::Modified); replaced only when listed in Approval::overwrite |
| A skill of that name that is not this program’s | Reported (Problem::Foreign), never replaced |
A copy counts as this program’s when its metadata block carries the record
the crate wrote, in the shape the crate writes it:
metadata:
installed-by: "devserial"
installed-version: "0.3.0"
content-digest: "sha256:…"The digest covers every file of the skill directory with its own value blanked.
Any edited, added or removed file makes the copy “changed”; .DS_Store and
Thumbs.db do not. Copies of this program in places the plan no longer
chooses, for example for a tool uninstalled since, are still updated and
removed.
§Supported tools
The built-in catalog, from
docs/tools.md.
“Measured” means the behaviour was observed with the tool on a test machine;
“documented” means it follows the vendor’s documentation only.
| Tool | Installed when this exists | Skill directories it reads | Evidence |
|---|---|---|---|
| Claude Code | ~/.claude ($CLAUDE_CONFIG_DIR when set) | ~/.claude/skills ($CLAUDE_CONFIG_DIR/skills) | measured |
| Codex | ~/.codex ($CODEX_HOME when set) | ~/.agents/skills | documented |
| Gemini CLI | ~/.gemini | ~/.gemini/skills, ~/.agents/skills | measured |
| GitHub Copilot | ~/.copilot ($COPILOT_HOME when set) | ~/.copilot/skills ($COPILOT_HOME/skills), ~/.agents/skills; in VS Code also ~/.claude/skills | documented |
| Cursor | ~/.cursor | ~/.cursor/skills, ~/.agents/skills, ~/.claude/skills | documented |
| OpenCode | ~/.config/opencode ($XDG_CONFIG_HOME/opencode when set) | ~/.config/opencode/skills ($XDG_CONFIG_HOME/opencode/skills), ~/.claude/skills, ~/.agents/skills | documented; XDG_CONFIG_HOME from secondary sources |
Claude Code reads only ~/.claude/skills, and Gemini CLI does not read it, so
a machine with both needs two copies. With Claude Code and Codex installed,
Cursor, OpenCode and Copilot in VS Code read both copies when they are
installed too; the plan names them in Plan::duplicated.
§Limits
- Windows paths follow the tools’ documentation, which only ever says
~. The test suite runs on Windows in CI, but no tool’s behaviour was measured there, and the symlink cases are tested on Unix only. - Four of the six tools are documented, not measured: Codex, Copilot, Cursor and OpenCode.
- Two programs writing the same skill at the same moment are not coordinated. Each write is atomic, so the place ends up with one complete version, but one of the two may report a failure.
- An interrupted process can leave a
.asi-*staging directory beside the skills directory. The next write of the same skill removes it once it is an hour old; a younger one may belong to a write in progress. - Package managers do not install skills. That would be installing without consent; the program asks at runtime instead.
§Contributing
See CONTRIBUTING.md for the workflow and the checks CI runs, and SECURITY.md for reporting a vulnerability.
§License
LGPL-3.0-or-later. See LICENSE.
Re-exports§
pub use semver;
Structs§
- Agent
Skill - A program’s skill on the user’s machine.
- Approval
- What the user agreed to.
- Assessment
- A plan and the step for every place it concerns.
- Catalog
- The tools and directories the planner knows.
- Consent
- The declined targets, and the file they are kept in.
- Environment
- A home directory and the environment variables that relocate tools.
- Installer
- A skill, the program it belongs to, and the machine to put it on.
- Location
- Where something lives: below the home directory, unless a variable moves it.
- Offer
- Places nobody has decided on, to be put to the user once.
- Outcome
- What happened in one place.
- Plan
- What the planner found and proposes.
- Program
- The program shipping the skill: its name goes into the record, and its version decides whether an installed copy is older.
- Skill
- A skill: its frontmatter, its instructions and any further files.
- Skill
Dir - A directory some tool reads skills from.
- Step
- One place, what is there and what would happen.
- Target
- One directory the skill would be written to.
- Tool
- A tool that reads skills.
- Unserved
- A tool the planner found installed but cannot serve, and why.
Enums§
- Action
- What the installer would do in a place, and why.
- Catalog
Error - Why an entry could not be added to a catalog.
- Done
- What happened.
- Error
- Why the machine could not be looked at or the answers not be kept.
- Found
- What is in a place under the skill’s name.
- Name
Error - Why a skill name was refused.
- Plan
Error - Why no plan could be made.
- Problem
- Why something needs the user’s attention.
- Skill
Error - Why a skill was refused.
- Why
- Why nothing is done.
Constants§
- SKILL_
FILE - The file every skill has, at the top of its directory.
Functions§
- plan
- Work out where a skill should go.
- validate_
name - Check a skill name against the Agent Skills specification.