mirror of
https://github.com/magnus919/agent-skills.git
synced 2026-09-14 13:06:30 +03:00
Drop the Dir.glob("#{ROOT}/bundles/*/SKILL.md") term from gen-llms-txt.rb,
gen-claude-marketplace.rb, and gen-codex-plugin.rb (the first glob */SKILL.md
now covers the 8 former bundle umbrellas) and refresh the header comments.
Regenerate llms.txt and .codex-plugin/plugin.json (./bundles/<name> ->
./<name>); .claude-plugin/marketplace.json is byte-identical. Update
test-gen-llms-txt.rb fixtures from bundles/zulu etc. to top-level zulu/ with
assertions [zulu](zulu/SKILL.md), and make the duplicate-guard test robust to
case-insensitive filesystems where case-variant dir names collapse.
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
91 lines
3.0 KiB
Ruby
91 lines
3.0 KiB
Ruby
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
# Generates and validates .claude-plugin/marketplace.json — the metadata-only
|
|
# catalog that lets Claude Code install skills straight from this repository:
|
|
#
|
|
# /plugin marketplace add magnus919/agent-skills
|
|
# /plugin install cli-builder@magnus-agent-skills
|
|
#
|
|
# Each public skill becomes a plugin entry whose source is the repository root
|
|
# and whose `skills` field points at the skill's own directory. `strict: false`
|
|
# means no per-skill plugin.json is required. Bundle-internal helper skills are
|
|
# intentionally excluded — they ship inside their bundle, not standalone.
|
|
#
|
|
# Usage:
|
|
# ruby scripts/gen-claude-marketplace.rb # validate committed file is current
|
|
# ruby scripts/gen-claude-marketplace.rb --write # regenerate the file
|
|
|
|
require "fileutils"
|
|
require "json"
|
|
require "yaml"
|
|
|
|
ROOT = File.expand_path("..", __dir__)
|
|
MARKETPLACE_PATH = File.join(ROOT, ".claude-plugin", "marketplace.json")
|
|
MARKETPLACE_NAME = "magnus-agent-skills" # "agent-skills" is reserved by Claude Code
|
|
|
|
# Public install candidates: top-level skills and bundle entrypoints. This is
|
|
# the same glob validate-skills.rb uses for the README catalog, and it excludes
|
|
# bundle-internal helper skills (<bundle>/skills/<sub>/SKILL.md).
|
|
PUBLIC_SKILLS = Dir.glob("#{ROOT}/*/SKILL.md").sort
|
|
|
|
def frontmatter(skill_path)
|
|
text = File.read(skill_path)
|
|
match = text.match(/\A---\n(.*?)\n---\n/m)
|
|
raise "#{skill_path}: missing YAML frontmatter" unless match
|
|
|
|
data = YAML.safe_load(match[1], permitted_classes: [], aliases: false)
|
|
raise "#{skill_path}: frontmatter must be a mapping" unless data.is_a?(Hash)
|
|
|
|
data
|
|
end
|
|
|
|
def build_marketplace
|
|
plugins = PUBLIC_SKILLS.map do |skill|
|
|
dir = File.dirname(skill)
|
|
name = File.basename(dir)
|
|
data = frontmatter(skill)
|
|
description = data["description"].to_s.gsub(/\s+/, " ").strip
|
|
{
|
|
"name" => name,
|
|
"source" => "./",
|
|
"skills" => ["./#{name}"],
|
|
"strict" => false,
|
|
"description" => description
|
|
}
|
|
end.sort_by { |entry| entry["name"] }
|
|
|
|
{
|
|
"name" => MARKETPLACE_NAME,
|
|
"owner" => { "name" => "Magnus Hedemark" },
|
|
"description" => "AI agent skills — reusable workflows, protocols, and knowledge packs for agentic systems.",
|
|
"plugins" => plugins
|
|
}
|
|
end
|
|
|
|
def render(marketplace)
|
|
JSON.pretty_generate(marketplace) + "\n"
|
|
end
|
|
|
|
expected = render(build_marketplace)
|
|
|
|
if ARGV.include?("--write")
|
|
FileUtils.mkdir_p(File.dirname(MARKETPLACE_PATH))
|
|
File.write(MARKETPLACE_PATH, expected)
|
|
puts "Wrote #{MARKETPLACE_PATH.delete_prefix("#{ROOT}/")} (#{PUBLIC_SKILLS.length} plugins)."
|
|
exit 0
|
|
end
|
|
|
|
unless File.file?(MARKETPLACE_PATH)
|
|
warn "#{MARKETPLACE_PATH.delete_prefix("#{ROOT}/")} is missing. Run: ruby scripts/gen-claude-marketplace.rb --write"
|
|
exit 1
|
|
end
|
|
|
|
actual = File.read(MARKETPLACE_PATH)
|
|
if actual != expected
|
|
warn "#{MARKETPLACE_PATH.delete_prefix("#{ROOT}/")} is out of date. Run: ruby scripts/gen-claude-marketplace.rb --write"
|
|
exit 1
|
|
end
|
|
|
|
puts "marketplace.json is current (#{PUBLIC_SKILLS.length} plugins)."
|