fix(skills): skip flat admin files when writing to external output dir#9
Conversation
Greptile SummaryThis PR guards the three flat admin files (
|
| Filename | Overview |
|---|---|
| src/iotcli/skills/generator.py | Adds is_default_dir guard in generate_all so flat admin files (iotcli.tools.json, iotcli.skill.yaml, system_prompt.md) are only written to the canonical ~/.iotcli/skills/ directory; _cleanup_stale stale-dir removal continues to run for external dirs and may delete non-iotcli skill dirs in shared external paths. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["generate_all(output_dir)"] --> B{"output_dir provided?"}
B -- "No" --> C["out = self.skills_dir (canonical)"]
B -- "Yes" --> D["out = Path(output_dir)"]
C --> E["Write per-device SKILL.md dirs"]
D --> E
E --> F{"is_default_dir?\nout.resolve() == skills_dir.resolve()"}
F -- "True (canonical dir)" --> G["_cleanup_stale(purge_legacy=True)\n removes stale device dirs +\n legacy *.skill.md files"]
F -- "False (external dir)" --> H["_cleanup_stale(purge_legacy=False)\n removes stale device dirs only\n ⚠️ may delete non-iotcli dirs"]
G --> I["Write iotcli.tools.json\nWrite iotcli.skill.yaml\nWrite system_prompt.md"]
H --> J["Skip flat admin files ✓"]
I --> K["Return results"]
J --> K
Comments Outside Diff (1)
-
src/iotcli/skills/generator.py, line 459-469 (link)Stale-dir cleanup deletes non-iotcli skill dirs in shared external paths
The primary motivation for this PR is to make
--output-dir ~/.claude/skillssafe for agent skill loaders. However,_cleanup_stalestill iterates over the entire external directory and deletes any subdirectory that (a) contains aSKILL.mdfile and (b) is not named after a current iotcli device slug. In a shared dir like~/.claude/skillsthis will destructively remove third-party skill dirs that iotcli never created.Concretely: if
~/.claude/skills/my-other-tool/SKILL.mdexists andmy-other-toolis not an iotcli device,generate_all --output-dir ~/.claude/skillssilently deletes it.The comment on line 185 acknowledges this ("we still remove orphan per-device SKILL.md dirs (we created those)") but the code has no record of which directories it actually created, so the assumption doesn't hold for a shared external dir.
A targeted fix would be to skip stale-dir cleanup entirely when
is_default_dirisFalse, or to track created directories and only clean up known ones:# Only run stale cleanup when we own the directory if is_default_dir: self._cleanup_stale(out, live_slugs, purge_legacy=True)
or alternatively, limit the per-device cleanup to only the slugs that were generated in the current invocation:
# In external dirs, only remove dirs we just overwrote whose device is gone if not is_default_dir: self._cleanup_stale(out, live_slugs, purge_legacy=False)
If the existing conservative approach (remove stale dirs even in external dirs) is intentional, the comment on line 185 should be strengthened to warn users that the external dir will have orphan device dirs cleaned up, so they should not co-locate unrelated skills with the same name as an iotcli device slug.
Reviews (2): Last reviewed commit: "docs(skills): update module and generate..." | Re-trigger Greptile
…nditional admin file output
|
@greptile review |
Summary
--output-dirpoints outside~/.iotcli/skills/(e.g.~/.claude/skills),system_prompt.md,iotcli.skill.yaml, andiotcli.tools.jsonwere being written there alongside the per-device SKILL.md dirssystem_prompt.mdin particular could confuse an agent's skill loader if read as raw context~/.iotcli/skills/dirTest plan
iotcli skills generate --output-dir /tmp/test→ only per-device dirs, no flat filesiotcli skills generate(no flag) → all files includingsystem_prompt.md,iotcli.tools.json,iotcli.skill.yaml