Class: Generators::Avo::SkillsGenerator
- Inherits:
-
BaseGenerator
- Object
- Rails::Generators::Base
- BaseGenerator
- Generators::Avo::SkillsGenerator
- Defined in:
- lib/generators/avo/skills_generator.rb
Overview
Installs the Avo skills loader into the host app.
Only the loader is copied — the skills themselves stay inside the gem, which is the whole point: a copied skill tree drifts from the locked Avo version with nothing to refresh it. Re-running this generator refreshes the loader.
Deliberately its own namespace rather than part of avo:install, so it does
not change behavior for apps that already ran the installer.
Constant Summary collapse
- TARGETS =
Claude Code scans .claude/skills; .agents/skills is the cross-agent convention; .cursor/skills is what Cursor reads. Installing to all three is why the loader is copied rather than symlinked — a symlink into a version-named gem directory breaks on the next
bundle update. { "claude" => ".claude/skills/avo", "agents" => ".agents/skills/avo", "cursor" => ".cursor/skills/avo" }.freeze
- LEGACY_ROOTS =
Where a pre-gem install of avo-hq/skills materialized its catalog.
npx skills addwrites project-locally, so the stale copies land in the same directories this generator installs into. [ ".claude/skills", ".agents/skills", ".cursor/skills" ].freeze
- GLOBAL_LEGACY_ROOT =
Checked, reported, and never deleted. This directory is shared by every project on the machine — a skill here may be deliberately installed for a different app, and a generator run inside one project has no business removing it. The user gets the command instead.
"~/.claude/skills"
Instance Method Summary collapse
-
#clean_legacy_skills ⇒ Object
A leftover catalog sits in the same scan directories as the loader and can shadow it, silently serving instructions written for a different Avo version — which is the whole problem this feature removes.
- #install_loader ⇒ Object
Methods inherited from BaseGenerator
Constructor Details
This class inherits a constructor from Generators::Avo::BaseGenerator
Instance Method Details
#clean_legacy_skills ⇒ Object
A leftover catalog sits in the same scan directories as the loader and can shadow it, silently serving instructions written for a different Avo version — which is the whole problem this feature removes. Install time is the right place to catch it: it is the one moment we know the user is present and thinking about skills.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/generators/avo/skills_generator.rb', line 69 def clean_legacy_skills leftovers = legacy_skill_dirs global = global_legacy_skill_dirs return if leftovers.empty? && global.empty? if leftovers.any? say "\nFound #{pluralize_skills(leftovers.length)} in this project from a previous avo-hq/skills install:" by_directory(leftovers).each { |dir, count| say " #{dir}#{" " * padding(dir)}#{count}", :yellow } say "These are not version-pinned and can shadow the skills that ship with your Avo gem." if remove_legacy? by_directory(leftovers).each do |dir, count| leftovers.select { |path| display_dir(path) == dir }.each { |path| FileUtils.rm_rf(path) } say_status :remove, "#{dir} (#{pluralize_skills(count)})", :red end else report_kept(leftovers) end end report_global(global) if global.any? say "\nIf you installed the Claude Code plugin, remove it with: /plugin uninstall avo-skills" end |
#install_loader ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/generators/avo/skills_generator.rb', line 54 def install_loader return if panel_cancelled? # Only the loader is written. The resolver stays inside the gem, where # `bundle update` refreshes it and it cannot drift; a copy in the app # would be one more file to keep in sync, and 250 lines of shell in # someone's repo is a reasonable thing to be suspicious of. destinations.each { |destination| copy_file "skills/SKILL.md", File.join(destination, "SKILL.md") } end |