From 930d07d8d346117fb94213261277c465cbde1e39 Mon Sep 17 00:00:00 2001 From: Scott Pfister Date: Thu, 16 Jul 2026 19:33:47 -0500 Subject: [PATCH 1/3] fix: use git-subdir source for claude-usage-report plugin A plugin entry that combined a bare relative-string source ("./skills/claude-usage-report") with a skills array ([".") tripped Claude Code's plugin resolver into its default: throw, surfaced as a misleading "update Claude Code" error. Switch to the git-subdir object form used by other skill-bearing marketplaces. After merge, re-pull with `/plugin marketplace update 7factor` (the local marketplaces copy is a cache). Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude-plugin/marketplace.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index e1792f6..0ce7918 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,7 +6,12 @@ "plugins": [ { "name": "claude-usage-report", - "source": "./skills/claude-usage-report", + "source": { + "source": "git-subdir", + "url": "https://github.com/7Factor/skills.git", + "path": "skills/claude-usage-report", + "ref": "main" + }, "skills": [ "." ], From 3f23b0b64fff9e0a1d6f52303925268204d4b662 Mon Sep 17 00:00:00 2001 From: Scott Pfister Date: Thu, 16 Jul 2026 20:59:28 -0500 Subject: [PATCH 2/3] fix(marketplace): use relative-path source and conventional skills layout The git-subdir source from the prior attempt made the plugin resolver throw its generic "source type your Claude Code version does not support" error, even on the latest Claude Code (2.1.212). That message is a misleading catch-all the resolver emits when it can't process an entry. Two coupled problems were feeding the throw: 1. the `git-subdir` object source, and 2. `skills: ["."]`, which trips the "Path escapes plugin directory" loader bug (same issue nicobailon/visual-explainer hit). `skills: ["."]` existed because SKILL.md sat at the plugin root, so the default `skills/` scan found nothing. Fix both by matching the conventional layout: - move the skill (SKILL.md + usage_report.py + update_pricing.py + prices.json) into skills/claude-usage-report/skills/claude-usage-report/ so the default scan finds it; drop the `skills` field entirely. - set the plugin source to the plain relative path "./skills/claude-usage-report" (the original, universally-supported form; resolves against the cloned marketplace repo). record_account.sh/.py, hooks/hooks.json, and .claude-plugin/plugin.json stay at the plugin root, so ${CLAUDE_PLUGIN_ROOT}/record_account.sh and the existing settings.json hook path keep working. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude-plugin/marketplace.json | 10 +--------- .../{ => skills/claude-usage-report}/SKILL.md | 0 .../{ => skills/claude-usage-report}/prices.json | 0 .../{ => skills/claude-usage-report}/update_pricing.py | 0 .../{ => skills/claude-usage-report}/usage_report.py | 0 5 files changed, 1 insertion(+), 9 deletions(-) rename skills/claude-usage-report/{ => skills/claude-usage-report}/SKILL.md (100%) rename skills/claude-usage-report/{ => skills/claude-usage-report}/prices.json (100%) rename skills/claude-usage-report/{ => skills/claude-usage-report}/update_pricing.py (100%) rename skills/claude-usage-report/{ => skills/claude-usage-report}/usage_report.py (100%) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 0ce7918..f4b3ae7 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,15 +6,7 @@ "plugins": [ { "name": "claude-usage-report", - "source": { - "source": "git-subdir", - "url": "https://github.com/7Factor/skills.git", - "path": "skills/claude-usage-report", - "ref": "main" - }, - "skills": [ - "." - ], + "source": "./skills/claude-usage-report", "description": "Usage/cost reports with self-refreshing pricing and per-account attribution." } ] diff --git a/skills/claude-usage-report/SKILL.md b/skills/claude-usage-report/skills/claude-usage-report/SKILL.md similarity index 100% rename from skills/claude-usage-report/SKILL.md rename to skills/claude-usage-report/skills/claude-usage-report/SKILL.md diff --git a/skills/claude-usage-report/prices.json b/skills/claude-usage-report/skills/claude-usage-report/prices.json similarity index 100% rename from skills/claude-usage-report/prices.json rename to skills/claude-usage-report/skills/claude-usage-report/prices.json diff --git a/skills/claude-usage-report/update_pricing.py b/skills/claude-usage-report/skills/claude-usage-report/update_pricing.py similarity index 100% rename from skills/claude-usage-report/update_pricing.py rename to skills/claude-usage-report/skills/claude-usage-report/update_pricing.py diff --git a/skills/claude-usage-report/usage_report.py b/skills/claude-usage-report/skills/claude-usage-report/usage_report.py similarity index 100% rename from skills/claude-usage-report/usage_report.py rename to skills/claude-usage-report/skills/claude-usage-report/usage_report.py From 0caaae95d54c8264e9dbb7a5e5a30e0fc6027fce Mon Sep 17 00:00:00 2001 From: Scott Pfister Date: Wed, 22 Jul 2026 22:57:09 -0500 Subject: [PATCH 3/3] fix: flatten skill layout to plugin root, drop nested skills/ dir The skills/ subdirectory scan approach doubled the plugin-name path segment (skills/claude-usage-report/skills/claude-usage-report/). The plugin resolver also supports a single SKILL.md directly at plugin root with no skills field declared at all, matching how other single-skill plugins (e.g. nicobailon/visual-explainer) are laid out in practice. Co-Authored-By: Claude Sonnet 5 --- .../claude-usage-report/{skills/claude-usage-report => }/SKILL.md | 0 .../{skills/claude-usage-report => }/prices.json | 0 .../{skills/claude-usage-report => }/update_pricing.py | 0 .../{skills/claude-usage-report => }/usage_report.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename skills/claude-usage-report/{skills/claude-usage-report => }/SKILL.md (100%) rename skills/claude-usage-report/{skills/claude-usage-report => }/prices.json (100%) rename skills/claude-usage-report/{skills/claude-usage-report => }/update_pricing.py (100%) rename skills/claude-usage-report/{skills/claude-usage-report => }/usage_report.py (100%) diff --git a/skills/claude-usage-report/skills/claude-usage-report/SKILL.md b/skills/claude-usage-report/SKILL.md similarity index 100% rename from skills/claude-usage-report/skills/claude-usage-report/SKILL.md rename to skills/claude-usage-report/SKILL.md diff --git a/skills/claude-usage-report/skills/claude-usage-report/prices.json b/skills/claude-usage-report/prices.json similarity index 100% rename from skills/claude-usage-report/skills/claude-usage-report/prices.json rename to skills/claude-usage-report/prices.json diff --git a/skills/claude-usage-report/skills/claude-usage-report/update_pricing.py b/skills/claude-usage-report/update_pricing.py similarity index 100% rename from skills/claude-usage-report/skills/claude-usage-report/update_pricing.py rename to skills/claude-usage-report/update_pricing.py diff --git a/skills/claude-usage-report/skills/claude-usage-report/usage_report.py b/skills/claude-usage-report/usage_report.py similarity index 100% rename from skills/claude-usage-report/skills/claude-usage-report/usage_report.py rename to skills/claude-usage-report/usage_report.py