Dependency predicates (depends-on)
Dependency predicates control when plugins and their components are active. A predicate matches against a workspace’s direct dependency set, not against individual packages in isolation. Today the dependency set is the workspace’s cargo dependency graph; a depends-on atom matches a direct dependency by name.
The depends-on field is accepted on the plugin itself, on [[skills]] groups, [[mcp_servers]] entries, [[plugins]] edges, and [subcommand.<name>] tables (see Plugin definitions), and in SKILL.md frontmatter. [[hooks]] and [[predicate]] entries have no depends-on field; gate a hook on a dependency with predicates = ["depends-on(serde)"].
The depends-on field is shorthand: depends-on = ["serde", "tokio"] lowers to a single any(depends-on(serde), depends-on(tokio)) predicate and is merged into the same list as the predicates field (ANDed together). Everything below describes the dependency-atom syntax depends-on accepts; the equivalent depends-on(<atom>) predicate is also usable directly in predicates.
Predicate syntax
A dependency atom is a package name with an optional version requirement.
Examples:
serdeserde>=1.0tokio^1.40regex<2.0serde=1.0serde==1.0.219*
Semantics:
- bare name: matches if the workspace has this package as a direct dependency (any version)
>=,<=,>,<,^,~: standard semver operators applied to the workspace’s version of the package=1.0: compatible-version matching, equivalent to^1.0==1.0.219: exact-version matching*: wildcard — always matches, even a workspace with zero dependencies
=is not Cargo’s=. In a dependency atom,=1.0means^1.0(1.0 or any later 1.x release), which is what a bare1.0means in Cargo. To pin an exact version, use==:serde==1.0.219matches only 1.0.219.
Further rules:
- Write the atom without spaces.
serde >=1.0is rejected; writeserde>=1.0. - Names match exactly, as the crate is published: a
serde-jsonatom does not match theserde_jsoncrate. - In TOML, an atom may carry a comma-separated range, every part of which must hold:
"serde>=1.0,<2.0". SKILL.md frontmatter splitsdepends-onon commas, so a range cannot be written there; usepredicates: depends-on(serde>=1.0,<2.0)instead.
Predicates match against direct workspace dependencies only, not transitive ones.
Usage in different contexts
Plugin manifests (TOML)
The depends-on field accepts a single atom string or an array of them:
depends-on = ["serde"]depends-on = ["serde", "tokio>=1.40"]depends-on = ["*"](wildcard — always active)
Skill frontmatter (YAML)
The depends-on field uses comma-separated values:
depends-on: serdedepends-on: serde, tokio>=1.40
Matching behavior
A depends-on list matches if at least one atom in the list matches the workspace. The wildcard * always matches — even a workspace with zero dependencies.
If there are multiple depends-on declarations in scope, all of them must match (AND composition). For example with skills, depends-on predicates can appear at three distinct levels:
- If a plugin defines
depends-onat the top-level, it must match before any other plugin contents will be considered. - If a skill-group within a plugin defines
depends-on, that predicate must match before the skills themselves will be fetched. - If the skills define
depends-onin their front-matter, those dependencies must match before the skills will be added to the project.
depends-on is purely a gate — it decides whether an item activates, not which crate to fetch. To load a crate’s own skills, name that crate explicitly in a [[plugins]] chained reference (source.cargo = "..."), gating the edge with depends-on as usual.
The crates field (in manifests and in SKILL.md frontmatter) and the crate(...) predicate are rejected; use depends-on.