add-crate
SkillDev toolsAdd a new member crate to a Cargo workspace in this repo using the `y5-template` binary. Use whenever the user asks to add/create/scaffold a new crate, module, or workspace member (e.g. "add a crate under compositor.window", "scaffold action.foo"). Handles the chain-prefix naming convention and non-interactive invocation.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the add-crate skill
What this skill tells your AI
The instructions your AI receives, as published by y5-snowies/nourish in .claude/skills/add-crate/SKILL.md and read by ahel’s review.
Scaffold a new member crate into a Cargo workspace using y5-template (on PATH at
~/.cargo/bin/y5-template; source in environment/toolkit/y5-template/). Do NOT hand-create
Cargo.toml/lib.rs by hand — use the tool so naming and the template stay correct.
ALWAYS run compositor.workspace/link.all.sh from the repo root after creating a crate (step 5) —
the crate is not wired into the workspaces until you do.
The naming convention (chain-prefix)
A crate is created exactly two levels below a workspace root, and each level's
directory name chains off its parent: {parent_tail}.{own_segment}.
compositor/ workspace root (Cargo.toml [workspace] members glob has ≥2 `*`)
compositor.action/ L0 (root_tail "compositor" + "action")
action.window/ L1 = the target directory
window.{Name}/ L2 = what the tool CREATES
- root_tail = last dot-segment of the workspace dir name (
compositor→compositor). - A valid L0 is
{root_tail}.{seg}, a valid L1 is{seg}.{sub}. - The created dir is
{L1_own_segment}.{Name}and must not already exist.
Steps
-
Find valid targets (the L1 dirs you can add into):
y5-template --scan /workspace --listThis prints every valid
<workspace> › <L0> › <L1>with its absolute path. -
Create the crate non-interactively. The picker needs a TTY, so use
--dir(which skips the picker when the dir validates) and pipe the Name to stdin:printf 'NAME\n' | y5-template --dir /workspace/compositor/compositor.action/action.windowNAMEbecomes the crate suffix → createswindow.NAME/.- Batch:
printf 'a, b, c\n' | y5-template --dir <L1_DIR>createswindow.a,window.b,window.catomically (aborts if any already exists). - Extra template vars: if the chosen template declares vars beyond
Name, they are prompted after Name — feed them as additional lines:printf 'NAME\nval1\nval2\n' | y5-template --dir <L1_DIR>. Check first with:y5-template --template <NAME> --helpis not enough — inspect the template under<workspace>/y5.template/<tpl>/for$${var}$$placeholders. --template <NAME>selects a non-default template (default isdefault).
-
Need a new L0 or L1 first? The
+ L0/L1bootstrap only works through the interactive picker, so non-interactively just create the chain-prefixed dirs yourself, then run step 2:mkdir -p /workspace/compositor/compositor.<L0>/<L0>.<L1> printf 'NAME\n' | y5-template --dir /workspace/compositor/compositor.<L0>/<L0>.<L1> -
Verify: confirm
{L1}.{Name}/exists with the template files, and that the workspaceCargo.tomlmember glob already covers it (it does if the glob iscompositor.<L0>/*/*-style — no manualmembersedit needed).The template's
lib.rsis already SHELL-conforming (extern crate+pub mod) — keep it that way. Code goes in the generated<module>.rsbeside it; afn,struct,implorconstwritten intolib.rsfails the lint, and that rule has no allowlist. Re-export fromlib.rswithpub use <module>::…if callers should see an item at the crate root. -
Write its
crate.json.Cargo.tomlis a GENERATED artifact — gitignored, and overwritten on every build — so a crate declares its dependencies incrate.jsonbesidelib.rs. It is JSONC, so a//comment above a dependency is kept and re-emitted above that line in the generated manifest:{ "deps": [ // Developer logging — provides error!/warn!/info!/trace!/abort!. "compositor_model_debug_instance_record", "smithay" ] }Names only. A crate never states a version, a feature or a manifest shape — those live in
compositor.workspace/vendor.catalog.json(external versions/features) andcompositor.workspace/workspace.catalog.json(per-crate features,[[bin]], build scripts, …).Only add what the crate actually uses: an unused dependency FAILS the lint (
deps-unused), and a dependency that is genuinely needed but never named in the source — e.g. spliced in bytonic::include_proto!— goes inkeepwith a reason. -
Regenerate.
environment/build.shandenvironment/check.shdo this for you before invoking cargo, so usually there is nothing to run. To refresh the tree for an editor without building:compositor.workspace/link.all.sh(which now just generates + lints).
Template variables (for reference)
For compositor/compositor.action/action.window + Name = handle:
| variable | value |
|---|---|
workspace_name | compositor |
L0 / L1 | action / window |
Name | handle |
fully_qualified_crate_name | compositor_action_window_handle |
fully_qualified_module_name | handle |
Notes
--scandefaults to$ZED_WORKTREE_ROOTthen cwd; pass--scan /workspaceexplicitly when running from elsewhere.- In Zed, humans use the picker via
alt-n(default template) /alt-shift-n(named); that path also pins the L1 of the currently-open file. The CLI--dirflow above is the equivalent for non-interactive/agent use. - Full reference:
environment/toolkit/y5-template/.
Signals
- GitHub stars
- 229
- Forks
- 7
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
add-crate- Source
- github.com/y5-snowies/nourish