Skip to main content

skill_embed/
lib.rs

1//! Ship agent skills inside a Rust binary, and give that binary a
2//! `skill install` command.
3//!
4//! It is the reverse of `gh skill install`. A tool carries its own skills in
5//! the executable, and writes them into the directory the user's agent reads
6//! from. The agent directories and the flag set are taken from
7//! `gh skill install`, so a user who knows that command already knows this one.
8//!
9//! Skills live under `skills/<name>/SKILL.md`, which is the layout defined by
10//! the [Agent Skills specification](https://agentskills.io/specification).
11//!
12//! ```no_run
13//! use std::process::ExitCode;
14//! use std::sync::LazyLock;
15//!
16//! use include_dir::{Dir, include_dir};
17//! use skill_embed::{Installer, SkillSet};
18//!
19//! static SKILLS_DIR: Dir<'static> = include_dir!("$CARGO_MANIFEST_DIR/skills");
20//!
21//! static SKILLS: LazyLock<Installer> = LazyLock::new(|| {
22//!     Installer::new(SkillSet::from_include_dir(&SKILLS_DIR).expect("valid skills"))
23//!         .with_tool_name("mytool")
24//!         .with_version(env!("CARGO_PKG_VERSION"))
25//! });
26//!
27//! fn main() -> ExitCode {
28//!     if let Some(code) = SKILLS.intercept() {
29//!         return code;
30//!     }
31//!     // the rest of your tool
32//!     ExitCode::SUCCESS
33//! }
34//! ```
35//!
36//! [`Installer::intercept`] gives a tool the skill subcommand in one line.
37//! [`Installer::run`] is for a tool that parses its own arguments, and the
38//! `skill-embed-clap` crate wires the same commands into
39//! [clap](https://docs.rs/clap).
40
41mod action;
42mod agent;
43mod cli;
44mod error;
45mod install;
46mod manifest;
47mod paths;
48mod projectroot;
49mod scope;
50mod skill;
51mod state;
52mod textfmt;
53mod tree;
54mod usage;
55
56pub use action::Action;
57pub use agent::{Agent, AgentSelector};
58pub use cli::{render_results, render_status};
59pub use error::{Error, ForceRequired, Result};
60pub use install::{InstallOptions, InstallResult, InstallStatus, InstallTarget, Installer};
61pub use scope::Scope;
62pub use skill::{File, SKILL_FILE, Skill, SkillSet};
63pub use state::State;
64
65/// Frontmatter keys written into an installed [`SKILL_FILE`].
66///
67/// They let a later run tell an outdated copy from one that was edited by hand,
68/// and they are namespaced so they never collide with the source tracking keys
69/// `gh skill install` writes.
70pub mod meta {
71    use crate::manifest;
72
73    /// Names the tool that installed the skill.
74    pub const EMBEDDED_BY: &str = manifest::KEY_EMBEDDED_BY;
75    /// The version of that tool.
76    pub const EMBEDDED_VERSION: &str = manifest::KEY_EMBEDDED_VERSION;
77    /// When the skill was installed, in RFC 3339 and UTC.
78    pub const EMBEDDED_AT: &str = manifest::KEY_EMBEDDED_AT;
79    /// The digest of what was installed.
80    pub const EMBEDDED_DIGEST: &str = manifest::KEY_EMBEDDED_DIGEST;
81}